From 0901b9accc0ee11072daebedbc385cf38364144a Mon Sep 17 00:00:00 2001
From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
Date: Sun, 21 Apr 2019 19:44:00 +0300
Subject: [PATCH 119/122] media: i2c: add AR0147 imager

This adds AR0147 imager

Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
---
 drivers/media/i2c/soc_camera/Kconfig       |   6 +
 drivers/media/i2c/soc_camera/Makefile      |   1 +
 drivers/media/i2c/soc_camera/ar0147.c      | 714 ++++++++++++++++++++++++++
 drivers/media/i2c/soc_camera/ar0147.h      |  36 ++
 drivers/media/i2c/soc_camera/ar0147_rev1.h | 607 ++++++++++++++++++++++
 drivers/media/i2c/soc_camera/ar0147_rev2.h | 796 +++++++++++++++++++++++++++++
 6 files changed, 2160 insertions(+)
 create mode 100644 drivers/media/i2c/soc_camera/ar0147.c
 create mode 100644 drivers/media/i2c/soc_camera/ar0147.h
 create mode 100644 drivers/media/i2c/soc_camera/ar0147_rev1.h
 create mode 100644 drivers/media/i2c/soc_camera/ar0147_rev2.h

diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig
index 627d8d9..edff0b0 100644
--- a/drivers/media/i2c/soc_camera/Kconfig
+++ b/drivers/media/i2c/soc_camera/Kconfig
@@ -106,3 +106,9 @@ config SOC_CAMERA_IMX219
 	depends on SOC_CAMERA && I2C
 	help
 	  This is Sony IMX219 driver
+
+config SOC_CAMERA_AR0147
+	tristate "AR0147 camera support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This is an AR0147 imager glue
diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile
index 4aa5046..367674b 100644
--- a/drivers/media/i2c/soc_camera/Makefile
+++ b/drivers/media/i2c/soc_camera/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_SOC_CAMERA_OV106XX)	+= ov106xx.o
 obj-$(CONFIG_SOC_CAMERA_IMX219)		+= imx219.o
 obj-y					+= dummy.o
 
+obj-$(CONFIG_SOC_CAMERA_AR0147)		+= ar0147.o
diff --git a/drivers/media/i2c/soc_camera/ar0147.c b/drivers/media/i2c/soc_camera/ar0147.c
new file mode 100644
index 0000000..cc7face
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ar0147.c
@@ -0,0 +1,714 @@
+/*
+ * ON Semiconductor AR0147 sensor camera driver
+ *
+ * Copyright (C) 2019 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 "max9286.h"
+#include "ar0147.h"
+
+#define AR0147_I2C_ADDR		0x10
+
+#define AR0147_PID		0x3000
+#define AR0147_REV		0x31FE
+#define AR0147_VERSION_REG	0x1D54
+
+#define AR0147_MEDIA_BUS_FMT	MEDIA_BUS_FMT_SGRBG12_1X12
+
+struct ar0147_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				max9286_addr;
+	int				max9271_addr;
+	int				ti9x4_addr;
+	int				ti9x3_addr;
+	int				port;
+	int				gpio_resetb;
+	int				gpio_fsin;
+	int				hts;
+	int				vts;
+	int				frame_preamble;
+};
+
+static char *mode = "hdr";
+module_param(mode, charp, 0644);
+MODULE_PARM_DESC(mode, " Modes linear,hdr,se,seplus (default: hdr)");
+
+static inline struct ar0147_priv *to_ar0147(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct ar0147_priv, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct ar0147_priv, hdl)->sd;
+}
+
+static void ar0147_s_port(struct i2c_client *client, int fwd_en)
+{
+	struct ar0147_priv *priv = to_ar0147(client);
+	int tmp_addr;
+
+	if (priv->max9286_addr) {
+		tmp_addr = client->addr;
+		client->addr = priv->max9286_addr;				/* Deserializer I2C address */
+		reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0);	/* Enable/disable reverse/forward control for this port */
+		usleep_range(5000, 5500);					/* wait 5ms */
+		client->addr = tmp_addr;
+	};
+}
+
+static int ar0147_set_regs(struct i2c_client *client, const struct ar0147_reg **pregs)
+{
+	struct ar0147_priv *priv = to_ar0147(client);
+	const struct ar0147_reg *regs;
+	int i, j;
+
+	for (j = 0; ; j++) {
+		regs = pregs[j];
+
+		if (!pregs[j])
+			break;
+
+		for (i = 0; ; i++) {
+			if (!regs[i].reg && !regs[i].val)
+				break;
+
+			if (regs[i].reg == AR0147_DELAY) {
+				mdelay(regs[i].val);
+				continue;
+			}
+			/* cache timings */
+			if (regs[i].reg == 0x300a)
+				priv->vts = regs[i].val;
+			if (regs[i].reg == 0x300c)
+				priv->hts = regs[i].val;
+			if (regs[i].reg == 0x31b0)
+				priv->frame_preamble = regs[i].val - 1;
+
+			if (priv->ti9x4_addr) {
+				/* Override default (MAXIM serializer) table */
+				/* PCLK=16Mhz/2 *48/1/8= 48Mhz - TI serializers */
+				switch (regs[i].reg) {
+				case 0x302A:
+					reg16_write16(client, regs[i].reg, 8); // VT_PIX_CLK_DIV
+					continue;
+				case 0x302C:
+					reg16_write16(client, regs[i].reg, 1); // VT_SYS_CLK_DIV
+					continue;
+				case 0x302E:
+					reg16_write16(client, regs[i].reg, 2); // PRE_PLL_CLK_DIV
+					continue;
+				case 0x3030:
+					reg16_write16(client, regs[i].reg, 48); // PLL_MULTIPLIER
+					continue;
+				case 0x3036:
+					reg16_write16(client, regs[i].reg, 8); // OP_WORD_CLK_DIV
+					continue;
+				case 0x3038:
+					reg16_write16(client, regs[i].reg, 1); // OP_SYS_CLK_DIV
+					continue;
+				case 0x300A:
+					reg16_write16(client, regs[i].reg, AR0147_SENSOR_HEIGHT + 142); // FRAME_LENGTH_LINES_
+					continue;
+				}
+			}
+
+			reg16_write16(client, regs[i].reg, regs[i].val);
+		}
+	}
+
+	return 0;
+}
+
+static int ar0147_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	return 0;
+}
+
+static int ar0147_set_window(struct v4l2_subdev *sd)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ar0147_priv *priv = to_ar0147(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);
+	/* horiz crop end */
+	reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1);
+	/* vert crop start */
+	reg16_write16(client, 0x3002, priv->rect.top);
+	/* vert crop end */
+	reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height - 1);
+
+	return 0;
+};
+
+static int ar0147_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 ar0147_priv *priv = to_ar0147(client);
+
+	if (format->pad)
+		return -EINVAL;
+
+	mf->width = priv->rect.width;
+	mf->height = priv->rect.height;
+	mf->code = AR0147_MEDIA_BUS_FMT;
+	mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	mf->field = V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int ar0147_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 = AR0147_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 ar0147_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 = AR0147_MEDIA_BUS_FMT;
+
+	return 0;
+}
+
+static int ar0147_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ar0147_priv *priv = to_ar0147(client);
+
+	memcpy(edid->edid, priv->id, 6);
+
+	edid->edid[6] = 0xff;
+	edid->edid[7] = client->addr;
+	edid->edid[8] = AR0147_VERSION_REG >> 8;
+	edid->edid[9] = AR0147_VERSION_REG & 0xff;
+
+	return 0;
+}
+
+static int ar0147_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 ar0147_priv *priv = to_ar0147(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 > AR0147_MAX_WIDTH) ||
+	    (rect->top + rect->height > AR0147_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;
+
+	ar0147_set_window(sd);
+
+	return 0;
+}
+
+static int ar0147_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 ar0147_priv *priv = to_ar0147(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 = AR0147_MAX_WIDTH;
+		sel->r.height = AR0147_MAX_HEIGHT;
+		return 0;
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		sel->r.left = 0;
+		sel->r.top = 0;
+		sel->r.width = AR0147_MAX_WIDTH;
+		sel->r.height = AR0147_MAX_HEIGHT;
+		return 0;
+	case V4L2_SEL_TGT_CROP:
+		sel->r = priv->rect;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ar0147_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 ar0147_g_register(struct v4l2_subdev *sd,
+			    struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+	u16 val = 0;
+
+	ret = reg16_read16(client, (u16)reg->reg, &val);
+	if (ret < 0)
+		return ret;
+
+	reg->val = val;
+	reg->size = sizeof(u16);
+
+	return 0;
+}
+
+static int ar0147_s_register(struct v4l2_subdev *sd,
+			    const struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return reg16_write16(client, (u16)reg->reg, (u16)reg->val);
+}
+#endif
+
+static struct v4l2_subdev_core_ops ar0147_core_ops = {
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = ar0147_g_register,
+	.s_register = ar0147_s_register,
+#endif
+};
+
+static int ar0147_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ar0147_priv *priv = to_ar0147(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);
+		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 |= 0x4000;
+		else
+			val &= ~0x4000;
+		ret |= reg16_write16(client, 0x3040, val);
+		break;
+	case V4L2_CID_VFLIP:
+		ret = reg16_read16(client, 0x3040, &val);
+		if (ctrl->val)
+			val |= 0x8000;
+		else
+			val &= ~0x8000;
+		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 ar0147_ctrl_ops = {
+	.s_ctrl = ar0147_s_ctrl,
+};
+
+static struct v4l2_subdev_video_ops ar0147_video_ops = {
+	.s_stream	= ar0147_s_stream,
+	.g_mbus_config	= ar0147_g_mbus_config,
+};
+
+static const struct v4l2_subdev_pad_ops ar0147_subdev_pad_ops = {
+	.get_edid	= ar0147_get_edid,
+	.enum_mbus_code	= ar0147_enum_mbus_code,
+	.get_selection	= ar0147_get_selection,
+	.set_selection	= ar0147_set_selection,
+	.get_fmt	= ar0147_get_fmt,
+	.set_fmt	= ar0147_set_fmt,
+};
+
+static struct v4l2_subdev_ops ar0147_subdev_ops = {
+	.core	= &ar0147_core_ops,
+	.video	= &ar0147_video_ops,
+	.pad	= &ar0147_subdev_pad_ops,
+};
+
+static void ar0147_otp_id_read(struct i2c_client *client)
+{
+	struct ar0147_priv *priv = to_ar0147(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 ssize_t ar0147_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 ar0147_priv *priv = to_ar0147(client);
+
+	ar0147_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_ar0147, S_IRUGO, ar0147_otp_id_show, NULL);
+
+static int ar0147_initialize(struct i2c_client *client)
+{
+	struct ar0147_priv *priv = to_ar0147(client);
+	u16 val = 0;
+	u16 pid = 0, rev = 0;
+	int ret = 0;
+	int tmp_addr;
+
+	ar0147_s_port(client, 1);
+
+	/* check and show model ID */
+	reg16_read16(client, AR0147_PID, &pid);
+
+	if (pid != AR0147_VERSION_REG) {
+		dev_dbg(&client->dev, "Product ID error %x\n\n\n", pid);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	/* check revision  */
+	reg16_read16(client, AR0147_REV, &rev);
+	/* Read OTP IDs */
+	ar0147_otp_id_read(client);
+	/* Program wizard registers */
+	switch (rev & 0xf) {
+		case 0x1:
+			ar0147_set_regs(client, ar0147_regs_hdr_mipi450mbps_12bit_30fps_rev1);
+			break;
+		case 0x2:
+			if (strcmp(mode, "hdr") == 0)
+				ar0147_set_regs(client, ar0147_regs_hdr_mipi450mbps_12bit_30fps_rev2);
+			else if (strcmp(mode, "seplus") == 0)
+				ar0147_set_regs(client, ar0147_regs_seplus_mipi450mbps_12bit_30fps_rev2);
+			else
+				dev_err(&client->dev, "Unsupported mode %s\n", mode);
+			break;
+		default:
+			dev_err(&client->dev, "Unsupported chip revision\n");
+	}
+
+	tmp_addr = client->addr;
+	if (priv->max9271_addr) {
+		/* setup serializer HS generator */
+		client->addr = priv->max9271_addr;			/* Serializer I2C address */
+		reg8_write(client, 0x4e, priv->frame_preamble >> 16);	/* HS delay */
+		reg8_write(client, 0x4f, (priv->frame_preamble >> 8) & 0xff);
+		reg8_write(client, 0x50, priv->frame_preamble & 0xff);
+		reg8_write(client, 0x54, AR0147_MAX_WIDTH >> 8);	/* HS high period */
+		reg8_write(client, 0x55, AR0147_MAX_WIDTH & 0xff);
+		reg8_write(client, 0x56, (priv->hts - AR0147_MAX_WIDTH) >> 8); /* HS low period */
+		reg8_write(client, 0x57, (priv->hts - AR0147_MAX_WIDTH) & 0xff);
+		reg8_write(client, 0x58, priv->vts >> 8);		/* HS count */
+		reg8_write(client, 0x59, priv->vts & 0xff);
+	}
+	client->addr = tmp_addr;
+
+	/* Enable stream */
+	reg16_read16(client, 0x301a, &val);
+	val |= (1 << 2);
+	reg16_write16(client, 0x301a, val);
+
+	dev_info(&client->dev, "ar0147 PID %x (rev %x), res %dx%d, mode=%s, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n",
+		 pid, rev, AR0147_MAX_WIDTH, AR0147_MAX_HEIGHT, mode, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
+err:
+	ar0147_s_port(client, 0);
+
+	return ret;
+}
+
+static int ar0147_parse_dt(struct device_node *np, struct ar0147_priv *priv)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&priv->sd);
+	int i;
+	struct device_node *endpoint = NULL, *rendpoint = NULL;
+	int tmp_addr = 0;
+
+	for (i = 0; ; i++) {
+		endpoint = of_graph_get_next_endpoint(np, endpoint);
+		if (!endpoint)
+			break;
+
+		rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0);
+		if (!rendpoint)
+			continue;
+
+		if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) &&
+		    !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) &&
+		    !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port))
+			break;
+
+		if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) &&
+		    !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") &&
+		    !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) &&
+		    !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port))
+			break;
+	}
+
+	of_node_put(endpoint);
+
+	if (!priv->max9286_addr && !priv->ti9x4_addr) {
+		dev_err(&client->dev, "deserializer does not present for AR0147\n");
+//		return -EINVAL;
+	}
+
+	ar0147_s_port(client, 1);
+
+	/* setup I2C translator address */
+	tmp_addr = client->addr;
+	if (priv->max9286_addr) {
+		client->addr = priv->max9271_addr;			/* Serializer I2C address */
+
+		reg8_write(client, 0x09, tmp_addr << 1);		/* Sensor translated I2C address */
+		reg8_write(client, 0x0A, AR0147_I2C_ADDR << 1);		/* Sensor native I2C address */
+		usleep_range(2000, 2500);				/* wait 2ms */
+	};
+	if (priv->ti9x4_addr) {
+		client->addr = priv->ti9x4_addr;			/* Deserializer I2C address */
+
+		reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */
+		usleep_range(2000, 2500);				/* wait 2ms */
+		reg8_write(client, 0x65, tmp_addr << 1);		/* Sensor translated I2C address */
+		reg8_write(client, 0x5d, AR0147_I2C_ADDR << 1);		/* Sensor native I2C address */
+
+		reg8_write(client, 0x6e, 0xa9);				/* GPIO0 - reset, GPIO1 - fsin */
+	}
+	client->addr = tmp_addr;
+
+	mdelay(10);
+
+	return 0;
+}
+
+static int ar0147_probe(struct i2c_client *client,
+		       const struct i2c_device_id *did)
+{
+	struct ar0147_priv *priv;
+	int ret;
+
+	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&priv->sd, client, &ar0147_subdev_ops);
+	priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	v4l2_ctrl_handler_init(&priv->hdl, 4);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, 0, 16, 1, 7);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops,
+			  V4L2_CID_CONTRAST, 0, 16, 1, 7);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops,
+			  V4L2_CID_SATURATION, 0, 7, 1, 2);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops,
+			  V4L2_CID_HUE, 0, 23, 1, 12);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops,
+			  V4L2_CID_GAMMA, -128, 128, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops,
+			  V4L2_CID_SHARPNESS, 0, 10, 1, 3);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops,
+			  V4L2_CID_AUTOGAIN, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops,
+			  V4L2_CID_GAIN, 1, 0x7ff, 1, 0x200);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops,
+			  V4L2_CID_ANALOGUE_GAIN, 1, 0xe, 1, 0x7);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops,
+			  V4L2_CID_EXPOSURE, 1, 0x400, 1, 0x300);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops,
+			  V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0147_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 = ar0147_parse_dt(client->dev.of_node, priv);
+	if (ret)
+		goto cleanup;
+
+	ret = ar0147_initialize(client);
+	if (ret < 0)
+		goto cleanup;
+
+	priv->rect.left = 0;
+	priv->rect.top = 0;
+	priv->rect.width = AR0147_MAX_WIDTH;
+	priv->rect.height = AR0147_MAX_HEIGHT;
+
+	ret = v4l2_async_register_subdev(&priv->sd);
+	if (ret)
+		goto cleanup;
+
+	if (device_create_file(&client->dev, &dev_attr_otp_id_ar0147) != 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);
+#ifdef CONFIG_SOC_CAMERA_AR0147
+	v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
+		client->addr, client->adapter->name);
+#endif
+	return ret;
+}
+
+static int ar0147_remove(struct i2c_client *client)
+{
+	struct ar0147_priv *priv = i2c_get_clientdata(client);
+
+	device_remove_file(&client->dev, &dev_attr_otp_id_ar0147);
+	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;
+}
+
+#ifdef CONFIG_SOC_CAMERA_AR0147
+static const struct i2c_device_id ar0147_id[] = {
+	{ "ar0147", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ar0147_id);
+
+static const struct of_device_id ar0147_of_ids[] = {
+	{ .compatible = "onnn,ar0147", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ar0147_of_ids);
+
+static struct i2c_driver ar0147_i2c_driver = {
+	.driver	= {
+		.name		= "ar0147",
+		.of_match_table	= ar0147_of_ids,
+	},
+	.probe		= ar0147_probe,
+	.remove		= ar0147_remove,
+	.id_table	= ar0147_id,
+};
+
+module_i2c_driver(ar0147_i2c_driver);
+
+MODULE_DESCRIPTION("SoC Camera driver for AR0147");
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/media/i2c/soc_camera/ar0147.h b/drivers/media/i2c/soc_camera/ar0147.h
new file mode 100644
index 0000000..0f7ce31
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ar0147.h
@@ -0,0 +1,36 @@
+/*
+ * ON Semiconductor AR0147 sensor camera wizard 1344x968@30/BGGR/BT601/RAW12
+ *
+ * Copyright (C) 2019 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 AR0147_DISPLAY_PATTERN_FIXED
+//#define AR0147_DISPLAY_PATTERN_COLOR_BAR
+
+//#define AR0147_EMBEDDED_LINE
+
+#define AR0147_MAX_WIDTH	1344
+#define AR0147_MAX_HEIGHT	968
+
+#define AR0147_DELAY		0xffff
+
+#define AR0147_SENSOR_WIDTH	1344
+#define AR0147_SENSOR_HEIGHT	968
+
+#define AR0147_X_START		((AR0147_SENSOR_WIDTH - AR0147_MAX_WIDTH) / 2)
+#define AR0147_Y_START		((AR0147_SENSOR_HEIGHT - AR0147_MAX_HEIGHT) / 2)
+#define AR0147_X_END		(AR0147_X_START + AR0147_MAX_WIDTH - 1)
+#define AR0147_Y_END		(AR0147_Y_START + AR0147_MAX_HEIGHT - 1)
+
+struct ar0147_reg {
+	u16	reg;
+	u16	val;
+};
+
+#include "ar0147_rev1.h"
+#include "ar0147_rev2.h"
diff --git a/drivers/media/i2c/soc_camera/ar0147_rev1.h b/drivers/media/i2c/soc_camera/ar0147_rev1.h
new file mode 100644
index 0000000..430e265
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ar0147_rev1.h
@@ -0,0 +1,607 @@
+/*
+ * ON Semiconductor AR0147 sensor camera wizard 1344x968@30/BGGR/BT601/RAW12
+ *
+ * Copyright (C) 2019 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 AR0147_REV1_2_Recommended_Settings
+
+static const struct ar0147_reg ar0147_rev1_Reset[] = {
+{0x301A, 0x0001},	// reset
+{AR0147_DELAY, 100},
+{0x301A, 0x10D8},	// Stream off and setup parallel
+{0x3070, 0x0001},
+{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)
+#ifdef AR0147_DISPLAY_PATTERN_FIXED
+{0x3070, 0x0001},
+#endif
+{0x3072, 0x0fff},	// R
+{0x3074, 0x0fff},	// G(GR row)
+{0x3076, 0x0fff},	// B
+{0x3078, 0x0fff},	// G(GB row)
+#ifdef AR0147_DISPLAY_PATTERN_COLOR_BAR
+{0x3070, 0x0002},
+#endif
+{AR0147_DELAY, 250},
+{ }
+}; /* Reset */
+
+static const struct ar0147_reg ar0147_rev1_Sensor_Setup[] = {
+/* Recommended_Settings */
+{0x30B0, 0x980C}, // DIGITAL_TEST
+{0x3C08, 0x0100},
+{0x3C0C, 0x0518},
+{0x3092, 0x1A24},
+{0x30B4, 0x01C7}, // TEMPSENS0_CTRL_REG
+{0x30B8, 0x0007}, // TEMPSENS1_CTRL_REG
+{0x3364, 0x0680},
+{0x3372, 0x700F},
+{0x350C, 0x035A},
+{0x350E, 0x0514},
+{0x3518, 0x14FE},
+{0x351A, 0x6000},
+{0x3520, 0x08CC},
+{0x3522, 0xCC08},
+{0x3524, 0x0C00},
+{0x3526, 0x0F00},
+{0x3528, 0xFFFF},
+{0x352A, 0x0897},
+{0x352C, 0x0012},
+{0x352E, 0x00FF},
+{0x3530, 0xFF00},
+{0x3536, 0xFF24},
+{0x3538, 0x3CFF},
+{0x353A, 0x90E0},
+{0x353C, 0x3F00},
+{0x3540, 0xC63C},
+{0x3542, 0x3C3C},
+{0x3544, 0x3C46},
+{0x3546, 0x5458},
+{0x3548, 0x5800},
+{0x354A, 0x007F},
+{0x3556, 0x1010},
+{0x3F90, 0x0800}, // TEMPVSENS0_TMG_CTRL
+{0x3F9A, 0x0000}, // TEMPVSENS0_BOOST_SAMP_CTRL
+{0x3116, 0x0001}, // HDR_CONTROL3
+{0x3102, 0x60A0},
+{0x3104, 0x60A0},
+{0x3106, 0x60A0},
+
+//Set REV1 Minimum Analog Gain to LCG 3.5X
+{0x3366, 0xCCCC},
+{0x3362, 0x0000},
+#ifdef AR0147_REV1_REV1_2_Recommended_Settings
+//Set REV1.2 Default Analog Gain to LCG 8X (minimum recommended)
+{0x3366, 0xEEEE},
+#endif /* REV1.2_Recommended_Settings */
+/* Recommended_Settings */
+
+/* Sequencer_Update */
+{0x2512, 0x8000},
+{0x2510, 0x0901},
+{0x2510, 0x3350},
+{0x2510, 0x2004},
+{0x2510, 0x1420},
+{0x2510, 0x1578},
+{0x2510, 0x087B},
+{0x2510, 0x24FF},
+{0x2510, 0x24FF},
+{0x2510, 0x24EA},
+{0x2510, 0x2410},
+{0x2510, 0x2224},
+{0x2510, 0x1015},
+{0x2510, 0x5813},
+{0x2510, 0x0214},
+{0x2510, 0x0024},
+{0x2510, 0xFF24},
+{0x2510, 0xFF24},
+{0x2510, 0xEA23},
+{0x2510, 0x2464},
+{0x2510, 0x7A24},
+{0x2510, 0x0405},
+{0x2510, 0x2C40},
+{0x2510, 0x2A54},
+{0x2510, 0x0AFF},
+{0x2510, 0x0A78},
+{0x2510, 0x4538},
+{0x2510, 0x5114},
+{0x2510, 0x4000},
+{0x2510, 0x0408},
+{0x2510, 0x0104},
+{0x2510, 0x0826},
+{0x2510, 0x5208},
+{0x2510, 0x1518},
+{0x2510, 0x13C8},
+{0x2510, 0x1002},
+{0x2510, 0x1016},
+{0x2510, 0x1181},
+{0x2510, 0x1189},
+{0x2510, 0x1056},
+{0x2510, 0x1210},
+{0x2510, 0x0902},
+{0x2510, 0x0D09},
+{0x2510, 0x0515},
+{0x2510, 0x8813},
+{0x2510, 0x8809},
+{0x2510, 0x3811},
+{0x2510, 0x9911},
+{0x2510, 0xD909},
+{0x2510, 0x1E12},
+{0x2510, 0x1410},
+{0x2510, 0xD609},
+{0x2510, 0x0112},
+{0x2510, 0x1012},
+{0x2510, 0x1212},
+{0x2510, 0x1011},
+{0x2510, 0xDD11},
+{0x2510, 0xD909},
+{0x2510, 0x0114},
+{0x2510, 0x4109},
+{0x2510, 0x0410},
+{0x2510, 0x5608},
+{0x2510, 0x11DB},
+{0x2510, 0x0903},
+{0x2510, 0x11FB},
+{0x2510, 0x11BB},
+{0x2510, 0x121A},
+{0x2510, 0x1210},
+{0x2510, 0x0812},
+{0x2510, 0x5010},
+{0x2510, 0x7610},
+{0x2510, 0xE614},
+{0x2510, 0x6109},
+{0x2510, 0x0612},
+{0x2510, 0x4012},
+{0x2510, 0x6009},
+{0x2510, 0x1C14},
+{0x2510, 0x6009},
+{0x2510, 0x0C0B},
+{0x2510, 0x0905},
+{0x2510, 0x15C8},
+{0x2510, 0x13C8},
+{0x2510, 0x0810},
+{0x2510, 0x6609},
+{0x2510, 0x0B15},
+{0x2510, 0x8813},
+{0x2510, 0x8809},
+{0x2510, 0x130C},
+{0x2510, 0x1440},
+{0x2510, 0x0903},
+{0x2510, 0x10E6},
+{0x2510, 0x11FB},
+{0x2510, 0x1262},
+{0x2510, 0x1260},
+{0x2510, 0x11FF},
+{0x2510, 0x11FB},
+{0x2510, 0x1441},
+{0x2510, 0x0902},
+{0x2510, 0x1066},
+{0x2510, 0x0912},
+{0x2510, 0x11BB},
+{0x2510, 0x1263},
+{0x2510, 0x1260},
+{0x2510, 0x1400},
+{0x2510, 0x1518},
+{0x2510, 0x11B8},
+{0x2510, 0x12A0},
+{0x2510, 0x1200},
+{0x2510, 0x1026},
+{0x2510, 0x1000},
+{0x2510, 0x1300},
+{0x2510, 0x1100},
+{0x2510, 0x3053},
+{0x2510, 0x4211},
+{0x2510, 0x0010},
+{0x2510, 0x0210},
+{0x2510, 0x1611},
+{0x2510, 0x0111},
+{0x2510, 0x0910},
+{0x2510, 0x5612},
+{0x2510, 0x100D},
+{0x2510, 0x0905},
+{0x2510, 0x1441},
+{0x2510, 0x0907},
+{0x2510, 0x1440},
+{0x2510, 0x0901},
+{0x2510, 0x15C8},
+{0x2510, 0x13C8},
+{0x2510, 0x091A},
+{0x2510, 0x1149},
+{0x2510, 0x0908},
+{0x2510, 0x1588},
+{0x2510, 0x1388},
+{0x2510, 0x091B},
+{0x2510, 0x1159},
+{0x2510, 0x090B},
+{0x2510, 0x1214},
+{0x2510, 0x0901},
+{0x2510, 0x1210},
+{0x2510, 0x10D6},
+{0x2510, 0x1212},
+{0x2510, 0x1210},
+{0x2510, 0x115D},
+{0x2510, 0x1159},
+{0x2510, 0x1056},
+{0x2510, 0x0903},
+{0x2510, 0x115B},
+{0x2510, 0x0814},
+{0x2510, 0x4109},
+{0x2510, 0x0114},
+{0x2510, 0x4009},
+{0x2510, 0x0C11},
+{0x2510, 0x7B11},
+{0x2510, 0x3B12},
+{0x2510, 0x1A12},
+{0x2510, 0x1009},
+{0x2510, 0x0112},
+{0x2510, 0x5010},
+{0x2510, 0xF610},
+{0x2510, 0xE614},
+{0x2510, 0x6009},
+{0x2510, 0x0115},
+{0x2510, 0xA813},
+{0x2510, 0xA812},
+{0x2510, 0x4012},
+{0x2510, 0x6009},
+{0x2510, 0x2415},
+{0x2510, 0x8809},
+{0x2510, 0x0110},
+{0x2510, 0x660B},
+{0x2510, 0x0813},
+{0x2510, 0x8809},
+{0x2510, 0x250C},
+{0x2510, 0x0902},
+{0x2510, 0x1440},
+{0x2510, 0x0907},
+{0x2510, 0x10E6},
+{0x2510, 0x1262},
+{0x2510, 0x1260},
+{0x2510, 0x117F},
+{0x2510, 0x117B},
+{0x2510, 0x1066},
+{0x2510, 0x0906},
+{0x2510, 0x1441},
+{0x2510, 0x0901},
+{0x2510, 0x1440},
+{0x2510, 0x090D},
+{0x2510, 0x113B},
+{0x2510, 0x1263},
+{0x2510, 0x1260},
+{0x2510, 0x1400},
+{0x2510, 0x1518},
+{0x2510, 0x1138},
+{0x2510, 0x12A0},
+{0x2510, 0x1200},
+{0x2510, 0x1026},
+{0x2510, 0x1000},
+{0x2510, 0x1300},
+{0x2510, 0x1100},
+{0x2510, 0x437A},
+{0x2510, 0x0605},
+{0x2510, 0x0741},
+{0x2510, 0x0E02},
+{0x2510, 0x3750},
+{0x2510, 0x2C44},
+{0x2510, 0x3714},
+{0x2510, 0x4000},
+{0x2510, 0x0408},
+{0x2510, 0x0104},
+{0x2510, 0x0811},
+{0x2510, 0x0010},
+{0x2510, 0x0210},
+{0x2510, 0x1611},
+{0x2510, 0x0111},
+{0x2510, 0x0910},
+{0x2510, 0x5612},
+{0x2510, 0x100D},
+{0x2510, 0x0906},
+{0x2510, 0x1441},
+{0x2510, 0x0907},
+{0x2510, 0x1440},
+{0x2510, 0x0901},
+{0x2510, 0x1588},
+{0x2510, 0x1388},
+{0x2510, 0x0921},
+{0x2510, 0x1149},
+{0x2510, 0x0908},
+{0x2510, 0x1588},
+{0x2510, 0x1388},
+{0x2510, 0x091B},
+{0x2510, 0x1159},
+{0x2510, 0x090B},
+{0x2510, 0x1214},
+{0x2510, 0x0901},
+{0x2510, 0x1210},
+{0x2510, 0x10D6},
+{0x2510, 0x1212},
+{0x2510, 0x1210},
+{0x2510, 0x115D},
+{0x2510, 0x1159},
+{0x2510, 0x1056},
+{0x2510, 0x0903},
+{0x2510, 0x115B},
+{0x2510, 0x0814},
+{0x2510, 0x4109},
+{0x2510, 0x0114},
+{0x2510, 0x4009},
+{0x2510, 0x0C11},
+{0x2510, 0x7B11},
+{0x2510, 0x3B12},
+{0x2510, 0x1A12},
+{0x2510, 0x1009},
+{0x2510, 0x0112},
+{0x2510, 0x5010},
+{0x2510, 0xF610},
+{0x2510, 0xE614},
+{0x2510, 0x6009},
+{0x2510, 0x0115},
+{0x2510, 0xA813},
+{0x2510, 0xA812},
+{0x2510, 0x4012},
+{0x2510, 0x6009},
+{0x2510, 0x2415},
+{0x2510, 0x8809},
+{0x2510, 0x0110},
+{0x2510, 0x660B},
+{0x2510, 0x0813},
+{0x2510, 0x8809},
+{0x2510, 0x250C},
+{0x2510, 0x0902},
+{0x2510, 0x1440},
+{0x2510, 0x0907},
+{0x2510, 0x10E6},
+{0x2510, 0x1262},
+{0x2510, 0x1260},
+{0x2510, 0x117F},
+{0x2510, 0x117B},
+{0x2510, 0x1066},
+{0x2510, 0x0906},
+{0x2510, 0x1441},
+{0x2510, 0x0901},
+{0x2510, 0x1440},
+{0x2510, 0x090D},
+{0x2510, 0x113B},
+{0x2510, 0x1263},
+{0x2510, 0x1260},
+{0x2510, 0x1440},
+{0x2510, 0x1598},
+{0x2510, 0x1139},
+{0x2510, 0x12A0},
+{0x2510, 0x1200},
+{0x2510, 0x1066},
+{0x2510, 0x1066},
+{0x2510, 0x1380},
+{0x2510, 0x1109},
+{0x2510, 0x0E02},
+{0x2510, 0x0920},
+{0x2510, 0x3708},
+{0x2510, 0x0015},
+{0x2510, 0x9813},
+{0x2510, 0x9810},
+{0x2510, 0x6610},
+{0x2510, 0x6611},
+{0x2510, 0x8911},
+{0x2510, 0x8910},
+{0x2510, 0x5612},
+{0x2510, 0x1009},
+{0x2510, 0x020D},
+{0x2510, 0x0905},
+{0x2510, 0x15A8},
+{0x2510, 0x13A8},
+{0x2510, 0x0934},
+{0x2510, 0x1588},
+{0x2510, 0x1388},
+{0x2510, 0x1199},
+{0x2510, 0x11D9},
+{0x2510, 0x091E},
+{0x2510, 0x1214},
+{0x2510, 0x10D6},
+{0x2510, 0x0901},
+{0x2510, 0x1210},
+{0x2510, 0x1212},
+{0x2510, 0x1210},
+{0x2510, 0x11DD},
+{0x2510, 0x11D9},
+{0x2510, 0x0901},
+{0x2510, 0x1441},
+{0x2510, 0x0904},
+{0x2510, 0x1056},
+{0x2510, 0x0811},
+{0x2510, 0xDB09},
+{0x2510, 0x0311},
+{0x2510, 0xFB11},
+{0x2510, 0xBB12},
+{0x2510, 0x1A12},
+{0x2510, 0x1008},
+{0x2510, 0x1250},
+{0x2510, 0x1076},
+{0x2510, 0x10E6},
+{0x2510, 0x1461},
+{0x2510, 0x0906},
+{0x2510, 0x1240},
+{0x2510, 0x1260},
+{0x2510, 0x091C},
+{0x2510, 0x1460},
+{0x2510, 0x090C},
+{0x2510, 0x0B09},
+{0x2510, 0x0515},
+{0x2510, 0xC813},
+{0x2510, 0xC808},
+{0x2510, 0x1066},
+{0x2510, 0x090B},
+{0x2510, 0x1588},
+{0x2510, 0x1388},
+{0x2510, 0x0913},
+{0x2510, 0x0C14},
+{0x2510, 0x4009},
+{0x2510, 0x0310},
+{0x2510, 0xE611},
+{0x2510, 0xFB12},
+{0x2510, 0x6212},
+{0x2510, 0x6011},
+{0x2510, 0xFF11},
+{0x2510, 0xFB14},
+{0x2510, 0x4109},
+{0x2510, 0x0210},
+{0x2510, 0x6609},
+{0x2510, 0x1211},
+{0x2510, 0xBB12},
+{0x2510, 0x6312},
+{0x2510, 0x6014},
+{0x2510, 0x0015},
+{0x2510, 0x1811},
+{0x2510, 0xB812},
+{0x2510, 0xA012},
+{0x2510, 0x0010},
+{0x2510, 0x2610},
+{0x2510, 0x0013},
+{0x2510, 0x0011},
+{0x2510, 0x007A},
+{0x2510, 0x0605},
+{0x2510, 0x0807},
+{0x2510, 0x0E02},
+{0x2510, 0x3709},
+{0x2510, 0x0655},
+{0x2510, 0x2CFE},
+{0x2510, 0x12FE},
+{0x2510, 0x062C},
+
+{0x1010, 0x0115},
+{0x3236, 0x00b3},
+{0x32e6, 0x009a},
+{0x322e, 0x258c},
+/* Sequencer_Update */
+
+{0x32D0, 0x3A02},
+{0x32D2, 0x3508},
+{0x32D4, 0x3702},
+{0x32D6, 0x3C04},
+{0x32DC, 0x370A},
+{ }
+}; /* Sensor_Setup */
+
+static const struct ar0147_reg ar0147_rev1_Serial_12_bit_Timing_Setup[] = {
+#if 0
+/* PCLK=24Mhz/3 *50 /1/8 = 50MHz */
+{0x302A, 8}, // VT_PIX_CLK_DIV
+{0x302C, 1}, // VT_SYS_CLK_DIV
+{0x302E, 3}, // PRE_PLL_CLK_DIV
+{0x3030, 50}, // PLL_MULTIPLIER
+{0x3036, 8}, // OP_WORD_CLK_DIV
+{0x3038, 1}, // OP_SYS_CLK_DIV
+#else
+/* PCLK=24Mhz/4 *75 /1/9 = 50MHz */
+{0x302A, 9}, // VT_PIX_CLK_DIV
+{0x302C, 1}, // VT_SYS_CLK_DIV
+{0x302E, 4}, // PRE_PLL_CLK_DIV
+{0x3030, 75}, // PLL_MULTIPLIER
+{0x3036, 12}, // OP_WORD_CLK_DIV
+{0x3038, 1}, // OP_SYS_CLK_DIV
+#endif
+{0x30B0, 0x980C}, // DIGITAL_TEST
+{0x31DC, 0x1FB0},
+{ }
+}; /* Serial_12_bit_Timing_Setup */
+
+static const struct ar0147_reg ar0147_rev1_Readout_Mode_Configuration[] = {
+{0x30A2, 0x0001}, // X_ODD_INC_
+{0x30A6, 0x0001}, // Y_ODD_INC_
+{0x3040, 0x0000}, // READ_MODE
+{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp
+{0x3044, 0x0400}, // DARK_CONTROL
+{0x3064, 0x0000}, // SMIA_TEST: disable emb data and stats
+{0x33E0, 0x0C80}, // TEST_ASIL_ROWS
+{0x3180, 0x0080}, // RESERVED_MFR_3180
+{0x33E4, 0x0080}, // RESERVED_MFR_33E4
+#ifdef AR0147_EMBEDDED_LINE
+{0x3064, 0x0180}, // SMIA_TEST: enable emb data and stats
+#endif /* HDR_Readout_Mode_Configuration */
+{ }
+}; /* Readout_Mode_Configuration */
+
+static const struct ar0147_reg ar0147_rev1_Full_Res_FOV[] = {
+{0x31B0, 0x0056}, // FRAME_PREAMBLE
+{0x31B2, 0x0045}, // LINE_PREAMBLE
+{0x3004, AR0147_X_START}, // X_ADDR_START_
+{0x3008, AR0147_X_END}, // X_ADDR_END_
+{0x3002, AR0147_Y_START}, // Y_ADDR_START_
+{0x3006, AR0147_Y_END}, // Y_ADDR_END_
+{0x3400, 0x10},
+{0x3402, (0x8000 & 0) | AR0147_MAX_WIDTH}, // X_OUTPUT_CONTROL
+{0x3404, (0x8000 & 0) | AR0147_MAX_HEIGHT}, // Y_OUTPUT_CONTROL
+{ }
+}; /* Full_Res_FOV */
+
+static const struct ar0147_reg ar0147_rev1_3exp_30FPS_Timing_and_Exposure[] = {
+{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp
+{0x30BA, 0x1002}, // DIGITAL_CTRL: 3exp max
+/* Row and Pixel Timing */
+{0x300C, AR0147_SENSOR_WIDTH + 52}, // LINE_LENGTH_PCK_ (1396)
+{0x300A, AR0147_SENSOR_HEIGHT + 226}, // FRAME_LENGTH_LINES_
+{0x3042, 0x0000}, // EXTRA_DELAY
+/* Exposure Settings */
+{0x3238, 0x0222}, // EXPOSURE_RATIO
+{0x3012, 0x0300}, // COARSE_INTEGRATION_TIME_
+
+{0x3014, 1550}, // FINE_INTEGRATION_TIME_
+{0x321E, 1550}, // FINE_INTEGRATION_TIME2
+{0x3222, 1550}, // FINE_INTEGRATION_TIME3
+
+{0x30B0, 0x980C}, // DIGITAL_TEST (MIPI ...)
+{0x32EA, 0x3C0E},
+{0x32EC, 0x72A1},
+{0x3C06, 0x083C},
+{0x3C08, 0x0100},
+{ }
+}; /* 3exp_30FPS_Timing_and_Exposure */
+
+static const struct ar0147_reg ar0147_rev1_Serial_HDR_12_bit_Output[] = {
+{0x31D0, 0x0001}, // COMPANDING
+{0x31AE, 0x0304}, // SERIAL_FORMAT: HISPI 4-lanes
+{0x31AC, 0x140C}, // DATA_FORMAT_BITS: ADC20, RAW12
+//{0x301A, 0x0118}, // RESET_REGISTER
+{0x301A, 0x0018}, // RESET_REGISTER
+{ }
+}; /* Serial_HDR_12_bit_Output */
+
+static const struct ar0147_reg ar0147_rev1_MIPI_12_bit_450MBps_Settings[] = {
+{0x31AE, 0x0204}, // SERIAL_FORMAT: MIPI 4-lanes
+{0x3342, 0x122C}, // exposure1 DT=0x2c emb=0x12
+{0x3346, 0x122C}, // exposure2 DT=0x2c emb=0x12
+{0x334A, 0x122C}, // exposure3 DT=0x2c emb=0x12
+{0x334E, 0x122C}, // exposure4 DT=0x2c emb=0x12
+{0x3344, 0x0011}, // exposure1 VC=0
+{0x3348, 0x0111}, // exposure1 VC=1
+{0x334C, 0x0211}, // exposure1 VC=2
+{0x3350, 0x0311}, // exposure1 VC=3
+{0x31B0, 0x41}, // frame_preamble
+{0x31B2, 0x2e}, // line_preamble
+
+{0x31B4, 0x2185},
+{0x31B6, 0x1105},
+{0x31B8, 0x2047},
+{0x31BA, 0x105},
+{0x31BC, 0x704},
+{ }
+}; /* MIPI_12_bit_450MBps_Settings */
+
+/* 3 Exp HDR, Full Resolution, MIPI 450MBps 4 lane 12-bit, 30FPS, XMCLK=24MHz */
+static const struct ar0147_reg *ar0147_regs_hdr_mipi450mbps_12bit_30fps_rev1[] = {
+	ar0147_rev1_Reset,
+	ar0147_rev1_Sensor_Setup,
+	ar0147_rev1_Serial_12_bit_Timing_Setup,
+	ar0147_rev1_Readout_Mode_Configuration,
+	ar0147_rev1_Full_Res_FOV,
+	ar0147_rev1_3exp_30FPS_Timing_and_Exposure,
+	ar0147_rev1_Serial_HDR_12_bit_Output,
+	ar0147_rev1_MIPI_12_bit_450MBps_Settings,
+	NULL
+};
diff --git a/drivers/media/i2c/soc_camera/ar0147_rev2.h b/drivers/media/i2c/soc_camera/ar0147_rev2.h
new file mode 100644
index 0000000..e5ccb8f
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ar0147_rev2.h
@@ -0,0 +1,796 @@
+/*
+ * ON Semiconductor AR0147 sensor camera wizard 1344x968@30/BGGR/BT601/RAW12
+ *
+ * Copyright (C) 2019 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 ar0147_reg ar0147_rev2_Reset[] = {
+{0x301A, 0x0001},	// reset
+{AR0147_DELAY, 100},
+{0x301A, 0x10D8},	// Stream off and setup parallel
+{0x3070, 0x0001},
+{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)
+#ifdef AR0147_DISPLAY_PATTERN_FIXED
+{0x3070, 0x0001},
+#endif
+{0x3072, 0x0fff},	// R
+{0x3074, 0x0fff},	// G(GR row)
+{0x3076, 0x0fff},	// B
+{0x3078, 0x0fff},	// G(GB row)
+#ifdef AR0147_DISPLAY_PATTERN_COLOR_BAR
+{0x3070, 0x0002},
+#endif
+{AR0147_DELAY, 250},
+{ }
+}; /* Reset */
+
+static const struct ar0147_reg ar0147_rev2_Sensor_Setup[] = {
+/* Recommended_Settings */
+{0x30B0, 0x980E}, // DIGITAL_TEST
+{0x3C08, 0x0000},
+{0x3C0C, 0x0518}, // DELAY_BUFFER_LLPCK_RD_WR_OVERLAP
+{0x3092, 0x1A24},
+{0x30B4, 0x01C7}, // TEMPSENS0_CTRL_REG
+{0x3372, 0x700F}, // DBLC_FS0_CONTROL
+{0x33EE, 0x0344},
+{0x350C, 0x035A},
+{0x350E, 0x0514},
+{0x3518, 0x14FE},
+{0x351A, 0x6000},
+{0x3520, 0x08CC},
+{0x3522, 0xCC08},
+{0x3524, 0x0C00},
+{0x3526, 0x0F00},
+{0x3528, 0xEEEE},
+{0x352A, 0x089F},
+{0x352C, 0x0012},
+{0x352E, 0x00EE},
+{0x3530, 0xEE00},
+{0x3536, 0xFF20},
+{0x3538, 0x3CFF},
+{0x353A, 0x9000},
+{0x353C, 0x7F00},
+{0x3540, 0xC62C},
+{0x3542, 0x4B4B},
+{0x3544, 0x3C46},
+{0x3546, 0x5A5A},
+{0x3548, 0x6400},
+{0x354A, 0x007F},
+{0x3556, 0x1010},
+{0x3566, 0x7328},
+{0x3F90, 0x0800}, // TEMPVSENS0_TMG_CTRL
+{0x3510, 0x011F},
+{0x353E, 0x801F},
+{0x3F9A, 0x0001}, // TEMPVSENS0_BOOST_SAMP_CTRL
+{0x3116, 0x0001}, // HDR_CONTROL3
+{0x3102, 0x60A0},
+{0x3104, 0x60A0},
+{0x3106, 0x60A0},
+{0x3362, 0x0000}, // DC_GAIN
+{0x3366, 0xCCCC}, // ANALOG_GAIN
+
+// Writes to bitfield R0x3552[5:4].
+// Be sure not to overwrite the other bitfields in this register.
+{0x3552, 0x0FB0},
+/* Recommended_Settings */
+
+/* Sequencer_Update */
+{0x2512, 0x8000},
+{0x2510, 0x0901},
+{0x2510, 0x3350},
+{0x2510, 0x2004},
+{0x2510, 0x1420},
+{0x2510, 0x1578},
+{0x2510, 0x087B},
+{0x2510, 0x24FF},
+{0x2510, 0x24FF},
+{0x2510, 0x24EA},
+{0x2510, 0x2410},
+{0x2510, 0x2224},
+{0x2510, 0x1015},
+{0x2510, 0xD813},
+{0x2510, 0x0214},
+{0x2510, 0x0024},
+{0x2510, 0xFF24},
+{0x2510, 0xFF24},
+{0x2510, 0xEA23},
+{0x2510, 0x2464},
+{0x2510, 0x7A24},
+{0x2510, 0x0405},
+{0x2510, 0x2C40},
+{0x2510, 0x0AFF},
+{0x2510, 0x0A78},
+{0x2510, 0x3851},
+{0x2510, 0x2A54},
+{0x2510, 0x1440},
+{0x2510, 0x0015},
+{0x2510, 0x0804},
+{0x2510, 0x0801},
+{0x2510, 0x0408},
+{0x2510, 0x2652},
+{0x2510, 0x0813},
+{0x2510, 0xC810},
+{0x2510, 0x0210},
+{0x2510, 0x1611},
+{0x2510, 0x8111},
+{0x2510, 0x8910},
+{0x2510, 0x5612},
+{0x2510, 0x1009},
+{0x2510, 0x020D},
+{0x2510, 0x0903},
+{0x2510, 0x1402},
+{0x2510, 0x15A8},
+{0x2510, 0x1388},
+{0x2510, 0x0938},
+{0x2510, 0x1199},
+{0x2510, 0x11D9},
+{0x2510, 0x091E},
+{0x2510, 0x1214},
+{0x2510, 0x10D6},
+{0x2510, 0x0901},
+{0x2510, 0x1210},
+{0x2510, 0x1212},
+{0x2510, 0x1210},
+{0x2510, 0x11DD},
+{0x2510, 0x11D9},
+{0x2510, 0x0901},
+{0x2510, 0x1441},
+{0x2510, 0x0904},
+{0x2510, 0x1056},
+{0x2510, 0x0811},
+{0x2510, 0xDB09},
+{0x2510, 0x0311},
+{0x2510, 0xFB11},
+{0x2510, 0xBB12},
+{0x2510, 0x1A12},
+{0x2510, 0x1008},
+{0x2510, 0x1250},
+{0x2510, 0x0B10},
+{0x2510, 0x7610},
+{0x2510, 0xE614},
+{0x2510, 0x6109},
+{0x2510, 0x0612},
+{0x2510, 0x4012},
+{0x2510, 0x6009},
+{0x2510, 0x1C14},
+{0x2510, 0x6009},
+{0x2510, 0x1215},
+{0x2510, 0xC813},
+{0x2510, 0xC808},
+{0x2510, 0x1066},
+{0x2510, 0x090B},
+{0x2510, 0x1588},
+{0x2510, 0x1388},
+{0x2510, 0x0913},
+{0x2510, 0x0C14},
+{0x2510, 0x4009},
+{0x2510, 0x0310},
+{0x2510, 0xE611},
+{0x2510, 0xFB12},
+{0x2510, 0x6212},
+{0x2510, 0x6011},
+{0x2510, 0xFF11},
+{0x2510, 0xFB14},
+{0x2510, 0x4109},
+{0x2510, 0x0210},
+{0x2510, 0x6609},
+{0x2510, 0x1211},
+{0x2510, 0xBB12},
+{0x2510, 0x6312},
+{0x2510, 0x6014},
+{0x2510, 0x0015},
+{0x2510, 0x1811},
+{0x2510, 0xB812},
+{0x2510, 0xA012},
+{0x2510, 0x0010},
+{0x2510, 0x2610},
+{0x2510, 0x0013},
+{0x2510, 0x0011},
+{0x2510, 0x0030},
+{0x2510, 0x5342},
+{0x2510, 0x1100},
+{0x2510, 0x1002},
+{0x2510, 0x1016},
+{0x2510, 0x1101},
+{0x2510, 0x1109},
+{0x2510, 0x1056},
+{0x2510, 0x1210},
+{0x2510, 0x0D09},
+{0x2510, 0x0314},
+{0x2510, 0x0214},
+{0x2510, 0x4309},
+{0x2510, 0x0514},
+{0x2510, 0x4009},
+{0x2510, 0x0115},
+{0x2510, 0xC813},
+{0x2510, 0xC809},
+{0x2510, 0x1A11},
+{0x2510, 0x4909},
+{0x2510, 0x0815},
+{0x2510, 0x8813},
+{0x2510, 0x8809},
+{0x2510, 0x1B11},
+{0x2510, 0x5909},
+{0x2510, 0x0B12},
+{0x2510, 0x1409},
+{0x2510, 0x0112},
+{0x2510, 0x1010},
+{0x2510, 0xD612},
+{0x2510, 0x1212},
+{0x2510, 0x1011},
+{0x2510, 0x5D11},
+{0x2510, 0x5910},
+{0x2510, 0x5609},
+{0x2510, 0x0311},
+{0x2510, 0x5B08},
+{0x2510, 0x1441},
+{0x2510, 0x0901},
+{0x2510, 0x1440},
+{0x2510, 0x090C},
+{0x2510, 0x117B},
+{0x2510, 0x113B},
+{0x2510, 0x121A},
+{0x2510, 0x1210},
+{0x2510, 0x0901},
+{0x2510, 0x1250},
+{0x2510, 0x10F6},
+{0x2510, 0x10E6},
+{0x2510, 0x1460},
+{0x2510, 0x0901},
+{0x2510, 0x15A8},
+{0x2510, 0x13A8},
+{0x2510, 0x1240},
+{0x2510, 0x1260},
+{0x2510, 0x0924},
+{0x2510, 0x1588},
+{0x2510, 0x0901},
+{0x2510, 0x1066},
+{0x2510, 0x0B08},
+{0x2510, 0x1388},
+{0x2510, 0x0925},
+{0x2510, 0x0C09},
+{0x2510, 0x0214},
+{0x2510, 0x4009},
+{0x2510, 0x0710},
+{0x2510, 0xE612},
+{0x2510, 0x6212},
+{0x2510, 0x6011},
+{0x2510, 0x7F11},
+{0x2510, 0x7B10},
+{0x2510, 0x6609},
+{0x2510, 0x0614},
+{0x2510, 0x4109},
+{0x2510, 0x0114},
+{0x2510, 0x4009},
+{0x2510, 0x0D11},
+{0x2510, 0x3B12},
+{0x2510, 0x6312},
+{0x2510, 0x6014},
+{0x2510, 0x0015},
+{0x2510, 0x1811},
+{0x2510, 0x3812},
+{0x2510, 0xA012},
+{0x2510, 0x0010},
+{0x2510, 0x2610},
+{0x2510, 0x0013},
+{0x2510, 0x0011},
+{0x2510, 0x0043},
+{0x2510, 0x7A06},
+{0x2510, 0x0507},
+{0x2510, 0x410E},
+{0x2510, 0x0237},
+{0x2510, 0x502C},
+{0x2510, 0x4414},
+{0x2510, 0x4000},
+{0x2510, 0x1508},
+{0x2510, 0x0408},
+{0x2510, 0x0104},
+{0x2510, 0x0826},
+{0x2510, 0x5508},
+{0x2510, 0x13C8},
+{0x2510, 0x1002},
+{0x2510, 0x1016},
+{0x2510, 0x1181},
+{0x2510, 0x1189},
+{0x2510, 0x1056},
+{0x2510, 0x1210},
+{0x2510, 0x0902},
+{0x2510, 0x0D09},
+{0x2510, 0x0314},
+{0x2510, 0x0215},
+{0x2510, 0xA813},
+{0x2510, 0xA814},
+{0x2510, 0x0309},
+{0x2510, 0x0614},
+{0x2510, 0x0209},
+{0x2510, 0x1F15},
+{0x2510, 0x8813},
+{0x2510, 0x8809},
+{0x2510, 0x0B11},
+{0x2510, 0x9911},
+{0x2510, 0xD909},
+{0x2510, 0x1E12},
+{0x2510, 0x1409},
+{0x2510, 0x0312},
+{0x2510, 0x1012},
+{0x2510, 0x1212},
+{0x2510, 0x1011},
+{0x2510, 0xDD11},
+{0x2510, 0xD909},
+{0x2510, 0x0114},
+{0x2510, 0x4009},
+{0x2510, 0x0711},
+{0x2510, 0xDB09},
+{0x2510, 0x0311},
+{0x2510, 0xFB11},
+{0x2510, 0xBB12},
+{0x2510, 0x1A12},
+{0x2510, 0x1009},
+{0x2510, 0x0112},
+{0x2510, 0x500B},
+{0x2510, 0x1076},
+{0x2510, 0x1066},
+{0x2510, 0x1460},
+{0x2510, 0x0901},
+{0x2510, 0x15C8},
+{0x2510, 0x0901},
+{0x2510, 0x1240},
+{0x2510, 0x1260},
+{0x2510, 0x0901},
+{0x2510, 0x13C8},
+{0x2510, 0x0956},
+{0x2510, 0x1588},
+{0x2510, 0x0901},
+{0x2510, 0x0C14},
+{0x2510, 0x4009},
+{0x2510, 0x0511},
+{0x2510, 0xFB12},
+{0x2510, 0x6212},
+{0x2510, 0x6011},
+{0x2510, 0xFF11},
+{0x2510, 0xFB09},
+{0x2510, 0x1911},
+{0x2510, 0xBB12},
+{0x2510, 0x6312},
+{0x2510, 0x6014},
+{0x2510, 0x0015},
+{0x2510, 0x1811},
+{0x2510, 0xB812},
+{0x2510, 0xA012},
+{0x2510, 0x0010},
+{0x2510, 0x2610},
+{0x2510, 0x0013},
+{0x2510, 0x0011},
+{0x2510, 0x0030},
+{0x2510, 0x5345},
+{0x2510, 0x1444},
+{0x2510, 0x1002},
+{0x2510, 0x1016},
+{0x2510, 0x1101},
+{0x2510, 0x1109},
+{0x2510, 0x1056},
+{0x2510, 0x1210},
+{0x2510, 0x0D09},
+{0x2510, 0x0314},
+{0x2510, 0x0614},
+{0x2510, 0x4709},
+{0x2510, 0x0514},
+{0x2510, 0x4409},
+{0x2510, 0x0115},
+{0x2510, 0x9813},
+{0x2510, 0x9809},
+{0x2510, 0x1A11},
+{0x2510, 0x4909},
+{0x2510, 0x0815},
+{0x2510, 0x8813},
+{0x2510, 0x8809},
+{0x2510, 0x1B11},
+{0x2510, 0x5909},
+{0x2510, 0x0B12},
+{0x2510, 0x1409},
+{0x2510, 0x0112},
+{0x2510, 0x1009},
+{0x2510, 0x0112},
+{0x2510, 0x1212},
+{0x2510, 0x1011},
+{0x2510, 0x5D11},
+{0x2510, 0x5909},
+{0x2510, 0x0511},
+{0x2510, 0x5B09},
+{0x2510, 0x1311},
+{0x2510, 0x7B11},
+{0x2510, 0x3B12},
+{0x2510, 0x1A12},
+{0x2510, 0x1009},
+{0x2510, 0x0112},
+{0x2510, 0x5010},
+{0x2510, 0x7610},
+{0x2510, 0x6614},
+{0x2510, 0x6409},
+{0x2510, 0x0115},
+{0x2510, 0xA813},
+{0x2510, 0xA812},
+{0x2510, 0x4012},
+{0x2510, 0x6009},
+{0x2510, 0x2015},
+{0x2510, 0x8809},
+{0x2510, 0x020B},
+{0x2510, 0x0901},
+{0x2510, 0x1388},
+{0x2510, 0x0925},
+{0x2510, 0x0C09},
+{0x2510, 0x0214},
+{0x2510, 0x4409},
+{0x2510, 0x0912},
+{0x2510, 0x6212},
+{0x2510, 0x6011},
+{0x2510, 0x7F11},
+{0x2510, 0x7B09},
+{0x2510, 0x1C11},
+{0x2510, 0x3B12},
+{0x2510, 0x6312},
+{0x2510, 0x6014},
+{0x2510, 0x0015},
+{0x2510, 0x1811},
+{0x2510, 0x3812},
+{0x2510, 0xA012},
+{0x2510, 0x0010},
+{0x2510, 0x2610},
+{0x2510, 0x0013},
+{0x2510, 0x0011},
+{0x2510, 0x0008},
+{0x2510, 0x7A06},
+{0x2510, 0x0508},
+{0x2510, 0x070E},
+{0x2510, 0x0237},
+{0x2510, 0x502C},
+{0x2510, 0xFE32},
+{0x2510, 0xFE06},
+{0x2510, 0x2C2C},
+
+{AR0147_DELAY, 200},
+
+{0x32e6, 0x009a}, //min_subrow
+{0x322e, 0x258c}, //clks_per_sample 396
+/* Sequencer_Update */
+
+{0x32D0, 0x3A02},
+{0x32D2, 0x3508},
+{0x32D4, 0x3702},
+{0x32D6, 0x3C04},
+{0x32DC, 0x370A},
+{0x32EA, 0x3CA8},
+{0x351E, 0x0000},
+{0x3510, 0x811F},
+
+//settings to rev1 default for non-Super Exposure mode settings
+//Super Exposure mode settings have additional settings
+{0x1010, 0x0155}, // FINE_INTEGRATION_TIME4_MIN
+{0x3236, 0x00B2}, // FINE_CORRECTION4
+{0x32EA, 0x3C0E},
+{0x32EC, 0x7151},
+{0x3116, 0x0001}, // HDR_CONTROL3
+{0x33E2, 0x0000}, // SAMPLE_CTRL
+{0x3088, 0x0400}, // LFM_CTRL
+{0x322A, 0x0039}, // FINE_INTEGRATION_CTRL
+{0x3238, 0x0333}, // EXPOSURE_RATIO
+{ }
+}; /* Sensor_Setup */
+
+static const struct ar0147_reg ar0147_rev2_Super_Exposure_Default_Plus_T2_Setup[] = {
+{0x3082, 0x0008}, // OPERATION_MODE_CTRL
+{0x30BA, 0x1003}, // DIGITAL_CTRL
+{0x3C06, 0x2024}, // CONFIGURE_BUFFERS1
+{0x3C08, 0x2100}, // CONFIGURE_BUFFERS2
+{0x3088, 0x0400},
+{0x32EA, 0x3CA9},
+{0x3510, 0x814F},
+{0x351E, 0x0100},
+{0x32EA, 0x3CA9},
+{0x32EC, 0x7281},
+{0x3212, 0x0000}, // COARSE_INTEGRATION_TIME2
+{0x3216, 0x0004}, // COARSE_INTEGRATION_TIME3
+{0x3238, 0x8222}, // EXPOSURE_RATIO
+{0x33E2, 0x0A10}, // SAMPLE_CTRL
+{0x3362, 0x0001}, // DC_GAIN
+{0x322A, 0x0539}, // FINE_INTEGRATION_CTRL
+{0x3014, 0x0123}, // FINE_INTEGRATION_TIME_
+{0x3222, 0x0490}, // FINE_INTEGRATION_TIME3
+{0x1008, 0x0123}, // FINE_INTEGRATION_TIME_MIN
+{0x100E, 0x043B}, // FINE_INTEGRATION_TIME3_MIN
+{0x3230, 0x00C7}, // FINE_CORRECTION
+{0x3234, 0x03DF}, // FINE_CORRECTION3
+{0x32D0, 0x3A02},
+{0x32D2, 0x3508},
+{0x32D4, 0x3702},
+{0x32D6, 0x3C04},
+{0x32DC, 0x370A},
+{0x3528, 0x99EE},
+{0x30FE, 0x0040}, // NOISE_PEDESTAL
+{0x3096, 0x0000}, // ROW_NOISE_ADJUST_1X_LCG_T2
+
+/* Digital_Lateral_Overflow_for_SE */
+{0x3116, 0x0001},
+{0x3100, 0xC001}, // FIELD_WR= DLO_CONTROL0, 0xE001
+{0x3102, 0x6100},
+{0x3104, 0x6100},
+{0x3106, 0x6100},
+{0x3108, 0x0CB1},
+{0x312A, 0x83E8},
+{0x3C82, 0x0FFF},
+/* Digital_Lateral_Overflow_for_SE */
+
+/* Other_Super_Exposure_Setup */
+{0x3536, 0xFF20},
+{0x3520, 0x0800},
+{0x3522, 0x0008},
+{0x3536, 0xFF20},
+{0x350C, 0x034A},
+{0x350E, 0x051C},
+{0x3540, 0xC62C},
+{0x3542, 0x4B4B},
+{0x3544, 0x4B46},
+{0x3546, 0x5A5A},
+{0x3548, 0x6400},
+{0x354A, 0x007F},
+{0x3524, 0x0600},
+{0x3372, 0xF40F}, // DBLC_FS0_CONTROL
+{0x3180, 0x0188},
+{0x3280, 0x0CB2}, // T1_BARRIER_C0
+{0x3282, 0x0CB2}, // T1_BARRIER_C1
+{0x3284, 0x0CB2}, // T1_BARRIER_C2
+{0x3286, 0x0CB2}, // T1_BARRIER_C3
+{0x3288, 0x0CB2}, // T2_BARRIER_C0
+{0x328A, 0x0CB2}, // T2_BARRIER_C1
+{0x328C, 0x0CB2}, // T2_BARRIER_C2
+{0x328E, 0x0CB2}, // T2_BARRIER_C3
+{0x3290, 0x0CB2}, // T3_BARRIER_C0
+{0x3292, 0x0CB2}, // T3_BARRIER_C1
+{0x3294, 0x0CB2}, // T3_BARRIER_C2
+{0x3296, 0x0CB2}, // T3_BARRIER_C3
+{0x3298, 0x0CB2}, // T4_BARRIER_C0
+{0x329A, 0x0CB2}, // T4_BARRIER_C1
+{0x329C, 0x0CB2}, // T4_BARRIER_C2
+{0x329E, 0x0CB2}, // T4_BARRIER_C3
+{0x3108, 0x0CB1},
+{0x312A, 0x83E8},
+{0x3C82, 0x0FFF},
+{0x3102, 0x6100},
+{0x3104, 0x6100},
+{0x3106, 0x6100},
+{0x3120, 0x0AF0},
+{0x3122, 0x0CB2},
+/* Other_Super_Exposure_Setup */
+{ }
+}; /* Super_Exposure_Default_Plus_T2_Setup */
+
+static const struct ar0147_reg ar0147_rev2_Serial_12_bit_Timing_Setup[] = {
+#if 0
+/* PCLK=24Mhz/3 *50 /1/8 = 50MHz */
+{0x302A, 8}, // VT_PIX_CLK_DIV
+{0x302C, 1}, // VT_SYS_CLK_DIV
+{0x302E, 3}, // PRE_PLL_CLK_DIV
+{0x3030, 50}, // PLL_MULTIPLIER
+{0x3036, 8}, // OP_WORD_CLK_DIV
+{0x3038, 1}, // OP_SYS_CLK_DIV
+#else
+/* PCLK=24Mhz/4 *75 /1/9 = 50MHz */
+{0x302A, 9}, // VT_PIX_CLK_DIV
+{0x302C, 1}, // VT_SYS_CLK_DIV
+{0x302E, 4}, // PRE_PLL_CLK_DIV
+{0x3030, 75}, // PLL_MULTIPLIER
+{0x3036, 12}, // OP_WORD_CLK_DIV
+{0x3038, 1}, // OP_SYS_CLK_DIV
+#endif
+{0x30B0, 0x980C}, // DIGITAL_TEST
+{0x31DC, 0x1FB0},
+{ }
+}; /* Serial_12_bit_Timing_Setup */
+
+static const struct ar0147_reg ar0147_rev2_Readout_Mode_Configuration[] = {
+{0x30A2, 0x0001}, // X_ODD_INC_
+{0x30A6, 0x0001}, // Y_ODD_INC_
+{0x3040, 0x0000}, // READ_MODE
+{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp
+{0x3044, 0x0400}, // DARK_CONTROL
+{0x3064, 0x0000}, // SMIA_TEST: disable emb data and stats
+{0x33E0, 0x0C80}, // TEST_ASIL_ROWS
+{0x3180, 0x0080}, // RESERVED_MFR_3180
+{0x33E4, 0x0080}, // RESERVED_MFR_33E4
+#ifdef AR0147_EMBEDDED_LINE
+{0x3064, 0x0180}, // SMIA_TEST: enable emb data and stats
+#endif
+{ }
+}; /* Readout_Mode_Configuration */
+
+static const struct ar0147_reg ar0147_rev2_Full_Res_FOV[] = {
+{0x31B0, 0x0056}, // FRAME_PREAMBLE
+{0x31B2, 0x0045}, // LINE_PREAMBLE
+{0x3004, AR0147_X_START}, // X_ADDR_START_
+{0x3008, AR0147_X_END}, // X_ADDR_END_
+{0x3002, AR0147_Y_START}, // Y_ADDR_START_
+{0x3006, AR0147_Y_END}, // Y_ADDR_END_
+{0x3400, 0x10},
+{0x3402, (0x8000 & 0) | AR0147_MAX_WIDTH}, // X_OUTPUT_CONTROL
+{0x3404, (0x8000 & 0) | AR0147_MAX_HEIGHT}, // Y_OUTPUT_CONTROL
+{ }
+}; /* Full_Res_FOV */
+
+static const struct ar0147_reg ar0147_rev2_3exp_30FPS_Timing_and_Exposure[] = {
+{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp
+{0x30BA, 0x1002}, // DIGITAL_CTRL: 3exp max
+
+/* Row and Pixel Timing */
+{0x300C, AR0147_SENSOR_WIDTH + 52}, // LINE_LENGTH_PCK_ (1396)
+{0x300A, AR0147_SENSOR_HEIGHT + 226}, // FRAME_LENGTH_LINES_
+{0x3042, 0x0000}, // EXTRA_DELAY
+
+/* Exposure Settings */
+{0x3238, 0x0222}, // EXPOSURE_RATIO
+{0x3012, 0x0300}, // COARSE_INTEGRATION_TIME_
+
+{0x3014, 1550}, // FINE_INTEGRATION_TIME_
+{0x321E, 1550}, // FINE_INTEGRATION_TIME2
+{0x3222, 1550}, // FINE_INTEGRATION_TIME3
+{0x30B0, 0x980C}, // DIGITAL_TEST (MIPI ...)
+{0x32EA, 0x3C0E},
+{0x32EC, 0x72A1},
+{0x3362, 0x0000}, // DC_GAIN
+{0x3366, 0xCCCC}, // ANALOG_GAIN
+{0x3364, 0x01CF}, // DCG_TRIM
+{0x3C06, 0x083C},
+{0x3C08, 0x0100},
+{ }
+}; /* 3exp_30FPS_Timing_and_Exposure */
+
+static const struct ar0147_reg ar0147_rev2_SE_Plus_T2_Default_Mode_30FPS_Timing_and_Exposure[] = {
+{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp
+{0x30BA, 0x1003}, // DIGITAL_CTRL: 4exp max
+
+/* Row and Pixel Timing */
+{0x300C, AR0147_SENSOR_WIDTH + 52}, // LINE_LENGTH_PCK_ (1396)
+{0x300A, AR0147_SENSOR_HEIGHT + 226}, // FRAME_LENGTH_LINES_
+{0x3042, 0x0000}, // EXTRA_DELAY
+
+/* Exposure Settings */
+{0x3238, 0x8222}, // EXPOSURE_RATIO: separate integartion time!?
+{0x3012, 0x0300}, // COARSE_INTEGRATION_TIME_
+
+{0x322A, 0x0539}, // FINE_INTEGRATION_CTRL
+{0x3014, 0x0123}, // FINE_INTEGRATION_TIME_
+{0x3222, 0x0490}, // FINE_INTEGRATION_TIME3
+{0x3362, 0x0001}, // DC_GAIN
+{0x3366, 0xFDF7}, // ANALOG_GAIN
+{0x3364, 0x01CF}, // DCG_TRIM
+
+{0x30B0, 0x980C}, // DIGITAL_TEST (MIPI ...)
+{0x32EC, 0x7281},
+{ }
+}; /* SE_Plus_T2_Default_Mode_30FPS_Timing_and_Exposure */
+
+static const struct ar0147_reg ar0147_rev2_Serial_4_Lane_20_to_12_bit_Output[] = {
+{0x31D0, 0x0001}, // COMPANDING
+{0x31AE, 0x0304}, // SERIAL_FORMAT: HISPI 4-lanes
+{0x31AC, 0x140C}, // DATA_FORMAT_BITS: ADC20, RAW12
+//{0x301A, 0x0118}, // RESET_REGISTER
+{0x301A, 0x0018}, // RESET_REGISTER
+{ }
+}; /* Serial_4_Lane_20_to_12_bit_Output */
+
+static const struct ar0147_reg ar0147_rev2_MIPI_12_bit_450MBps_Settings[] = {
+{0x31AE, 0x0204}, // SERIAL_FORMAT: MIPI 4-lanes
+{0x3342, 0x122C}, // exposure1 DT=0x2c emb=0x12
+{0x3346, 0x122C}, // exposure2 DT=0x2c emb=0x12
+{0x334A, 0x122C}, // exposure3 DT=0x2c emb=0x12
+{0x334E, 0x122C}, // exposure4 DT=0x2c emb=0x12
+{0x3344, 0x0011}, // exposure1 VC=0
+{0x3348, 0x0111}, // exposure1 VC=1
+{0x334C, 0x0211}, // exposure1 VC=2
+{0x3350, 0x0311}, // exposure1 VC=3
+{0x31B0, 0x41}, // frame_preamble
+{0x31B2, 0x2e}, // line_preamble
+
+{0x31B4, 0x2185},
+{0x31B6, 0x1105},
+{0x31B8, 0x2047},
+{0x31BA, 0x105},
+{0x31BC, 0x704},
+{ }
+}; /* MIPI_12_bit_450MBps_Settings */
+
+static const struct ar0147_reg ar0147_rev2_shutter_and_booster_settings[] = {
+{0x32EA, 0x3CA8},
+{0x32F6, 0x3A01},
+{0x32D2, 0x200A},
+{0x32D0, 0x3005},
+{0x32D4, 0x3505},
+{0x32F8, 0x3C03},
+{0x32DC, 0x220C},
+{0x32D6, 0x3207},
+{0x32E2, 0x3707},
+{0x3260, 0x00FF},
+{0x3262, 0x00FF},
+{0x3528, 0xEEEE},
+{0x353E, 0x801F},
+{0x3532, 0x8F4C},
+{0x3250, 0x0005},
+{0x3252, 0x0107},
+{0x3256, 0x03E8},
+{0x3258, 0x0300},
+{0x325A, 0x0A13},
+{0x325E, 0x0186},
+{0x3524, 0x0C00},
+{0x3536, 0xFF38},
+{0x3532, 0x8F48},
+{0x3526, 0x8F00},
+{0x3536, 0xDF18},
+{0x3520, 0x0C00},
+{0x352E, 0x00FF},
+{0x3530, 0xFF00},
+{0x3532, 0x8F68},
+{0x3536, 0xDF18},
+{0x3252, 0x0107},
+{0x325E, 0x0186},
+{0x3096, 0x0000},
+{0x3504, 0x9100},
+{0x354E, 0x1480},
+{0x355A, 0x0B0E},
+{0x3372, 0xF50F},
+{0x337A, 0x100E},
+{0x3554, 0x1599},
+{0x32EA, 0x3CA9},
+{0x3510, 0x9753},
+{0x3520, 0x0800},
+{0x3522, 0x0008},
+{0x3524, 0x0C00},
+{0x3526, 0x0F00},
+{0x3528, 0xDDDD},
+{0x352A, 0x089F},
+{0x352C, 0x0012},
+{0x352E, 0x00FF},
+{0x3530, 0xFF00},
+{0x3532, 0x8F48},
+{0x3536, 0xFF38},
+{0x3538, 0x24FF},
+{0x353A, 0x9000},
+{0x353C, 0x7F00},
+{0x312A, 0x83E8},
+{0x3C82, 0x0FFF},
+{ }
+}; /* shutter_and_booster_settings */
+
+/* 3 Exp HDR, Full Resolution, MIPI 450MBPS 4 lane 12-bit, 30FPS, XMCLK=24MHz */
+static const struct ar0147_reg *ar0147_regs_hdr_mipi450mbps_12bit_30fps_rev2[] = {
+	ar0147_rev2_Reset,
+	ar0147_rev2_Sensor_Setup,
+	ar0147_rev2_Serial_12_bit_Timing_Setup,
+	ar0147_rev2_Readout_Mode_Configuration,
+	ar0147_rev2_Full_Res_FOV,
+	ar0147_rev2_3exp_30FPS_Timing_and_Exposure,
+	ar0147_rev2_Serial_4_Lane_20_to_12_bit_Output,
+	ar0147_rev2_MIPI_12_bit_450MBps_Settings,
+	NULL
+};
+
+/* Super-Exposure Plus T2, Full Resolution, MIPI 450MBPS 4 lane 12-bit, 30FPS, XMCLK=24MHz */
+static const struct ar0147_reg *ar0147_regs_seplus_mipi450mbps_12bit_30fps_rev2[] = {
+	ar0147_rev2_Reset,
+	ar0147_rev2_Sensor_Setup,
+	ar0147_rev2_Super_Exposure_Default_Plus_T2_Setup,
+	ar0147_rev2_Serial_12_bit_Timing_Setup,
+	ar0147_rev2_Readout_Mode_Configuration,
+	ar0147_rev2_Full_Res_FOV,
+	ar0147_rev2_SE_Plus_T2_Default_Mode_30FPS_Timing_and_Exposure,
+	ar0147_rev2_Serial_4_Lane_20_to_12_bit_Output,
+	ar0147_rev2_MIPI_12_bit_450MBps_Settings,
+	ar0147_rev2_shutter_and_booster_settings,
+	NULL
+};
-- 
2.7.4

