From 6509268d16bf6136907337a5101705449d4b844f Mon Sep 17 00:00:00 2001
From: Andrey Dolnikov <andrey.dolnikov@cogentembedded.com>
Date: Wed, 7 Nov 2018 22:42:50 +0300
Subject: [PATCH 080/122] media: i2c: soc_camera: Bunch update from 2.23.1

---
 drivers/media/i2c/soc_camera/ap0101_ar014x.c |   78 +-
 drivers/media/i2c/soc_camera/ar0132.c        |    3 +-
 drivers/media/i2c/soc_camera/ar0132.h        |    9 +-
 drivers/media/i2c/soc_camera/ar0140.c        |  648 +++++
 drivers/media/i2c/soc_camera/ar0140.h        |  475 ++++
 drivers/media/i2c/soc_camera/ar0143.c        |  678 +++++
 drivers/media/i2c/soc_camera/ar0143.h        |  549 ++++
 drivers/media/i2c/soc_camera/ar0220.c        |   20 +-
 drivers/media/i2c/soc_camera/ar0220.h        |   18 +-
 drivers/media/i2c/soc_camera/ar0231.c        |  580 ++++
 drivers/media/i2c/soc_camera/ar0231.h        |   34 +
 drivers/media/i2c/soc_camera/ar0231_rev4.h   |  348 +++
 drivers/media/i2c/soc_camera/ar0233.c        |  579 ++++
 drivers/media/i2c/soc_camera/ar0233.h        |  409 +++
 drivers/media/i2c/soc_camera/gw4200_ar014x.c |  592 ++++
 drivers/media/i2c/soc_camera/gw4200_ar014x.h |   28 +
 drivers/media/i2c/soc_camera/imx390.c        |  574 ++++
 drivers/media/i2c/soc_camera/imx390.h        | 3818 ++++++++++++++++++++++++++
 drivers/media/i2c/soc_camera/max9286.c       |  406 ++-
 drivers/media/i2c/soc_camera/max9286.h       |    1 +
 drivers/media/i2c/soc_camera/ov10635.c       |   38 +-
 drivers/media/i2c/soc_camera/ov10635.h       |   10 +-
 drivers/media/i2c/soc_camera/ov106xx.c       |   79 +-
 drivers/media/i2c/soc_camera/ov2775.c        |   14 +-
 drivers/media/i2c/soc_camera/ov2775.h        |   32 +-
 drivers/media/i2c/soc_camera/ov490_ov10640.c |    1 -
 drivers/media/i2c/soc_camera/ov495_ov2775.c  |   16 +-
 drivers/media/i2c/soc_camera/ox03a.c         |  589 ++++
 drivers/media/i2c/soc_camera/ox03a.h         | 1766 ++++++++++++
 drivers/media/i2c/soc_camera/ti9x4.c         |   94 +-
 30 files changed, 12305 insertions(+), 181 deletions(-)
 create mode 100644 drivers/media/i2c/soc_camera/ar0140.c
 create mode 100644 drivers/media/i2c/soc_camera/ar0140.h
 create mode 100644 drivers/media/i2c/soc_camera/ar0143.c
 create mode 100644 drivers/media/i2c/soc_camera/ar0143.h
 create mode 100644 drivers/media/i2c/soc_camera/ar0231.c
 create mode 100644 drivers/media/i2c/soc_camera/ar0231.h
 create mode 100644 drivers/media/i2c/soc_camera/ar0231_rev4.h
 create mode 100644 drivers/media/i2c/soc_camera/ar0233.c
 create mode 100644 drivers/media/i2c/soc_camera/ar0233.h
 create mode 100644 drivers/media/i2c/soc_camera/gw4200_ar014x.c
 create mode 100644 drivers/media/i2c/soc_camera/gw4200_ar014x.h
 create mode 100644 drivers/media/i2c/soc_camera/imx390.c
 create mode 100644 drivers/media/i2c/soc_camera/imx390.h
 create mode 100644 drivers/media/i2c/soc_camera/ox03a.c
 create mode 100644 drivers/media/i2c/soc_camera/ox03a.h

diff --git a/drivers/media/i2c/soc_camera/ap0101_ar014x.c b/drivers/media/i2c/soc_camera/ap0101_ar014x.c
index d8025a4..142942d 100644
--- a/drivers/media/i2c/soc_camera/ap0101_ar014x.c
+++ b/drivers/media/i2c/soc_camera/ap0101_ar014x.c
@@ -19,11 +19,10 @@
 #include <media/soc_camera.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
-#include <media/v4l2-fwnode.h>
 
 #include "ap0101_ar014x.h"
 
-#define AP0101_I2C_ADDR		0x5d
+static const int ap0101_i2c_addr[] = {0x5d, 0x48};
 
 #define AP0101_PID		0x0000
 #define AP0101_VERSION_REG	0x0160
@@ -37,6 +36,8 @@ struct ap0101_priv {
 	struct v4l2_ctrl_handler	hdl;
 	struct media_pad		pad;
 	struct v4l2_rect		rect;
+	int				max_width;
+	int				max_height;
 	int				init_complete;
 	u8				id[6];
 	int				exposure;
@@ -48,6 +49,9 @@ struct ap0101_priv {
 	int				port;
 	int				gpio_resetb;
 	int				gpio_fsin;
+	int				hts;
+	int				vts;
+	int				frame_preamble;
 };
 
 static inline struct ap0101_priv *to_ap0101(const struct i2c_client *client)
@@ -207,8 +211,8 @@ static int ap0101_set_selection(struct v4l2_subdev *sd,
 	rect->width = ALIGN(rect->width, 2);
 	rect->height = ALIGN(rect->height, 2);
 
-	if ((rect->left + rect->width > AP0101_MAX_WIDTH) ||
-	    (rect->top + rect->height > AP0101_MAX_HEIGHT))
+	if ((rect->left + rect->width > priv->max_width) ||
+	    (rect->top + rect->height > priv->max_height))
 		*rect = priv->rect;
 
 	priv->rect.left = rect->left;
@@ -233,14 +237,14 @@ static int ap0101_get_selection(struct v4l2_subdev *sd,
 	case V4L2_SEL_TGT_CROP_BOUNDS:
 		sel->r.left = 0;
 		sel->r.top = 0;
-		sel->r.width = AP0101_MAX_WIDTH;
-		sel->r.height = AP0101_MAX_HEIGHT;
+		sel->r.width = priv->max_width;
+		sel->r.height = priv->max_height;
 		return 0;
 	case V4L2_SEL_TGT_CROP_DEFAULT:
 		sel->r.left = 0;
 		sel->r.top = 0;
-		sel->r.width = AP0101_MAX_WIDTH;
-		sel->r.height = AP0101_MAX_HEIGHT;
+		sel->r.width = priv->max_width;
+		sel->r.height = priv->max_height;
 		return 0;
 	case V4L2_SEL_TGT_CROP:
 		sel->r = priv->rect;
@@ -381,11 +385,29 @@ static DEVICE_ATTR(otp_id_ap0101, S_IRUGO, ap0101_otp_id_show, NULL);
 static int ap0101_initialize(struct i2c_client *client)
 {
 	struct ap0101_priv *priv = to_ap0101(client);
-	u16 pid = 0;
+	u16 pid = 0, val = 0;
 	int ret = 0;
+	int tmp_addr;
+	int i;
 
 	ap0101_s_port(client, 1);
 
+	for (i = 0; i < ARRAY_SIZE(ap0101_i2c_addr); i++) {
+		tmp_addr = client->addr;
+		if (priv->max9286_addr) {
+			client->addr = priv->max9271_addr;			/* Serializer I2C address */
+			reg8_write(client, 0x0A, ap0101_i2c_addr[i] << 1);	/* Sensor native I2C address */
+			usleep_range(2000, 2500);				/* wait 2ms */
+		};
+		client->addr = tmp_addr;
+
+		/* check model ID */
+		reg16_read16(client, AP0101_PID, &pid);
+
+		if (pid == AP0101_VERSION_REG)
+			break;
+	}
+
 	/* check and show model ID */
 	reg16_read16(client, AP0101_PID, &pid);
 
@@ -394,14 +416,42 @@ static int ap0101_initialize(struct i2c_client *client)
 		ret = -ENODEV;
 		goto err;
 	}
-
+#if 1
+	/* read resolution used by current firmware */
+	reg16_read16(client, 0xca90, &val);
+	priv->max_width = val;
+	reg16_read16(client, 0xca92, &val);
+	priv->max_height = val;
+#else
+	priv->max_width = AP0101_MAX_WIDTH;
+	priv->max_height = AP0101_MAX_HEIGHT;
+#endif
 	/* Program wizard registers */
 	ap0101_set_regs(client, ap0101_regs_wizard, ARRAY_SIZE(ap0101_regs_wizard));
 	/* Read OTP IDs */
 	ap0101_otp_id_read(client);
 
+	tmp_addr = client->addr;
+	if (priv->max9271_addr) {
+		/* setup serializer HS generator */
+		client->addr = priv->max9271_addr;			/* Serializer I2C address */
+		priv->frame_preamble = 5;
+		priv->hts = 1280 * 2 + 548;
+		priv->vts = 960;
+		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, (priv->max_width * 2) >> 8);	/* HS high period */
+		reg8_write(client, 0x55, (priv->max_width * 2) & 0xff);
+		reg8_write(client, 0x56, (priv->hts - priv->max_width * 2) >> 8); /* HS low period */
+		reg8_write(client, 0x57, (priv->hts - priv->max_width * 2) & 0xff);
+		reg8_write(client, 0x58, priv->vts >> 8);		/* HS count */
+		reg8_write(client, 0x59, priv->vts & 0xff);
+	}
+	client->addr = tmp_addr;
+
 	dev_info(&client->dev, "ap0101 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n",
-		 pid, AP0101_MAX_WIDTH, AP0101_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
+		 pid, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
 err:
 	ap0101_s_port(client, 0);
 
@@ -443,9 +493,7 @@ static int ap0101_parse_dt(struct device_node *np, struct ap0101_priv *priv)
 	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, AP0101_I2C_ADDR << 1);		/* Sensor native I2C address */
 		usleep_range(2000, 2500);				/* wait 2ms */
 	};
 	client->addr = tmp_addr;
@@ -518,8 +566,8 @@ static int ap0101_probe(struct i2c_client *client,
 
 	priv->rect.left = 0;
 	priv->rect.top = 0;
-	priv->rect.width = AP0101_MAX_WIDTH;
-	priv->rect.height = AP0101_MAX_HEIGHT;
+	priv->rect.width = priv->max_width;
+	priv->rect.height = priv->max_height;
 
 	ret = v4l2_async_register_subdev(&priv->sd);
 	if (ret)
diff --git a/drivers/media/i2c/soc_camera/ar0132.c b/drivers/media/i2c/soc_camera/ar0132.c
index 72dfbb4..18bc5dc 100644
--- a/drivers/media/i2c/soc_camera/ar0132.c
+++ b/drivers/media/i2c/soc_camera/ar0132.c
@@ -19,7 +19,6 @@
 #include <media/soc_camera.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
-#include <media/v4l2-fwnode.h>
 
 #include "ar0132.h"
 
@@ -29,7 +28,7 @@
 #define AR0132_PID		0x3000
 #define AR0132_VERSION_REG	0x2400
 
-#define AR0132_MEDIA_BUS_FMT	MEDIA_BUS_FMT_SBGGR12_1X12
+#define AR0132_MEDIA_BUS_FMT	MEDIA_BUS_FMT_SGRBG12_1X12
 
 struct ar0132_priv {
 	struct v4l2_subdev		sd;
diff --git a/drivers/media/i2c/soc_camera/ar0132.h b/drivers/media/i2c/soc_camera/ar0132.h
index bafa193..7dfc4e3 100644
--- a/drivers/media/i2c/soc_camera/ar0132.h
+++ b/drivers/media/i2c/soc_camera/ar0132.h
@@ -14,16 +14,15 @@
 
 #define AR0132_EMBEDDED_LINE
 
-#define AR0132_MAX_WIDTH		1665 // (1110*3/2)
+#define AR0132_MAX_WIDTH		1104
 #define AR0132_MAX_HEIGHT		624
 
 #define AR0132_DELAY			0xffff
 
 #define AR0132_MAX_ROI_DIM_X		1288
 #define AR0132_MAX_ROI_DIM_Y		968
-#define AR0132_InfoLines		4
 
-#define AR0132_ROI_DIM_X		1110 // 1104
+#define AR0132_ROI_DIM_X		1104
 #define AR0132_ROI_DIM_Y		620 // AR0132_MAX_HEIGHT
 
 #define AR0132_ROI_Y_START		0x00AE
@@ -57,11 +56,11 @@ static const struct ar0132_reg ar0132_regs_wizard[] = {
 			//256: Walking 1 test pattern (12 bit)
 #ifdef AR0132_DISPLAY_PATTERN_FIXED
 {0x3070, 0x0001},
+#endif
 {0x3072, 0x0123},	// R
 {0x3074, 0x0456},	// G(GR row)
 {0x3076, 0x0abc},	// B
 {0x3078, 0x0def},	// G(GB row)
-#endif
 #ifdef AR0132_DISPLAY_PATTERN_COLOR_BAR
 {0x3070, 0x0002},
 #endif
@@ -150,7 +149,7 @@ static const struct ar0132_reg ar0132_regs_wizard[] = {
 {0x302E, AR0132_PLL_Pre_Clk_Div},
 {0x3030, AR0132_PLL_Multiplier},
 {0x3032, 0x0000},	// SCALING_MODE = 0
-{0x3040, 0xC000},	// READ_MODE    = read_mode_vert_flip    | read_mode_horiz_mirror
+{0x3040, 0x0000},	// READ_MODE    = read_mode_vert_flip    | read_mode_horiz_mirror
 {0x3044, 0x0404},	// Dark Control = 1028
 {0x30A6, 0x0001},	// Y Odd Inc. (A) = 1
 {0x30A8, 0x0001},	// Y Odd Inc. (B) = 1
diff --git a/drivers/media/i2c/soc_camera/ar0140.c b/drivers/media/i2c/soc_camera/ar0140.c
new file mode 100644
index 0000000..807b6f8
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ar0140.c
@@ -0,0 +1,648 @@
+/*
+ * ON Semiconductor AR0140 sensor camera driver
+ *
+ * Copyright (C) 2018 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 "ar0140.h"
+
+#define AR0140_I2C_ADDR		0x10
+
+#define AR0140_PID		0x3000
+#define AR0140_VERSION_REG	0x0051
+
+#define AR0140_MEDIA_BUS_FMT	MEDIA_BUS_FMT_SGRBG12_1X12
+
+struct ar0140_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 inline struct ar0140_priv *to_ar0140(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct ar0140_priv, sd);
+}
+
+static void ar0140_s_port(struct i2c_client *client, int fwd_en)
+{
+	struct ar0140_priv *priv = to_ar0140(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 ar0140_set_regs(struct i2c_client *client,
+			  const struct ar0140_reg *regs, int nr_regs)
+{
+	struct ar0140_priv *priv = to_ar0140(client);
+	int i;
+
+	for (i = 0; i < nr_regs; i++) {
+		if (regs[i].reg == AR0140_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;
+
+		reg16_write16(client, regs[i].reg, regs[i].val);
+	}
+
+	return 0;
+}
+
+static int ar0140_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	return 0;
+}
+
+static int ar0140_set_window(struct v4l2_subdev *sd)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ar0140_priv *priv = to_ar0140(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 ar0140_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 ar0140_priv *priv = to_ar0140(client);
+
+	if (format->pad)
+		return -EINVAL;
+
+	mf->width = priv->rect.width;
+	mf->height = priv->rect.height;
+	mf->code = AR0140_MEDIA_BUS_FMT;
+	mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	mf->field = V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int ar0140_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 = AR0140_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 ar0140_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 = AR0140_MEDIA_BUS_FMT;
+
+	return 0;
+}
+
+static int ar0140_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ar0140_priv *priv = to_ar0140(client);
+
+	memcpy(edid->edid, priv->id, 6);
+
+	edid->edid[6] = 0xff;
+	edid->edid[7] = client->addr;
+	edid->edid[8] = AR0140_VERSION_REG >> 8;
+	edid->edid[9] = AR0140_VERSION_REG & 0xff;
+
+	return 0;
+}
+
+static int ar0140_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 ar0140_priv *priv = to_ar0140(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 > AR0140_MAX_WIDTH) ||
+	    (rect->top + rect->height > AR0140_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;
+
+	ar0140_set_window(sd);
+
+	return 0;
+}
+
+static int ar0140_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 ar0140_priv *priv = to_ar0140(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 = AR0140_MAX_WIDTH;
+		sel->r.height = AR0140_MAX_HEIGHT;
+		return 0;
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		sel->r.left = 0;
+		sel->r.top = 0;
+		sel->r.width = AR0140_MAX_WIDTH;
+		sel->r.height = AR0140_MAX_HEIGHT;
+		return 0;
+	case V4L2_SEL_TGT_CROP:
+		sel->r = priv->rect;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ar0140_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 ar0140_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 ar0140_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 ar0140_core_ops = {
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = ar0140_g_register,
+	.s_register = ar0140_s_register,
+#endif
+};
+
+static int ar0140_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ar0140_priv *priv = to_ar0140(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, 0x305e, ctrl->val);
+		break;
+	case V4L2_CID_ANALOGUE_GAIN:
+		/* Analog gain */
+		ret = reg16_write16(client, 0x3060, 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 ar0140_ctrl_ops = {
+	.s_ctrl = ar0140_s_ctrl,
+};
+
+static struct v4l2_subdev_video_ops ar0140_video_ops = {
+	.s_stream	= ar0140_s_stream,
+	.g_mbus_config	= ar0140_g_mbus_config,
+};
+
+static const struct v4l2_subdev_pad_ops ar0140_subdev_pad_ops = {
+	.get_edid	= ar0140_get_edid,
+	.enum_mbus_code	= ar0140_enum_mbus_code,
+	.get_selection	= ar0140_get_selection,
+	.set_selection	= ar0140_set_selection,
+	.get_fmt	= ar0140_get_fmt,
+	.set_fmt	= ar0140_set_fmt,
+};
+
+static struct v4l2_subdev_ops ar0140_subdev_ops = {
+	.core	= &ar0140_core_ops,
+	.video	= &ar0140_video_ops,
+	.pad	= &ar0140_subdev_pad_ops,
+};
+
+static void ar0140_otp_id_read(struct i2c_client *client)
+{
+	struct ar0140_priv *priv = to_ar0140(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 ar0140_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 ar0140_priv *priv = to_ar0140(client);
+
+	ar0140_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_ar0140, S_IRUGO, ar0140_otp_id_show, NULL);
+
+static int ar0140_initialize(struct i2c_client *client)
+{
+	struct ar0140_priv *priv = to_ar0140(client);
+	u16 val = 0;
+	u16 pid = 0;
+	int ret = 0;
+	int tmp_addr;
+
+	ar0140_s_port(client, 1);
+
+	/* check and show model ID */
+	reg16_read16(client, AR0140_PID, &pid);
+
+	if (pid != AR0140_VERSION_REG) {
+		dev_dbg(&client->dev, "Product ID error %x\n", pid);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	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, AR0140_MAX_WIDTH >> 8);	/* HS high period */
+		reg8_write(client, 0x55, AR0140_MAX_WIDTH & 0xff);
+		reg8_write(client, 0x56, (priv->hts - AR0140_MAX_WIDTH) >> 8); /* HS low period */
+		reg8_write(client, 0x57, (priv->hts - AR0140_MAX_WIDTH) & 0xff);
+		reg8_write(client, 0x58, priv->vts >> 8);		/* HS count */
+		reg8_write(client, 0x59, priv->vts & 0xff);
+	}
+	client->addr = tmp_addr;
+
+	/* Read OTP IDs */
+	ar0140_otp_id_read(client);
+	/* Program wizard registers */
+	ar0140_set_regs(client, ar0140_regs_wizard, ARRAY_SIZE(ar0140_regs_wizard));
+	/* Enable stream */
+	reg16_read16(client, 0x301a, &val);	// read inital reset_register value
+	val |= (1 << 2);			// Set streamOn bit
+	reg16_write16(client, 0x301a, val);	// Start Streaming
+
+	dev_info(&client->dev, "ar0140 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n",
+		 pid, AR0140_MAX_WIDTH, AR0140_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
+err:
+	ar0140_s_port(client, 0);
+
+	return ret;
+}
+
+static int ar0140_parse_dt(struct device_node *np, struct ar0140_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 AR0140\n");
+		return -EINVAL;
+	}
+
+	ar0140_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, AR0140_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, AR0140_I2C_ADDR << 1);		/* Sensor native I2C address */
+
+		reg8_write(client, 0x6e, 0x9a);				/* GPIO0 - fsin, GPIO1 - reset */
+	}
+	client->addr = tmp_addr;
+
+	mdelay(10);
+
+	return 0;
+}
+
+static int ar0140_probe(struct i2c_client *client,
+		       const struct i2c_device_id *did)
+{
+	struct ar0140_priv *priv;
+	int ret;
+
+	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&priv->sd, client, &ar0140_subdev_ops);
+	priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	v4l2_ctrl_handler_init(&priv->hdl, 4);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, 0, 16, 1, 7);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops,
+			  V4L2_CID_CONTRAST, 0, 16, 1, 7);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops,
+			  V4L2_CID_SATURATION, 0, 7, 1, 2);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops,
+			  V4L2_CID_HUE, 0, 23, 1, 12);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops,
+			  V4L2_CID_GAMMA, -128, 128, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops,
+			  V4L2_CID_SHARPNESS, 0, 10, 1, 3);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops,
+			  V4L2_CID_AUTOGAIN, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops,
+			  V4L2_CID_GAIN, 1, 0x7ff, 1, 0x80);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops,
+			  V4L2_CID_ANALOGUE_GAIN, 1, 0x7ff, 1, 0x1);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops,
+			  V4L2_CID_EXPOSURE, 1, 0x400, 1, 0x206);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops,
+			  V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0140_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 = ar0140_parse_dt(client->dev.of_node, priv);
+	if (ret)
+		goto cleanup;
+
+	ret = ar0140_initialize(client);
+	if (ret < 0)
+		goto cleanup;
+
+	priv->rect.left = 0;
+	priv->rect.top = 0;
+	priv->rect.width = AR0140_MAX_WIDTH;
+	priv->rect.height = AR0140_MAX_HEIGHT;
+
+	ret = v4l2_async_register_subdev(&priv->sd);
+	if (ret)
+		goto cleanup;
+
+	if (device_create_file(&client->dev, &dev_attr_otp_id_ar0140) != 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_AR0140
+	v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
+		client->addr, client->adapter->name);
+#endif
+	return ret;
+}
+
+static int ar0140_remove(struct i2c_client *client)
+{
+	struct ar0140_priv *priv = i2c_get_clientdata(client);
+
+	device_remove_file(&client->dev, &dev_attr_otp_id_ar0140);
+	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_AR0140
+static const struct i2c_device_id ar0140_id[] = {
+	{ "ar0140", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ar0140_id);
+
+static const struct of_device_id ar0140_of_ids[] = {
+	{ .compatible = "aptina,ar0140", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ar0140_of_ids);
+
+static struct i2c_driver ar0140_i2c_driver = {
+	.driver	= {
+		.name		= "ar0140",
+		.of_match_table	= ar0140_of_ids,
+	},
+	.probe		= ar0140_probe,
+	.remove		= ar0140_remove,
+	.id_table	= ar0140_id,
+};
+
+module_i2c_driver(ar0140_i2c_driver);
+
+MODULE_DESCRIPTION("SoC Camera driver for AR0140");
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/media/i2c/soc_camera/ar0140.h b/drivers/media/i2c/soc_camera/ar0140.h
new file mode 100644
index 0000000..f90762c
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ar0140.h
@@ -0,0 +1,475 @@
+/*
+ * ON Semiconductor AR0140 sensor camera wizard 1344x968@30/BGGR/BT601/RAW12
+ *
+ * Copyright (C) 2018 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 AR0140_DISPLAY_PATTERN_FIXED
+//#define AR0140_DISPLAY_PATTERN_COLOR_BAR
+
+//#define AR0140_EMBEDDED_LINE
+
+#define AR0140_MAX_WIDTH	1280
+#define AR0140_MAX_HEIGHT	800
+
+#define AR0140_DELAY		0xffff
+
+#define AR0140_SENSOR_WIDTH	1280
+#define AR0140_SENSOR_HEIGHT	800
+
+#define AR0140_X_START		((AR0140_SENSOR_WIDTH - AR0140_MAX_WIDTH) / 2)
+#define AR0140_Y_START		((AR0140_SENSOR_HEIGHT - AR0140_MAX_HEIGHT) / 2)
+#define AR0140_X_END		(AR0140_X_START + AR0140_MAX_WIDTH - 1)
+#define AR0140_Y_END		(AR0140_Y_START + AR0140_MAX_HEIGHT + 1) /* must be +1 and not -1 or 2 lines missed - bug in imager? */
+
+struct ar0140_reg {
+	u16	reg;
+	u16	val;
+};
+
+static const struct ar0140_reg ar0140_regs_wizard[] = {
+{0x301A, 0x0001},	// reset
+{AR0140_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 AR0140_DISPLAY_PATTERN_FIXED
+{0x3070, 0x0001},
+#endif
+{0x3072, 0x0fff},	// R
+{0x3074, 0x0fff},	// G(GR row)
+{0x3076, 0x0fff},	// B
+{0x3078, 0x0fff},	// G(GB row)
+#ifdef AR0140_DISPLAY_PATTERN_COLOR_BAR
+{0x3070, 0x0002},
+#endif
+{AR0140_DELAY, 250},
+/* SEQ_CTRL_PORT */
+{0x3088, 0x8000},
+/* SEQ_DATA_PORT */
+{0x3086, 0x4558},
+{0x3086, 0x6E9B},
+{0x3086, 0x4A31},
+{0x3086, 0x4342},
+{0x3086, 0x8E03},
+{0x3086, 0x2714},
+{0x3086, 0x4578},
+{0x3086, 0x7B3D},
+{0x3086, 0xFF3D},
+{0x3086, 0xFF3D},
+{0x3086, 0xEA27},
+{0x3086, 0x043D},
+{0x3086, 0x1027},
+{0x3086, 0x0527},
+{0x3086, 0x1535},
+{0x3086, 0x2705},
+{0x3086, 0x3D10},
+{0x3086, 0x4558},
+{0x3086, 0x2704},
+{0x3086, 0x2714},
+{0x3086, 0x3DFF},
+{0x3086, 0x3DFF},
+{0x3086, 0x3DEA},
+{0x3086, 0x2704},
+{0x3086, 0x6227},
+{0x3086, 0x288E},
+{0x3086, 0x0036},
+{0x3086, 0x2708},
+{0x3086, 0x3D64},
+{0x3086, 0x7A3D},
+{0x3086, 0x0444},
+{0x3086, 0x2C4B},
+{0x3086, 0x8F00},
+{0x3086, 0x4372},
+{0x3086, 0x719F},
+{0x3086, 0x6343},
+{0x3086, 0x166F},
+{0x3086, 0x9F92},
+{0x3086, 0x1244},
+{0x3086, 0x1663},
+{0x3086, 0x4316},
+{0x3086, 0x9326},
+{0x3086, 0x0426},
+{0x3086, 0x848E},
+{0x3086, 0x0327},
+{0x3086, 0xFC5C},
+{0x3086, 0x0D57},
+{0x3086, 0x5417},
+{0x3086, 0x0955},
+{0x3086, 0x5649},
+{0x3086, 0x5F53},
+{0x3086, 0x0553},
+{0x3086, 0x0728},
+{0x3086, 0x6C4C},
+{0x3086, 0x0928},
+{0x3086, 0x2C72},
+{0x3086, 0xAD7C},
+{0x3086, 0xA928},
+{0x3086, 0xA879},
+{0x3086, 0x6026},
+{0x3086, 0x9C5C},
+{0x3086, 0x1B45},
+{0x3086, 0x4845},
+{0x3086, 0x0845},
+{0x3086, 0x8826},
+{0x3086, 0xBE8E},
+{0x3086, 0x0127},
+{0x3086, 0xF817},
+{0x3086, 0x0227},
+{0x3086, 0xFA17},
+{0x3086, 0x095C},
+{0x3086, 0x0B17},
+{0x3086, 0x1026},
+{0x3086, 0xBA5C},
+{0x3086, 0x0317},
+{0x3086, 0x1026},
+{0x3086, 0xB217},
+{0x3086, 0x065F},
+{0x3086, 0x2888},
+{0x3086, 0x9060},
+{0x3086, 0x27F2},
+{0x3086, 0x1710},
+{0x3086, 0x26A2},
+{0x3086, 0x26A3},
+{0x3086, 0x5F4D},
+{0x3086, 0x2808},
+{0x3086, 0x1927},
+{0x3086, 0xFA84},
+{0x3086, 0x69A0},
+{0x3086, 0x785D},
+{0x3086, 0x2888},
+{0x3086, 0x8710},
+{0x3086, 0x8C82},
+{0x3086, 0x8926},
+{0x3086, 0xB217},
+{0x3086, 0x036B},
+{0x3086, 0x9C60},
+{0x3086, 0x9417},
+{0x3086, 0x2926},
+{0x3086, 0x8345},
+{0x3086, 0xA817},
+{0x3086, 0x0727},
+{0x3086, 0xFB17},
+{0x3086, 0x2945},
+{0x3086, 0x881F},
+{0x3086, 0x1708},
+{0x3086, 0x27FA},
+{0x3086, 0x5D87},
+{0x3086, 0x108C},
+{0x3086, 0x8289},
+{0x3086, 0x170E},
+{0x3086, 0x4826},
+{0x3086, 0x9A28},
+{0x3086, 0x884C},
+{0x3086, 0x0B79},
+{0x3086, 0x1730},
+{0x3086, 0x2692},
+{0x3086, 0x1709},
+{0x3086, 0x9160},
+{0x3086, 0x27F2},
+{0x3086, 0x1710},
+{0x3086, 0x2682},
+{0x3086, 0x2683},
+{0x3086, 0x5F4D},
+{0x3086, 0x2808},
+{0x3086, 0x1927},
+{0x3086, 0xFA84},
+{0x3086, 0x69A1},
+{0x3086, 0x785D},
+{0x3086, 0x2888},
+{0x3086, 0x8710},
+{0x3086, 0x8C80},
+{0x3086, 0x8A26},
+{0x3086, 0x9217},
+{0x3086, 0x036B},
+{0x3086, 0x9D95},
+{0x3086, 0x2603},
+{0x3086, 0x5C01},
+{0x3086, 0x4558},
+{0x3086, 0x8E00},
+{0x3086, 0x2798},
+{0x3086, 0x170A},
+{0x3086, 0x4A65},
+{0x3086, 0x4316},
+{0x3086, 0x6643},
+{0x3086, 0x165B},
+{0x3086, 0x4316},
+{0x3086, 0x5943},
+{0x3086, 0x168E},
+{0x3086, 0x0327},
+{0x3086, 0x9C45},
+{0x3086, 0x7817},
+{0x3086, 0x0727},
+{0x3086, 0x9D17},
+{0x3086, 0x225D},
+{0x3086, 0x8710},
+{0x3086, 0x2808},
+{0x3086, 0x530D},
+{0x3086, 0x8C80},
+{0x3086, 0x8A45},
+{0x3086, 0x5823},
+{0x3086, 0x1708},
+{0x3086, 0x8E01},
+{0x3086, 0x2798},
+{0x3086, 0x8E00},
+{0x3086, 0x2644},
+{0x3086, 0x5C05},
+{0x3086, 0x1244},
+{0x3086, 0x4B71},
+{0x3086, 0x759E},
+{0x3086, 0x8B85},
+{0x3086, 0x0143},
+{0x3086, 0x7271},
+{0x3086, 0xA346},
+{0x3086, 0x4316},
+{0x3086, 0x6FA3},
+{0x3086, 0x9612},
+{0x3086, 0x4416},
+{0x3086, 0x4643},
+{0x3086, 0x1697},
+{0x3086, 0x2604},
+{0x3086, 0x2684},
+{0x3086, 0x8E03},
+{0x3086, 0x27FC},
+{0x3086, 0x5C0D},
+{0x3086, 0x5754},
+{0x3086, 0x1709},
+{0x3086, 0x5556},
+{0x3086, 0x495F},
+{0x3086, 0x5305},
+{0x3086, 0x5307},
+{0x3086, 0x286C},
+{0x3086, 0x4C09},
+{0x3086, 0x282C},
+{0x3086, 0x72AE},
+{0x3086, 0x7CAA},
+{0x3086, 0x28A8},
+{0x3086, 0x7960},
+{0x3086, 0x269C},
+{0x3086, 0x5C1B},
+{0x3086, 0x4548},
+{0x3086, 0x4508},
+{0x3086, 0x4588},
+{0x3086, 0x26BE},
+{0x3086, 0x8E01},
+{0x3086, 0x27F8},
+{0x3086, 0x1702},
+{0x3086, 0x27FA},
+{0x3086, 0x1709},
+{0x3086, 0x5C0B},
+{0x3086, 0x1710},
+{0x3086, 0x26BA},
+{0x3086, 0x5C03},
+{0x3086, 0x1710},
+{0x3086, 0x26B2},
+{0x3086, 0x1706},
+{0x3086, 0x5F28},
+{0x3086, 0x8898},
+{0x3086, 0x6027},
+{0x3086, 0xF217},
+{0x3086, 0x1026},
+{0x3086, 0xA226},
+{0x3086, 0xA35F},
+{0x3086, 0x4D28},
+{0x3086, 0x081A},
+{0x3086, 0x27FA},
+{0x3086, 0x8469},
+{0x3086, 0xA578},
+{0x3086, 0x5D28},
+{0x3086, 0x8887},
+{0x3086, 0x108C},
+{0x3086, 0x8289},
+{0x3086, 0x26B2},
+{0x3086, 0x1703},
+{0x3086, 0x6BA4},
+{0x3086, 0x6099},
+{0x3086, 0x1729},
+{0x3086, 0x2683},
+{0x3086, 0x45A8},
+{0x3086, 0x1707},
+{0x3086, 0x27FB},
+{0x3086, 0x1729},
+{0x3086, 0x4588},
+{0x3086, 0x2017},
+{0x3086, 0x0827},
+{0x3086, 0xFA5D},
+{0x3086, 0x8710},
+{0x3086, 0x8C82},
+{0x3086, 0x8917},
+{0x3086, 0x0E48},
+{0x3086, 0x269A},
+{0x3086, 0x2888},
+{0x3086, 0x4C0B},
+{0x3086, 0x7917},
+{0x3086, 0x3026},
+{0x3086, 0x9217},
+{0x3086, 0x099A},
+{0x3086, 0x6027},
+{0x3086, 0xF217},
+{0x3086, 0x1026},
+{0x3086, 0x8226},
+{0x3086, 0x835F},
+{0x3086, 0x4D28},
+{0x3086, 0x081A},
+{0x3086, 0x27FA},
+{0x3086, 0x8469},
+{0x3086, 0xAB78},
+{0x3086, 0x5D28},
+{0x3086, 0x8887},
+{0x3086, 0x108C},
+{0x3086, 0x808A},
+{0x3086, 0x2692},
+{0x3086, 0x1703},
+{0x3086, 0x6BA6},
+{0x3086, 0xA726},
+{0x3086, 0x035C},
+{0x3086, 0x0145},
+{0x3086, 0x588E},
+{0x3086, 0x0027},
+{0x3086, 0x9817},
+{0x3086, 0x0A4A},
+{0x3086, 0x0A43},
+{0x3086, 0x160B},
+{0x3086, 0x438E},
+{0x3086, 0x0327},
+{0x3086, 0x9C45},
+{0x3086, 0x7817},
+{0x3086, 0x0727},
+{0x3086, 0x9D17},
+{0x3086, 0x225D},
+{0x3086, 0x8710},
+{0x3086, 0x2808},
+{0x3086, 0x530D},
+{0x3086, 0x8C80},
+{0x3086, 0x8A45},
+{0x3086, 0x5817},
+{0x3086, 0x088E},
+{0x3086, 0x0127},
+{0x3086, 0x988E},
+{0x3086, 0x0076},
+{0x3086, 0xAC77},
+{0x3086, 0xAC46},
+{0x3086, 0x4416},
+{0x3086, 0x16A8},
+{0x3086, 0x7A26},
+{0x3086, 0x445C},
+{0x3086, 0x0512},
+{0x3086, 0x444B},
+{0x3086, 0x7175},
+{0x3086, 0xA24A},
+{0x3086, 0x0343},
+{0x3086, 0x1604},
+{0x3086, 0x4316},
+{0x3086, 0x5843},
+{0x3086, 0x165A},
+{0x3086, 0x4316},
+{0x3086, 0x0643},
+{0x3086, 0x1607},
+{0x3086, 0x4316},
+{0x3086, 0x8E03},
+{0x3086, 0x279C},
+{0x3086, 0x4578},
+{0x3086, 0x7B17},
+{0x3086, 0x078B},
+{0x3086, 0x8627},
+{0x3086, 0x9D17},
+{0x3086, 0x2345},
+{0x3086, 0x5822},
+{0x3086, 0x1708},
+{0x3086, 0x8E01},
+{0x3086, 0x2798},
+{0x3086, 0x8E00},
+{0x3086, 0x2644},
+{0x3086, 0x5C05},
+{0x3086, 0x1244},
+{0x3086, 0x4B8D},
+{0x3086, 0x602C},
+{0x3086, 0x2C2C},
+{0x3086, 0x2C00},
+/* End Sequencer */
+#ifdef AR0140_EMBEDDED_LINE
+{0x3064, 0x1982}, // SMIA_TEST
+#else
+{0x3064, 0x1802}, // SMIA_TEST
+#endif
+/* PCLK=27Mhz/0x2 *0x30 /1/0x10 - TI serializers */
+{0x302A, 0x0010}, // vt_pix_clk_div
+{0x302E, 0x0002}, // pre_pll_clk_div
+{0x3030, 0x0030}, // pll_multiplier
+#if 0
+/* Resolution: 1284x804x29.98p */
+{0x3002, 0x001A}, // y_addr_start 
+{0x3004, 0x0014}, // x_addr_start 
+{0x3006, 0x033D}, // y_addr_end}, 804 lines
+{0x3008, 0x0517}, // x_addr_end}, 1284px
+{0x300A, 0x0344}, // frame_length_lines}, 840 lines
+{0x300C, 0x0648}, // line_length_pck}, 1608px
+#else
+{0x31B0, 0x0056}, // FRAME_PREAMBLE
+{0x31B2, 0x0045}, // LINE_PREAMBLE
+{0x3004, AR0140_X_START}, // X_ADDR_START_
+{0x3008, AR0140_X_END}, // X_ADDR_END_
+{0x3002, AR0140_Y_START}, // Y_ADDR_START_
+{0x3006, AR0140_Y_END}, // Y_ADDR_END_
+{0x3402, 0x0000 | AR0140_MAX_WIDTH}, // X_OUTPUT_CONTROL
+{0x3404, 0x0000 | AR0140_MAX_HEIGHT}, // Y_OUTPUT_CONTROL
+{0x300A, AR0140_SENSOR_HEIGHT + 36}, // FRAME_LENGTH_LINES_
+{0x300C, AR0140_SENSOR_WIDTH + 328}, // LINE_LENGTH_PCK_
+#endif
+/* Rev3 Optimized Settings */
+{0x3044, 0x0400},
+{0x3052, 0xA134},
+{0x3092, 0x010F},
+{0x30FE, 0x0080},
+{0x3ECE, 0x40FF},
+{0x3ED0, 0xFF40},
+{0x3ED2, 0xA906},
+{0x3ED4, 0x001F},
+{0x3ED6, 0x638F},
+{0x3ED8, 0xCC99},
+{0x3EDA, 0x0888},
+{0x3EDE, 0x8878},
+{0x3EE0, 0x7744},
+{0x3EE2, 0x5563},
+{0x3EE4, 0xAAE0},
+{0x3EE6, 0x3400},
+{0x3EEA, 0xA4FF},
+{0x3EEC, 0x80F0},
+{0x3EEE, 0x0000},
+{0x31E0, 0x1701},
+/* HDR mode */
+/* 2D Motion Compensation */
+{0x318A, 0x0E74}, // hdr_mc_ctrl1
+{0x318C, 0xC000}, // hdr_mc_ctrl2
+{0x318E, 0x0800}, // hdr_mc_ctrl3: Gain before DLO set to 1
+{0x3190, 0x0000}, // hdr_mc_ctrl4: if DLO enabled overrides 2D MC
+{0x3192, 0x0400}, // hdr_mc_ctrl5
+{0x3194, 0x0BB8}, // hdr_mc_ctrl6: T1 barrier set to 3000
+{0x3196, 0x0E74}, // hdr_mc_ctrl7: T2 barrier set to 3700
+{0x3198, 0x183C}, // hdr_mc_ctrl8: Motion detect Q1 set to 60}, Q2 set to 24
+{0x3200, 0x0002}, // adacd_control
+{0x3202, 0x00A0}, // adacd_noise_model1
+{0x3206, 0x0A06}, // adacd_noise_floor1
+{0x3208, 0x1A12}, // adacd_noise_floor2
+{0x320A, 0x0080}, // adacd_pedestal
+{0x306E, 0x9010}, // datapath select - LV noncontinuous
+{0x31AC, 0x100C}, // DATA_FORMAT_BITS: RAW12
+{0x31AE, 0x0301}, // SERIAL_FORMAT
+{0x301A, 0x11D8}, // RESET_REGISTER
+// patch start
+{0x3012, 0x0206}, // COARSE_INTEGRATION_TIME_: T1 exposure - max=0x400
+// patch end
+// enable trigger
+{0x340A, 0x0070}, // GPIO_CONTROL1: GPIO3 is trigger
+{0x340C, 0x0080}, // GPIO_CONTROL2: GPIO3 is trigger
+{0x30CE, 0x0120}, // TRIGGER_MODE
+//{0x30DC, 0x0120}, // TRIGGER_DELAY
+};
diff --git a/drivers/media/i2c/soc_camera/ar0143.c b/drivers/media/i2c/soc_camera/ar0143.c
new file mode 100644
index 0000000..b51dcfc
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ar0143.c
@@ -0,0 +1,678 @@
+/*
+ * ON Semiconductor AR0143 sensor camera driver
+ *
+ * Copyright (C) 2018 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 "ar0143.h"
+
+#define AR0143_I2C_ADDR		0x10
+
+#define AR0143_PID		0x3000
+#define AR0143_VERSION_REG	0x0D54
+
+#define AR0143_MEDIA_BUS_FMT	MEDIA_BUS_FMT_SGRBG12_1X12
+
+struct ar0143_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 inline struct ar0143_priv *to_ar0143(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct ar0143_priv, sd);
+}
+
+static void ar0143_s_port(struct i2c_client *client, int fwd_en)
+{
+	struct ar0143_priv *priv = to_ar0143(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 ar0143_set_regs(struct i2c_client *client,
+			  const struct ar0143_reg *regs, int nr_regs)
+{
+	struct ar0143_priv *priv = to_ar0143(client);
+	int i;
+
+	for (i = 0; i < nr_regs; i++) {
+		if (regs[i].reg == AR0143_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, AR0143_SENSOR_HEIGHT + 142); // FRAME_LENGTH_LINES_
+				continue;
+			}
+		}
+
+		reg16_write16(client, regs[i].reg, regs[i].val);
+	}
+
+	return 0;
+}
+
+static int ar0143_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	return 0;
+}
+
+static int ar0143_set_window(struct v4l2_subdev *sd)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ar0143_priv *priv = to_ar0143(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 ar0143_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 ar0143_priv *priv = to_ar0143(client);
+
+	if (format->pad)
+		return -EINVAL;
+
+	mf->width = priv->rect.width;
+	mf->height = priv->rect.height;
+	mf->code = AR0143_MEDIA_BUS_FMT;
+	mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	mf->field = V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int ar0143_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 = AR0143_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 ar0143_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 = AR0143_MEDIA_BUS_FMT;
+
+	return 0;
+}
+
+static int ar0143_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ar0143_priv *priv = to_ar0143(client);
+
+	memcpy(edid->edid, priv->id, 6);
+
+	edid->edid[6] = 0xff;
+	edid->edid[7] = client->addr;
+	edid->edid[8] = AR0143_VERSION_REG >> 8;
+	edid->edid[9] = AR0143_VERSION_REG & 0xff;
+
+	return 0;
+}
+
+static int ar0143_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 ar0143_priv *priv = to_ar0143(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 > AR0143_MAX_WIDTH) ||
+	    (rect->top + rect->height > AR0143_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;
+
+	ar0143_set_window(sd);
+
+	return 0;
+}
+
+static int ar0143_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 ar0143_priv *priv = to_ar0143(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 = AR0143_MAX_WIDTH;
+		sel->r.height = AR0143_MAX_HEIGHT;
+		return 0;
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		sel->r.left = 0;
+		sel->r.top = 0;
+		sel->r.width = AR0143_MAX_WIDTH;
+		sel->r.height = AR0143_MAX_HEIGHT;
+		return 0;
+	case V4L2_SEL_TGT_CROP:
+		sel->r = priv->rect;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ar0143_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 ar0143_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 ar0143_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 ar0143_core_ops = {
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = ar0143_g_register,
+	.s_register = ar0143_s_register,
+#endif
+};
+
+static int ar0143_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ar0143_priv *priv = to_ar0143(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 ar0143_ctrl_ops = {
+	.s_ctrl = ar0143_s_ctrl,
+};
+
+static struct v4l2_subdev_video_ops ar0143_video_ops = {
+	.s_stream	= ar0143_s_stream,
+	.g_mbus_config	= ar0143_g_mbus_config,
+};
+
+static const struct v4l2_subdev_pad_ops ar0143_subdev_pad_ops = {
+	.get_edid	= ar0143_get_edid,
+	.enum_mbus_code	= ar0143_enum_mbus_code,
+	.get_selection	= ar0143_get_selection,
+	.set_selection	= ar0143_set_selection,
+	.get_fmt	= ar0143_get_fmt,
+	.set_fmt	= ar0143_set_fmt,
+};
+
+static struct v4l2_subdev_ops ar0143_subdev_ops = {
+	.core	= &ar0143_core_ops,
+	.video	= &ar0143_video_ops,
+	.pad	= &ar0143_subdev_pad_ops,
+};
+
+static void ar0143_otp_id_read(struct i2c_client *client)
+{
+	struct ar0143_priv *priv = to_ar0143(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 ar0143_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 ar0143_priv *priv = to_ar0143(client);
+
+	ar0143_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_ar0143, S_IRUGO, ar0143_otp_id_show, NULL);
+
+static int ar0143_initialize(struct i2c_client *client)
+{
+	struct ar0143_priv *priv = to_ar0143(client);
+	u16 val = 0;
+	u16 pid = 0;
+	int ret = 0;
+	int tmp_addr;
+
+	ar0143_s_port(client, 1);
+
+	/* check and show model ID */
+	reg16_read16(client, AR0143_PID, &pid);
+
+	if (pid != AR0143_VERSION_REG) {
+		dev_dbg(&client->dev, "Product ID error %x\n", pid);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	/* Program wizard registers */
+	ar0143_set_regs(client, ar0143_regs_wizard, ARRAY_SIZE(ar0143_regs_wizard));
+
+	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, AR0143_MAX_WIDTH >> 8);	/* HS high period */
+		reg8_write(client, 0x55, AR0143_MAX_WIDTH & 0xff);
+		reg8_write(client, 0x56, (priv->hts - AR0143_MAX_WIDTH) >> 8); /* HS low period */
+		reg8_write(client, 0x57, (priv->hts - AR0143_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);	// read inital reset_register value
+	val |= (1 << 2);			// Set streamOn bit
+	reg16_write16(client, 0x301a, val);	// Start Streaming
+
+	/* Read OTP IDs */
+	ar0143_otp_id_read(client);
+
+	dev_info(&client->dev, "ar0143 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n",
+		 pid, AR0143_MAX_WIDTH, AR0143_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
+err:
+	ar0143_s_port(client, 0);
+
+	return ret;
+}
+
+static int ar0143_parse_dt(struct device_node *np, struct ar0143_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 AR0143\n");
+		return -EINVAL;
+	}
+
+	ar0143_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, AR0143_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, AR0143_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 ar0143_probe(struct i2c_client *client,
+		       const struct i2c_device_id *did)
+{
+	struct ar0143_priv *priv;
+	int ret;
+
+	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&priv->sd, client, &ar0143_subdev_ops);
+	priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	v4l2_ctrl_handler_init(&priv->hdl, 4);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, 0, 16, 1, 7);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops,
+			  V4L2_CID_CONTRAST, 0, 16, 1, 7);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops,
+			  V4L2_CID_SATURATION, 0, 7, 1, 2);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops,
+			  V4L2_CID_HUE, 0, 23, 1, 12);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops,
+			  V4L2_CID_GAMMA, -128, 128, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops,
+			  V4L2_CID_SHARPNESS, 0, 10, 1, 3);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops,
+			  V4L2_CID_AUTOGAIN, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops,
+			  V4L2_CID_GAIN, 1, 0x7ff, 1, 0x200);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops,
+			  V4L2_CID_ANALOGUE_GAIN, 1, 0xe, 1, 0x7);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops,
+			  V4L2_CID_EXPOSURE, 1, 0x400, 1, 0x300);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops,
+			  V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0143_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 = ar0143_parse_dt(client->dev.of_node, priv);
+	if (ret)
+		goto cleanup;
+
+	ret = ar0143_initialize(client);
+	if (ret < 0)
+		goto cleanup;
+
+	priv->rect.left = 0;
+	priv->rect.top = 0;
+	priv->rect.width = AR0143_MAX_WIDTH;
+	priv->rect.height = AR0143_MAX_HEIGHT;
+
+	ret = v4l2_async_register_subdev(&priv->sd);
+	if (ret)
+		goto cleanup;
+
+	if (device_create_file(&client->dev, &dev_attr_otp_id_ar0143) != 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_AR0143
+	v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
+		client->addr, client->adapter->name);
+#endif
+	return ret;
+}
+
+static int ar0143_remove(struct i2c_client *client)
+{
+	struct ar0143_priv *priv = i2c_get_clientdata(client);
+
+	device_remove_file(&client->dev, &dev_attr_otp_id_ar0143);
+	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_AR0143
+static const struct i2c_device_id ar0143_id[] = {
+	{ "ar0143", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ar0143_id);
+
+static const struct of_device_id ar0143_of_ids[] = {
+	{ .compatible = "aptina,ar0143", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ar0143_of_ids);
+
+static struct i2c_driver ar0143_i2c_driver = {
+	.driver	= {
+		.name		= "ar0143",
+		.of_match_table	= ar0143_of_ids,
+	},
+	.probe		= ar0143_probe,
+	.remove		= ar0143_remove,
+	.id_table	= ar0143_id,
+};
+
+module_i2c_driver(ar0143_i2c_driver);
+
+MODULE_DESCRIPTION("SoC Camera driver for AR0143");
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/media/i2c/soc_camera/ar0143.h b/drivers/media/i2c/soc_camera/ar0143.h
new file mode 100644
index 0000000..774a438
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ar0143.h
@@ -0,0 +1,549 @@
+/*
+ * ON Semiconductor AR0143 sensor camera wizard 1344x968@30/BGGR/BT601/RAW12
+ *
+ * Copyright (C) 2018 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 AR0143_DISPLAY_PATTERN_FIXED
+//#define AR0143_DISPLAY_PATTERN_COLOR_BAR
+
+//#define AR0143_EMBEDDED_LINE
+
+#define AR0143_MAX_WIDTH	1344
+#define AR0143_MAX_HEIGHT	968
+
+#define AR0143_DELAY		0xffff
+
+#define AR0143_SENSOR_WIDTH	1344
+#define AR0143_SENSOR_HEIGHT	968
+
+#define AR0143_X_START		((AR0143_SENSOR_WIDTH - AR0143_MAX_WIDTH) / 2)
+#define AR0143_Y_START		((AR0143_SENSOR_HEIGHT - AR0143_MAX_HEIGHT) / 2)
+#define AR0143_X_END		(AR0143_X_START + AR0143_MAX_WIDTH - 1)
+#define AR0143_Y_END		(AR0143_Y_START + AR0143_MAX_HEIGHT + 1) /* must be +1 and not -1 or 2 lines missed - bug in imager? */
+
+struct ar0143_reg {
+	u16	reg;
+	u16	val;
+};
+
+static const struct ar0143_reg ar0143_regs_wizard[] = {
+{0x301A, 0x0001},	// reset
+{AR0143_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 AR0143_DISPLAY_PATTERN_FIXED
+{0x3070, 0x0001},
+#endif
+{0x3072, 0x0fff},	// R
+{0x3074, 0x0fff},	// G(GR row)
+{0x3076, 0x0fff},	// B
+{0x3078, 0x0fff},	// G(GB row)
+#ifdef AR0143_DISPLAY_PATTERN_COLOR_BAR
+{0x3070, 0x0002},
+#endif
+{AR0143_DELAY, 250},
+// start demo init
+{0x3100, 0x4000}, // DLO_CONTROL0
+{0x3102, 0x6060}, // RESERVED_MFR_3102
+{0x3104, 0x6060}, // RESERVED_MFR_3104
+{0x3106, 0x6060}, // RESERVED_MFR_3106
+{0x3108, 0x0F9F}, // RESERVED_MFR_3108
+{0x3280, 0x0FA0}, // T1_BARRIER_C0
+{0x3282, 0x0FA0}, // T1_BARRIER_C1
+{0x3284, 0x0FA0}, // T1_BARRIER_C2
+{0x3286, 0x0FA0}, // T1_BARRIER_C3
+{0x3288, 0x0FA0}, // T2_BARRIER_C0
+{0x328A, 0x0FA0}, // T2_BARRIER_C1
+{0x328C, 0x0FA0}, // T2_BARRIER_C2
+{0x328E, 0x0FA0}, // T2_BARRIER_C3
+{0x3290, 0x0FA0}, // T3_BARRIER_C0
+{0x3292, 0x0FA0}, // T3_BARRIER_C1
+{0x3294, 0x0FA0}, // T3_BARRIER_C2
+{0x3296, 0x0FA0}, // T3_BARRIER_C3
+{0x3298, 0x0FA0}, // T4_BARRIER_C0
+{0x329A, 0x0FA0}, // T4_BARRIER_C1
+{0x329C, 0x0FA0}, // T4_BARRIER_C2
+{0x329E, 0x0FA0}, // T4_BARRIER_C3
+{0x3110, 0x0011}, // HDR_CONTROL0
+{0x3112, 0x7FE7}, // RESERVED_MFR_3112
+{0x3114, 0x0000}, // RESERVED_MFR_3114
+{0x3116, 0xC000}, // HDR_CONTROL3
+{0x3120, 0x0BA0}, // HDR_SC_CONTROL0
+{0x3122, 0x0FA0}, // HDR_SC_CONTROL1
+{0x3124, 0x00B4}, // HDR_MD_CONTROL0
+{0x3126, 0x0030}, // HDR_MD_CONTROL1
+{0x3128, 0x6100}, // RESERVED_MFR_3128
+{0x3506, 0x3333}, // RESERVED_MFR_3506
+{0x3508, 0x3333}, // RESERVED_MFR_3508
+{0x350A, 0x3333}, // RESERVED_MFR_350A
+{0x350C, 0x035F}, // RESERVED_MFR_350C
+{0x350E, 0xEF14}, // RESERVED_MFR_350E
+{0x3086, 0x0600}, // RESERVED_MFR_3086
+{0x3C00, 0xDD67}, // RESERVED_MFR_3C00
+{0x3092, 0x1C24}, // RESERVED_MFR_3092
+{0x3096, 0x147E}, // RESERVED_MFR_3096
+{0x3750, 0x147E}, // RESERVED_MFR_3750
+{0x30B0, 0x0800}, // DIGITAL_TEST
+{0x30FE, 0x0000}, // NOISE_PEDESTAL
+{0x32D0, 0x3A02}, // RESERVED_MFR_32D0
+{0x32D6, 0x3C04}, // RESERVED_MFR_32D6
+{0x3C0C, 0x0516}, // DELAY_BUFFER_LLPCK_RD_WR_OVERLAP
+{0x3F94, 0x483e}, // TEMPVSENS0_FLAG_CTRL
+{0x3F96, 0xFFFE}, // TEMPVSENS1_FLAG_CTRL
+{0x3088, 0x6680}, // LFM_CTRL
+{0x33E2, 0x0000}, // SAMPLE_CTRL
+{0x3366, 0x7777}, // ANALOG_GAIN
+{0x3056, 0x0080}, // GREEN1_GAIN
+{0x305C, 0x0080}, // GREEN2_GAIN
+{0x3058, 0x0080}, // BLUE_GAIN
+{0x305A, 0x0080}, // RED_GAIN
+{0x306E, 0x9010}, // DATAPATH_SELECT
+{0x3044, 0x0400}, // DARK_CONTROL
+{0x30BA, 0x01E2}, // DIGITAL_CTRL
+{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA
+{0x3362, 0x0000}, // DC_GAIN
+{0x3364, 0x005B}, // RESERVED_MFR_3364
+{0x3370, 0x0131}, // DBLC_CONTROL
+{0x3372, 0x700F}, // DBLC_FS0_CONTROL
+{0x3386, 0x0000}, // DBLC_PEDESTAL
+{0x3C04, 0x0E80}, // RESERVED_MFR_3C04
+{0x30B4, 0x01C7}, // TEMPSENS0_CTRL_REG
+{0x30B8, 0x0007}, // TEMPSENS1_CTRL_REG
+{0x3F90, 0x8D03}, // TEMPVSENS0_TMG_CTRL
+{0x3F92, 0x0D03}, // TEMPVSENS1_TMG_CTRL
+{0x3502, 0x0808}, // RESERVED_MFR_3502
+{0x3566, 0x1D28}, // RESERVED_MFR_3566
+{0x3518, 0x1FFE}, // RESERVED_MFR_3518
+{0x3526, 0x0F00}, // RESERVED_MFR_3526
+{0x3528, 0xDDDD}, // RESERVED_MFR_3528
+{0x352A, 0x089F}, // RESERVED_MFR_352A
+{0x352E, 0x0011}, // RESERVED_MFR_352E
+{0x3530, 0x4400}, // RESERVED_MFR_3530
+{0x3536, 0xFF07}, // RESERVED_MFR_3536
+{0x3538, 0xFFFF}, // RESERVED_MFR_3538
+{0x353A, 0x9000}, // RESERVED_MFR_353A
+{0x353C, 0x3F00}, // RESERVED_MFR_353C
+{0x32EC, 0x72A1}, // RESERVED_MFR_32EC
+{0x3540, 0xC637}, // RESERVED_MFR_3540
+{0x3542, 0x464B}, // RESERVED_MFR_3542
+{0x3544, 0x4B50}, // RESERVED_MFR_3544
+{0x3546, 0x545A}, // RESERVED_MFR_3546
+{0x3548, 0x5A00}, // RESERVED_MFR_3548
+{0x354A, 0x007F}, // RESERVED_MFR_354A
+{0x3556, 0x101F}, // RESERVED_MFR_3556
+{0x3566, 0x3328}, // RESERVED_MFR_3566
+{0x337A, 0x0CA3}, // DBLC_SCALE0
+{0x3372, 0x710F}, // DBLC_FS0_CONTROL
+{0x3520, 0x4688}, // RESERVED_MFR_3520
+{0x3522, 0x8840}, // RESERVED_MFR_3522
+{0x3524, 0x4046}, // RESERVED_MFR_3524
+{0x352C, 0x4646}, // RESERVED_MFR_352C
+{0x2512, 0x8000}, // SEQ_CTRL_PORT
+{0x2510, 0x0903}, // SEQ_DATA_PORT
+{0x2510, 0x3350}, // SEQ_DATA_PORT
+{0x2510, 0x2004}, // SEQ_DATA_PORT
+{0x2510, 0x1420}, // SEQ_DATA_PORT
+{0x2510, 0x1578}, // SEQ_DATA_PORT
+{0x2510, 0x087B}, // SEQ_DATA_PORT
+{0x2510, 0x24FF}, // SEQ_DATA_PORT
+{0x2510, 0x24FF}, // SEQ_DATA_PORT
+{0x2510, 0x24EA}, // SEQ_DATA_PORT
+{0x2510, 0x2410}, // SEQ_DATA_PORT
+{0x2510, 0x2224}, // SEQ_DATA_PORT
+{0x2510, 0x1015}, // SEQ_DATA_PORT
+{0x2510, 0x5813}, // SEQ_DATA_PORT
+{0x2510, 0x0214}, // SEQ_DATA_PORT
+{0x2510, 0x0024}, // SEQ_DATA_PORT
+{0x2510, 0xFF24}, // SEQ_DATA_PORT
+{0x2510, 0xFF24}, // SEQ_DATA_PORT
+{0x2510, 0xEA23}, // SEQ_DATA_PORT
+{0x2510, 0x2464}, // SEQ_DATA_PORT
+{0x2510, 0x7A24}, // SEQ_DATA_PORT
+{0x2510, 0x0405}, // SEQ_DATA_PORT
+{0x2510, 0x2C40}, // SEQ_DATA_PORT
+{0x2510, 0x0AFF}, // SEQ_DATA_PORT
+{0x2510, 0x0ACC}, // SEQ_DATA_PORT
+{0x2510, 0x0A07}, // 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, 0x2652}, // SEQ_DATA_PORT
+{0x2510, 0x0815}, // SEQ_DATA_PORT
+{0x2510, 0x1813}, // SEQ_DATA_PORT
+{0x2510, 0xC810}, // SEQ_DATA_PORT
+{0x2510, 0x0210}, // SEQ_DATA_PORT
+{0x2510, 0x1611}, // SEQ_DATA_PORT
+{0x2510, 0x8111}, // SEQ_DATA_PORT
+{0x2510, 0x8910}, // SEQ_DATA_PORT
+{0x2510, 0x5612}, // SEQ_DATA_PORT
+{0x2510, 0x1009}, // SEQ_DATA_PORT
+{0x2510, 0x020D}, // SEQ_DATA_PORT
+{0x2510, 0x0905}, // SEQ_DATA_PORT
+{0x2510, 0x1588}, // SEQ_DATA_PORT
+{0x2510, 0x1388}, // SEQ_DATA_PORT
+{0x2510, 0x0938}, // SEQ_DATA_PORT
+{0x2510, 0x1199}, // SEQ_DATA_PORT
+{0x2510, 0x11D9}, // SEQ_DATA_PORT
+{0x2510, 0x091E}, // SEQ_DATA_PORT
+{0x2510, 0x1214}, // SEQ_DATA_PORT
+{0x2510, 0x10D6}, // SEQ_DATA_PORT
+{0x2510, 0x0901}, // 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, 0x0901}, // SEQ_DATA_PORT
+{0x2510, 0x1441}, // SEQ_DATA_PORT
+{0x2510, 0x0904}, // SEQ_DATA_PORT
+{0x2510, 0x1056}, // SEQ_DATA_PORT
+{0x2510, 0x0811}, // SEQ_DATA_PORT
+{0x2510, 0xDB09}, // SEQ_DATA_PORT
+{0x2510, 0x0311}, // SEQ_DATA_PORT
+{0x2510, 0xFB11}, // SEQ_DATA_PORT
+{0x2510, 0xBB12}, // SEQ_DATA_PORT
+{0x2510, 0x1A12}, // SEQ_DATA_PORT
+{0x2510, 0x1008}, // SEQ_DATA_PORT
+{0x2510, 0x1250}, // SEQ_DATA_PORT
+{0x2510, 0x1076}, // SEQ_DATA_PORT
+{0x2510, 0x10E6}, // SEQ_DATA_PORT
+{0x2510, 0x1461}, // SEQ_DATA_PORT
+{0x2510, 0x0906}, // SEQ_DATA_PORT
+{0x2510, 0x1240}, // SEQ_DATA_PORT
+{0x2510, 0x1260}, // SEQ_DATA_PORT
+{0x2510, 0x091C}, // SEQ_DATA_PORT
+{0x2510, 0x1460}, // SEQ_DATA_PORT
+{0x2510, 0x090C}, // SEQ_DATA_PORT
+{0x2510, 0x0B09}, // SEQ_DATA_PORT
+{0x2510, 0x0515}, // SEQ_DATA_PORT
+{0x2510, 0xC813}, // SEQ_DATA_PORT
+{0x2510, 0xC808}, // SEQ_DATA_PORT
+{0x2510, 0x1066}, // SEQ_DATA_PORT
+{0x2510, 0x090B}, // SEQ_DATA_PORT
+{0x2510, 0x1588}, // SEQ_DATA_PORT
+{0x2510, 0x1388}, // SEQ_DATA_PORT
+{0x2510, 0x0913}, // SEQ_DATA_PORT
+{0x2510, 0x0C14}, // SEQ_DATA_PORT
+{0x2510, 0x4009}, // SEQ_DATA_PORT
+{0x2510, 0x0310}, // SEQ_DATA_PORT
+{0x2510, 0xE611}, // SEQ_DATA_PORT
+{0x2510, 0xFB12}, // SEQ_DATA_PORT
+{0x2510, 0x6212}, // SEQ_DATA_PORT
+{0x2510, 0x6011}, // SEQ_DATA_PORT
+{0x2510, 0xFF11}, // SEQ_DATA_PORT
+{0x2510, 0xFB14}, // SEQ_DATA_PORT
+{0x2510, 0x4109}, // SEQ_DATA_PORT
+{0x2510, 0x0210}, // SEQ_DATA_PORT
+{0x2510, 0x6609}, // SEQ_DATA_PORT
+{0x2510, 0x1211}, // SEQ_DATA_PORT
+{0x2510, 0xBB12}, // SEQ_DATA_PORT
+{0x2510, 0x6312}, // SEQ_DATA_PORT
+{0x2510, 0x6014}, // SEQ_DATA_PORT
+{0x2510, 0x0015}, // SEQ_DATA_PORT
+{0x2510, 0x1811}, // SEQ_DATA_PORT
+{0x2510, 0xB812}, // SEQ_DATA_PORT
+{0x2510, 0xA012}, // SEQ_DATA_PORT
+{0x2510, 0x0010}, // SEQ_DATA_PORT
+{0x2510, 0x2610}, // SEQ_DATA_PORT
+{0x2510, 0x0013}, // SEQ_DATA_PORT
+{0x2510, 0x0011}, // SEQ_DATA_PORT
+{0x2510, 0x8030}, // SEQ_DATA_PORT
+{0x2510, 0x5342}, // SEQ_DATA_PORT
+{0x2510, 0x1100}, // SEQ_DATA_PORT
+{0x2510, 0x1002}, // SEQ_DATA_PORT
+{0x2510, 0x1016}, // SEQ_DATA_PORT
+{0x2510, 0x1101}, // SEQ_DATA_PORT
+{0x2510, 0x1109}, // SEQ_DATA_PORT
+{0x2510, 0x1056}, // SEQ_DATA_PORT
+{0x2510, 0x1210}, // SEQ_DATA_PORT
+{0x2510, 0x0D09}, // SEQ_DATA_PORT
+{0x2510, 0x0614}, // SEQ_DATA_PORT
+{0x2510, 0x4009}, // SEQ_DATA_PORT
+{0x2510, 0x0214}, // SEQ_DATA_PORT
+{0x2510, 0x6009}, // SEQ_DATA_PORT
+{0x2510, 0x0615}, // SEQ_DATA_PORT
+{0x2510, 0x4C13}, // SEQ_DATA_PORT
+{0x2510, 0x0C09}, // SEQ_DATA_PORT
+{0x2510, 0x0713}, // SEQ_DATA_PORT
+{0x2510, 0x4C09}, // SEQ_DATA_PORT
+{0x2510, 0x0715}, // SEQ_DATA_PORT
+{0x2510, 0xCC09}, // SEQ_DATA_PORT
+{0x2510, 0x0211}, // SEQ_DATA_PORT
+{0x2510, 0x4908}, // SEQ_DATA_PORT
+{0x2510, 0x1461}, // SEQ_DATA_PORT
+{0x2510, 0x1460}, // SEQ_DATA_PORT
+{0x2510, 0x0903}, // SEQ_DATA_PORT
+{0x2510, 0x1588}, // SEQ_DATA_PORT
+{0x2510, 0x1308}, // SEQ_DATA_PORT
+{0x2510, 0x0905}, // SEQ_DATA_PORT
+{0x2510, 0x1388}, // SEQ_DATA_PORT
+{0x2510, 0x0913}, // SEQ_DATA_PORT
+{0x2510, 0x1159}, // SEQ_DATA_PORT
+{0x2510, 0x090B}, // SEQ_DATA_PORT
+{0x2510, 0x1214}, // SEQ_DATA_PORT
+{0x2510, 0x0901}, // SEQ_DATA_PORT
+{0x2510, 0x1210}, // SEQ_DATA_PORT
+{0x2510, 0x10D6}, // SEQ_DATA_PORT
+{0x2510, 0x1212}, // SEQ_DATA_PORT
+{0x2510, 0x1210}, // SEQ_DATA_PORT
+{0x2510, 0x115D}, // SEQ_DATA_PORT
+{0x2510, 0x1159}, // SEQ_DATA_PORT
+{0x2510, 0x1056}, // SEQ_DATA_PORT
+{0x2510, 0x0903}, // SEQ_DATA_PORT
+{0x2510, 0x115B}, // SEQ_DATA_PORT
+{0x2510, 0x0913}, // SEQ_DATA_PORT
+{0x2510, 0x111B}, // SEQ_DATA_PORT
+{0x2510, 0x113B}, // SEQ_DATA_PORT
+{0x2510, 0x121A}, // SEQ_DATA_PORT
+{0x2510, 0x1210}, // SEQ_DATA_PORT
+{0x2510, 0x0901}, // SEQ_DATA_PORT
+{0x2510, 0x1250}, // SEQ_DATA_PORT
+{0x2510, 0x10F6}, // SEQ_DATA_PORT
+{0x2510, 0x10E6}, // SEQ_DATA_PORT
+{0x2510, 0x0903}, // SEQ_DATA_PORT
+{0x2510, 0x15AB}, // SEQ_DATA_PORT
+{0x2510, 0x13AB}, // SEQ_DATA_PORT
+{0x2510, 0x1240}, // SEQ_DATA_PORT
+{0x2510, 0x1260}, // SEQ_DATA_PORT
+{0x2510, 0x0964}, // SEQ_DATA_PORT
+{0x2510, 0x1588}, // SEQ_DATA_PORT
+{0x2510, 0x0903}, // SEQ_DATA_PORT
+{0x2510, 0x0B08}, // SEQ_DATA_PORT
+{0x2510, 0x0813}, // SEQ_DATA_PORT
+{0x2510, 0x8809}, // SEQ_DATA_PORT
+{0x2510, 0x0715}, // SEQ_DATA_PORT
+{0x2510, 0x8D13}, // SEQ_DATA_PORT
+{0x2510, 0x8D09}, // SEQ_DATA_PORT
+{0x2510, 0x0D15}, // SEQ_DATA_PORT
+{0x2510, 0x8813}, // SEQ_DATA_PORT
+{0x2510, 0x8809}, // SEQ_DATA_PORT
+{0x2510, 0x0310}, // SEQ_DATA_PORT
+{0x2510, 0x6609}, // SEQ_DATA_PORT
+{0x2510, 0x030C}, // SEQ_DATA_PORT
+{0x2510, 0x0914}, // SEQ_DATA_PORT
+{0x2510, 0x10E6}, // SEQ_DATA_PORT
+{0x2510, 0x1262}, // SEQ_DATA_PORT
+{0x2510, 0x1260}, // SEQ_DATA_PORT
+{0x2510, 0x113F}, // SEQ_DATA_PORT
+{0x2510, 0x113B}, // SEQ_DATA_PORT
+{0x2510, 0x1066}, // SEQ_DATA_PORT
+{0x2510, 0x117B}, // SEQ_DATA_PORT
+{0x2510, 0x0927}, // SEQ_DATA_PORT
+{0x2510, 0x113B}, // SEQ_DATA_PORT
+{0x2510, 0x1263}, // SEQ_DATA_PORT
+{0x2510, 0x1260}, // SEQ_DATA_PORT
+{0x2510, 0x1400}, // SEQ_DATA_PORT
+{0x2510, 0x155A}, // SEQ_DATA_PORT
+{0x2510, 0x1138}, // 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, 0x437A}, // SEQ_DATA_PORT
+{0x2510, 0x0605}, // SEQ_DATA_PORT
+{0x2510, 0x0807}, // SEQ_DATA_PORT
+{0x2510, 0x4137}, // SEQ_DATA_PORT
+{0x2510, 0x502C}, // SEQ_DATA_PORT
+{0x2510, 0x2CFE}, // SEQ_DATA_PORT
+{0x2510, 0x16FE}, // SEQ_DATA_PORT
+{0x2510, 0x0C2C}, // SEQ_DATA_PORT
+{0x1008, 0x0338}, // FINE_INTEGRATION_TIME_MIN
+{0x100C, 0x051B}, // FINE_INTEGRATION_TIME2_MIN
+{0x100E, 0x06FE}, // FINE_INTEGRATION_TIME3_MIN
+{0x1010, 0x0155}, // FINE_INTEGRATION_TIME4_MIN
+{0x3230, 0x02D6}, // FINE_CORRECTION
+{0x3232, 0x04B9}, // FINE_CORRECTION2
+{0x3234, 0x069C}, // FINE_CORRECTION3
+{0x3236, 0x00F3}, // FINE_CORRECTION4
+{0x32E6, 0x00DA}, // RESERVED_MFR_32E6
+{0x350C, 0x035F}, // 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
+{0x302A, 0x0008}, // VT_PIX_CLK_DIV
+{0x302C, 0x0001}, // VT_SYS_CLK_DIV
+{0x302E, 0x0002}, // PRE_PLL_CLK_DIV
+{0x3030, 0x0034}, // PLL_MULTIPLIER
+{0x3036, 0x0008}, // OP_WORD_CLK_DIV
+{0x3038, 0x0001}, // OP_SYS_CLK_DIV
+{0x31DC, 0x0030}, // RESERVED_MFR_31DC
+{0x30A2, 0x0001}, // X_ODD_INC_
+{0x30A6, 0x0001}, // Y_ODD_INC_
+{0x3040, 0x0000}, // READ_MODE
+{0x3044, 0x0400}, // DARK_CONTROL
+{0x3180, 0x0080}, // RESERVED_MFR_3180
+{0x33E4, 0x0080}, // RESERVED_MFR_33E4
+{0x33E0, 0x0880}, // TEST_ASIL_ROWS
+#ifdef AR0143_EMBEDDED_LINE
+{0x3064, 0x1982}, // SMIA_TEST
+#else
+{0x3064, 0x1802}, // SMIA_TEST
+#endif
+{0x3004, 0x0000}, // X_ADDR_START_
+{0x3008, 0x053F}, // X_ADDR_END_
+{0x3002, 0x0000}, // Y_ADDR_START_
+{0x3006, 0x03C7}, // Y_ADDR_END_
+{0x3400, 0x0010}, // RESERVED_MFR_3400
+{0x3402, 0x0A80}, // X_OUTPUT_CONTROL
+{0x3404, 0x0790}, // Y_OUTPUT_CONTROL
+{0x3082, 0x0008}, // OPERATION_MODE_CTRL
+{0x30BA, 0x01E2}, // DIGITAL_CTRL
+{0x300C, 0x09A0}, // LINE_LENGTH_PCK_
+{0x300A, 0x041E}, // FRAME_LENGTH_LINES_
+{0x3042, 0x0000}, // EXTRA_DELAY
+{0x3238, 0x0333}, // EXPOSURE_RATIO
+{0x3012, 0x036E}, // COARSE_INTEGRATION_TIME_
+{0x3014, 0x0A7A}, // FINE_INTEGRATION_TIME_
+{0x321E, 0x0A7A}, // FINE_INTEGRATION_TIME2
+{0x3222, 0x0A7A}, // FINE_INTEGRATION_TIME3
+{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA
+{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA
+{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA
+{0x32EC, 0x72A1}, // RESERVED_MFR_32EC
+{0x32EC, 0x72A1}, // RESERVED_MFR_32EC
+{0x32EC, 0x72A1}, // RESERVED_MFR_32EC
+{0x32EC, 0x72A1}, // RESERVED_MFR_32EC
+{0x32EC, 0x72A1}, // RESERVED_MFR_32EC
+{0x32EC, 0x72A1}, // RESERVED_MFR_32EC
+{0x3C06, 0x083C}, // RESERVED_MFR_3C06
+{0x3C08, 0x0100}, // RESERVED_MFR_3C08
+{0x31D0, 0x0001}, // COMPANDING
+{0x31AC, 0x1410}, // DATA_FORMAT_BITS: 2xRAW8
+{0x301A, 0x1098}, // RESET_REGISTER
+{0x301A, 0x1018}, // RESET_REGISTER
+{0x301A, 0x0018}, // RESET_REGISTER
+{0x31AE, 0x0204}, // SERIAL_FORMAT
+{0x3342, 0x122A}, // MIPI_F1_PDT_EDT
+{0x3346, 0x122A}, // MIPI_F2_PDT_EDT
+{0x334A, 0x122A}, // MIPI_F3_PDT_EDT
+{0x334E, 0x122A}, // MIPI_F4_PDT_EDT
+{0x3344, 0x0011}, // MIPI_F1_VDT_VC
+{0x3348, 0x0111}, // MIPI_F2_VDT_VC
+{0x334C, 0x0211}, // MIPI_F3_VDT_VC
+{0x3350, 0x0311}, // MIPI_F4_VDT_VC
+{0x31B0, 0x0061}, // FRAME_PREAMBLE
+{0x31B2, 0x004C}, // LINE_PREAMBLE
+{0x31B4, 0x51C8}, // RESERVED_MFR_31B4
+{0x31B6, 0x424B}, // RESERVED_MFR_31B6
+{0x31B8, 0x40CF}, // RESERVED_MFR_31B8
+{0x31BA, 0x028B}, // RESERVED_MFR_31BA
+{0x31BC, 0x0D09}, // RESERVED_MFR_31BC
+// end demo init
+// start reg wizard WIDTHxHEIGHT@30fps
+#define NEW_TBL
+#ifdef NEW_TBL
+/* PCLK=27Mhz/0x5 *0x5d /1/0xa - MAXIM serializers */
+{0x302A, 0x000A}, // VT_PIX_CLK_DIV
+{0x302C, 0x0001}, // VT_SYS_CLK_DIV
+{0x302E, 0x0005}, // PRE_PLL_CLK_DIV
+{0x3030, 0x005d}, // PLL_MULTIPLIER
+{0x3036, 0x000A}, // OP_WORD_CLK_DIV
+{0x3038, 0x0001}, // OP_SYS_CLK_DIV
+#else
+/* PCLK=27Mhz/0x9 *134 /1/8 - MAXIM serializers */
+{0x302A, 0x0008}, // VT_PIX_CLK_DIV
+{0x302C, 0x0001}, // VT_SYS_CLK_DIV
+{0x302E, 0x0009}, // PRE_PLL_CLK_DIV
+{0x3030, 134}, // PLL_MULTIPLIER
+{0x3036, 0x0008}, // OP_WORD_CLK_DIV
+{0x3038, 0x0001}, // OP_SYS_CLK_DIV
+#endif
+{0x31B0, 0x0056}, // FRAME_PREAMBLE
+{0x31B2, 0x0045}, // LINE_PREAMBLE
+{0x3004, AR0143_X_START}, // X_ADDR_START_
+{0x3008, AR0143_X_END}, // X_ADDR_END_
+{0x3002, AR0143_Y_START}, // Y_ADDR_START_
+{0x3006, AR0143_Y_END}, // Y_ADDR_END_
+{0x3402, 0x0000 | AR0143_MAX_WIDTH}, // X_OUTPUT_CONTROL
+{0x3404, 0x0000 | AR0143_MAX_HEIGHT}, // Y_OUTPUT_CONTROL
+{0x31B4, 0x2207}, // RESERVED_MFR_31B4
+{0x31B6, 0x220B}, // RESERVED_MFR_31B6
+{0x31B8, 0x404B}, // RESERVED_MFR_31B8
+{0x31BA, 0x020A}, // RESERVED_MFR_31BA
+{0x31BC, 0x0C08}, // RESERVED_MFR_31BC
+{0x3040, 0x0000}, // READ_MODE
+{0x30BA, 0x01E2}, // DIGITAL_CTRL
+{0x3082, 0x0008}, // OPERATION_MODE_CTRL
+{0x3044, 0x0400}, // DARK_CONTROL
+{0x33E0, 0x0880}, // TEST_ASIL_ROWS
+{0x3180, 0x0080}, // RESERVED_MFR_3180
+{0x33E4, 0x0080}, // RESERVED_MFR_33E4
+{0x3032, 0x0000}, // RESERVED_MFR_3032
+{0x3400, 0x0010}, // RESERVED_MFR_3400
+{0x31D0, 0x0001}, // COMPANDING
+//{0x31AC, 0x1410}, // DATA_FORMAT_BITS: 2xRAW8
+{0x31AC, 0x140C}, // DATA_FORMAT_BITS: RAW12
+{0x3C08, 0x0100}, // RESERVED_MFR_3C08
+{0x3C0C, 0x0518}, // DELAY_BUFFER_LLPCK_RD_WR_OVERLAP
+#ifdef NEW_TBL
+//{0x300A, 0x0438}, // FRAME_LENGTH_LINES_
+//{0x300C, 0x060e}, // LINE_LENGTH_PCK_
+{0x300A, AR0143_SENSOR_HEIGHT + 157}, // FRAME_LENGTH_LINES_
+{0x300C, AR0143_SENSOR_WIDTH + 144}, // LINE_LENGTH_PCK_
+#else
+{0x300A, 0x048A}, // FRAME_LENGTH_LINES_
+{0x300C, 0x05BA}, // LINE_LENGTH_PCK_
+#endif
+{0x3018, 0x0000}, // FINE_INTEGRATION_TIME_CB
+{0x1008, 0x0338}, // FINE_INTEGRATION_TIME_MIN
+{0x100C, 0x051B}, // FINE_INTEGRATION_TIME2_MIN
+{0x100E, 0x06FE}, // FINE_INTEGRATION_TIME3_MIN
+{0x1010, 0x0155}, // FINE_INTEGRATION_TIME4_MIN
+#ifdef NEW_TBL
+{0x3012, 0x0206}, // COARSE_INTEGRATION_TIME_
+{0x3014, 0x06e8}, // FINE_INTEGRATION_TIME_
+{0x321E, 0x06E8}, // FINE_INTEGRATION_TIME2
+{0x3222, 0x06E8}, // FINE_INTEGRATION_TIME3
+#else
+{0x3012, 0x0332}, // COARSE_INTEGRATION_TIME_
+{0x3014, 0x0694}, // FINE_INTEGRATION_TIME_
+{0x321E, 0x0694}, // FINE_INTEGRATION_TIME2
+{0x3222, 0x0694}, // FINE_INTEGRATION_TIME3
+#endif
+{0x32EC, 0x72A0}, // RESERVED_MFR_32EC
+{0x31C6, 0x0000}, // HISPI_CONTROL
+#ifdef NEW_TBL
+{0x3082, 0x0000}, // OPERATION_MODE_CTRL: 1 exposure
+{0x3238, 0x0222}, // auto exposure time ratio - Fixed!
+#else
+// patch start
+//{0x30BA, 0x01E2}, // DIGITAL_CTRL: 3 exposures
+//{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3 exposures
+{0x3082, 0x0000}, // OPERATION_MODE_CTRL: 1 exposure
+//{0x30fe, 0x07ff}, // NOISE PEDESTAL
+//{0x305e, 0x3333}, // DIGITAL COLOR GLOBAL GAIN
+{0x3308, 0x200}, // DIGITAL GLOBAL GAIN: max=0x7ff
+//{0x3060, 0x7777}, // ANALOG COLOR GAIN
+{0x3366, 0x0666}, // ANALOG_GAIN - Fixed!
+//{0x3238, 0x8000}, // manual exposure time
+{0x3238, 0x0222}, // auto exposure time ratio - Fixed!
+{0x3012, 0x0300}, // T1 exposure - max=0x400
+//{0x3212, 0x0004}, // T2 exposure - not used in auto
+//{0x3216, 0x0001}, // T3 exposure - not used in auto
+#endif
+// patch eof
+{0x301A, 0x01d8}, // RESET_REGISTER
+// enable trigger
+{0x340A, 0x0070}, // GPIO_CONTROL1: GPIO3 is trigger
+{0x340C, 0x0080}, // GPIO_CONTROL2: GPIO3 is trigger
+{0x30CE, 0x0120}, // TRIGGER_MODE
+//{0x30DC, 0x0120}, // TRIGGER_DELAY
+// end reg wizard WIDTHxHEIGHT@30fps
+};
diff --git a/drivers/media/i2c/soc_camera/ar0220.c b/drivers/media/i2c/soc_camera/ar0220.c
index 8813522..b1ca101 100644
--- a/drivers/media/i2c/soc_camera/ar0220.c
+++ b/drivers/media/i2c/soc_camera/ar0220.c
@@ -19,7 +19,6 @@
 #include <media/soc_camera.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
-#include <media/v4l2-fwnode.h>
 
 #include "ar0220.h"
 
@@ -29,7 +28,7 @@
 #define AR0220_PID		0x3000
 #define AR0220_VERSION_REG	0x0C54
 
-#define AR0220_MEDIA_BUS_FMT	MEDIA_BUS_FMT_SBGGR8_1X8
+#define AR0220_MEDIA_BUS_FMT	MEDIA_BUS_FMT_SGRBG14_1X14
 
 struct ar0220_priv {
 	struct v4l2_subdev		sd;
@@ -47,7 +46,6 @@ struct ar0220_priv {
 	int				port;
 	int				gpio_resetb;
 	int				gpio_fsin;
-
 };
 
 static inline struct ar0220_priv *to_ar0220(const struct i2c_client *client)
@@ -319,6 +317,7 @@ static int ar0220_initialize(struct i2c_client *client)
 	u16 val = 0;
 	u16 pid = 0;
 	int ret = 0;
+	int tmp_addr;
 
 	/* check and show model ID */
 	reg16_read16(client, AR0220_PID, &pid);
@@ -329,6 +328,16 @@ static int ar0220_initialize(struct i2c_client *client)
 		goto err;
 	}
 
+	/* setup XCLK */
+	tmp_addr = client->addr;
+	if (priv->ti9x4_addr) {
+		/* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=27MHz: CLKDIV=2, M=15, N=251: 22.5792*160/8*15/251=26.987MHz=CLK_OUT */
+		client->addr = priv->ti9x3_addr;			/* Serializer I2C address */
+		reg8_write(client, 0x06, 0x6f);				/* Set CLKDIV and M */
+		reg8_write(client, 0x07, 0xfb);				/* Set N */
+	}
+	client->addr = tmp_addr;
+
 	/* Program wizard registers */
 	ar0220_set_regs(client, ar0220_regs_wizard, ARRAY_SIZE(ar0220_regs_wizard));
 
@@ -386,11 +395,8 @@ static int ar0220_parse_dt(struct device_node *np, struct ar0220_priv *priv)
 		usleep_range(2000, 2500);				/* wait 2ms */
 		reg8_write(client, 0x65, tmp_addr << 1);		/* Sensor translated I2C address */
 		reg8_write(client, 0x5d, AR0220_I2C_ADDR << 1);		/* Sensor native I2C address */
-//		reg8_write(client, 0x6e, 0xa9);				/* GPIO0 - reset, GPIO1 - fsin */
 
-		client->addr = priv->ti9x3_addr;			/* Serializer I2C address */
-		reg8_write(client, 0x06, 0x41);				/* Set clock divider M */
-		reg8_write(client, 0x07, 0x25);				/* Set clock divider N = 27MHz */
+//		reg8_write(client, 0x6e, 0xa9);				/* GPIO0 - reset, GPIO1 - fsin */
 	}
 	client->addr = tmp_addr;
 
diff --git a/drivers/media/i2c/soc_camera/ar0220.h b/drivers/media/i2c/soc_camera/ar0220.h
index 8ef557d..205c351 100644
--- a/drivers/media/i2c/soc_camera/ar0220.h
+++ b/drivers/media/i2c/soc_camera/ar0220.h
@@ -12,7 +12,7 @@
 //#define AR0220_DISPLAY_PATTERN_FIXED
 //#define AR0220_DISPLAY_PATTERN_COLOR_BAR
 
-#define AR0220_MAX_WIDTH	3648 // (1820*2=3640) <- must be multiple of 16 - requred by R-CAR VIN
+#define AR0220_MAX_WIDTH	1820
 #define AR0220_MAX_HEIGHT	944
 
 #define AR0220_DELAY		0xffff
@@ -25,14 +25,14 @@ struct ar0220_reg {
 static const struct ar0220_reg ar0220_regs_wizard[] = {
 {0x301A, 0x0018}, // RESET_REGISTER
 {AR0220_DELAY, 500}, // Wait 500ms
-{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)
+{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 AR0220_DISPLAY_PATTERN_FIXED
 {0x3070, 0x0001},
 #endif
diff --git a/drivers/media/i2c/soc_camera/ar0231.c b/drivers/media/i2c/soc_camera/ar0231.c
new file mode 100644
index 0000000..176e1bf
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ar0231.c
@@ -0,0 +1,580 @@
+/*
+ * ON Semiconductor AR0231 sensor camera driver
+ *
+ * Copyright (C) 2018 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 "ar0231.h"
+
+#define AR0231_I2C_ADDR		0x10
+
+#define AR0231_PID		0x3000
+#define AR0231_VERSION_REG	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				max9286_addr;
+	int				max9271_addr;
+	int				port;
+	int				gpio_resetb;
+	int				gpio_fsin;
+};
+
+static inline struct ar0231_priv *to_ar0231(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct ar0231_priv, sd);
+}
+
+static void ar0231_s_port(struct i2c_client *client, int fwd_en)
+{
+	struct ar0231_priv *priv = to_ar0231(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 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 int ar0231_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	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_VERSION_REG >> 8;
+	edid->edid[9] = AR0231_VERSION_REG & 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;
+
+	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;
+	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 ar0231_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 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 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 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;
+	u16 pid = 0;
+	int ret = 0;
+
+	/* check and show model ID */
+	reg16_read16(client, AR0231_PID, &pid);
+
+	if (pid != AR0231_VERSION_REG) {
+		dev_dbg(&client->dev, "Product ID error %x\n", pid);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	/* Program wizard registers */
+	ar0231_set_regs(client, ar0231_regs_wizard_rev4, ARRAY_SIZE(ar0231_regs_wizard_rev4));
+
+	/* Enable stream */
+	reg16_read16(client, 0x301a, &val);	// read inital reset_register value
+	val |= (1 << 2);			// Set streamOn bit
+	reg16_write16(client, 0x301a, val);	// Start Streaming
+
+	/* Read OTP IDs */
+	ar0231_otp_id_read(client);
+
+	dev_info(&client->dev, "ar0231 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n",
+		 pid, AR0231_MAX_WIDTH, AR0231_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
+err:
+	ar0231_s_port(client, 0);
+	return ret;
+}
+
+static int ar0231_parse_dt(struct device_node *np, struct ar0231_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;
+	}
+
+	of_node_put(endpoint);
+
+	if (!priv->max9286_addr) {
+		dev_err(&client->dev, "deserializer does not present\n");
+		return -EINVAL;
+	}
+
+	ar0231_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, AR0231_I2C_ADDR << 1);		/* Sensor native I2C address */
+		usleep_range(2000, 2500);				/* wait 2ms */
+	};
+	client->addr = tmp_addr;
+
+	mdelay(10);
+
+	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);
+#ifdef CONFIG_SOC_CAMERA_AR0231
+	v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
+		client->addr, client->adapter->name);
+#endif
+	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;
+}
+
+#ifdef CONFIG_SOC_CAMERA_AR0231
+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 = "aptina,ar0231", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ar0231_of_ids);
+
+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");
+#endif
diff --git a/drivers/media/i2c/soc_camera/ar0231.h b/drivers/media/i2c/soc_camera/ar0231.h
new file mode 100644
index 0000000..b63dc91
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ar0231.h
@@ -0,0 +1,34 @@
+/*
+ * ON Semiconductor AR0231 sensor camera wizard 1928x1208@30/BGGR/BT601
+ *
+ * Copyright (C) 2018 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	1928
+#define AR0231_MAX_HEIGHT	1208
+
+#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"
diff --git a/drivers/media/i2c/soc_camera/ar0231_rev4.h b/drivers/media/i2c/soc_camera/ar0231_rev4.h
new file mode 100644
index 0000000..d4614ec
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ar0231_rev4.h
@@ -0,0 +1,348 @@
+/*
+ * ON Semiconductor AR0231 sensor camera wizard 1920x1080@30/BGGR/MIPI
+ *
+ * Copyright (C) 2018 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[] = {
+{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
+{0x33E0, 0x0880}, // RESERVED_MFR_33E0
+{0x3180, 0x0080}, // RESERVED_MFR_3180
+{0x33E4, 0x0080}, // RESERVED_MFR_33E4
+
+//HDR Readout Mode Configuration
+#ifdef AR0231_EMBEDDED_LINE
+{0x3064, 0x1982}, // SMIA_TEST
+#else
+{0x3064, 0x1802}, // SMIA_TEST
+#endif
+
+#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
+
+//Row and Pixel Timing
+{0x300A, 0x5af},
+{0x300C, 0x7ba},
+
+//Exposure Settings
+{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
+{0x31AC, 0x140C}, // DATA_FORMAT_BITS
+
+//{0x301A, 0x01d8}, // RESET_REGISTER
+{0x301A, 0x01dc}, // RESET_REGISTER - stream on
+
+//{AR0231_DELAY, 100}, // Wait 100ms
+
+#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
+#endif
+
+#define NEW_TIMINGS
+#ifdef NEW_TIMINGS
+/* the sequence must be updated to use following timings, now it is a hack */
+{0x300A, AR0231_SENSOR_HEIGHT + 225}, // FRAME_LENGTH_LINES_
+{0x300C, AR0231_SENSOR_WIDTH + 120}, // LINE_LENGTH_PCK_
+{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/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c
new file mode 100644
index 0000000..6d034e2
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ar0233.c
@@ -0,0 +1,579 @@
+/*
+ * ON Semiconductor AR0233 sensor camera driver
+ *
+ * Copyright (C) 2018 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 "ar0233.h"
+
+#define AR0233_I2C_ADDR		0x10
+
+#define AR0233_PID		0x3000
+#define AR0233_VERSION_REG	0x0354
+
+#define AR0233_MEDIA_BUS_FMT	MEDIA_BUS_FMT_SGRBG12_1X12
+
+struct ar0233_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				ti9x4_addr;
+	int				ti9x3_addr;
+	int				port;
+	int				gpio_resetb;
+	int				gpio_fsin;
+};
+
+static inline struct ar0233_priv *to_ar0233(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct ar0233_priv, sd);
+}
+
+static int ar0233_set_regs(struct i2c_client *client,
+			  const struct ar0233_reg *regs, int nr_regs)
+{
+	int i;
+
+	for (i = 0; i < nr_regs; i++) {
+		if (regs[i].reg == AR0233_DELAY) {
+			mdelay(regs[i].val);
+			continue;
+		}
+
+		reg16_write16(client, regs[i].reg, regs[i].val);
+	}
+
+	return 0;
+}
+
+static int ar0233_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	return 0;
+}
+
+static int ar0233_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 ar0233_priv *priv = to_ar0233(client);
+
+	if (format->pad)
+		return -EINVAL;
+
+	mf->width = priv->rect.width;
+	mf->height = priv->rect.height;
+	mf->code = AR0233_MEDIA_BUS_FMT;
+	mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	mf->field = V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int ar0233_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 = AR0233_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 ar0233_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 = AR0233_MEDIA_BUS_FMT;
+
+	return 0;
+}
+
+static int ar0233_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ar0233_priv *priv = to_ar0233(client);
+
+	memcpy(edid->edid, priv->id, 6);
+
+	edid->edid[6] = 0xff;
+	edid->edid[7] = client->addr;
+	edid->edid[8] = AR0233_VERSION_REG >> 8;
+	edid->edid[9] = AR0233_VERSION_REG & 0xff;
+
+	return 0;
+}
+
+static int ar0233_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 ar0233_priv *priv = to_ar0233(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 > AR0233_MAX_WIDTH) ||
+	    (rect->top + rect->height > AR0233_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;
+
+	return 0;
+}
+
+static int ar0233_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 ar0233_priv *priv = to_ar0233(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 = AR0233_MAX_WIDTH;
+		sel->r.height = AR0233_MAX_HEIGHT;
+		return 0;
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		sel->r.left = 0;
+		sel->r.top = 0;
+		sel->r.width = AR0233_MAX_WIDTH;
+		sel->r.height = AR0233_MAX_HEIGHT;
+		return 0;
+	case V4L2_SEL_TGT_CROP:
+		sel->r = priv->rect;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ar0233_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 ar0233_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 ar0233_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 ar0233_core_ops = {
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = ar0233_g_register,
+	.s_register = ar0233_s_register,
+#endif
+};
+
+static int ar0233_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ar0233_priv *priv = to_ar0233(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 ar0233_ctrl_ops = {
+	.s_ctrl = ar0233_s_ctrl,
+};
+
+static struct v4l2_subdev_video_ops ar0233_video_ops = {
+	.s_stream	= ar0233_s_stream,
+	.g_mbus_config	= ar0233_g_mbus_config,
+};
+
+static const struct v4l2_subdev_pad_ops ar0233_subdev_pad_ops = {
+	.get_edid	= ar0233_get_edid,
+	.enum_mbus_code	= ar0233_enum_mbus_code,
+	.get_selection	= ar0233_get_selection,
+	.set_selection	= ar0233_set_selection,
+	.get_fmt	= ar0233_get_fmt,
+	.set_fmt	= ar0233_set_fmt,
+};
+
+static struct v4l2_subdev_ops ar0233_subdev_ops = {
+	.core	= &ar0233_core_ops,
+	.video	= &ar0233_video_ops,
+	.pad	= &ar0233_subdev_pad_ops,
+};
+
+static void ar0233_otp_id_read(struct i2c_client *client)
+{
+	struct ar0233_priv *priv = to_ar0233(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 ar0233_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 ar0233_priv *priv = to_ar0233(client);
+
+	ar0233_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_ar0233, S_IRUGO, ar0233_otp_id_show, NULL);
+
+static int ar0233_initialize(struct i2c_client *client)
+{
+	struct ar0233_priv *priv = to_ar0233(client);
+	u16 val = 0;
+	u16 pid = 0;
+	int ret = 0;
+	int tmp_addr;
+
+	/* check and show model ID */
+	reg16_read16(client, AR0233_PID, &pid);
+
+	if (pid != AR0233_VERSION_REG) {
+		dev_dbg(&client->dev, "Product ID error %x\n", pid);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	/* setup XCLK */
+	tmp_addr = client->addr;
+	if (priv->ti9x4_addr) {
+		/* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=27MHz: CLKDIV=2, M=15, N=251: 22.5792*160/8*15/251=26.987MHz=CLK_OUT */
+		client->addr = priv->ti9x3_addr;			/* Serializer I2C address */
+		reg8_write(client, 0x06, 0x6f);				/* Set CLKDIV and M */
+		reg8_write(client, 0x07, 0xfb);				/* Set N */
+		reg8_write(client, 0x0e, 0x1f);				/* Set FSIN GPIO to output */
+	}
+	client->addr = tmp_addr;
+
+	/* Program wizard registers */
+	ar0233_set_regs(client, ar0233_regs_wizard, ARRAY_SIZE(ar0233_regs_wizard));
+
+	/* Enable stream */
+	reg16_read16(client, 0x301a, &val);	// read inital reset_register value
+	val |= (1 << 2);			// Set streamOn bit
+	reg16_write16(client, 0x301a, val);	// Start Streaming
+
+	/* Read OTP IDs */
+	ar0233_otp_id_read(client);
+
+	dev_info(&client->dev, "ar0233 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n",
+		 pid, AR0233_MAX_WIDTH, AR0233_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
+err:
+	return ret;
+}
+
+static int ar0233_parse_dt(struct device_node *np, struct ar0233_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, "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->ti9x4_addr) {
+		dev_err(&client->dev, "deserializer does not present\n");
+		return -EINVAL;
+	}
+
+	/* setup I2C translator address */
+	tmp_addr = client->addr;
+	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, AR0233_I2C_ADDR << 1);		/* Sensor native I2C address */
+
+		reg8_write(client, 0x6e, 0x8a);				/* GPIO0 - fsin, GPIO1 - NC */
+	}
+	client->addr = tmp_addr;
+
+	mdelay(10);
+
+	return 0;
+}
+
+static int ar0233_probe(struct i2c_client *client,
+		       const struct i2c_device_id *did)
+{
+	struct ar0233_priv *priv;
+	int ret;
+
+	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&priv->sd, client, &ar0233_subdev_ops);
+	priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	v4l2_ctrl_handler_init(&priv->hdl, 4);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, 0, 16, 1, 7);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops,
+			  V4L2_CID_CONTRAST, 0, 16, 1, 7);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops,
+			  V4L2_CID_SATURATION, 0, 7, 1, 2);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops,
+			  V4L2_CID_HUE, 0, 23, 1, 12);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops,
+			  V4L2_CID_GAMMA, -128, 128, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops,
+			  V4L2_CID_SHARPNESS, 0, 10, 1, 3);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops,
+			  V4L2_CID_AUTOGAIN, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops,
+			  V4L2_CID_GAIN, 1, 0x7ff, 1, 0x200);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops,
+			  V4L2_CID_ANALOGUE_GAIN, 1, 0xe, 1, 0xa);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops,
+			  V4L2_CID_EXPOSURE, 1, 0x600, 1, 0x144);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops,
+			  V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ar0233_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 = ar0233_parse_dt(client->dev.of_node, priv);
+	if (ret)
+		goto cleanup;
+
+	ret = ar0233_initialize(client);
+	if (ret < 0)
+		goto cleanup;
+
+	priv->rect.left = 0;
+	priv->rect.top = 0;
+	priv->rect.width = AR0233_MAX_WIDTH;
+	priv->rect.height = AR0233_MAX_HEIGHT;
+
+	ret = v4l2_async_register_subdev(&priv->sd);
+	if (ret)
+		goto cleanup;
+
+	if (device_create_file(&client->dev, &dev_attr_otp_id_ar0233) != 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_AR0233
+	v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
+		client->addr, client->adapter->name);
+#endif
+	return ret;
+}
+
+static int ar0233_remove(struct i2c_client *client)
+{
+	struct ar0233_priv *priv = i2c_get_clientdata(client);
+
+	device_remove_file(&client->dev, &dev_attr_otp_id_ar0233);
+	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_AR0233
+static const struct i2c_device_id ar0233_id[] = {
+	{ "ar0233", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ar0233_id);
+
+static const struct of_device_id ar0233_of_ids[] = {
+	{ .compatible = "aptina,ar0233", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ar0233_of_ids);
+
+static struct i2c_driver ar0233_i2c_driver = {
+	.driver	= {
+		.name		= "ar0233",
+		.of_match_table	= ar0233_of_ids,
+	},
+	.probe		= ar0233_probe,
+	.remove		= ar0233_remove,
+	.id_table	= ar0233_id,
+};
+
+module_i2c_driver(ar0233_i2c_driver);
+
+MODULE_DESCRIPTION("SoC Camera driver for AR0233");
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/media/i2c/soc_camera/ar0233.h b/drivers/media/i2c/soc_camera/ar0233.h
new file mode 100644
index 0000000..f88e5a3
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ar0233.h
@@ -0,0 +1,409 @@
+/*
+ * ON Semiconductor AR0233 sensor camera wizard 1920x1080@30/BGGR/MIPI
+ *
+ * Copyright (C) 2018 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 AR0233_DISPLAY_PATTERN_FIXED
+//#define AR0233_DISPLAY_PATTERN_COLOR_BAR
+
+#define AR0233_MAX_WIDTH	1792 //1920
+#define AR0233_MAX_HEIGHT	1080
+
+#define AR0233_DELAY		0xffff
+
+#define AR0233_SENSOR_WIDTH	1920
+#define AR0233_SENSOR_HEIGHT	1280
+
+#define AR0233_X_START		((AR0233_SENSOR_WIDTH - AR0233_MAX_WIDTH) / 2)
+#define AR0233_Y_START		((AR0233_SENSOR_HEIGHT - AR0233_MAX_HEIGHT) / 2)
+#define AR0233_X_END		(AR0233_X_START + AR0233_MAX_WIDTH - 1)
+#define AR0233_Y_END		(AR0233_Y_START + AR0233_MAX_HEIGHT - 1)
+
+struct ar0233_reg {
+	u16	reg;
+	u16	val;
+};
+
+static const struct ar0233_reg ar0233_regs_wizard[] = {
+{0x301A, 0x0018}, // RESET_REGISTER
+{AR0233_DELAY, 500}, // Wait 500ms
+{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 AR0233_DISPLAY_PATTERN_FIXED
+{0x3070, 0x0001},
+#endif
+#ifdef AR0233_DISPLAY_PATTERN_COLOR_BAR
+{0x3070, 0x0002},
+#endif
+{AR0233_DELAY, 100}, // Wait 100ms
+
+{0x3092, 0x0C24},
+{0x337A, 0x0C80},
+{0x3520, 0x1288},
+{0x3522, 0x880C},
+{0x3524, 0x0C12},
+{0x352C, 0x1212},
+{0x354A, 0x007F},
+{0x350C, 0x0568},
+{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},
+
+{AR0233_DELAY, 200}, // Wait 200ms
+
+{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, 0x00E0},
+{0x1008, 0x036F},
+{0x100C, 0x058F},
+{0x100E, 0x07AF},
+{0x1010, 0x014F},
+{0x3230, 0x0312},
+{0x3232, 0x0532},
+{0x3234, 0x0752},
+{0x3236, 0x00F2},
+{0x3566, 0x3328},
+{0x32D0, 0x3A02},
+{0x32D2, 0x3508},
+{0x32D4, 0x3702},
+{0x32D6, 0x3C04},
+{0x32DC, 0x370A},
+{0x30B0, 0x0800},
+{0x302A, 0x0006},
+{0x302C, 0x0001},
+{0x302E, 0x0002},
+{0x3030, 0x002C},
+{0x3036, 0x000C},
+{0x3038, 0x0001},
+{0x30B0, 0x0A00},
+{0x30A2, 0x0001},
+{0x30A6, 0x0001},
+{0x3040, 0x0000},
+{0x3040, 0x0000},
+{0x3044, 0x0400},
+{0x3044, 0x0400},
+{0x3044, 0x0400},
+{0x3044, 0x0400},
+{0x3064, 0x1882},
+{0x3064, 0x1802},
+{0x3064, 0x1802},
+{0x3064, 0x1802},
+{0x33E0, 0x0C80},
+{0x33E0, 0x0C80},
+{0x3180, 0x0080},
+{0x33E4, 0x0080},
+{0x33E0, 0x0C80},
+{0x33E0, 0x0C80},
+{0x3004, AR0233_X_START}, // X_ADDR_START_
+{0x3008, AR0233_X_END}, // X_ADDR_END_
+{0x3002, AR0233_Y_START}, // Y_ADDR_START_
+{0x3006, AR0233_Y_END}, // Y_ADDR_END_
+{0x3402, 0x0000 | AR0233_MAX_WIDTH}, // X_OUTPUT_CONTROL
+{0x3404, 0x0000 | AR0233_MAX_HEIGHT}, // Y_OUTPUT_CONTROL
+{0x3032, 0x0000},
+{0x3400, 0x0010},
+#if 1
+/* disable HDR */
+{0x3082, 0x0000},
+{0x30BA, 0x11F2},
+#endif
+{AR0233_DELAY, 100}, // Wait 100ms
+
+#if 0
+{0x300A, AR0233_SENSOR_HEIGHT + 356}, // FRAME_LENGTH_LINES_
+{0x300C, AR0233_SENSOR_WIDTH + 100}, // LINE_LENGTH_PCK_
+#else
+{0x300A, AR0233_SENSOR_HEIGHT + 208}, // FRAME_LENGTH_LINES_
+{0x300C, AR0233_SENSOR_WIDTH + 300}, // LINE_LENGTH_PCK_
+#endif
+{0x3042, 0x0000},
+{0x3238, 0x0222},
+{0x3012, 0x0144},
+{0x3014, AR0233_SENSOR_WIDTH + 100},
+{0x321E, AR0233_SENSOR_WIDTH + 100},
+{0x3222, AR0233_SENSOR_WIDTH + 100},
+{0x30B0, 0x0B00},
+{0x32EA, 0x3C0E},
+{0x32EA, 0x3C0E},
+{0x32EA, 0x3C0E},
+{0x32EC, 0x72A1},
+{0x32EC, 0x72A1},
+{0x32EC, 0x72A1},
+{0x32EC, 0x72A1},
+{0x32EC, 0x72A1},
+{0x32EC, 0x72A1},
+{0x31D0, 0x0001}, // COMPANDING
+{0x31AE, 0x0004},
+{0x31AE, 0x0304},
+{0x31AC, 0x140C}, // DATA_FORMAT_BITS: RAW12
+{0x301A, 0x1098},
+{0x301A, 0x1018},
+{0x301A, 0x1018},
+{0x31AE, 0x0204},
+{0x3342, 0x122C},
+{0x3346, 0x122C},
+{0x334A, 0x122C},
+{0x334E, 0x122C},
+{0x3344, 0x0011},
+{0x3348, 0x0111},
+{0x334C, 0x0211},
+{0x3350, 0x0311},
+{0x31B0, 0x0049},
+{0x31B2, 0x0033},
+{0x31B4, 0x2185},
+{0x31B6, 0x1146},
+{0x31B8, 0x3047},
+{0x31BA, 0x0186},
+{0x31BC, 0x0805},
+#if 1
+/* 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
+#endif
+{0x3366, 0x0aaa}, // ANALOG_GAIN
+{0x301A, 0x011C},
+};
diff --git a/drivers/media/i2c/soc_camera/gw4200_ar014x.c b/drivers/media/i2c/soc_camera/gw4200_ar014x.c
new file mode 100644
index 0000000..2de6fe7
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/gw4200_ar014x.c
@@ -0,0 +1,592 @@
+/*
+ * ON Semiconductor GW4200-AR014X sensor camera driver
+ *
+ * Copyright (C) 2018 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 "gw4200_ar014x.h"
+
+#define GW4200_I2C_ADDR		0x6d
+
+#define GW4200_PID		0x00
+#define GW4200_VERSION_REG	0xda
+
+#define GW4200_MEDIA_BUS_FMT	MEDIA_BUS_FMT_YUYV8_2X8
+
+static void gw4200_otp_id_read(struct i2c_client *client);
+
+struct gw4200_priv {
+	struct v4l2_subdev		sd;
+	struct v4l2_ctrl_handler	hdl;
+	struct media_pad		pad;
+	struct v4l2_rect		rect;
+	int				init_complete;
+	u8				id[6];
+	int				exposure;
+	int				gain;
+	int				autogain;
+	/* serializers */
+	int				max9286_addr;
+	int				max9271_addr;
+	int				port;
+	int				gpio_resetb;
+	int				gpio_fsin;
+};
+
+static inline struct gw4200_priv *to_gw4200(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct gw4200_priv, sd);
+}
+
+static void gw4200_s_port(struct i2c_client *client, int fwd_en)
+{
+	struct gw4200_priv *priv = to_gw4200(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;
+	};
+}
+
+#if 0
+static int gw4200_set_regs(struct i2c_client *client,
+			  const struct gw4200_reg *regs, int nr_regs)
+{
+	int i;
+
+	for (i = 0; i < nr_regs; i++) {
+		if (regs[i].reg == GW4200_DELAY) {
+			mdelay(regs[i].val);
+			continue;
+		}
+
+		reg16_write16(client, regs[i].reg, regs[i].val);
+	}
+
+	return 0;
+}
+#endif
+
+static u16 gw4200_ar014x_read(struct i2c_client *client, u16 addr)
+{
+	u16 reg_val = 0;
+
+	reg16_write16(client, 0x0040, 0x8d00);
+	usleep_range(100, 150); /* wait 100 us */
+	reg16_write16(client, 0xfc00, addr);
+	reg16_write16(client, 0xfc02, 0x0200); /* 2 bytes */
+	reg16_write16(client, 0x0040, 0x8d05);
+	usleep_range(100, 150); /* wait 100 us */
+	reg16_write16(client, 0x0040, 0x8d08);
+	usleep_range(100, 150); /* wait 100 us */
+	reg16_read16(client, 0xfc00, &reg_val);
+	reg16_write16(client, 0x0040, 0x8d02);
+	usleep_range(100, 150); /* wait 100 us */
+
+	return reg_val;
+}
+
+static void gw4200_ar014x_write(struct i2c_client *client, u16 addr, u16 val)
+{
+	reg16_write16(client, 0x0040, 0x8d00);
+	usleep_range(100, 150); /* wait 100 us */
+	reg16_write16(client, 0xfc00, addr);
+	reg16_write16(client, 0xfc02, 0x0200 | (val >> 8)); /* 2 bytes */
+	reg16_write16(client, 0xfc04, (val & 0xff) << 8);
+	reg16_write16(client, 0x0040, 0x8d06);
+	usleep_range(100, 150); /* wait 100 us */
+	reg16_write16(client, 0x0040, 0x8d08);
+	usleep_range(100, 150); /* wait 100 us */
+	reg16_write16(client, 0x0040, 0x8d02);
+	usleep_range(100, 150); /* wait 100 us */
+}
+
+static int gw4200_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	return 0;
+}
+
+static int gw4200_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 gw4200_priv *priv = to_gw4200(client);
+
+	if (format->pad)
+		return -EINVAL;
+
+	mf->width = priv->rect.width;
+	mf->height = priv->rect.height;
+	mf->code = GW4200_MEDIA_BUS_FMT;
+	mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	mf->field = V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int gw4200_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 = GW4200_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 gw4200_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 = GW4200_MEDIA_BUS_FMT;
+
+	return 0;
+}
+
+static int gw4200_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct gw4200_priv *priv = to_gw4200(client);
+
+	gw4200_otp_id_read(client);
+
+	memcpy(edid->edid, priv->id, 6);
+
+	edid->edid[6] = 0xff;
+	edid->edid[7] = client->addr;
+	edid->edid[8] = GW4200_VERSION_REG >> 8;
+	edid->edid[9] = GW4200_VERSION_REG & 0xff;
+
+	return 0;
+}
+
+static int gw4200_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 gw4200_priv *priv = to_gw4200(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 > GW4200_MAX_WIDTH) ||
+	    (rect->top + rect->height > GW4200_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;
+
+	return 0;
+}
+
+static int gw4200_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 gw4200_priv *priv = to_gw4200(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 = GW4200_MAX_WIDTH;
+		sel->r.height = GW4200_MAX_HEIGHT;
+		return 0;
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		sel->r.left = 0;
+		sel->r.top = 0;
+		sel->r.width = GW4200_MAX_WIDTH;
+		sel->r.height = GW4200_MAX_HEIGHT;
+		return 0;
+	case V4L2_SEL_TGT_CROP:
+		sel->r = priv->rect;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int gw4200_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 gw4200_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 gw4200_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 gw4200_core_ops = {
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = gw4200_g_register,
+	.s_register = gw4200_s_register,
+#endif
+};
+
+static int gw4200_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct gw4200_priv *priv = to_gw4200(client);
+	int ret = -EINVAL;
+
+	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:
+	case V4L2_CID_GAIN:
+	case V4L2_CID_EXPOSURE:
+	case V4L2_CID_HFLIP:
+	case V4L2_CID_VFLIP:
+		break;
+	}
+
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops gw4200_ctrl_ops = {
+	.s_ctrl = gw4200_s_ctrl,
+};
+
+static struct v4l2_subdev_video_ops gw4200_video_ops = {
+	.s_stream	= gw4200_s_stream,
+	.g_mbus_config	= gw4200_g_mbus_config,
+};
+
+static const struct v4l2_subdev_pad_ops gw4200_subdev_pad_ops = {
+	.get_edid	= gw4200_get_edid,
+	.enum_mbus_code	= gw4200_enum_mbus_code,
+	.get_selection	= gw4200_get_selection,
+	.set_selection	= gw4200_set_selection,
+	.get_fmt	= gw4200_get_fmt,
+	.set_fmt	= gw4200_set_fmt,
+};
+
+static struct v4l2_subdev_ops gw4200_subdev_ops = {
+	.core	= &gw4200_core_ops,
+	.video	= &gw4200_video_ops,
+	.pad	= &gw4200_subdev_pad_ops,
+};
+
+static void gw4200_otp_id_read(struct i2c_client *client)
+{
+	struct gw4200_priv *priv = to_gw4200(client);
+	int i;
+
+	/* read camera id from ar014x OTP memory */
+	gw4200_ar014x_write(client, 0x3054, 0x400);
+	gw4200_ar014x_write(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 */
+		priv->id[i]     = gw4200_ar014x_read(client, 0x3800 + i + 4) >> 8;
+		priv->id[i + 1] = gw4200_ar014x_read(client, 0x3800 + i + 4) & 0xff;
+	}
+}
+
+static ssize_t gw4200_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 gw4200_priv *priv = to_gw4200(client);
+
+	gw4200_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_gw4200, S_IRUGO, gw4200_otp_id_show, NULL);
+
+static int gw4200_initialize(struct i2c_client *client)
+{
+	struct gw4200_priv *priv = to_gw4200(client);
+	u8 pid = 0;
+	int ret = 0;
+
+	gw4200_s_port(client, 1);
+
+	/* check and show model ID */
+	reg8_read(client, GW4200_PID, &pid);
+
+	if (pid != GW4200_VERSION_REG) {
+		dev_err(&client->dev, "Product ID error %x\n", pid);
+		ret = -ENODEV;
+		goto err;
+	}
+
+#if 0
+	/* Program wizard registers */
+	gw4200_set_regs(client, gw4200_regs_wizard, ARRAY_SIZE(gw4200_regs_wizard));
+	/* Read OTP IDs */
+	gw4200_otp_id_read(client);
+#endif
+
+	dev_info(&client->dev, "gw4200 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n",
+		 pid, GW4200_MAX_WIDTH, GW4200_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
+err:
+	gw4200_s_port(client, 0);
+
+	return ret;
+}
+
+static int gw4200_parse_dt(struct device_node *np, struct gw4200_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;
+	}
+
+	of_node_put(endpoint);
+
+	if (!priv->max9286_addr) {
+		dev_err(&client->dev, "deserializer does not present for GW4200\n");
+		return -EINVAL;
+	}
+
+	gw4200_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, GW4200_I2C_ADDR << 1);		/* Sensor native I2C address */
+		usleep_range(2000, 2500);				/* wait 2ms */
+	};
+	client->addr = tmp_addr;
+
+	mdelay(10);
+
+	return 0;
+}
+
+static int gw4200_probe(struct i2c_client *client,
+		       const struct i2c_device_id *did)
+{
+	struct gw4200_priv *priv;
+	int ret;
+
+	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&priv->sd, client, &gw4200_subdev_ops);
+	priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	priv->exposure = 0x100;
+	priv->gain = 0x100;
+	priv->autogain = 1;
+	v4l2_ctrl_handler_init(&priv->hdl, 4);
+	v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, 0, 16, 1, 7);
+	v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops,
+			  V4L2_CID_CONTRAST, 0, 16, 1, 7);
+	v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops,
+			  V4L2_CID_SATURATION, 0, 7, 1, 2);
+	v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops,
+			  V4L2_CID_HUE, 0, 23, 1, 12);
+	v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops,
+			  V4L2_CID_GAMMA, -128, 128, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops,
+			  V4L2_CID_SHARPNESS, 0, 10, 1, 3);
+	v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops,
+			  V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain);
+	v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops,
+			  V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain);
+	v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops,
+			  V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure);
+	v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops,
+			  V4L2_CID_HFLIP, 0, 1, 1, 1);
+	v4l2_ctrl_new_std(&priv->hdl, &gw4200_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 = gw4200_parse_dt(client->dev.of_node, priv);
+	if (ret)
+		goto cleanup;
+
+	ret = gw4200_initialize(client);
+	if (ret < 0)
+		goto cleanup;
+
+	priv->rect.left = 0;
+	priv->rect.top = 0;
+	priv->rect.width = GW4200_MAX_WIDTH;
+	priv->rect.height = GW4200_MAX_HEIGHT;
+
+	ret = v4l2_async_register_subdev(&priv->sd);
+	if (ret)
+		goto cleanup;
+
+	if (device_create_file(&client->dev, &dev_attr_otp_id_gw4200) != 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_GW4200
+	v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
+		client->addr, client->adapter->name);
+#endif
+	return ret;
+}
+
+static int gw4200_remove(struct i2c_client *client)
+{
+	struct gw4200_priv *priv = i2c_get_clientdata(client);
+
+	device_remove_file(&client->dev, &dev_attr_otp_id_gw4200);
+	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_GW4200
+static const struct i2c_device_id gw4200_id[] = {
+	{ "gw4200", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, gw4200_id);
+
+static const struct of_device_id gw4200_of_ids[] = {
+	{ .compatible = "aptina,gw4200", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, gw4200_of_ids);
+
+static struct i2c_driver gw4200_i2c_driver = {
+	.driver	= {
+		.name		= "gw4200",
+		.of_match_table	= gw4200_of_ids,
+	},
+	.probe		= gw4200_probe,
+	.remove		= gw4200_remove,
+	.id_table	= gw4200_id,
+};
+
+module_i2c_driver(gw4200_i2c_driver);
+
+MODULE_DESCRIPTION("SoC Camera driver for GW4200");
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/media/i2c/soc_camera/gw4200_ar014x.h b/drivers/media/i2c/soc_camera/gw4200_ar014x.h
new file mode 100644
index 0000000..003f2a6
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/gw4200_ar014x.h
@@ -0,0 +1,28 @@
+/*
+ * ON Semiconductor gw4200-ar014x sensor camera wizard 1280x720@30/UYVY/BT601/8bit
+ *
+ * Copyright (C) 2018 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 GW4200_MAX_WIDTH	1280
+#define GW4200_MAX_HEIGHT	960
+
+#define GW4200_DELAY		0xffff
+
+struct gw4200_reg {
+	u16	reg;
+	u16	val;
+};
+
+static const struct gw4200_reg gw4200_regs_wizard[] = {
+/* enable FSIN */
+{0xc88c, 0x0303},
+{0xfc00, 0x2800},
+{0x0040, 0x8100},
+{GW4200_DELAY, 100},
+};
diff --git a/drivers/media/i2c/soc_camera/imx390.c b/drivers/media/i2c/soc_camera/imx390.c
new file mode 100644
index 0000000..fc73b4b
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/imx390.c
@@ -0,0 +1,574 @@
+/*
+ * OmniVision IMX390 sensor camera driver
+ *
+ * Copyright (C) 2018 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 "imx390.h"
+
+static const int imx390_i2c_addr[] = {0x21, 0x1a};
+
+#define IMX390_PID		0x0330
+#define IMX390_VER		0x0330
+#define IMX390_VERSION_REG	0x1515
+
+#define IMX390_MEDIA_BUS_FMT	MEDIA_BUS_FMT_SRGGB12_1X12
+
+struct imx390_priv {
+	struct v4l2_subdev		sd;
+	struct v4l2_ctrl_handler	hdl;
+	struct media_pad		pad;
+	struct v4l2_rect		rect;
+	int				init_complete;
+	u8				id[6];
+	int				exposure;
+	int				gain;
+	int				autogain;
+	/* serializers */
+	int				ti9x4_addr;
+	int				ti9x3_addr;
+	int				port;
+	int				gpio_resetb;
+	int				gpio_fsin;
+};
+
+static inline struct imx390_priv *to_imx390(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct imx390_priv, sd);
+}
+
+static int imx390_set_regs(struct i2c_client *client,
+			  const struct imx390_reg *regs, int nr_regs)
+{
+	int i;
+
+	for (i = 0; i < nr_regs; i++) {
+		if (regs[i].reg == IMX390_DELAY) {
+			mdelay(regs[i].val);
+			continue;
+		}
+
+		reg16_write(client, regs[i].reg, regs[i].val);
+	}
+
+	return 0;
+}
+
+static int imx390_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	return 0;
+}
+
+static int imx390_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 imx390_priv *priv = to_imx390(client);
+
+	if (format->pad)
+		return -EINVAL;
+
+	mf->width = priv->rect.width;
+	mf->height = priv->rect.height;
+	mf->code = IMX390_MEDIA_BUS_FMT;
+	mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	mf->field = V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int imx390_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 = IMX390_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 imx390_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 = IMX390_MEDIA_BUS_FMT;
+
+	return 0;
+}
+
+static int imx390_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct imx390_priv *priv = to_imx390(client);
+
+	memcpy(edid->edid, priv->id, 6);
+
+	edid->edid[6] = 0xff;
+	edid->edid[7] = client->addr;
+	edid->edid[8] = IMX390_VERSION_REG >> 8;
+	edid->edid[9] = IMX390_VERSION_REG & 0xff;
+
+	return 0;
+}
+
+static int imx390_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 imx390_priv *priv = to_imx390(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 > IMX390_MAX_WIDTH) ||
+	    (rect->top + rect->height > IMX390_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;
+
+	return 0;
+}
+
+static int imx390_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 imx390_priv *priv = to_imx390(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 = IMX390_MAX_WIDTH;
+		sel->r.height = IMX390_MAX_HEIGHT;
+		return 0;
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		sel->r.left = 0;
+		sel->r.top = 0;
+		sel->r.width = IMX390_MAX_WIDTH;
+		sel->r.height = IMX390_MAX_HEIGHT;
+		return 0;
+	case V4L2_SEL_TGT_CROP:
+		sel->r = priv->rect;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int imx390_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 imx390_g_register(struct v4l2_subdev *sd,
+			    struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+	u8 val = 0;
+
+	ret = reg16_read(client, (u16)reg->reg, &val);
+	if (ret < 0)
+		return ret;
+
+	reg->val = val;
+	reg->size = sizeof(u8);
+
+	return 0;
+}
+
+static int imx390_s_register(struct v4l2_subdev *sd,
+			    const struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return reg16_write(client, (u16)reg->reg, (u8)reg->val);
+}
+#endif
+
+static struct v4l2_subdev_core_ops imx390_core_ops = {
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = imx390_g_register,
+	.s_register = imx390_s_register,
+#endif
+};
+
+static int imx390_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct imx390_priv *priv = to_imx390(client);
+	int ret = -EINVAL;
+	int val;
+
+	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 = 0;
+		break;
+	case V4L2_CID_ANALOGUE_GAIN:
+		/* Analog gain */
+		ret = 0;
+		break;
+	case V4L2_CID_EXPOSURE:
+		val = 0xfff - ctrl->val;
+		ret = reg16_write(client, 0x0c, val); /* LSB */
+		ret |= reg16_write(client, 0x0d, val >> 8);
+//		ret |= reg16_write(client, 0x0e, ctrl->val >> 16); /* MSB */
+		break;
+	case V4L2_CID_HFLIP:
+	case V4L2_CID_VFLIP:
+		break;
+	}
+
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops imx390_ctrl_ops = {
+	.s_ctrl = imx390_s_ctrl,
+};
+
+static struct v4l2_subdev_video_ops imx390_video_ops = {
+	.s_stream	= imx390_s_stream,
+	.g_mbus_config	= imx390_g_mbus_config,
+};
+
+static const struct v4l2_subdev_pad_ops imx390_subdev_pad_ops = {
+	.get_edid	= imx390_get_edid,
+	.enum_mbus_code	= imx390_enum_mbus_code,
+	.get_selection	= imx390_get_selection,
+	.set_selection	= imx390_set_selection,
+	.get_fmt	= imx390_get_fmt,
+	.set_fmt	= imx390_set_fmt,
+};
+
+static struct v4l2_subdev_ops imx390_subdev_ops = {
+	.core	= &imx390_core_ops,
+	.video	= &imx390_video_ops,
+	.pad	= &imx390_subdev_pad_ops,
+};
+
+static void imx390_otp_id_read(struct i2c_client *client)
+{
+	struct imx390_priv *priv = to_imx390(client);
+	int i;
+	u8 val = 0;
+
+	/* read camera id from imx390 OTP memory */
+	for (i = 0; i < 6; i++) {
+		reg16_read(client, 0x3050 + i, &val);
+		priv->id[i] = val;
+	}
+}
+
+static ssize_t imx390_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 imx390_priv *priv = to_imx390(client);
+
+	imx390_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_imx390, S_IRUGO, imx390_otp_id_show, NULL);
+
+static int imx390_initialize(struct i2c_client *client)
+{
+	struct imx390_priv *priv = to_imx390(client);
+	u8 val = 0;
+	u16 pid;
+	int ret = 0;
+	int tmp_addr;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(imx390_i2c_addr); i++) {
+		tmp_addr = client->addr;
+		if (priv->ti9x4_addr) {
+			client->addr = priv->ti9x4_addr;		/* Deserializer I2C address */
+			reg8_write(client, 0x5d, imx390_i2c_addr[i] << 1); /* Sensor native I2C address */
+			usleep_range(2000, 2500);			/* wait 2ms */
+		}
+		client->addr = tmp_addr;
+
+		/* check model ID */
+		reg16_read(client, IMX390_PID, &val);
+		pid = val;
+		reg16_read(client, IMX390_VER, &val);
+		pid = (pid << 8) | val;
+
+		if (pid == IMX390_VERSION_REG)
+			break;
+	}
+
+	if (pid != IMX390_VERSION_REG) {
+		dev_dbg(&client->dev, "Product ID error %x\n", pid);
+		ret = -ENODEV;
+		goto err;
+	}
+
+#if 0
+	/* setup XCLK */
+	tmp_addr = client->addr;
+	if (priv->ti9x4_addr) {
+		/* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=25MHz: CLKDIV=4, M=7, N=253: 22.5792*160/4*7/253=24.989MHz=CLK_OUT */
+		client->addr = priv->ti9x3_addr;			/* Serializer I2C address */
+		reg8_write(client, 0x06, 0x47);				/* Set CLKDIV and M */
+		reg8_write(client, 0x07, 0xfd);				/* Set N */
+	}
+	client->addr = tmp_addr;
+#endif
+
+	/* Read OTP IDs */
+	imx390_otp_id_read(client);
+	/* Program wizard registers */
+	imx390_set_regs(client, imx390_regs_wizard, ARRAY_SIZE(imx390_regs_wizard));
+
+	dev_info(&client->dev, "imx390 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n",
+		 pid, IMX390_MAX_WIDTH, IMX390_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
+
+err:
+	return ret;
+}
+
+static int imx390_parse_dt(struct device_node *np, struct imx390_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, "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->ti9x4_addr) {
+		dev_err(&client->dev, "deserializer does not present\n");
+		return -EINVAL;
+	}
+
+	/* setup I2C translator address */
+	tmp_addr = client->addr;
+	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, 0x6e, 0xa9);				/* GPIO0 - reset, GPIO1 - fsin */
+	}
+	client->addr = tmp_addr;
+
+	return 0;
+}
+
+static int imx390_probe(struct i2c_client *client,
+		       const struct i2c_device_id *did)
+{
+	struct imx390_priv *priv;
+	int ret;
+
+	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&priv->sd, client, &imx390_subdev_ops);
+	priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	priv->exposure = 0x100;
+	priv->gain = 0x100;
+	priv->autogain = 1;
+	v4l2_ctrl_handler_init(&priv->hdl, 4);
+	v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, 0, 16, 1, 7);
+	v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops,
+			  V4L2_CID_CONTRAST, 0, 16, 1, 7);
+	v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops,
+			  V4L2_CID_SATURATION, 0, 7, 1, 2);
+	v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops,
+			  V4L2_CID_HUE, 0, 23, 1, 12);
+	v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops,
+			  V4L2_CID_GAMMA, -128, 128, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops,
+			  V4L2_CID_SHARPNESS, 0, 10, 1, 3);
+	v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops,
+			  V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain);
+	v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops,
+			  V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain);
+	v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops,
+			  V4L2_CID_ANALOGUE_GAIN, 1, 0xe, 1, 0x7);
+	v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops,
+			  V4L2_CID_EXPOSURE, 0, 0xff0, 1, 0xfff - 0x2f2);
+	v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops,
+			  V4L2_CID_HFLIP, 0, 1, 1, 1);
+	v4l2_ctrl_new_std(&priv->hdl, &imx390_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 = imx390_parse_dt(client->dev.of_node, priv);
+	if (ret)
+		goto cleanup;
+
+	ret = imx390_initialize(client);
+	if (ret < 0)
+		goto cleanup;
+
+	priv->rect.left = 0;
+	priv->rect.top = 0;
+	priv->rect.width = IMX390_MAX_WIDTH;
+	priv->rect.height = IMX390_MAX_HEIGHT;
+
+	ret = v4l2_async_register_subdev(&priv->sd);
+	if (ret)
+		goto cleanup;
+
+	if (device_create_file(&client->dev, &dev_attr_otp_id_imx390) != 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_IMX390
+	v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
+		client->addr, client->adapter->name);
+#endif
+	return ret;
+}
+
+static int imx390_remove(struct i2c_client *client)
+{
+	struct imx390_priv *priv = i2c_get_clientdata(client);
+
+	device_remove_file(&client->dev, &dev_attr_otp_id_imx390);
+	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_IMX390
+static const struct i2c_device_id imx390_id[] = {
+	{ "imx390", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, imx390_id);
+
+static const struct of_device_id imx390_of_ids[] = {
+	{ .compatible = "sony,imx390", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, imx390_of_ids);
+
+static struct i2c_driver imx390_i2c_driver = {
+	.driver	= {
+		.name		= "imx390",
+		.of_match_table	= imx390_of_ids,
+	},
+	.probe		= imx390_probe,
+	.remove		= imx390_remove,
+	.id_table	= imx390_id,
+};
+
+module_i2c_driver(imx390_i2c_driver);
+
+MODULE_DESCRIPTION("SoC Camera driver for IMX390");
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/media/i2c/soc_camera/imx390.h b/drivers/media/i2c/soc_camera/imx390.h
new file mode 100644
index 0000000..a7189e8
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/imx390.h
@@ -0,0 +1,3818 @@
+/*
+ * OmniVision IMX390 sensor camera wizard 1920x1080@30/BGGR/MIPI
+ *
+ * Copyright (C) 2018 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 IMX390_DISPLAY_PATTERN_COLOR_BAR
+
+#define IMX390_MAX_WIDTH	1920
+#define IMX390_MAX_HEIGHT	1080
+
+#define IMX390_DELAY		0xffff
+#define IMX390_DT		0x2c /* MIPI Data Type RAW12 */
+
+struct imx390_reg {
+	u16	reg;
+	u8	val;
+};
+
+/* wizard: MIPI 1920x1080 RAW12 Linear 30fps 700Mbps */
+static const struct imx390_reg imx390_regs_wizard[] = {
+{0x000C, 0xF2},
+{0x000D, 0x02},
+{0x000E, 0x00},
+{0x0010, 0xF2},
+{0x0011, 0x02},
+{0x0012, 0x00},
+{0x0018, 0x15},
+{0x0019, 0x00},
+{0x001A, 0x0C},
+{0x001B, 0x00},
+{0x0038, 0x00},
+{0x003C, 0x00},
+{0x003D, 0x00},
+{0x003E, 0x00},
+{0x0040, 0x00},
+{0x0041, 0x00},
+{0x0042, 0x00},
+{0x0044, 0x00},
+{0x0045, 0x00},
+{0x0046, 0x00},
+{0x0048, 0x00},
+{0x0049, 0x00},
+{0x004A, 0x00},
+{0x004C, 0x00},
+{0x004D, 0x00},
+{0x004E, 0x00},
+{0x0050, 0x00},
+{0x0051, 0x00},
+{0x0052, 0x00},
+{0x0054, 0x00},
+{0x0055, 0x00},
+{0x0056, 0x00},
+{0x0058, 0x00},
+{0x0059, 0x00},
+{0x005A, 0x00},
+{0x005C, 0x00},
+{0x005D, 0x00},
+{0x005E, 0x00},
+{0x0060, 0x00},
+{0x0061, 0x00},
+{0x0062, 0x00},
+{0x0064, 0x00},
+{0x0065, 0x00},
+{0x0066, 0x00},
+{0x0068, 0x00},
+{0x0069, 0x00},
+{0x006A, 0x00},
+{0x0078, 0x00},
+{0x007C, 0x00},
+{0x007D, 0x00},
+{0x0080, 0x00},
+{0x0081, 0x00},
+{0x00F4, 0x1C},
+{0x00F5, 0xF8},
+{0x00F6, 0x01},
+{0x00F8, 0x03},
+{0x00F9, 0x00}, // non-HDR
+//{0x00F9, 0x01}, // HDR
+{0x00FA, 0x00},
+{0x00FB, 0x00},
+{0x0114, 0x00},
+{0x0115, 0x01},
+{0x0118, 0x20},
+{0x0119, 0x03},
+{0x011A, 0x00},
+{0x011B, 0x41},
+{0x011C, 0x80},
+{0x011D, 0x00},
+{0x0120, 0x20},
+{0x0121, 0x00},
+{0x0122, 0x00},
+{0x0123, 0x44},
+{0x0124, 0x00},
+{0x0125, 0x01},
+{0x0128, 0xAC},
+{0x0129, 0x0D},
+{0x012A, 0x00},
+{0x012B, 0xA4},
+{0x012C, 0x00},
+{0x012D, 0x01},
+{0x0130, 0xC4},
+{0x0131, 0x09},
+{0x0132, 0x00},
+{0x0133, 0xDA},
+//{0x013A,  ,3},
+{0x013B, 0x01},
+//{0x013C,  ,3},
+//{0x013D,  ,3},
+//{0x013E,  ,3},
+//{0x0140,  ,3},
+//{0x0141,  ,3},
+//{0x0142,  ,3},
+//{0x0144,  ,3},
+//{0x0145,  ,3},
+//{0x0146,  ,3},
+//{0x0148,  ,3},
+//{0x0149,  ,3},
+//{0x014A,  ,3},
+//{0x014C,  ,3},
+//{0x014D,  ,3},
+//{0x014E,  ,3},
+//{0x0150,  ,3},
+//{0x0151,  ,3},
+//{0x0152,  ,3},
+//{0x0154,  ,3},
+//{0x0155,  ,3},
+//{0x0156,  ,3},
+//{0x0158,  ,3},
+//{0x0159,  ,3},
+//{0x015A,  ,3},
+//{0x015C,  ,3},
+//{0x015D,  ,3},
+//{0x015E,  ,3},
+//{0x0160,  ,3},
+//{0x0161,  ,3},
+//{0x0162,  ,3},
+//{0x0164,  ,3},
+//{0x0165,  ,3},
+//{0x0166,  ,3},
+//{0x0168,  ,3},
+//{0x0169,  ,3},
+//{0x016A,  ,3},
+//{0x016C,  ,3},
+//{0x016D,  ,3},
+//{0x016E,  ,3},
+//{0x0170,  ,3},
+//{0x0171,  ,3},
+//{0x0172,  ,3},
+//{0x0174,  ,3},
+//{0x0175,  ,3},
+//{0x0176,  ,3},
+//{0x0178,  ,3},
+//{0x0179,  ,3},
+//{0x017A,  ,3},
+//{0x017C,  ,3},
+//{0x017D,  ,3},
+//{0x017E,  ,3},
+//{0x0180,  ,3},
+//{0x0181,  ,3},
+//{0x0182,  ,3},
+//{0x0184,  ,3},
+//{0x0185,  ,3},
+//{0x0186,  ,3},
+//{0x0188,  ,3},
+//{0x0189,  ,3},
+//{0x018A,  ,3},
+//{0x018C,  ,3},
+//{0x018D,  ,3},
+//{0x018E,  ,3},
+//{0x0190,  ,3},
+//{0x0191,  ,3},
+//{0x0192,  ,3},
+//{0x0194,  ,3},
+//{0x0195,  ,3},
+//{0x0196,  ,3},
+//{0x0198,  ,3},
+//{0x0199,  ,3},
+//{0x019A,  ,3},
+//{0x019B,  ,3},
+//{0x019C,  ,3},
+//{0x019D,  ,3},
+//{0x019E,  ,3},
+//{0x019F,  ,3},
+//{0x01A0,  ,3},
+//{0x01A1,  ,3},
+//{0x01A2,  ,3},
+//{0x01A3,  ,3},
+//{0x01A4,  ,3},
+//{0x01A5,  ,3},
+//{0x01A6,  ,3},
+//{0x01A7,  ,3},
+//{0x01A8,  ,3},
+//{0x01A9,  ,3},
+//{0x01AA,  ,3},
+//{0x01AB,  ,3},
+//{0x01AC,  ,3},
+//{0x01AD,  ,3},
+//{0x01AE,  ,3},
+//{0x01AF,  ,3},
+//{0x01B0,  ,3},
+//{0x01B1,  ,3},
+//{0x01B2,  ,3},
+//{0x01B3,  ,3},
+//{0x01B4,  ,3},
+//{0x01B5,  ,3},
+//{0x01B6,  ,3},
+//{0x01B7,  ,3},
+//{0x01B8,  ,3},
+//{0x01B9,  ,3},
+//{0x01BA,  ,3},
+//{0x01BB,  ,3},
+//{0x01BC,  ,3},
+//{0x01BD,  ,3},
+//{0x01BE,  ,3},
+//{0x01BF,  ,3},
+//{0x01C0,  ,3},
+//{0x01C1,  ,3},
+//{0x01C2,  ,3},
+//{0x01C3,  ,3},
+{0x01C4, 0x00},
+{0x01C5, 0x00},
+{0x01CC, 0x01},
+{0x01D0, 0x09},
+{0x01D4, 0x01},
+{0x0232, 0x7E},
+{0x0233, 0x00},
+{0x0390, 0x00},
+{0x0391, 0x00},
+{0x0392, 0x00},
+#ifdef IMX390_DISPLAY_PATTERN_COLOR_BAR
+{0x01DB, 0x32},
+{0x03C0, 0x02},
+#else
+{0x03C0, 0x00},
+#endif
+{0x2000, 0x55},
+{0x2001, 0x55},
+{0x2002, 0x55},
+{0x2003, 0x05},
+{0x2004, 0x02},
+{0x2008, 0x65},
+{0x2009, 0x04},
+{0x200A, 0x00},
+{0x200C, 0x30},
+{0x200D, 0x11},
+{0x2010, 0x04},
+{0x2014, 0x01},
+{0x2018, 0x02},
+{0x2019, 0x04},
+{0x201A, 0x00},
+{0x201C, 0x21},
+{0x201D, 0x11},
+{0x201E, 0x00},
+{0x201F, 0x00},
+{0x2020, 0xBC},
+{0x2021, 0x00},
+{0x2022, 0x7F},
+{0x2023, 0x00},
+{0x2024, 0xBA},
+{0x2025, 0x00},
+{0x2026, 0x81},
+{0x2027, 0x00},
+{0x2028, 0x7D},
+{0x2029, 0x90},
+{0x202A, 0x05},
+{0x202C, 0xFC},
+{0x202D, 0x02},
+{0x202E, 0x25},
+{0x202F, 0x03},
+{0x2030, 0x05},
+{0x2031, 0x02},
+{0x2032, 0xCA},
+{0x2033, 0x02},
+{0x2034, 0xFC},
+{0x2035, 0x02},
+{0x2036, 0x25},
+{0x2037, 0x03},
+{0x2038, 0x25},
+{0x2039, 0x97},
+{0x203A, 0xEC},
+{0x203B, 0x01},
+{0x203C, 0xF5},
+{0x203D, 0x8E},
+{0x203E, 0x0C},
+{0x203F, 0x2D},
+{0x2040, 0x69},
+{0x2041, 0x01},
+{0x2042, 0x8E},
+{0x2043, 0x01},
+{0x2044, 0x0C},
+{0x2045, 0x02},
+{0x2046, 0x31},
+{0x2047, 0x02},
+{0x2048, 0x6A},
+{0x2049, 0x01},
+{0x204A, 0x8E},
+{0x204B, 0x01},
+{0x204C, 0x0D},
+{0x204D, 0x02},
+{0x204E, 0x31},
+{0x204F, 0x02},
+{0x2050, 0x7B},
+{0x2051, 0x00},
+{0x2052, 0x7D},
+{0x2053, 0x00},
+{0x2054, 0x95},
+{0x2055, 0x00},
+{0x2056, 0x97},
+{0x2057, 0x00},
+{0x2058, 0xAD},
+{0x2059, 0x00},
+{0x205A, 0xAF},
+{0x205B, 0x00},
+{0x205C, 0x92},
+{0x205D, 0x00},
+{0x205E, 0x94},
+{0x205F, 0x00},
+{0x2060, 0x8E},
+{0x2061, 0x00},
+{0x2062, 0x90},
+{0x2063, 0x00},
+{0x2064, 0xB1},
+{0x2065, 0x00},
+{0x2066, 0xB3},
+{0x2067, 0x00},
+{0x2068, 0x08},
+{0x2069, 0x00},
+{0x206A, 0x04},
+{0x206B, 0x00},
+{0x206C, 0x84},
+{0x206D, 0x00},
+{0x206E, 0x80},
+{0x206F, 0x00},
+{0x2070, 0x04},
+{0x2071, 0x00},
+{0x2072, 0x46},
+{0x2073, 0x00},
+{0x2074, 0xE9},
+{0x2075, 0x01},
+{0x2076, 0x74},
+{0x2077, 0x02},
+{0x2078, 0x80},
+{0x2079, 0x00},
+{0x207A, 0xC1},
+{0x207B, 0x00},
+{0x207C, 0xFF},
+{0x207D, 0x03},
+{0x207E, 0xFF},
+{0x207F, 0x03},
+{0x2080, 0x78},
+{0x2081, 0x00},
+{0x2082, 0x6A},
+{0x2083, 0x01},
+{0x2084, 0xE4},
+{0x2085, 0x01},
+{0x2086, 0x2B},
+{0x2087, 0x03},
+{0x2088, 0x00},
+{0x2089, 0x00},
+{0x208A, 0xFF},
+{0x208B, 0x03},
+{0x208C, 0xFF},
+{0x208D, 0x03},
+{0x208E, 0xFF},
+{0x208F, 0x03},
+{0x2090, 0x7D},
+{0x2091, 0x00},
+{0x2092, 0x62},
+{0x2093, 0x01},
+{0x2094, 0xE9},
+{0x2095, 0x01},
+{0x2096, 0x00},
+{0x2097, 0x00},
+{0x2098, 0x7C},
+{0x2099, 0x00},
+{0x209A, 0x21},
+{0x209B, 0x03},
+{0x209C, 0xE9},
+{0x209D, 0x01},
+{0x209E, 0x21},
+{0x209F, 0x03},
+{0x20A0, 0xFF},
+{0x20A1, 0x03},
+{0x20A2, 0xFF},
+{0x20A3, 0x03},
+{0x20A4, 0xFF},
+{0x20A5, 0x03},
+{0x20A6, 0xFF},
+{0x20A7, 0x03},
+{0x20A8, 0xFF},
+{0x20A9, 0x03},
+{0x20AA, 0xFF},
+{0x20AB, 0x03},
+{0x20AC, 0xFF},
+{0x20AD, 0x03},
+{0x20AE, 0xFF},
+{0x20AF, 0x03},
+{0x20B0, 0xFF},
+{0x20B1, 0x03},
+{0x20B2, 0xFF},
+{0x20B3, 0x03},
+{0x20B4, 0x87},
+{0x20B5, 0xCC},
+{0x20B6, 0x87},
+{0x20B7, 0x08},
+{0x20B8, 0xF4},
+{0x20B9, 0xA5},
+{0x20BA, 0x07},
+{0x20BC, 0x1F},
+{0x20BD, 0x01},
+{0x20BE, 0xF6},
+{0x20BF, 0x00},
+{0x20C0, 0x90},
+{0x20C1, 0x01},
+{0x20C2, 0x67},
+{0x20C3, 0x01},
+{0x20C4, 0xFF},
+{0x20C5, 0x03},
+{0x20C6, 0xFF},
+{0x20C7, 0x03},
+{0x20C8, 0x33},
+{0x20C9, 0x02},
+{0x20CA, 0x0A},
+{0x20CB, 0x02},
+{0x20CC, 0x7F},
+{0x20CD, 0x00},
+{0x20CE, 0xD2},
+{0x20CF, 0x00},
+{0x20D0, 0x81},
+{0x20D1, 0x00},
+{0x20D2, 0x87},
+{0x20D3, 0x00},
+{0x20D4, 0x09},
+{0x20D5, 0x00},
+{0x20D8, 0x7F},
+{0x20D9, 0x00},
+{0x20DA, 0x62},
+{0x20DB, 0x01},
+{0x20DC, 0x7F},
+{0x20DD, 0x00},
+{0x20DE, 0x62},
+{0x20DF, 0x01},
+{0x20E0, 0x65},
+{0x20E1, 0x00},
+{0x20E2, 0x75},
+{0x20E3, 0x00},
+{0x20E4, 0xE0},
+{0x20E5, 0x00},
+{0x20E6, 0xF0},
+{0x20E7, 0x00},
+{0x20E8, 0x4C},
+{0x20E9, 0x01},
+{0x20EA, 0x5C},
+{0x20EB, 0x01},
+{0x20EC, 0xD1},
+{0x20ED, 0x01},
+{0x20EE, 0xE1},
+{0x20EF, 0x01},
+{0x20F0, 0x93},
+{0x20F1, 0x02},
+{0x20F2, 0xA3},
+{0x20F3, 0x02},
+{0x20F4, 0x0D},
+{0x20F5, 0x03},
+{0x20F6, 0x1D},
+{0x20F7, 0x03},
+{0x20F8, 0x57},
+{0x20F9, 0x00},
+{0x20FA, 0x7B},
+{0x20FB, 0x00},
+{0x20FC, 0xD2},
+{0x20FD, 0x00},
+{0x20FE, 0xF6},
+{0x20FF, 0x00},
+{0x2100, 0x3E},
+{0x2101, 0x01},
+{0x2102, 0x60},
+{0x2103, 0x01},
+{0x2104, 0xC3},
+{0x2105, 0x01},
+{0x2106, 0xE5},
+{0x2107, 0x01},
+{0x2108, 0x85},
+{0x2109, 0x02},
+{0x210A, 0xA9},
+{0x210B, 0x02},
+{0x210C, 0xFF},
+{0x210D, 0x02},
+{0x210E, 0x21},
+{0x210F, 0x03},
+{0x2110, 0xFF},
+{0x2111, 0x03},
+{0x2112, 0x00},
+{0x2113, 0x00},
+{0x2114, 0xFF},
+{0x2115, 0x03},
+{0x2116, 0xFF},
+{0x2117, 0x03},
+{0x2118, 0xFF},
+{0x2119, 0x03},
+{0x211A, 0xFF},
+{0x211B, 0x03},
+{0x211C, 0xFF},
+{0x211D, 0x03},
+{0x211E, 0xFF},
+{0x211F, 0x03},
+{0x2120, 0xFF},
+{0x2121, 0x03},
+{0x2122, 0xFF},
+{0x2123, 0x03},
+{0x2124, 0xFF},
+{0x2125, 0x03},
+{0x2126, 0xFF},
+{0x2127, 0x03},
+{0x2128, 0x7D},
+{0x2129, 0x90},
+{0x212A, 0xD5},
+{0x212B, 0x07},
+{0x212C, 0x64},
+{0x212D, 0x01},
+{0x2130, 0x5F},
+{0x2131, 0x7D},
+{0x2132, 0x05},
+{0x2134, 0x78},
+{0x2135, 0x00},
+{0x2136, 0x76},
+{0x2137, 0x00},
+{0x2138, 0xF3},
+{0x2139, 0x00},
+{0x213A, 0xF1},
+{0x213B, 0x00},
+{0x213C, 0xA6},
+{0x213D, 0x02},
+{0x213E, 0xA4},
+{0x213F, 0x02},
+{0x2140, 0x7D},
+{0x2141, 0x00},
+{0x2142, 0x8D},
+{0x2143, 0x00},
+{0x2144, 0xA1},
+{0x2145, 0x01},
+{0x2146, 0xB1},
+{0x2147, 0x01},
+{0x2148, 0xAB},
+{0x2149, 0x02},
+{0x214A, 0xBB},
+{0x214B, 0x02},
+{0x214C, 0x17},
+{0x214D, 0x5C},
+{0x214E, 0x00},
+{0x2150, 0x00},
+{0x2151, 0x00},
+{0x2152, 0xF8},
+{0x2153, 0x00},
+{0x2154, 0xBE},
+{0x2155, 0x00},
+{0x2156, 0x7D},
+{0x2157, 0x00},
+{0x2158, 0x25},
+{0x2159, 0x00},
+{0x215A, 0x7D},
+{0x215B, 0x00},
+{0x215C, 0x62},
+{0x215D, 0x01},
+{0x215E, 0xFF},
+{0x215F, 0x03},
+{0x2160, 0x26},
+{0x2161, 0x00},
+{0x2162, 0x7D},
+{0x2163, 0x00},
+{0x2164, 0x63},
+{0x2165, 0x01},
+{0x2166, 0xFF},
+{0x2167, 0x03},
+{0x2168, 0xCB},
+{0x2169, 0x02},
+{0x216A, 0xCF},
+{0x216B, 0x02},
+{0x216C, 0xFF},
+{0x216D, 0x03},
+{0x216E, 0xFF},
+{0x216F, 0x03},
+{0x2170, 0xFF},
+{0x2171, 0x03},
+{0x2172, 0xFF},
+{0x2173, 0x03},
+{0x2174, 0xFF},
+{0x2175, 0x03},
+{0x2176, 0xFF},
+{0x2177, 0x03},
+{0x2178, 0x7E},
+{0x2179, 0x00},
+{0x217A, 0xBD},
+{0x217B, 0x00},
+{0x217C, 0xEC},
+{0x217D, 0x01},
+{0x217E, 0x7B},
+{0x217F, 0x02},
+{0x2180, 0xD1},
+{0x2181, 0x02},
+{0x2182, 0x25},
+{0x2183, 0x03},
+{0x2184, 0x7F},
+{0x2185, 0x00},
+{0x2186, 0xBD},
+{0x2187, 0x00},
+{0x2188, 0xED},
+{0x2189, 0x01},
+{0x218A, 0x7B},
+{0x218B, 0x02},
+{0x218C, 0xD2},
+{0x218D, 0x02},
+{0x218E, 0x25},
+{0x218F, 0x03},
+{0x2190, 0xFF},
+{0x2191, 0x03},
+{0x2192, 0xFF},
+{0x2193, 0x03},
+{0x2194, 0xE9},
+{0x2195, 0x01},
+{0x2196, 0x21},
+{0x2197, 0x03},
+{0x2198, 0x17},
+{0x2199, 0xFC},
+{0x219A, 0x7F},
+{0x219B, 0x01},
+{0x219C, 0xFF},
+{0x219D, 0x03},
+{0x21A0, 0x1B},
+{0x21A1, 0x1B},
+{0x21A2, 0x1B},
+{0x21A3, 0x1B},
+{0x21A4, 0x2E},
+{0x21A5, 0x80},
+{0x21A6, 0x00},
+{0x21A8, 0x04},
+{0x21A9, 0x98},
+{0x21AA, 0x60},
+{0x21AB, 0x03},
+{0x21AC, 0x7F},
+{0x21AD, 0x80},
+{0x21AE, 0x09},
+{0x21B0, 0x1C},
+{0x21B1, 0x00},
+{0x21B2, 0xA0},
+{0x21B3, 0x00},
+{0x21B4, 0x0C},
+{0x21B5, 0x00},
+{0x21B6, 0x2D},
+{0x21B7, 0x00},
+{0x21B8, 0x20},
+{0x21B9, 0x00},
+{0x21BA, 0x02},
+{0x21BB, 0x00},
+{0x21BC, 0xCC},
+{0x21BD, 0x00},
+{0x21BE, 0x4A},
+{0x21BF, 0x00},
+{0x21C0, 0xD0},
+{0x21C1, 0x00},
+{0x21C2, 0x44},
+{0x21C3, 0x00},
+{0x21C4, 0x00},
+{0x21C5, 0xE0},
+{0x21C6, 0x00},
+{0x21C8, 0x11},
+{0x21C9, 0x00},
+{0x21CA, 0x02},
+{0x21CC, 0x08},
+{0x21CD, 0xC0},
+{0x21CE, 0x0C},
+{0x21D0, 0x44},
+{0x21D1, 0x00},
+{0x21D2, 0x02},
+{0x21D4, 0x02},
+{0x21D5, 0x20},
+{0x21D6, 0x2C},
+{0x21D8, 0xFE},
+{0x21D9, 0x9D},
+{0x21DA, 0xDF},
+{0x21DB, 0x03},
+{0x21DC, 0x62},
+{0x21DD, 0x01},
+{0x21DE, 0x7F},
+{0x21DF, 0x00},
+{0x21E0, 0xB7},
+{0x21E1, 0x01},
+{0x21E2, 0xB5},
+{0x21E3, 0x01},
+{0x21E4, 0xC1},
+{0x21E5, 0x02},
+{0x21E6, 0xBF},
+{0x21E7, 0x02},
+{0x21E8, 0xB3},
+{0x21E9, 0x0D},
+{0x21EA, 0x00},
+{0x21EB, 0x04},
+#if 1
+{0x21EC, 0x90},
+{0x21ED, 0x07},
+{0x21EE, 0x58},
+{0x21EF, 0x04},
+#else
+{0x21EC, 0x80},
+{0x21ED, 0x07},
+{0x21EE, 0x38},
+{0x21EF, 0x04},
+#endif
+{0x21F0, 0x54},
+{0x21F1, 0x04},
+{0x21F4, 0x02},
+{0x21F5, 0x00},
+{0x21F6, 0x00},
+{0x21F8, 0x3C},
+{0x21F9, 0x00},
+{0x21FC, 0x28},
+{0x21FD, 0x00},
+{0x21FE, 0x3C},
+{0x21FF, 0x00},
+{0x2200, 0x00},
+{0x2204, 0x4C},
+{0x2205, 0x04},
+{0x2206, 0x65},
+{0x2207, 0x04},
+{0x2208, 0x0A},
+{0x2209, 0x00},
+{0x220C, 0x47},
+{0x220D, 0x00},
+{0x220E, 0x1F},
+{0x220F, 0x00},
+{0x2210, 0x17},
+{0x2211, 0x00},
+{0x2212, 0x0F},
+{0x2213, 0x00},
+{0x2214, 0x17},
+{0x2215, 0x00},
+{0x2216, 0x47},
+{0x2217, 0x00},
+{0x2218, 0x0F},
+{0x2219, 0x00},
+{0x221A, 0x0F},
+{0x221B, 0x00},
+{0x221C, 0x03},
+{0x2220, 0x20},
+{0x2221, 0x20},
+{0x2222, 0x22},
+{0x2223, 0x02},
+{0x2224, 0xA7},
+{0x2225, 0xAA},
+{0x2226, 0x80},
+{0x2227, 0x08},
+{0x2228, 0x01},
+{0x22B2, 0x92},
+{0x22B4, 0x20},
+{0x22B5, 0x00},
+{0x22B6, 0x20},
+{0x22B7, 0x00},
+{0x22B8, 0x20},
+{0x22B9, 0x00},
+{0x22BA, 0x20},
+{0x22BB, 0x00},
+{0x22BC, 0x20},
+{0x22BD, 0x00},
+{0x22BE, 0x20},
+{0x22BF, 0x00},
+{0x22C0, 0x20},
+{0x22C1, 0x00},
+{0x22C2, 0x20},
+{0x22C3, 0x00},
+{0x22C4, 0x20},
+{0x22C5, 0x00},
+{0x22C6, 0x20},
+{0x22C7, 0x00},
+{0x22C8, 0x20},
+{0x22C9, 0x00},
+{0x22CA, 0x20},
+{0x22CB, 0x00},
+{0x22CC, 0x20},
+{0x22CD, 0x00},
+{0x22CE, 0x20},
+{0x22CF, 0x00},
+{0x22DA, 0x00},
+{0x2308, 0x01},
+{0x2311, 0x09},
+{0x2318, 0x40},
+{0x2319, 0xCD},
+{0x231A, 0x54},
+{0x2324, 0x20},
+{0x2325, 0x00},
+{0x2328, 0x00},
+{0x2354, 0x0C},
+{0x23C0, 0x5D},
+{0x244C, 0x00},
+{0x244D, 0x02},
+{0x244E, 0x54},
+{0x244F, 0x02},
+{0x24A0, 0x00},
+{0x24DA, 0x6F},
+{0x24DB, 0x00},
+{0x24DC, 0x62},
+{0x24DD, 0x01},
+{0x24EA, 0x32},
+{0x24EB, 0x00},
+{0x24EC, 0xDC},
+{0x24ED, 0x00},
+{0x24FA, 0x32},
+{0x24FB, 0x00},
+{0x24FC, 0xDD},
+{0x24FD, 0x00},
+{0x254A, 0x15},
+{0x254B, 0x01},
+{0x255A, 0x15},
+{0x255B, 0x01},
+{0x2560, 0x01},
+{0x2561, 0x00},
+{0x2562, 0x2A},
+{0x2563, 0x00},
+{0x2564, 0xF8},
+{0x2565, 0x00},
+{0x2566, 0x15},
+{0x2567, 0x01},
+{0x2568, 0x0C},
+{0x2569, 0x02},
+{0x256A, 0x31},
+{0x256B, 0x02},
+{0x2578, 0x90},
+{0x2579, 0x01},
+{0x257A, 0x92},
+{0x257B, 0x01},
+{0x257C, 0xB8},
+{0x257D, 0x02},
+{0x257E, 0xBA},
+{0x257F, 0x02},
+{0x2584, 0x90},
+{0x2585, 0x01},
+{0x2586, 0x92},
+{0x2587, 0x01},
+{0x2588, 0xB8},
+{0x2589, 0x02},
+{0x258A, 0xBA},
+{0x258B, 0x02},
+{0x26B8, 0x10},
+{0x26B9, 0x00},
+{0x26BA, 0x33},
+{0x26BB, 0x00},
+{0x26BC, 0x89},
+{0x26BD, 0x00},
+{0x26BE, 0xB0},
+{0x26BF, 0x00},
+{0x26C4, 0x4E},
+{0x26C5, 0x00},
+{0x26C8, 0xC9},
+{0x26C9, 0x00},
+{0x26CC, 0x35},
+{0x26CD, 0x01},
+{0x26D0, 0xBA},
+{0x26D1, 0x01},
+{0x26D4, 0x7C},
+{0x26D5, 0x02},
+{0x26D8, 0xF6},
+{0x26D9, 0x02},
+{0x26DE, 0x51},
+{0x26DF, 0x00},
+{0x26E0, 0x7F},
+{0x26E1, 0x00},
+{0x26E2, 0xCC},
+{0x26E3, 0x00},
+{0x26E4, 0xF8},
+{0x26E5, 0x00},
+{0x26E6, 0x38},
+{0x26E7, 0x01},
+{0x26E8, 0x65},
+{0x26E9, 0x01},
+{0x26EA, 0xBD},
+{0x26EB, 0x01},
+{0x26EE, 0x7F},
+{0x26EF, 0x02},
+{0x26F0, 0xAB},
+{0x26F1, 0x02},
+{0x26F2, 0xF9},
+{0x26F3, 0x02},
+{0x2722, 0x59},
+{0x2723, 0x02},
+{0x2938, 0x55},
+{0x2939, 0x00},
+{0x293A, 0x17},
+{0x293B, 0x00},
+{0x293C, 0xD0},
+{0x293D, 0x00},
+{0x293E, 0x91},
+{0x293F, 0x00},
+{0x2940, 0x3C},
+{0x2941, 0x01},
+{0x2942, 0x0C},
+{0x2943, 0x01},
+{0x2944, 0xC1},
+{0x2945, 0x01},
+{0x2946, 0x76},
+{0x2947, 0x01},
+{0x2948, 0x83},
+{0x2949, 0x02},
+{0x294A, 0xFB},
+{0x294B, 0x01},
+{0x294C, 0xFD},
+{0x294D, 0x02},
+{0x294E, 0xBF},
+{0x294F, 0x02},
+{0x2A06, 0xFF},
+{0x2A07, 0x03},
+{0x2A20, 0x00},
+{0x2A21, 0x00},
+{0x2A22, 0x7D},
+{0x2A23, 0x00},
+{0x2B11, 0x19},
+{0x2B13, 0x15},
+{0x2B14, 0x14},
+{0x2B15, 0x13},
+{0x2B16, 0x12},
+{0x2B17, 0x11},
+{0x2B18, 0x10},
+{0x2B19, 0x0F},
+{0x2B1A, 0x0E},
+{0x2B1B, 0x0D},
+{0x2B1C, 0x0C},
+{0x2B1D, 0x0B},
+{0x2B1E, 0x0A},
+{0x2B1F, 0x09},
+{0x2B20, 0x08},
+{0x2B21, 0x07},
+{0x2B22, 0x06},
+{0x2B23, 0x05},
+{0x2B24, 0x04},
+{0x2B25, 0x03},
+{0x2B26, 0x03},
+{0x2B38, 0x01},
+{0x2B45, 0xE3},
+{0x2B50, 0x01},
+{0x2B51, 0x00},
+//{0x2B62,  ,3},
+{0x2B6D, 0x47},
+{0x2B70, 0x02},
+{0x2B71, 0x02},
+{0x2B72, 0x02},
+{0x2B7F, 0x7F},
+{0x2B80, 0x94},
+{0x2B81, 0x06},
+{0x2B87, 0x1B},
+{0x2B88, 0x1B},
+{0x2B89, 0x17},
+{0x2B8A, 0x12},
+{0x2B8B, 0x12},
+{0x2B8D, 0x2B},
+{0x2B8E, 0x2B},
+{0x2B8F, 0x2B},
+{0x2B90, 0x7F},
+{0x2B91, 0x1F},
+{0x2B94, 0x7F},
+{0x2B95, 0x27},
+{0x2B98, 0x7F},
+{0x2B99, 0x57},
+{0x2BA8, 0xBC},
+{0x2BA9, 0x62},
+{0x2BC1, 0x70},
+{0x2BC5, 0x80},
+{0x2BD5, 0x30},
+{0x2BD6, 0xF0},
+{0x2BD8, 0xDB},
+{0x2BD9, 0xF6},
+{0x2BDA, 0x63},
+{0x2BDB, 0x0C},
+{0x2BDC, 0x5C},
+{0x2C98, 0xE1},
+{0x2C99, 0x2E},
+{0x2C9B, 0x86},
+{0x2CA9, 0x80},
+{0x2CAA, 0x01},
+{0x2D39, 0x0E},
+{0x2D54, 0x00},
+{0x2D5B, 0x58},
+{0x3000, 0x00},
+{0x3001, 0x40},
+{0x3002, 0x23},
+{0x3003, 0xA1},
+{0x3004, 0x00},
+{0x3005, 0x20},
+{0x3006, 0x94},
+{0x3007, 0x00},
+{0x3008, 0x06},
+{0x3009, 0xB4},
+{0x300A, 0x1F},
+{0x300B, 0x28},
+{0x300C, 0x00},
+{0x300D, 0x18},
+{0x300E, 0x90},
+{0x300F, 0x97},
+{0x3010, 0x00},
+{0x3011, 0x40},
+{0x3012, 0x21},
+{0x3013, 0x21},
+{0x3014, 0x00},
+{0x3015, 0x20},
+{0x3016, 0x94},
+{0x3017, 0x00},
+{0x3018, 0x00},
+{0x3019, 0x09},
+{0x301A, 0x46},
+{0x301B, 0x28},
+//{0x3053,  ,3},
+{0x3070, 0xC1},
+{0x3071, 0x81},
+{0x3072, 0x29},
+{0x3073, 0x81},
+//{0x3370,  ,3},
+//{0x3374,  ,3},
+//{0x3375,  ,3},
+//{0x3376,  ,3},
+//{0x3377,  ,3},
+#if 1
+{0x3410, 0x90},
+{0x3411, 0x07},
+{0x3418, 0x48},
+{0x3419, 0x04},
+#else
+{0x3410, 0x80},
+{0x3411, 0x07},
+{0x3418, 0x38},
+{0x3419, 0x04},
+#endif
+//{0x34C0,  ,3},
+//{0x34C1,  ,3},
+//{0x34C2,  ,3},
+//{0x34C3,  ,3},
+//{0x34C4,  ,3},
+//{0x34C5,  ,3},
+//{0x34C6,  ,3},
+//{0x34C7,  ,3},
+//{0x34C8,  ,3},
+//{0x34C9,  ,3},
+//{0x34CA,  ,3},
+//{0x34CB,  ,3},
+//{0x34CC,  ,3},
+//{0x34CD,  ,3},
+//{0x34CE,  ,3},
+//{0x34CF,  ,3},
+{0x3584, 0x00},
+{0x3586, 0x00},
+{0x3587, 0x01},
+{0x3588, 0xE6},
+{0x3589, 0x00},
+{0x3590, 0x00},
+{0x3591, 0x00},
+{0x3594, 0x40},
+{0x3598, 0x03},
+{0x3599, 0x00},
+{0x359A, 0x80},
+{0x359B, 0x00},
+{0x359C, 0x00},
+{0x359D, 0x01},
+{0x359E, 0x00},
+{0x359F, 0x02},
+{0x35A0, 0x00},
+{0x35A1, 0x04},
+{0x35A2, 0x20},
+{0x35A3, 0x00},
+{0x35A4, 0x40},
+{0x35A5, 0x00},
+{0x35A6, 0x80},
+{0x35A7, 0x00},
+{0x35A8, 0x00},
+{0x35A9, 0x01},
+{0x35AA, 0x3A},
+{0x35AB, 0x00},
+{0x35AC, 0x80},
+{0x35AD, 0x00},
+{0x35AE, 0x00},
+{0x35AF, 0x01},
+{0x35B0, 0x00},
+{0x35B1, 0x02},
+{0x35B2, 0x00},
+{0x35B3, 0x04},
+{0x35B4, 0x02},
+{0x35B5, 0x00},
+{0x35B6, 0x04},
+{0x35B7, 0x00},
+{0x35B8, 0x08},
+{0x35B9, 0x00},
+{0x35BA, 0x10},
+{0x35BB, 0x00},
+{0x35BC, 0x03},
+{0x35BD, 0x00},
+{0x35C8, 0x00},
+{0x35C9, 0x01},
+{0x35CA, 0x00},
+{0x35CB, 0x04},
+{0x35CC, 0x00},
+{0x35CD, 0x10},
+{0x35CE, 0x00},
+{0x35CF, 0x40},
+{0x35D0, 0x00},
+{0x35D1, 0x0C},
+{0x35D2, 0x00},
+{0x35D3, 0x0C},
+{0x35D4, 0x00},
+{0x35D5, 0x0C},
+{0x35D6, 0x00},
+{0x35D7, 0x0C},
+{0x35D8, 0x00},
+{0x35D9, 0x00},
+{0x35DA, 0x08},
+{0x35DB, 0x00},
+{0x35DC, 0xD8},
+{0x35DD, 0x0E},
+{0x35F0, 0x00},
+{0x35F1, 0x10},
+{0x35F2, 0x00},
+{0x35F3, 0x10},
+{0x35F4, 0x00},
+{0x35F5, 0x10},
+{0x35F6, 0x00},
+{0x35F7, 0x03},
+{0x35F8, 0x00},
+{0x35F9, 0x01},
+{0x35FA, 0x38},
+{0x35FB, 0x00},
+{0x35FC, 0xB3},
+{0x35FD, 0x01},
+{0x35FE, 0x00},
+{0x35FF, 0x00},
+{0x3600, 0x04},
+{0x3601, 0x06},
+{0x3604, 0x03},
+{0x3605, 0x00},
+{0x3608, 0x03},
+{0x3609, 0x00},
+{0x360C, 0x00},
+{0x360D, 0x00},
+{0x3610, 0x10},
+{0x3611, 0x01},
+{0x3612, 0x00},
+{0x3613, 0x00},
+{0x3614, 0x00},
+{0x3615, 0x00},
+{0x361C, 0x00},
+{0x361D, 0x01},
+{0x361E, 0x00},
+{0x361F, 0x01},
+{0x3620, 0x01},
+{0x3621, 0x00},
+{0x3622, 0xB0},
+{0x3623, 0x04},
+{0x3624, 0xDC},
+{0x3625, 0x05},
+{0x3626, 0x00},
+{0x3627, 0x01},
+{0x3628, 0xFF},
+{0x3629, 0x0F},
+{0x362A, 0x00},
+{0x362B, 0x10},
+{0x362C, 0x00},
+{0x362D, 0x01},
+//{0x3630,  ,3},
+//{0x3631,  ,3},
+//{0x3632,  ,3},
+//{0x3633,  ,3},
+//{0x3634,  ,3},
+//{0x3635,  ,3},
+//{0x3636,  ,3},
+//{0x3637,  ,3},
+//{0x3638,  ,3},
+//{0x3639,  ,3},
+//{0x363A,  ,3},
+//{0x363B,  ,3},
+//{0x363C,  ,3},
+//{0x363D,  ,3},
+//{0x363E,  ,3},
+//{0x363F,  ,3},
+{0x36C4, 0x99},
+{0x36C5, 0x09},
+{0x36C6, 0x18},
+{0x36C7, 0x07},
+{0x36C8, 0x65},
+{0x36C9, 0x0E},
+{0x36CC, 0x99},
+{0x36CD, 0x01},
+{0x36CE, 0x47},
+{0x36CF, 0x00},
+{0x36D0, 0x04},
+{0x36D1, 0x00},
+{0x36D4, 0x65},
+{0x36D5, 0x0E},
+{0x36D6, 0xA4},
+{0x36D7, 0x0A},
+{0x36D8, 0x65},
+{0x36D9, 0x0E},
+{0x36DC, 0x65},
+{0x36DD, 0x0E},
+{0x36DE, 0xA4},
+{0x36DF, 0x0A},
+{0x36E0, 0x65},
+{0x36E1, 0x0E},
+{0x36E4, 0x65},
+{0x36E5, 0x0E},
+{0x36E6, 0xA4},
+{0x36E7, 0x0A},
+{0x36E8, 0x65},
+{0x36E9, 0x0E},
+{0x36EE, 0x00},
+{0x36EF, 0x00},
+{0x36F0, 0x00},
+{0x36F1, 0x80},
+{0x36F8, 0x00},
+{0x3702, 0x03},
+{0x3703, 0x04},
+{0x3704, 0x08},
+{0x370E, 0x0E},
+{0x3718, 0x62},
+{0x3719, 0x4A},
+{0x371A, 0x38},
+{0x371B, 0x20},
+{0x371C, 0x64},
+{0x371D, 0x42},
+{0x371E, 0x32},
+{0x371F, 0x1B},
+{0x3720, 0x98},
+{0x3721, 0xA0},
+{0x3722, 0xA8},
+{0x3723, 0xB0},
+{0x3748, 0xA5},
+{0x3749, 0x9B},
+{0x374A, 0x91},
+{0x374B, 0x7D},
+{0x37C0, 0x00},
+{0x37C1, 0x00},
+{0x37C2, 0x00},
+{0x37C4, 0x00},
+{0x37C5, 0x00},
+{0x37C6, 0x00},
+{0x37C8, 0x00},
+{0x37C9, 0x00},
+{0x37CA, 0x00},
+{0x37CC, 0x00},
+{0x37CD, 0x00},
+{0x37CE, 0x00},
+{0x37D0, 0x00},
+{0x37D1, 0x00},
+{0x37D2, 0x00},
+{0x37D4, 0x00},
+{0x37D5, 0x00},
+{0x37D6, 0x00},
+{0x37D8, 0x00},
+{0x37D9, 0x00},
+{0x37DA, 0x00},
+{0x37DC, 0x00},
+{0x37DD, 0x00},
+{0x37DE, 0x00},
+{0x37E0, 0x00},
+{0x37E1, 0x00},
+{0x37E2, 0x00},
+{0x37E4, 0x00},
+{0x37E5, 0x00},
+{0x37E6, 0x00},
+{0x37E8, 0x00},
+{0x37E9, 0x00},
+{0x37EA, 0x00},
+{0x37EC, 0x00},
+{0x37ED, 0x00},
+{0x37EE, 0x00},
+{0x37F0, 0x00},
+{0x37F4, 0x00},
+{0x37F5, 0x1E},
+{0x37F6, 0x34},
+{0x37F7, 0x00},
+{0x37F8, 0xFF},
+{0x37F9, 0xFF},
+{0x37FA, 0x03},
+{0x37FC, 0x00},
+{0x37FD, 0x00},
+{0x37FE, 0x04},
+{0x3800, 0xFF},
+{0x3801, 0xFF},
+{0x3802, 0x03},
+{0x3804, 0x00},
+{0x3805, 0x00},
+{0x3806, 0x04},
+{0x3808, 0x00},
+{0x3809, 0x00},
+{0x380A, 0x00},
+{0x380C, 0x00},
+{0x380D, 0x00},
+{0x380E, 0x00},
+{0x3810, 0x00},
+{0x3811, 0x00},
+{0x3812, 0x00},
+{0x3814, 0x00},
+{0x3815, 0x00},
+{0x3816, 0x00},
+{0x3818, 0x00},
+{0x3819, 0x00},
+{0x381A, 0x00},
+{0x381C, 0x00},
+{0x381D, 0x00},
+{0x381E, 0x00},
+{0x3820, 0x00},
+{0x3821, 0x00},
+{0x3822, 0x00},
+{0x3824, 0x00},
+{0x3825, 0x00},
+{0x3826, 0x00},
+{0x3828, 0x00},
+{0x3829, 0x00},
+{0x382A, 0x00},
+{0x382C, 0x00},
+{0x382D, 0x00},
+{0x382E, 0x00},
+{0x3830, 0x00},
+{0x3831, 0x00},
+{0x3832, 0x00},
+{0x3834, 0x00},
+{0x3835, 0x00},
+{0x3836, 0x00},
+{0x3838, 0x22},
+{0x3839, 0x00},
+{0x383A, 0x25},
+{0x383B, 0x00},
+{0x383C, 0x1A},
+{0x383D, 0x00},
+{0x383E, 0x26},
+{0x383F, 0x00},
+{0x3840, 0x07},
+{0x3841, 0x00},
+{0x3842, 0x06},
+{0x3843, 0x00},
+{0x3844, 0x03},
+{0x3845, 0x00},
+{0x3846, 0x02},
+{0x3847, 0x00},
+{0x3848, 0xFB},
+{0x3849, 0xFF},
+{0x384A, 0xFF},
+{0x384B, 0xFF},
+{0x384C, 0xF3},
+{0x384D, 0xFF},
+{0x384E, 0xF2},
+{0x384F, 0xFF},
+{0x3850, 0xFF},
+{0x3851, 0x0F},
+{0x3852, 0x00},
+{0x3853, 0x10},
+{0x3854, 0xFF},
+{0x3855, 0x0F},
+{0x3856, 0x00},
+{0x3857, 0x10},
+{0x3858, 0xFF},
+{0x3859, 0x0F},
+{0x385A, 0x00},
+{0x385B, 0x10},
+{0x385C, 0x02},
+{0x385D, 0x00},
+{0x385E, 0x06},
+{0x385F, 0x00},
+{0x3860, 0x06},
+{0x3861, 0x00},
+{0x3862, 0x08},
+{0x3863, 0x00},
+{0x3864, 0x02},
+{0x3865, 0x00},
+{0x38A0, 0x01},
+{0x38A1, 0x01},
+{0x38A2, 0x00},
+{0x38A3, 0x01},
+{0x38A4, 0x07},
+{0x38A5, 0x00},
+{0x38A6, 0x04},
+{0x38A7, 0x05},
+{0x38A8, 0x00},
+{0x38A9, 0x00},
+{0x38AC, 0x00},
+{0x38AD, 0x00},
+{0x38AE, 0x01},
+{0x38B0, 0x02},
+{0x38B2, 0x22},
+{0x38B3, 0x00},
+{0x38B4, 0x17},
+{0x38B5, 0x00},
+{0x38B6, 0x11},
+{0x38B7, 0x00},
+{0x38B8, 0x0E},
+{0x38B9, 0x00},
+{0x38BA, 0x2A},
+{0x38BB, 0x00},
+{0x38BC, 0x1C},
+{0x38BD, 0x00},
+{0x38BE, 0x14},
+{0x38BF, 0x00},
+{0x38C0, 0x10},
+{0x38C1, 0x00},
+{0x38C2, 0x31},
+{0x38C3, 0x00},
+{0x38C4, 0x21},
+{0x38C5, 0x00},
+{0x38C6, 0x18},
+{0x38C7, 0x00},
+{0x38C8, 0x12},
+{0x38C9, 0x00},
+{0x38CA, 0x3C},
+{0x38CB, 0x00},
+{0x38CC, 0x29},
+{0x38CD, 0x00},
+{0x38CE, 0x1D},
+{0x38CF, 0x00},
+{0x38D0, 0x15},
+{0x38D1, 0x00},
+{0x38D2, 0x4E},
+{0x38D3, 0x00},
+{0x38D4, 0x35},
+{0x38D5, 0x00},
+{0x38D6, 0x26},
+{0x38D7, 0x00},
+{0x38D8, 0x1A},
+{0x38D9, 0x00},
+{0x38DA, 0x69},
+{0x38DB, 0x00},
+{0x38DC, 0x48},
+{0x38DD, 0x00},
+{0x38DE, 0x33},
+{0x38DF, 0x00},
+{0x38E0, 0x22},
+{0x38E1, 0x00},
+{0x38E2, 0x93},
+{0x38E3, 0x00},
+{0x38E4, 0x64},
+{0x38E5, 0x00},
+{0x38E6, 0x48},
+{0x38E7, 0x00},
+{0x38E8, 0x30},
+{0x38E9, 0x00},
+{0x38EA, 0xD3},
+{0x38EB, 0x00},
+{0x38EC, 0x90},
+{0x38ED, 0x00},
+{0x38EE, 0x69},
+{0x38EF, 0x00},
+{0x38F0, 0x49},
+{0x38F1, 0x00},
+{0x38F2, 0x39},
+{0x38F3, 0x01},
+{0x38F4, 0xD5},
+{0x38F5, 0x00},
+{0x38F6, 0x9F},
+{0x38F7, 0x00},
+{0x38F8, 0x75},
+{0x38F9, 0x00},
+{0x38FA, 0x00},
+{0x38FB, 0x01},
+{0x38FC, 0x00},
+{0x38FD, 0x01},
+{0x38FE, 0x00},
+{0x38FF, 0x01},
+{0x3900, 0x00},
+{0x3901, 0x01},
+{0x3902, 0x60},
+{0x3903, 0x00},
+{0x3904, 0x25},
+{0x3905, 0x00},
+{0x3906, 0x18},
+{0x3907, 0x00},
+{0x3908, 0x10},
+{0x3909, 0x00},
+{0x390A, 0xFF},
+{0x390B, 0x00},
+{0x390C, 0xD5},
+{0x390D, 0x00},
+{0x390E, 0xAA},
+{0x390F, 0x00},
+{0x3910, 0x85},
+{0x3911, 0x00},
+{0x3912, 0xFF},
+{0x3913, 0x00},
+{0x3914, 0xD5},
+{0x3915, 0x00},
+{0x3916, 0xAA},
+{0x3917, 0x00},
+{0x3918, 0x85},
+{0x3919, 0x00},
+{0x391A, 0xFF},
+{0x391B, 0x00},
+{0x391C, 0xD5},
+{0x391D, 0x00},
+{0x391E, 0xAA},
+{0x391F, 0x00},
+{0x3920, 0x85},
+{0x3921, 0x00},
+{0x3922, 0x40},
+{0x3923, 0x00},
+{0x3924, 0x40},
+{0x3925, 0x00},
+{0x3926, 0x40},
+{0x3927, 0x00},
+{0x3928, 0x40},
+{0x3929, 0x00},
+{0x392A, 0x80},
+{0x392B, 0x00},
+{0x392C, 0x80},
+{0x392D, 0x00},
+{0x392E, 0x80},
+{0x392F, 0x00},
+{0x3930, 0x80},
+{0x3931, 0x00},
+{0x3932, 0x4C},
+{0x3933, 0x4C},
+{0x3934, 0x4C},
+{0x3940, 0x01},
+{0x3941, 0x01},
+{0x3942, 0x00},
+{0x3943, 0x01},
+{0x3944, 0x07},
+{0x3945, 0x00},
+{0x3946, 0x04},
+{0x3947, 0x05},
+{0x3948, 0x00},
+{0x3949, 0x00},
+{0x394C, 0x00},
+{0x394D, 0x00},
+{0x394E, 0x01},
+{0x3950, 0x03},
+{0x3952, 0x14},
+{0x3953, 0x00},
+{0x3954, 0x0F},
+{0x3955, 0x00},
+{0x3956, 0x0E},
+{0x3957, 0x00},
+{0x3958, 0x0E},
+{0x3959, 0x00},
+{0x395A, 0x19},
+{0x395B, 0x00},
+{0x395C, 0x11},
+{0x395D, 0x00},
+{0x395E, 0x0F},
+{0x395F, 0x00},
+{0x3960, 0x0E},
+{0x3961, 0x00},
+{0x3962, 0x1C},
+{0x3963, 0x00},
+{0x3964, 0x13},
+{0x3965, 0x00},
+{0x3966, 0x0F},
+{0x3967, 0x00},
+{0x3968, 0x0E},
+{0x3969, 0x00},
+{0x396A, 0x23},
+{0x396B, 0x00},
+{0x396C, 0x15},
+{0x396D, 0x00},
+{0x396E, 0x11},
+{0x396F, 0x00},
+{0x3970, 0x0E},
+{0x3971, 0x00},
+{0x3972, 0x2E},
+{0x3973, 0x00},
+{0x3974, 0x1A},
+{0x3975, 0x00},
+{0x3976, 0x14},
+{0x3977, 0x00},
+{0x3978, 0x0F},
+{0x3979, 0x00},
+{0x397A, 0x3E},
+{0x397B, 0x00},
+{0x397C, 0x23},
+{0x397D, 0x00},
+{0x397E, 0x1A},
+{0x397F, 0x00},
+{0x3980, 0x12},
+{0x3981, 0x00},
+{0x3982, 0x56},
+{0x3983, 0x00},
+{0x3984, 0x31},
+{0x3985, 0x00},
+{0x3986, 0x25},
+{0x3987, 0x00},
+{0x3988, 0x1A},
+{0x3989, 0x00},
+{0x398A, 0x7B},
+{0x398B, 0x00},
+{0x398C, 0x49},
+{0x398D, 0x00},
+{0x398E, 0x39},
+{0x398F, 0x00},
+{0x3990, 0x2C},
+{0x3991, 0x00},
+{0x3992, 0xB4},
+{0x3993, 0x00},
+{0x3994, 0x75},
+{0x3995, 0x00},
+{0x3996, 0x61},
+{0x3997, 0x00},
+{0x3998, 0x53},
+{0x3999, 0x00},
+{0x399A, 0x00},
+{0x399B, 0x01},
+{0x399C, 0x00},
+{0x399D, 0x01},
+{0x399E, 0x00},
+{0x399F, 0x01},
+{0x39A0, 0x00},
+{0x39A1, 0x01},
+{0x39A2, 0x60},
+{0x39A3, 0x00},
+{0x39A4, 0x20},
+{0x39A5, 0x00},
+{0x39A6, 0x15},
+{0x39A7, 0x00},
+{0x39A8, 0x10},
+{0x39A9, 0x00},
+{0x39AA, 0xFF},
+{0x39AB, 0x00},
+{0x39AC, 0xD5},
+{0x39AD, 0x00},
+{0x39AE, 0xAA},
+{0x39AF, 0x00},
+{0x39B0, 0x85},
+{0x39B1, 0x00},
+{0x39B2, 0xFF},
+{0x39B3, 0x00},
+{0x39B4, 0xD5},
+{0x39B5, 0x00},
+{0x39B6, 0xAA},
+{0x39B7, 0x00},
+{0x39B8, 0x85},
+{0x39B9, 0x00},
+{0x39BA, 0xFF},
+{0x39BB, 0x00},
+{0x39BC, 0xD5},
+{0x39BD, 0x00},
+{0x39BE, 0xAA},
+{0x39BF, 0x00},
+{0x39C0, 0x85},
+{0x39C1, 0x00},
+{0x39C2, 0x40},
+{0x39C3, 0x00},
+{0x39C4, 0x40},
+{0x39C5, 0x00},
+{0x39C6, 0x40},
+{0x39C7, 0x00},
+{0x39C8, 0x40},
+{0x39C9, 0x00},
+{0x39CA, 0x80},
+{0x39CB, 0x00},
+{0x39CC, 0x80},
+{0x39CD, 0x00},
+{0x39CE, 0x80},
+{0x39CF, 0x00},
+{0x39D0, 0x80},
+{0x39D1, 0x00},
+{0x39D2, 0x4C},
+{0x39D3, 0x4C},
+{0x39D4, 0x4C},
+{0x39E0, 0x01},
+{0x39E1, 0x00},
+{0x39E4, 0x40},
+{0x39E5, 0x01},
+{0x39E6, 0x01},
+{0x39E8, 0x00},
+{0x39E9, 0x01},
+{0x39EA, 0x00},
+{0x39EB, 0x00},
+{0x39EC, 0x01},
+{0x39ED, 0x00},
+{0x39EE, 0x01},
+{0x39F0, 0x03},
+{0x39F1, 0x04},
+{0x39F2, 0x0E},
+{0x39F4, 0x1C},
+{0x39F5, 0x00},
+{0x39F6, 0x13},
+{0x39F7, 0x00},
+{0x39F8, 0x0D},
+{0x39F9, 0x00},
+{0x39FA, 0x07},
+{0x39FB, 0x00},
+{0x39FC, 0x38},
+{0x39FD, 0x00},
+{0x39FE, 0x1C},
+{0x39FF, 0x00},
+{0x3A00, 0x11},
+{0x3A01, 0x00},
+{0x3A02, 0x08},
+{0x3A03, 0x00},
+{0x3A04, 0x4A},
+{0x3A05, 0x00},
+{0x3A06, 0x23},
+{0x3A07, 0x00},
+{0x3A08, 0x15},
+{0x3A09, 0x00},
+{0x3A0A, 0x09},
+{0x3A0B, 0x00},
+{0x3A0C, 0x65},
+{0x3A0D, 0x00},
+{0x3A0E, 0x2D},
+{0x3A0F, 0x00},
+{0x3A10, 0x1A},
+{0x3A11, 0x00},
+{0x3A12, 0x0B},
+{0x3A13, 0x00},
+{0x3A14, 0x8D},
+{0x3A15, 0x00},
+{0x3A16, 0x3D},
+{0x3A17, 0x00},
+{0x3A18, 0x23},
+{0x3A19, 0x00},
+{0x3A1A, 0x0E},
+{0x3A1B, 0x00},
+{0x3A1C, 0xC5},
+{0x3A1D, 0x00},
+{0x3A1E, 0x55},
+{0x3A1F, 0x00},
+{0x3A20, 0x30},
+{0x3A21, 0x00},
+{0x3A22, 0x13},
+{0x3A23, 0x00},
+{0x3A24, 0x16},
+{0x3A25, 0x01},
+{0x3A26, 0x76},
+{0x3A27, 0x00},
+{0x3A28, 0x42},
+{0x3A29, 0x00},
+{0x3A2A, 0x1A},
+{0x3A2B, 0x00},
+{0x3A2C, 0x88},
+{0x3A2D, 0x01},
+{0x3A2E, 0xA7},
+{0x3A2F, 0x00},
+{0x3A30, 0x5D},
+{0x3A31, 0x00},
+{0x3A32, 0x24},
+{0x3A33, 0x00},
+{0x3A34, 0x2A},
+{0x3A35, 0x02},
+{0x3A36, 0xEB},
+{0x3A37, 0x00},
+{0x3A38, 0x83},
+{0x3A39, 0x00},
+{0x3A3A, 0x32},
+{0x3A3B, 0x00},
+{0x3A3C, 0x00},
+{0x3A3D, 0x01},
+{0x3A3E, 0x00},
+{0x3A3F, 0x01},
+{0x3A40, 0x00},
+{0x3A41, 0x01},
+{0x3A42, 0x00},
+{0x3A43, 0x01},
+{0x3A44, 0x70},
+{0x3A45, 0x00},
+{0x3A46, 0x25},
+{0x3A47, 0x00},
+{0x3A48, 0x18},
+{0x3A49, 0x00},
+{0x3A4A, 0x10},
+{0x3A4B, 0x00},
+{0x3A4C, 0xFF},
+{0x3A4D, 0x00},
+{0x3A4E, 0xD5},
+{0x3A4F, 0x00},
+{0x3A50, 0xAA},
+{0x3A51, 0x00},
+{0x3A52, 0x85},
+{0x3A53, 0x00},
+{0x3A54, 0xFF},
+{0x3A55, 0x00},
+{0x3A56, 0xD5},
+{0x3A57, 0x00},
+{0x3A58, 0xAA},
+{0x3A59, 0x00},
+{0x3A5A, 0x85},
+{0x3A5B, 0x00},
+{0x3A5C, 0xFF},
+{0x3A5D, 0x00},
+{0x3A5E, 0xD5},
+{0x3A5F, 0x00},
+{0x3A60, 0xAA},
+{0x3A61, 0x00},
+{0x3A62, 0x85},
+{0x3A63, 0x00},
+{0x3A64, 0x1C},
+{0x3A65, 0x00},
+{0x3A66, 0x13},
+{0x3A67, 0x00},
+{0x3A68, 0x0D},
+{0x3A69, 0x00},
+{0x3A6A, 0x07},
+{0x3A6B, 0x00},
+{0x3A6C, 0x0D},
+{0x3A6D, 0x00},
+{0x3A6E, 0x0B},
+{0x3A6F, 0x00},
+{0x3A70, 0x06},
+{0x3A71, 0x00},
+{0x3A72, 0x05},
+{0x3A73, 0x00},
+{0x3A74, 0x19},
+{0x3A75, 0x00},
+{0x3A76, 0x14},
+{0x3A77, 0x00},
+{0x3A78, 0x0F},
+{0x3A79, 0x00},
+{0x3A7A, 0x0A},
+{0x3A7B, 0x00},
+{0x3A7C, 0x80},
+{0x3A7D, 0x00},
+{0x3A7E, 0x80},
+{0x3A7F, 0x00},
+{0x3A80, 0x80},
+{0x3A81, 0x00},
+{0x3A82, 0x80},
+{0x3A83, 0x00},
+{0x3A84, 0x08},
+{0x3A85, 0x00},
+{0x3A86, 0x05},
+{0x3A87, 0x00},
+{0x3A88, 0x04},
+{0x3A89, 0x00},
+{0x3A8A, 0x03},
+{0x3A8B, 0x00},
+{0x3A8C, 0xCD},
+{0x3A8D, 0x00},
+{0x3A8E, 0xAA},
+{0x3A8F, 0x00},
+{0x3A90, 0x8C},
+{0x3A91, 0x00},
+{0x3A92, 0x64},
+{0x3A93, 0x00},
+{0x3A94, 0xCD},
+{0x3A95, 0x00},
+{0x3A96, 0xAA},
+{0x3A97, 0x00},
+{0x3A98, 0x8C},
+{0x3A99, 0x00},
+{0x3A9A, 0x64},
+{0x3A9B, 0x00},
+{0x3A9C, 0x08},
+{0x3A9D, 0x10},
+{0x3A9E, 0x4C},
+{0x3A9F, 0x4C},
+{0x3AA0, 0x4C},
+{0x3AA1, 0x04},
+{0x3AA2, 0x05},
+{0x3AC0, 0x01},
+{0x3AC4, 0x81},
+{0x3AC5, 0x00},
+{0x3AC6, 0x00},
+{0x3AC7, 0x00},
+{0x3AC8, 0x00},
+{0x3AC9, 0x00},
+{0x3ACA, 0x00},
+{0x3ACB, 0x00},
+{0x3ACC, 0x02},
+{0x3ACD, 0x00},
+{0x3ACE, 0x81},
+{0x3ACF, 0x00},
+{0x3AD0, 0x00},
+{0x3AD1, 0x00},
+{0x3AD2, 0xFD},
+{0x3AD3, 0x03},
+{0x3AD4, 0x02},
+{0x3AD5, 0x00},
+{0x3AD6, 0x00},
+{0x3AD7, 0x00},
+{0x3AD8, 0x81},
+{0x3AD9, 0x00},
+{0x3ADA, 0xFD},
+{0x3ADB, 0x03},
+{0x3ADC, 0xFF},
+{0x3ADD, 0x03},
+{0x3ADE, 0x01},
+{0x3ADF, 0x00},
+{0x3AE0, 0x01},
+{0x3AE1, 0x00},
+{0x3AE2, 0x7E},
+{0x3AE3, 0x00},
+{0x3AF4, 0x00},
+{0x3AF6, 0x40},
+{0x3AF7, 0x1E},
+{0x3AF8, 0x01},
+{0x3AFA, 0x63},
+{0x3AFB, 0x09},
+{0x3AFC, 0x11},
+{0x3AFD, 0x09},
+{0x3AFE, 0x00},
+{0x3AFF, 0x00},
+{0x3B00, 0x00},
+{0x3B01, 0x00},
+{0x3B02, 0x84},
+{0x3B03, 0x06},
+{0x3B04, 0x30},
+{0x3B05, 0x06},
+{0x3B06, 0x00},
+{0x3B07, 0x00},
+{0x3B08, 0x00},
+{0x3B09, 0x00},
+{0x3B0A, 0x00},
+{0x3B0B, 0x00},
+{0x3B0C, 0x00},
+{0x3B0D, 0x00},
+{0x3B0E, 0x00},
+{0x3B0F, 0x00},
+{0x3B10, 0x00},
+{0x3B11, 0x00},
+{0x3B12, 0x00},
+{0x3B13, 0x00},
+{0x3B14, 0x00},
+{0x3B15, 0x00},
+{0x3B16, 0x00},
+{0x3B17, 0x00},
+{0x3B18, 0x00},
+{0x3B19, 0x00},
+{0x3B1A, 0x00},
+{0x3B1B, 0x00},
+{0x3B1C, 0x00},
+{0x3B1D, 0x00},
+{0x3B1E, 0x00},
+{0x3B1F, 0x00},
+{0x3B20, 0x00},
+{0x3B21, 0x00},
+{0x3B22, 0x00},
+{0x3B23, 0x00},
+{0x3B24, 0x00},
+{0x3B25, 0x00},
+{0x3B26, 0x00},
+{0x3B27, 0x00},
+{0x3B28, 0x00},
+{0x3B29, 0x00},
+{0x3B2A, 0x00},
+{0x3B2C, 0x00},
+{0x3B2E, 0x00},
+{0x3B30, 0x00},
+{0x3B32, 0x0C},
+{0x4000, 0xD1},
+{0x4001, 0xC0},
+{0x4002, 0xC0},
+{0x4003, 0xB8},
+{0x4004, 0xC0},
+{0x4005, 0xB8},
+{0x4006, 0xB9},
+{0x4007, 0xB7},
+{0x4008, 0xB0},
+{0x4009, 0xAB},
+{0x400A, 0xAC},
+{0x400B, 0xAB},
+{0x400C, 0xA8},
+{0x400D, 0xA6},
+{0x400E, 0xA6},
+{0x400F, 0xA5},
+{0x4010, 0xA2},
+{0x4011, 0xA0},
+{0x4012, 0xA0},
+{0x4013, 0x9F},
+{0x4014, 0xA4},
+{0x4015, 0xA2},
+{0x4016, 0xA2},
+{0x4017, 0x9C},
+{0x4018, 0xA8},
+{0x4019, 0xA6},
+{0x401A, 0xA8},
+{0x401B, 0xAA},
+{0x401C, 0xB0},
+{0x401D, 0xAE},
+{0x401E, 0xAE},
+{0x401F, 0xAE},
+{0x4020, 0xBA},
+{0x4021, 0xAE},
+{0x4022, 0xAF},
+{0x4023, 0xAE},
+{0x4024, 0xC6},
+{0x4025, 0xBD},
+{0x4026, 0xBD},
+{0x4027, 0xBA},
+{0x4028, 0xB0},
+{0x4029, 0xA9},
+{0x402A, 0xAA},
+{0x402B, 0xA8},
+{0x402C, 0x9F},
+{0x402D, 0x9C},
+{0x402E, 0x9C},
+{0x402F, 0x9B},
+{0x4030, 0x93},
+{0x4031, 0x91},
+{0x4032, 0x92},
+{0x4033, 0x91},
+{0x4034, 0x8D},
+{0x4035, 0x8C},
+{0x4036, 0x8C},
+{0x4037, 0x8C},
+{0x4038, 0x8F},
+{0x4039, 0x8E},
+{0x403A, 0x8E},
+{0x403B, 0x8E},
+{0x403C, 0x98},
+{0x403D, 0x96},
+{0x403E, 0x96},
+{0x403F, 0x95},
+{0x4040, 0xA4},
+{0x4041, 0xA0},
+{0x4042, 0xA0},
+{0x4043, 0x9E},
+{0x4044, 0xB3},
+{0x4045, 0xAE},
+{0x4046, 0xAF},
+{0x4047, 0xAB},
+{0x4048, 0xC2},
+{0x4049, 0xB7},
+{0x404A, 0xB8},
+{0x404B, 0xB5},
+{0x404C, 0xAB},
+{0x404D, 0xA4},
+{0x404E, 0xA5},
+{0x404F, 0xA3},
+{0x4050, 0x99},
+{0x4051, 0x96},
+{0x4052, 0x96},
+{0x4053, 0x96},
+{0x4054, 0x8B},
+{0x4055, 0x8A},
+{0x4056, 0x8A},
+{0x4057, 0x8A},
+{0x4058, 0x82},
+{0x4059, 0x81},
+{0x405A, 0x81},
+{0x405B, 0x81},
+{0x405C, 0x85},
+{0x405D, 0x86},
+{0x405E, 0x85},
+{0x405F, 0x85},
+{0x4060, 0x90},
+{0x4061, 0x90},
+{0x4062, 0x8F},
+{0x4063, 0x8F},
+{0x4064, 0x9D},
+{0x4065, 0x9B},
+{0x4066, 0x9B},
+{0x4067, 0x9A},
+{0x4068, 0xAF},
+{0x4069, 0xAA},
+{0x406A, 0xAC},
+{0x406B, 0xAA},
+{0x406C, 0xC2},
+{0x406D, 0xB7},
+{0x406E, 0xB8},
+{0x406F, 0xB5},
+{0x4070, 0xAB},
+{0x4071, 0xA4},
+{0x4072, 0xA4},
+{0x4073, 0xA3},
+{0x4074, 0x99},
+{0x4075, 0x96},
+{0x4076, 0x96},
+{0x4077, 0x96},
+{0x4078, 0x8B},
+{0x4079, 0x8A},
+{0x407A, 0x8A},
+{0x407B, 0x8A},
+{0x407C, 0x82},
+{0x407D, 0x82},
+{0x407E, 0x82},
+{0x407F, 0x82},
+{0x4080, 0x85},
+{0x4081, 0x86},
+{0x4082, 0x86},
+{0x4083, 0x86},
+{0x4084, 0x90},
+{0x4085, 0x90},
+{0x4086, 0x8F},
+{0x4087, 0x8F},
+{0x4088, 0x9D},
+{0x4089, 0x9B},
+{0x408A, 0x9B},
+{0x408B, 0x99},
+{0x408C, 0xAE},
+{0x408D, 0xAA},
+{0x408E, 0xAA},
+{0x408F, 0xA7},
+{0x4090, 0xC7},
+{0x4091, 0xBA},
+{0x4092, 0xBC},
+{0x4093, 0xB9},
+{0x4094, 0xB1},
+{0x4095, 0xA8},
+{0x4096, 0xA8},
+{0x4097, 0xA7},
+{0x4098, 0x9F},
+{0x4099, 0x9B},
+{0x409A, 0x9B},
+{0x409B, 0x9B},
+{0x409C, 0x93},
+{0x409D, 0x91},
+{0x409E, 0x91},
+{0x409F, 0x91},
+{0x40A0, 0x8D},
+{0x40A1, 0x8C},
+{0x40A2, 0x8C},
+{0x40A3, 0x8C},
+{0x40A4, 0x8E},
+{0x40A5, 0x8E},
+{0x40A6, 0x8D},
+{0x40A7, 0x8D},
+{0x40A8, 0x96},
+{0x40A9, 0x95},
+{0x40AA, 0x95},
+{0x40AB, 0x94},
+{0x40AC, 0xA2},
+{0x40AD, 0x9F},
+{0x40AE, 0x9F},
+{0x40AF, 0x9D},
+{0x40B0, 0xB1},
+{0x40B1, 0xAC},
+{0x40B2, 0xAB},
+{0x40B3, 0xAA},
+{0x40B4, 0xD3},
+{0x40B5, 0xBC},
+{0x40B6, 0xBD},
+{0x40B7, 0xBC},
+{0x40B8, 0xC1},
+{0x40B9, 0xB7},
+{0x40BA, 0xB7},
+{0x40BB, 0xB5},
+{0x40BC, 0xB0},
+{0x40BD, 0xAA},
+{0x40BE, 0xAA},
+{0x40BF, 0xAA},
+{0x40C0, 0xA8},
+{0x40C1, 0xA4},
+{0x40C2, 0xA4},
+{0x40C3, 0xA4},
+{0x40C4, 0xA2},
+{0x40C5, 0x9F},
+{0x40C6, 0x9F},
+{0x40C7, 0x9F},
+{0x40C8, 0xA3},
+{0x40C9, 0xA0},
+{0x40CA, 0xA0},
+{0x40CB, 0xA0},
+{0x40CC, 0xA6},
+{0x40CD, 0xA3},
+{0x40CE, 0xA3},
+{0x40CF, 0xA2},
+{0x40D0, 0xAF},
+{0x40D1, 0xAB},
+{0x40D2, 0xAA},
+{0x40D3, 0xA8},
+{0x40D4, 0xBA},
+{0x40D5, 0xAE},
+{0x40D6, 0xAE},
+{0x40D7, 0xAB},
+{0x4100, 0xBD},
+{0x4101, 0xBA},
+{0x4102, 0xBD},
+{0x4103, 0xB7},
+{0x4104, 0xB7},
+{0x4105, 0xB7},
+{0x4106, 0xB8},
+{0x4107, 0xB5},
+{0x4108, 0xAB},
+{0x4109, 0xAA},
+{0x410A, 0xAC},
+{0x410B, 0xAB},
+{0x410C, 0xA4},
+{0x410D, 0xA5},
+{0x410E, 0xA5},
+{0x410F, 0xA4},
+{0x4110, 0x9F},
+{0x4111, 0xA0},
+{0x4112, 0xA0},
+{0x4113, 0x9F},
+{0x4114, 0xA0},
+{0x4115, 0xA0},
+{0x4116, 0xA0},
+{0x4117, 0x9F},
+{0x4118, 0xA1},
+{0x4119, 0xA1},
+{0x411A, 0xA1},
+{0x411B, 0xA0},
+{0x411C, 0xA7},
+{0x411D, 0xA6},
+{0x411E, 0xA6},
+{0x411F, 0xA6},
+{0x4120, 0xA7},
+{0x4121, 0xA6},
+{0x4122, 0xA6},
+{0x4123, 0xA3},
+{0x4124, 0xB9},
+{0x4125, 0xB9},
+{0x4126, 0xBA},
+{0x4127, 0xB8},
+{0x4128, 0xA6},
+{0x4129, 0xA7},
+{0x412A, 0xA7},
+{0x412B, 0xA6},
+{0x412C, 0x9B},
+{0x412D, 0x9B},
+{0x412E, 0x9B},
+{0x412F, 0x9B},
+{0x4130, 0x91},
+{0x4131, 0x92},
+{0x4132, 0x92},
+{0x4133, 0x91},
+{0x4134, 0x8C},
+{0x4135, 0x8C},
+{0x4136, 0x8C},
+{0x4137, 0x8C},
+{0x4138, 0x8D},
+{0x4139, 0x8D},
+{0x413A, 0x8D},
+{0x413B, 0x8D},
+{0x413C, 0x93},
+{0x413D, 0x93},
+{0x413E, 0x93},
+{0x413F, 0x92},
+{0x4140, 0x9A},
+{0x4141, 0x9A},
+{0x4142, 0x9A},
+{0x4143, 0x99},
+{0x4144, 0xA7},
+{0x4145, 0xA5},
+{0x4146, 0xA6},
+{0x4147, 0xA6},
+{0x4148, 0xB8},
+{0x4149, 0xB4},
+{0x414A, 0xB4},
+{0x414B, 0xB3},
+{0x414C, 0xA3},
+{0x414D, 0xA2},
+{0x414E, 0xA3},
+{0x414F, 0xA2},
+{0x4150, 0x96},
+{0x4151, 0x96},
+{0x4152, 0x96},
+{0x4153, 0x96},
+{0x4154, 0x8A},
+{0x4155, 0x8A},
+{0x4156, 0x8A},
+{0x4157, 0x8A},
+{0x4158, 0x82},
+{0x4159, 0x82},
+{0x415A, 0x82},
+{0x415B, 0x82},
+{0x415C, 0x84},
+{0x415D, 0x85},
+{0x415E, 0x84},
+{0x415F, 0x84},
+{0x4160, 0x8D},
+{0x4161, 0x8D},
+{0x4162, 0x8D},
+{0x4163, 0x8D},
+{0x4164, 0x96},
+{0x4165, 0x96},
+{0x4166, 0x96},
+{0x4167, 0x95},
+{0x4168, 0xA5},
+{0x4169, 0xA2},
+{0x416A, 0xA3},
+{0x416B, 0xA2},
+{0x416C, 0xB7},
+{0x416D, 0xB3},
+{0x416E, 0xB5},
+{0x416F, 0xB4},
+{0x4170, 0xA4},
+{0x4171, 0xA2},
+{0x4172, 0xA3},
+{0x4173, 0xA2},
+{0x4174, 0x97},
+{0x4175, 0x96},
+{0x4176, 0x96},
+{0x4177, 0x96},
+{0x4178, 0x8B},
+{0x4179, 0x8A},
+{0x417A, 0x8A},
+{0x417B, 0x8A},
+{0x417C, 0x81},
+{0x417D, 0x81},
+{0x417E, 0x81},
+{0x417F, 0x81},
+{0x4180, 0x84},
+{0x4181, 0x84},
+{0x4182, 0x84},
+{0x4183, 0x84},
+{0x4184, 0x8C},
+{0x4185, 0x8D},
+{0x4186, 0x8D},
+{0x4187, 0x8D},
+{0x4188, 0x95},
+{0x4189, 0x96},
+{0x418A, 0x96},
+{0x418B, 0x95},
+{0x418C, 0xA1},
+{0x418D, 0xA1},
+{0x418E, 0xA1},
+{0x418F, 0xA0},
+{0x4190, 0xBC},
+{0x4191, 0xB8},
+{0x4192, 0xB8},
+{0x4193, 0xB9},
+{0x4194, 0xA8},
+{0x4195, 0xA5},
+{0x4196, 0xA6},
+{0x4197, 0xA5},
+{0x4198, 0x9C},
+{0x4199, 0x9A},
+{0x419A, 0x9A},
+{0x419B, 0x9A},
+{0x419C, 0x91},
+{0x419D, 0x91},
+{0x419E, 0x91},
+{0x419F, 0x91},
+{0x41A0, 0x8B},
+{0x41A1, 0x8B},
+{0x41A2, 0x8B},
+{0x41A3, 0x8B},
+{0x41A4, 0x8C},
+{0x41A5, 0x8C},
+{0x41A6, 0x8C},
+{0x41A7, 0x8C},
+{0x41A8, 0x91},
+{0x41A9, 0x92},
+{0x41AA, 0x91},
+{0x41AB, 0x91},
+{0x41AC, 0x98},
+{0x41AD, 0x99},
+{0x41AE, 0x99},
+{0x41AF, 0x98},
+{0x41B0, 0xA3},
+{0x41B1, 0xA3},
+{0x41B2, 0xA3},
+{0x41B3, 0xA2},
+{0x41B4, 0xC1},
+{0x41B5, 0xB8},
+{0x41B6, 0xB9},
+{0x41B7, 0xBA},
+{0x41B8, 0xB8},
+{0x41B9, 0xB4},
+{0x41BA, 0xB4},
+{0x41BB, 0xB4},
+{0x41BC, 0xAA},
+{0x41BD, 0xA7},
+{0x41BE, 0xA7},
+{0x41BF, 0xA8},
+{0x41C0, 0xA4},
+{0x41C1, 0xA2},
+{0x41C2, 0xA2},
+{0x41C3, 0xA3},
+{0x41C4, 0x9E},
+{0x41C5, 0x9D},
+{0x41C6, 0x9D},
+{0x41C7, 0x9D},
+{0x41C8, 0x9E},
+{0x41C9, 0x9D},
+{0x41CA, 0x9D},
+{0x41CB, 0x9D},
+{0x41CC, 0x9E},
+{0x41CD, 0x9E},
+{0x41CE, 0x9E},
+{0x41CF, 0x9E},
+{0x41D0, 0xA3},
+{0x41D1, 0xA3},
+{0x41D2, 0xA2},
+{0x41D3, 0xA1},
+{0x41D4, 0xA7},
+{0x41D5, 0xA7},
+{0x41D6, 0xA7},
+{0x41D7, 0xA3},
+{0x4200, 0xCE},
+{0x4201, 0xC0},
+{0x4202, 0xC1},
+{0x4203, 0xB9},
+{0x4204, 0xC3},
+{0x4205, 0xB9},
+{0x4206, 0xBC},
+{0x4207, 0xBD},
+{0x4208, 0xB3},
+{0x4209, 0xAE},
+{0x420A, 0xAF},
+{0x420B, 0xAE},
+{0x420C, 0xAA},
+{0x420D, 0xA8},
+{0x420E, 0xA8},
+{0x420F, 0xA6},
+{0x4210, 0xA4},
+{0x4211, 0xA2},
+{0x4212, 0xA2},
+{0x4213, 0xA0},
+{0x4214, 0xA4},
+{0x4215, 0xA3},
+{0x4216, 0xA2},
+{0x4217, 0xA0},
+{0x4218, 0xA7},
+{0x4219, 0xA5},
+{0x421A, 0xA3},
+{0x421B, 0xA1},
+{0x421C, 0xB0},
+{0x421D, 0xA8},
+{0x421E, 0xA8},
+{0x421F, 0xA6},
+{0x4220, 0xB4},
+{0x4221, 0xAA},
+{0x4222, 0xA5},
+{0x4223, 0xA3},
+{0x4224, 0xC7},
+{0x4225, 0xBC},
+{0x4226, 0xBE},
+{0x4227, 0xBC},
+{0x4228, 0xB0},
+{0x4229, 0xA9},
+{0x422A, 0xA9},
+{0x422B, 0xA8},
+{0x422C, 0xA0},
+{0x422D, 0x9D},
+{0x422E, 0x9D},
+{0x422F, 0x9C},
+{0x4230, 0x94},
+{0x4231, 0x93},
+{0x4232, 0x93},
+{0x4233, 0x92},
+{0x4234, 0x8E},
+{0x4235, 0x8D},
+{0x4236, 0x8D},
+{0x4237, 0x8C},
+{0x4238, 0x8F},
+{0x4239, 0x8E},
+{0x423A, 0x8E},
+{0x423B, 0x8D},
+{0x423C, 0x96},
+{0x423D, 0x94},
+{0x423E, 0x94},
+{0x423F, 0x92},
+{0x4240, 0xA1},
+{0x4241, 0x9C},
+{0x4242, 0x9C},
+{0x4243, 0x99},
+{0x4244, 0xB0},
+{0x4245, 0xA8},
+{0x4246, 0xAB},
+{0x4247, 0xA7},
+{0x4248, 0xC3},
+{0x4249, 0xB7},
+{0x424A, 0xB7},
+{0x424B, 0xBC},
+{0x424C, 0xAB},
+{0x424D, 0xA4},
+{0x424E, 0xA5},
+{0x424F, 0xA5},
+{0x4250, 0x9A},
+{0x4251, 0x97},
+{0x4252, 0x97},
+{0x4253, 0x98},
+{0x4254, 0x8C},
+{0x4255, 0x8B},
+{0x4256, 0x8B},
+{0x4257, 0x8B},
+{0x4258, 0x82},
+{0x4259, 0x82},
+{0x425A, 0x82},
+{0x425B, 0x82},
+{0x425C, 0x85},
+{0x425D, 0x85},
+{0x425E, 0x85},
+{0x425F, 0x84},
+{0x4260, 0x8F},
+{0x4261, 0x8E},
+{0x4262, 0x8E},
+{0x4263, 0x8D},
+{0x4264, 0x9B},
+{0x4265, 0x98},
+{0x4266, 0x98},
+{0x4267, 0x95},
+{0x4268, 0xAE},
+{0x4269, 0xA5},
+{0x426A, 0xA7},
+{0x426B, 0xA2},
+{0x426C, 0xC2},
+{0x426D, 0xB7},
+{0x426E, 0xB8},
+{0x426F, 0xB9},
+{0x4270, 0xAA},
+{0x4271, 0xA4},
+{0x4272, 0xA4},
+{0x4273, 0xA5},
+{0x4274, 0x99},
+{0x4275, 0x96},
+{0x4276, 0x97},
+{0x4277, 0x98},
+{0x4278, 0x8B},
+{0x4279, 0x8A},
+{0x427A, 0x8A},
+{0x427B, 0x8B},
+{0x427C, 0x81},
+{0x427D, 0x81},
+{0x427E, 0x81},
+{0x427F, 0x82},
+{0x4280, 0x84},
+{0x4281, 0x84},
+{0x4282, 0x84},
+{0x4283, 0x84},
+{0x4284, 0x8E},
+{0x4285, 0x8E},
+{0x4286, 0x8D},
+{0x4287, 0x8C},
+{0x4288, 0x9A},
+{0x4289, 0x97},
+{0x428A, 0x97},
+{0x428B, 0x95},
+{0x428C, 0xAA},
+{0x428D, 0xA3},
+{0x428E, 0xA3},
+{0x428F, 0xA2},
+{0x4290, 0xC7},
+{0x4291, 0xBA},
+{0x4292, 0xC0},
+{0x4293, 0xC3},
+{0x4294, 0xB0},
+{0x4295, 0xA7},
+{0x4296, 0xA7},
+{0x4297, 0xA9},
+{0x4298, 0x9F},
+{0x4299, 0x9B},
+{0x429A, 0x9B},
+{0x429B, 0x9D},
+{0x429C, 0x93},
+{0x429D, 0x91},
+{0x429E, 0x91},
+{0x429F, 0x92},
+{0x42A0, 0x8C},
+{0x42A1, 0x8B},
+{0x42A2, 0x8B},
+{0x42A3, 0x8C},
+{0x42A4, 0x8D},
+{0x42A5, 0x8C},
+{0x42A6, 0x8C},
+{0x42A7, 0x8C},
+{0x42A8, 0x94},
+{0x42A9, 0x93},
+{0x42AA, 0x92},
+{0x42AB, 0x91},
+{0x42AC, 0x9E},
+{0x42AD, 0x9B},
+{0x42AE, 0x9B},
+{0x42AF, 0x98},
+{0x42B0, 0xAC},
+{0x42B1, 0xA6},
+{0x42B2, 0xA6},
+{0x42B3, 0xA2},
+{0x42B4, 0xCE},
+{0x42B5, 0xBA},
+{0x42B6, 0xBC},
+{0x42B7, 0xB7},
+{0x42B8, 0xC5},
+{0x42B9, 0xB5},
+{0x42BA, 0xBA},
+{0x42BB, 0xC0},
+{0x42BC, 0xB1},
+{0x42BD, 0xA8},
+{0x42BE, 0xAE},
+{0x42BF, 0xAF},
+{0x42C0, 0xA7},
+{0x42C1, 0xA3},
+{0x42C2, 0xA3},
+{0x42C3, 0xA5},
+{0x42C4, 0xA0},
+{0x42C5, 0x9D},
+{0x42C6, 0x9D},
+{0x42C7, 0x9F},
+{0x42C8, 0xA0},
+{0x42C9, 0x9E},
+{0x42CA, 0x9E},
+{0x42CB, 0x9F},
+{0x42CC, 0xA2},
+{0x42CD, 0xA0},
+{0x42CE, 0xA0},
+{0x42CF, 0xA0},
+{0x42D0, 0xA8},
+{0x42D1, 0xA5},
+{0x42D2, 0xA5},
+{0x42D3, 0xA2},
+{0x42D4, 0xB3},
+{0x42D5, 0xAA},
+{0x42D6, 0xAB},
+{0x42D7, 0xA3},
+{0x42D8, 0x00},
+{0x42D9, 0x00},
+{0x4300, 0xA2},
+{0x4301, 0xAE},
+{0x4302, 0xAD},
+{0x4303, 0xB5},
+{0x4304, 0x95},
+{0x4305, 0x9A},
+{0x4306, 0x98},
+{0x4307, 0x9B},
+{0x4308, 0x8D},
+{0x4309, 0x90},
+{0x430A, 0x8F},
+{0x430B, 0x91},
+{0x430C, 0x86},
+{0x430D, 0x88},
+{0x430E, 0x87},
+{0x430F, 0x89},
+{0x4310, 0x86},
+{0x4311, 0x87},
+{0x4312, 0x86},
+{0x4313, 0x88},
+{0x4314, 0x89},
+{0x4315, 0x88},
+{0x4316, 0x88},
+{0x4317, 0x8E},
+{0x4318, 0x90},
+{0x4319, 0x8F},
+{0x431A, 0x8C},
+{0x431B, 0x8C},
+{0x431C, 0x9C},
+{0x431D, 0x99},
+{0x431E, 0x98},
+{0x431F, 0x99},
+{0x4320, 0xAB},
+{0x4321, 0xB0},
+{0x4322, 0xAD},
+{0x4323, 0xAF},
+{0x4324, 0x9B},
+{0x4325, 0x9F},
+{0x4326, 0x9E},
+{0x4327, 0xA1},
+{0x4328, 0x8E},
+{0x4329, 0x91},
+{0x432A, 0x90},
+{0x432B, 0x93},
+{0x432C, 0x86},
+{0x432D, 0x88},
+{0x432E, 0x87},
+{0x432F, 0x89},
+{0x4330, 0x82},
+{0x4331, 0x84},
+{0x4332, 0x83},
+{0x4333, 0x84},
+{0x4334, 0x82},
+{0x4335, 0x82},
+{0x4336, 0x82},
+{0x4337, 0x83},
+{0x4338, 0x85},
+{0x4339, 0x84},
+{0x433A, 0x84},
+{0x433B, 0x85},
+{0x433C, 0x8A},
+{0x433D, 0x89},
+{0x433E, 0x88},
+{0x433F, 0x89},
+{0x4340, 0x93},
+{0x4341, 0x91},
+{0x4342, 0x91},
+{0x4343, 0x93},
+{0x4344, 0xA0},
+{0x4345, 0x9E},
+{0x4346, 0x9D},
+{0x4347, 0xA1},
+{0x4348, 0x95},
+{0x4349, 0x9B},
+{0x434A, 0x9A},
+{0x434B, 0x9C},
+{0x434C, 0x8A},
+{0x434D, 0x8D},
+{0x434E, 0x8C},
+{0x434F, 0x8D},
+{0x4350, 0x83},
+{0x4351, 0x85},
+{0x4352, 0x84},
+{0x4353, 0x85},
+{0x4354, 0x80},
+{0x4355, 0x81},
+{0x4356, 0x81},
+{0x4357, 0x81},
+{0x4358, 0x80},
+{0x4359, 0x80},
+{0x435A, 0x80},
+{0x435B, 0x80},
+{0x435C, 0x82},
+{0x435D, 0x81},
+{0x435E, 0x81},
+{0x435F, 0x81},
+{0x4360, 0x85},
+{0x4361, 0x84},
+{0x4362, 0x84},
+{0x4363, 0x85},
+{0x4364, 0x8D},
+{0x4365, 0x8B},
+{0x4366, 0x8B},
+{0x4367, 0x8D},
+{0x4368, 0x98},
+{0x4369, 0x98},
+{0x436A, 0x95},
+{0x436B, 0x98},
+{0x436C, 0x95},
+{0x436D, 0x9A},
+{0x436E, 0x99},
+{0x436F, 0x9A},
+{0x4370, 0x8A},
+{0x4371, 0x8D},
+{0x4372, 0x8C},
+{0x4373, 0x8C},
+{0x4374, 0x83},
+{0x4375, 0x85},
+{0x4376, 0x84},
+{0x4377, 0x84},
+{0x4378, 0x80},
+{0x4379, 0x80},
+{0x437A, 0x80},
+{0x437B, 0x80},
+{0x437C, 0x7F},
+{0x437D, 0x7F},
+{0x437E, 0x7F},
+{0x437F, 0x7F},
+{0x4380, 0x81},
+{0x4381, 0x80},
+{0x4382, 0x80},
+{0x4383, 0x81},
+{0x4384, 0x84},
+{0x4385, 0x83},
+{0x4386, 0x83},
+{0x4387, 0x84},
+{0x4388, 0x8B},
+{0x4389, 0x8A},
+{0x438A, 0x8A},
+{0x438B, 0x8C},
+{0x438C, 0x97},
+{0x438D, 0x96},
+{0x438E, 0x96},
+{0x438F, 0x99},
+{0x4390, 0x99},
+{0x4391, 0x9F},
+{0x4392, 0x9E},
+{0x4393, 0x9D},
+{0x4394, 0x8D},
+{0x4395, 0x90},
+{0x4396, 0x90},
+{0x4397, 0x8F},
+{0x4398, 0x85},
+{0x4399, 0x87},
+{0x439A, 0x87},
+{0x439B, 0x86},
+{0x439C, 0x81},
+{0x439D, 0x83},
+{0x439E, 0x82},
+{0x439F, 0x82},
+{0x43A0, 0x80},
+{0x43A1, 0x81},
+{0x43A2, 0x81},
+{0x43A3, 0x81},
+{0x43A4, 0x82},
+{0x43A5, 0x82},
+{0x43A6, 0x82},
+{0x43A7, 0x82},
+{0x43A8, 0x86},
+{0x43A9, 0x85},
+{0x43AA, 0x85},
+{0x43AB, 0x87},
+{0x43AC, 0x8D},
+{0x43AD, 0x8D},
+{0x43AE, 0x8D},
+{0x43AF, 0x90},
+{0x43B0, 0x9A},
+{0x43B1, 0x9A},
+{0x43B2, 0x9B},
+{0x43B3, 0x9D},
+{0x43B4, 0xA0},
+{0x43B5, 0xAD},
+{0x43B6, 0xAC},
+{0x43B7, 0xAA},
+{0x43B8, 0x93},
+{0x43B9, 0x97},
+{0x43BA, 0x97},
+{0x43BB, 0x96},
+{0x43BC, 0x8B},
+{0x43BD, 0x8E},
+{0x43BE, 0x8E},
+{0x43BF, 0x8C},
+{0x43C0, 0x83},
+{0x43C1, 0x85},
+{0x43C2, 0x85},
+{0x43C3, 0x84},
+{0x43C4, 0x82},
+{0x43C5, 0x84},
+{0x43C6, 0x83},
+{0x43C7, 0x83},
+{0x43C8, 0x83},
+{0x43C9, 0x84},
+{0x43CA, 0x84},
+{0x43CB, 0x85},
+{0x43CC, 0x8A},
+{0x43CD, 0x8A},
+{0x43CE, 0x8A},
+{0x43CF, 0x8C},
+{0x43D0, 0x92},
+{0x43D1, 0x93},
+{0x43D2, 0x93},
+{0x43D3, 0x96},
+{0x43D4, 0x9F},
+{0x43D5, 0xA6},
+{0x43D6, 0xA5},
+{0x43D7, 0xAA},
+{0x4400, 0xA1},
+{0x4401, 0xAB},
+{0x4402, 0xA7},
+{0x4403, 0xB0},
+{0x4404, 0x91},
+{0x4405, 0x96},
+{0x4406, 0x94},
+{0x4407, 0x99},
+{0x4408, 0x8A},
+{0x4409, 0x8E},
+{0x440A, 0x8C},
+{0x440B, 0x8F},
+{0x440C, 0x85},
+{0x440D, 0x86},
+{0x440E, 0x86},
+{0x440F, 0x88},
+{0x4410, 0x85},
+{0x4411, 0x86},
+{0x4412, 0x85},
+{0x4413, 0x87},
+{0x4414, 0x88},
+{0x4415, 0x87},
+{0x4416, 0x87},
+{0x4417, 0x89},
+{0x4418, 0x91},
+{0x4419, 0x8F},
+{0x441A, 0x8F},
+{0x441B, 0x90},
+{0x441C, 0x9C},
+{0x441D, 0x9B},
+{0x441E, 0x9A},
+{0x441F, 0x9A},
+{0x4420, 0xB3},
+{0x4421, 0xB1},
+{0x4422, 0xB0},
+{0x4423, 0xB2},
+{0x4424, 0x96},
+{0x4425, 0x9C},
+{0x4426, 0x9A},
+{0x4427, 0x9E},
+{0x4428, 0x8B},
+{0x4429, 0x8F},
+{0x442A, 0x8E},
+{0x442B, 0x91},
+{0x442C, 0x84},
+{0x442D, 0x87},
+{0x442E, 0x86},
+{0x442F, 0x88},
+{0x4430, 0x82},
+{0x4431, 0x83},
+{0x4432, 0x82},
+{0x4433, 0x84},
+{0x4434, 0x82},
+{0x4435, 0x82},
+{0x4436, 0x82},
+{0x4437, 0x83},
+{0x4438, 0x84},
+{0x4439, 0x84},
+{0x443A, 0x84},
+{0x443B, 0x84},
+{0x443C, 0x8B},
+{0x443D, 0x89},
+{0x443E, 0x89},
+{0x443F, 0x89},
+{0x4440, 0x95},
+{0x4441, 0x93},
+{0x4442, 0x93},
+{0x4443, 0x93},
+{0x4444, 0xA2},
+{0x4445, 0xA2},
+{0x4446, 0xA1},
+{0x4447, 0xA0},
+{0x4448, 0x8F},
+{0x4449, 0x97},
+{0x444A, 0x97},
+{0x444B, 0x98},
+{0x444C, 0x87},
+{0x444D, 0x8B},
+{0x444E, 0x8A},
+{0x444F, 0x8B},
+{0x4450, 0x81},
+{0x4451, 0x83},
+{0x4452, 0x83},
+{0x4453, 0x84},
+{0x4454, 0x7F},
+{0x4455, 0x80},
+{0x4456, 0x80},
+{0x4457, 0x81},
+{0x4458, 0x80},
+{0x4459, 0x80},
+{0x445A, 0x80},
+{0x445B, 0x80},
+{0x445C, 0x82},
+{0x445D, 0x81},
+{0x445E, 0x81},
+{0x445F, 0x81},
+{0x4460, 0x87},
+{0x4461, 0x85},
+{0x4462, 0x85},
+{0x4463, 0x86},
+{0x4464, 0x90},
+{0x4465, 0x8E},
+{0x4466, 0x8E},
+{0x4467, 0x8E},
+{0x4468, 0x9B},
+{0x4469, 0x9C},
+{0x446A, 0x9A},
+{0x446B, 0x9A},
+{0x446C, 0x91},
+{0x446D, 0x97},
+{0x446E, 0x95},
+{0x446F, 0x95},
+{0x4470, 0x87},
+{0x4471, 0x8A},
+{0x4472, 0x8A},
+{0x4473, 0x89},
+{0x4474, 0x81},
+{0x4475, 0x83},
+{0x4476, 0x83},
+{0x4477, 0x83},
+{0x4478, 0x7F},
+{0x4479, 0x80},
+{0x447A, 0x80},
+{0x447B, 0x80},
+{0x447C, 0x80},
+{0x447D, 0x80},
+{0x447E, 0x80},
+{0x447F, 0x7F},
+{0x4480, 0x81},
+{0x4481, 0x81},
+{0x4482, 0x81},
+{0x4483, 0x81},
+{0x4484, 0x85},
+{0x4485, 0x85},
+{0x4486, 0x85},
+{0x4487, 0x85},
+{0x4488, 0x8E},
+{0x4489, 0x8D},
+{0x448A, 0x8D},
+{0x448B, 0x8E},
+{0x448C, 0x9D},
+{0x448D, 0x9C},
+{0x448E, 0x9C},
+{0x448F, 0x9C},
+{0x4490, 0x94},
+{0x4491, 0x9B},
+{0x4492, 0x9A},
+{0x4493, 0x97},
+{0x4494, 0x8A},
+{0x4495, 0x8E},
+{0x4496, 0x8E},
+{0x4497, 0x8C},
+{0x4498, 0x84},
+{0x4499, 0x86},
+{0x449A, 0x86},
+{0x449B, 0x84},
+{0x449C, 0x81},
+{0x449D, 0x83},
+{0x449E, 0x83},
+{0x449F, 0x81},
+{0x44A0, 0x81},
+{0x44A1, 0x82},
+{0x44A2, 0x82},
+{0x44A3, 0x81},
+{0x44A4, 0x83},
+{0x44A5, 0x83},
+{0x44A6, 0x83},
+{0x44A7, 0x83},
+{0x44A8, 0x88},
+{0x44A9, 0x88},
+{0x44AA, 0x88},
+{0x44AB, 0x88},
+{0x44AC, 0x91},
+{0x44AD, 0x91},
+{0x44AE, 0x91},
+{0x44AF, 0x92},
+{0x44B0, 0xA0},
+{0x44B1, 0xA0},
+{0x44B2, 0xA0},
+{0x44B3, 0xA0},
+{0x44B4, 0x9E},
+{0x44B5, 0xA9},
+{0x44B6, 0xA8},
+{0x44B7, 0xA3},
+{0x44B8, 0x90},
+{0x44B9, 0x95},
+{0x44BA, 0x95},
+{0x44BB, 0x92},
+{0x44BC, 0x8A},
+{0x44BD, 0x8E},
+{0x44BE, 0x8E},
+{0x44BF, 0x8B},
+{0x44C0, 0x84},
+{0x44C1, 0x86},
+{0x44C2, 0x86},
+{0x44C3, 0x84},
+{0x44C4, 0x84},
+{0x44C5, 0x85},
+{0x44C6, 0x85},
+{0x44C7, 0x84},
+{0x44C8, 0x86},
+{0x44C9, 0x87},
+{0x44CA, 0x87},
+{0x44CB, 0x86},
+{0x44CC, 0x8D},
+{0x44CD, 0x8E},
+{0x44CE, 0x8E},
+{0x44CF, 0x8D},
+{0x44D0, 0x98},
+{0x44D1, 0x98},
+{0x44D2, 0x99},
+{0x44D3, 0x9A},
+{0x44D4, 0xA9},
+{0x44D5, 0xAA},
+{0x44D6, 0xAA},
+{0x44D7, 0xAD},
+{0x4500, 0x9F},
+{0x4501, 0xA8},
+{0x4502, 0xA5},
+{0x4503, 0xAF},
+{0x4504, 0x8F},
+{0x4505, 0x96},
+{0x4506, 0x92},
+{0x4507, 0x94},
+{0x4508, 0x89},
+{0x4509, 0x8D},
+{0x450A, 0x8A},
+{0x450B, 0x8E},
+{0x450C, 0x84},
+{0x450D, 0x85},
+{0x450E, 0x84},
+{0x450F, 0x87},
+{0x4510, 0x84},
+{0x4511, 0x85},
+{0x4512, 0x84},
+{0x4513, 0x86},
+{0x4514, 0x87},
+{0x4515, 0x86},
+{0x4516, 0x86},
+{0x4517, 0x88},
+{0x4518, 0x8F},
+{0x4519, 0x8D},
+{0x451A, 0x8D},
+{0x451B, 0x8F},
+{0x451C, 0x9A},
+{0x451D, 0x9A},
+{0x451E, 0x98},
+{0x451F, 0x9A},
+{0x4520, 0xAF},
+{0x4521, 0xAF},
+{0x4522, 0xB2},
+{0x4523, 0xB1},
+{0x4524, 0x95},
+{0x4525, 0x9B},
+{0x4526, 0x97},
+{0x4527, 0x9C},
+{0x4528, 0x8A},
+{0x4529, 0x8E},
+{0x452A, 0x8D},
+{0x452B, 0x90},
+{0x452C, 0x84},
+{0x452D, 0x86},
+{0x452E, 0x85},
+{0x452F, 0x87},
+{0x4530, 0x81},
+{0x4531, 0x82},
+{0x4532, 0x82},
+{0x4533, 0x83},
+{0x4534, 0x81},
+{0x4535, 0x81},
+{0x4536, 0x81},
+{0x4537, 0x82},
+{0x4538, 0x84},
+{0x4539, 0x83},
+{0x453A, 0x83},
+{0x453B, 0x84},
+{0x453C, 0x8A},
+{0x453D, 0x88},
+{0x453E, 0x88},
+{0x453F, 0x89},
+{0x4540, 0x94},
+{0x4541, 0x92},
+{0x4542, 0x91},
+{0x4543, 0x92},
+{0x4544, 0xA1},
+{0x4545, 0xA0},
+{0x4546, 0x9C},
+{0x4547, 0x9D},
+{0x4548, 0x8F},
+{0x4549, 0x96},
+{0x454A, 0x95},
+{0x454B, 0x92},
+{0x454C, 0x87},
+{0x454D, 0x8A},
+{0x454E, 0x89},
+{0x454F, 0x8A},
+{0x4550, 0x81},
+{0x4551, 0x83},
+{0x4552, 0x82},
+{0x4553, 0x83},
+{0x4554, 0x7F},
+{0x4555, 0x80},
+{0x4556, 0x80},
+{0x4557, 0x81},
+{0x4558, 0x7F},
+{0x4559, 0x80},
+{0x455A, 0x7F},
+{0x455B, 0x80},
+{0x455C, 0x81},
+{0x455D, 0x81},
+{0x455E, 0x81},
+{0x455F, 0x81},
+{0x4560, 0x86},
+{0x4561, 0x85},
+{0x4562, 0x85},
+{0x4563, 0x85},
+{0x4564, 0x8F},
+{0x4565, 0x8D},
+{0x4566, 0x8D},
+{0x4567, 0x8D},
+{0x4568, 0x99},
+{0x4569, 0x9A},
+{0x456A, 0x97},
+{0x456B, 0x99},
+{0x456C, 0x90},
+{0x456D, 0x95},
+{0x456E, 0x93},
+{0x456F, 0x92},
+{0x4570, 0x87},
+{0x4571, 0x8A},
+{0x4572, 0x88},
+{0x4573, 0x87},
+{0x4574, 0x81},
+{0x4575, 0x83},
+{0x4576, 0x82},
+{0x4577, 0x82},
+{0x4578, 0x7F},
+{0x4579, 0x80},
+{0x457A, 0x80},
+{0x457B, 0x80},
+{0x457C, 0x80},
+{0x457D, 0x80},
+{0x457E, 0x80},
+{0x457F, 0x80},
+{0x4580, 0x81},
+{0x4581, 0x81},
+{0x4582, 0x81},
+{0x4583, 0x81},
+{0x4584, 0x85},
+{0x4585, 0x85},
+{0x4586, 0x84},
+{0x4587, 0x85},
+{0x4588, 0x8E},
+{0x4589, 0x8D},
+{0x458A, 0x8C},
+{0x458B, 0x8D},
+{0x458C, 0x9B},
+{0x458D, 0x9B},
+{0x458E, 0x9A},
+{0x458F, 0x98},
+{0x4590, 0x94},
+{0x4591, 0x9A},
+{0x4592, 0x94},
+{0x4593, 0x90},
+{0x4594, 0x8A},
+{0x4595, 0x8D},
+{0x4596, 0x8C},
+{0x4597, 0x89},
+{0x4598, 0x84},
+{0x4599, 0x86},
+{0x459A, 0x85},
+{0x459B, 0x83},
+{0x459C, 0x82},
+{0x459D, 0x83},
+{0x459E, 0x82},
+{0x459F, 0x80},
+{0x45A0, 0x81},
+{0x45A1, 0x82},
+{0x45A2, 0x81},
+{0x45A3, 0x80},
+{0x45A4, 0x83},
+{0x45A5, 0x83},
+{0x45A6, 0x83},
+{0x45A7, 0x83},
+{0x45A8, 0x88},
+{0x45A9, 0x87},
+{0x45AA, 0x87},
+{0x45AB, 0x88},
+{0x45AC, 0x91},
+{0x45AD, 0x90},
+{0x45AE, 0x90},
+{0x45AF, 0x91},
+{0x45B0, 0x9F},
+{0x45B1, 0x9F},
+{0x45B2, 0x9E},
+{0x45B3, 0x9F},
+{0x45B4, 0x9F},
+{0x45B5, 0xA8},
+{0x45B6, 0xA6},
+{0x45B7, 0xA7},
+{0x45B8, 0x8D},
+{0x45B9, 0x95},
+{0x45BA, 0x90},
+{0x45BB, 0x8A},
+{0x45BC, 0x89},
+{0x45BD, 0x8D},
+{0x45BE, 0x88},
+{0x45BF, 0x86},
+{0x45C0, 0x84},
+{0x45C1, 0x86},
+{0x45C2, 0x85},
+{0x45C3, 0x82},
+{0x45C4, 0x84},
+{0x45C5, 0x85},
+{0x45C6, 0x85},
+{0x45C7, 0x83},
+{0x45C8, 0x86},
+{0x45C9, 0x86},
+{0x45CA, 0x86},
+{0x45CB, 0x85},
+{0x45CC, 0x8E},
+{0x45CD, 0x8D},
+{0x45CE, 0x8D},
+{0x45CF, 0x8C},
+{0x45D0, 0x99},
+{0x45D1, 0x98},
+{0x45D2, 0x98},
+{0x45D3, 0x98},
+{0x45D4, 0xA6},
+{0x45D5, 0xA9},
+{0x45D6, 0xA7},
+{0x45D7, 0xAC},
+{0x7000, 0xAB},
+{0x7001, 0xBA},
+{0x7002, 0x40},
+{0x7003, 0x02},
+{0x7004, 0x00},
+{0x7005, 0x00},
+{0x7006, 0x00},
+{0x7007, 0x00},
+{0x7008, 0x00},
+{0x7009, 0x00},
+{0x700A, 0x00},
+{0x700B, 0x00},
+{0x700C, 0x00},
+{0x700D, 0x00},
+{0x700E, 0x00},
+{0x700F, 0x00},
+{0x7010, 0x55},
+{0x7011, 0x88},
+{0x7012, 0x40},
+{0x7013, 0x01},
+{0x7014, 0x72},
+{0x7015, 0xF1},
+{0x7016, 0x02},
+{0x7017, 0xF8},
+{0x7018, 0x00},
+{0x7019, 0x00},
+{0x701A, 0x00},
+{0x701B, 0x00},
+{0x701C, 0x00},
+{0x701D, 0x00},
+{0x701E, 0x00},
+{0x701F, 0x00},
+{0x7020, 0x00},
+{0x7021, 0x00},
+{0x7022, 0x00},
+{0x7023, 0x00},
+{0x7024, 0x00},
+{0x7025, 0x00},
+{0x7026, 0x00},
+{0x7027, 0x00},
+{0x7028, 0x00},
+{0x7029, 0x00},
+{0x702A, 0x00},
+{0x702B, 0x00},
+{0x702C, 0x00},
+{0x702D, 0x00},
+{0x702E, 0x00},
+{0x702F, 0x00},
+{0x7030, 0x00},
+{0x7031, 0x00},
+{0x7032, 0x00},
+{0x7033, 0x00},
+{0x7034, 0x00},
+{0x7035, 0x00},
+{0x7036, 0x00},
+{0x7037, 0x00},
+{0x7038, 0x00},
+{0x7039, 0x00},
+{0x703A, 0x00},
+{0x703B, 0x00},
+{0x703C, 0x00},
+{0x703D, 0x00},
+{0x703E, 0x00},
+{0x703F, 0x00},
+{0x7040, 0x00},
+{0x7041, 0x00},
+{0x7042, 0x00},
+{0x7043, 0x00},
+{0x7044, 0x00},
+{0x7045, 0x00},
+{0x7046, 0x00},
+{0x7047, 0x00},
+{0x7048, 0x00},
+{0x7049, 0x00},
+{0x704A, 0x00},
+{0x704B, 0x00},
+{0x704C, 0x00},
+{0x704D, 0x00},
+{0x704E, 0x00},
+{0x704F, 0x00},
+{0x7050, 0x00},
+{0x7051, 0x00},
+{0x7052, 0x00},
+{0x7053, 0x00},
+{0x7054, 0x00},
+{0x7055, 0x00},
+{0x7056, 0x00},
+{0x7057, 0x00},
+{0x7058, 0x00},
+{0x7059, 0x00},
+{0x705A, 0x00},
+{0x705B, 0x00},
+{0x705C, 0x00},
+{0x705D, 0x00},
+{0x705E, 0x00},
+{0x705F, 0x00},
+{0x7060, 0x00},
+{0x7061, 0x00},
+{0x7062, 0x00},
+{0x7063, 0x00},
+{0x7064, 0x00},
+{0x7065, 0x00},
+{0x7066, 0x00},
+{0x7067, 0x00},
+{0x7068, 0x00},
+{0x7069, 0x00},
+{0x706A, 0x00},
+{0x706B, 0x00},
+{0x706C, 0x00},
+{0x706D, 0x00},
+{0x706E, 0x00},
+{0x706F, 0x00},
+{0x7070, 0x00},
+{0x7071, 0x00},
+{0x7072, 0x00},
+{0x7073, 0x00},
+{0x7074, 0x00},
+{0x7075, 0x00},
+{0x7076, 0x00},
+{0x7077, 0x00},
+{0x7078, 0x00},
+{0x7079, 0x00},
+{0x707A, 0x00},
+{0x707B, 0x00},
+{0x707C, 0x00},
+{0x707D, 0x00},
+{0x707E, 0x00},
+{0x707F, 0x00},
+{0x7080, 0x00},
+{0x7081, 0x00},
+{0x7082, 0x00},
+{0x7083, 0x00},
+{0x7084, 0x00},
+{0x7085, 0x00},
+{0x7086, 0x00},
+{0x7087, 0x00},
+{0x7088, 0x00},
+{0x7089, 0x00},
+{0x708A, 0x00},
+{0x708B, 0x00},
+{0x708C, 0x00},
+{0x708D, 0x00},
+{0x708E, 0x00},
+{0x708F, 0x00},
+{0x7090, 0x00},
+{0x7091, 0xF0},
+{0x7092, 0x02},
+{0x7093, 0xF8},
+{0x7094, 0x8D},
+{0x7095, 0xF6},
+{0x7096, 0xFA},
+{0x7097, 0xFF},
+{0x7098, 0xF0},
+{0x7099, 0xB5},
+{0x709A, 0x04},
+{0x709B, 0x46},
+{0x709C, 0x8F},
+{0x709D, 0xB0},
+{0x709E, 0x5F},
+{0x709F, 0x48},
+{0x70A0, 0x0C},
+{0x70A1, 0x90},
+{0x70A2, 0x5F},
+{0x70A3, 0x48},
+{0x70A4, 0x06},
+{0x70A5, 0x90},
+{0x70A6, 0x20},
+{0x70A7, 0x46},
+{0x70A8, 0x34},
+{0x70A9, 0x30},
+{0x70AA, 0x0B},
+{0x70AB, 0x90},
+{0x70AC, 0x5B},
+{0x70AD, 0x48},
+{0x70AE, 0x5A},
+{0x70AF, 0x49},
+{0x70B0, 0x26},
+{0x70B1, 0x46},
+{0x70B2, 0x66},
+{0x70B3, 0x30},
+{0x70B4, 0x3A},
+{0x70B5, 0x31},
+{0x70B6, 0x3C},
+{0x70B7, 0x36},
+{0x70B8, 0x05},
+{0x70B9, 0x90},
+{0x70BA, 0x0A},
+{0x70BB, 0x30},
+{0x70BC, 0x04},
+{0x70BD, 0x90},
+{0x70BE, 0x59},
+{0x70BF, 0x48},
+{0x70C0, 0x55},
+{0x70C1, 0x4A},
+{0x70C2, 0x40},
+{0x70C3, 0x6E},
+{0x70C4, 0xC0},
+{0x70C5, 0x07},
+{0x70C6, 0x7D},
+{0x70C7, 0xD1},
+{0x70C8, 0x17},
+{0x70C9, 0x88},
+{0x70CA, 0x0A},
+{0x70CB, 0x5E},
+{0x70CC, 0x0D},
+{0x70CD, 0x92},
+{0x70CE, 0x53},
+{0x70CF, 0x49},
+{0x70D0, 0x55},
+{0x70D1, 0x48},
+{0x70D2, 0x94},
+{0x70D3, 0x31},
+{0x70D4, 0x89},
+{0x70D5, 0x6B},
+{0x70D6, 0x80},
+{0x70D7, 0x68},
+{0x70D8, 0x09},
+{0x70D9, 0x02},
+{0x70DA, 0x00},
+{0x70DB, 0x03},
+{0x70DC, 0x09},
+{0x70DD, 0x0E},
+{0x70DE, 0x00},
+{0x70DF, 0x0B},
+{0x70E0, 0x49},
+{0x70E1, 0x1C},
+{0x70E2, 0x48},
+{0x70E3, 0x43},
+{0x70E4, 0x4D},
+{0x70E5, 0x49},
+{0x70E6, 0x6C},
+{0x70E7, 0x39},
+{0x70E8, 0x8A},
+{0x70E9, 0x6A},
+{0x70EA, 0x07},
+{0x70EB, 0x92},
+{0x70EC, 0xCA},
+{0x70ED, 0x6A},
+{0x70EE, 0x00},
+{0x70EF, 0x21},
+{0x70F0, 0xC9},
+{0x70F1, 0x43},
+{0x70F2, 0x03},
+{0x70F3, 0x92},
+{0x70F4, 0x00},
+{0x70F5, 0x22},
+{0x70F6, 0x00},
+{0x70F7, 0x91},
+{0x70F8, 0x01},
+{0x70F9, 0x92},
+{0x70FA, 0x39},
+{0x70FB, 0x46},
+{0x70FC, 0x8F},
+{0x70FD, 0xF6},
+{0x70FE, 0xCE},
+{0x70FF, 0xFB},
+{0x7100, 0x01},
+{0x7101, 0x22},
+{0x7102, 0x00},
+{0x7103, 0x23},
+{0x7104, 0x8C},
+{0x7105, 0xF6},
+{0x7106, 0x02},
+{0x7107, 0xFA},
+{0x7108, 0x00},
+{0x7109, 0x21},
+{0x710A, 0x05},
+{0x710B, 0x46},
+{0x710C, 0x01},
+{0x710D, 0x91},
+{0x710E, 0x00},
+{0x710F, 0x90},
+{0x7110, 0x39},
+{0x7111, 0x46},
+{0x7112, 0x07},
+{0x7113, 0x98},
+{0x7114, 0x8F},
+{0x7115, 0xF6},
+{0x7116, 0xC2},
+{0x7117, 0xFB},
+{0x7118, 0x0D},
+{0x7119, 0x9A},
+{0x711A, 0xD3},
+{0x711B, 0x17},
+{0x711C, 0x80},
+{0x711D, 0x18},
+{0x711E, 0x59},
+{0x711F, 0x41},
+{0x7120, 0x01},
+{0x7121, 0x22},
+{0x7122, 0x00},
+{0x7123, 0x23},
+{0x7124, 0x8C},
+{0x7125, 0xF6},
+{0x7126, 0xCD},
+{0x7127, 0xF9},
+{0x7128, 0x07},
+{0x7129, 0x90},
+{0x712A, 0x00},
+{0x712B, 0x20},
+{0x712C, 0x01},
+{0x712D, 0x90},
+{0x712E, 0x00},
+{0x712F, 0x95},
+{0x7130, 0x39},
+{0x7131, 0x46},
+{0x7132, 0x03},
+{0x7133, 0x98},
+{0x7134, 0x8F},
+{0x7135, 0xF6},
+{0x7136, 0xB2},
+{0x7137, 0xFB},
+{0x7138, 0x01},
+{0x7139, 0x22},
+{0x713A, 0x00},
+{0x713B, 0x23},
+{0x713C, 0x8C},
+{0x713D, 0xF6},
+{0x713E, 0xE6},
+{0x713F, 0xF9},
+{0x7140, 0x02},
+{0x7141, 0x46},
+{0x7142, 0x07},
+{0x7143, 0x98},
+{0x7144, 0x00},
+{0x7145, 0x23},
+{0x7146, 0x81},
+{0x7147, 0x0B},
+{0x7148, 0x80},
+{0x7149, 0x04},
+{0x714A, 0x7A},
+{0x714B, 0xF6},
+{0x714C, 0x54},
+{0x714D, 0xF8},
+{0x714E, 0x37},
+{0x714F, 0x4A},
+{0x7150, 0x00},
+{0x7151, 0x23},
+{0x7152, 0x00},
+{0x7153, 0x92},
+{0x7154, 0x01},
+{0x7155, 0x93},
+{0x7156, 0x01},
+{0x7157, 0x22},
+{0x7158, 0x8C},
+{0x7159, 0xF6},
+{0x715A, 0xD8},
+{0x715B, 0xF9},
+{0x715C, 0x05},
+{0x715D, 0x46},
+{0x715E, 0x60},
+{0x715F, 0x68},
+{0x7160, 0x00},
+{0x7161, 0x23},
+{0x7162, 0x01},
+{0x7163, 0x0C},
+{0x7164, 0x00},
+{0x7165, 0x04},
+{0x7166, 0xE2},
+{0x7167, 0x68},
+{0x7168, 0x7A},
+{0x7169, 0xF6},
+{0x716A, 0x45},
+{0x716B, 0xF8},
+{0x716C, 0x00},
+{0x716D, 0x22},
+{0x716E, 0xD2},
+{0x716F, 0x43},
+{0x7170, 0x00},
+{0x7171, 0x23},
+{0x7172, 0x00},
+{0x7173, 0x92},
+{0x7174, 0x01},
+{0x7175, 0x93},
+{0x7176, 0x1A},
+{0x7177, 0x46},
+{0x7178, 0x8C},
+{0x7179, 0xF6},
+{0x717A, 0xC8},
+{0x717B, 0xF9},
+{0x717C, 0x29},
+{0x717D, 0x46},
+{0x717E, 0x8F},
+{0x717F, 0xF6},
+{0x7180, 0x8D},
+{0x7181, 0xFB},
+{0x7182, 0x8A},
+{0x7183, 0x03},
+{0x7184, 0x80},
+{0x7185, 0x0C},
+{0x7186, 0x10},
+{0x7187, 0x43},
+{0x7188, 0x00},
+{0x7189, 0x22},
+{0x718A, 0xD2},
+{0x718B, 0x43},
+{0x718C, 0x00},
+{0x718D, 0x23},
+{0x718E, 0x00},
+{0x718F, 0x92},
+{0x7190, 0x89},
+{0x7191, 0x0C},
+{0x7192, 0x01},
+{0x7193, 0x93},
+{0x7194, 0x1A},
+{0x7195, 0x46},
+{0x7196, 0x8C},
+{0x7197, 0xF6},
+{0x7198, 0xB9},
+{0x7199, 0xF9},
+{0x719A, 0x00},
+{0x719B, 0x24},
+{0x719C, 0x03},
+{0x719D, 0x90},
+{0x719E, 0x0C},
+{0x719F, 0x98},
+{0x71A0, 0x61},
+{0x71A1, 0x00},
+{0x71A2, 0x45},
+{0x71A3, 0x5A},
+{0x71A4, 0x06},
+{0x71A5, 0x98},
+{0x71A6, 0x22},
+{0x71A7, 0x4A},
+{0x71A8, 0x40},
+{0x71A9, 0x5A},
+{0x71AA, 0x00},
+{0x71AB, 0x21},
+{0x71AC, 0x8C},
+{0x71AD, 0xF6},
+{0x71AE, 0xBE},
+{0x71AF, 0xF9},
+{0x71B0, 0x07},
+{0x71B1, 0x46},
+{0x71B2, 0x28},
+{0x71B3, 0x46},
+{0x71B4, 0x03},
+{0x71B5, 0x99},
+{0x71B6, 0x8F},
+{0x71B7, 0xF6},
+{0x71B8, 0x71},
+{0x71B9, 0xFB},
+{0x71BA, 0x3A},
+{0x71BB, 0x46},
+{0x71BC, 0x00},
+{0x71BD, 0x23},
+{0x71BE, 0x79},
+{0x71BF, 0xF6},
+{0x71C0, 0xCA},
+{0x71C1, 0xFF},
+{0x71C2, 0x00},
+{0x71C3, 0xE0},
+{0x71C4, 0x0F},
+{0x71C5, 0xE0},
+{0x71C6, 0x8A},
+{0x71C7, 0x02},
+{0x71C8, 0x80},
+{0x71C9, 0x0D},
+{0x71CA, 0x10},
+{0x71CB, 0x43},
+{0x71CC, 0x19},
+{0x71CD, 0x4A},
+{0x71CE, 0x00},
+{0x71CF, 0x23},
+{0x71D0, 0x00},
+{0x71D1, 0x92},
+{0x71D2, 0x89},
+{0x71D3, 0x0D},
+{0x71D4, 0x01},
+{0x71D5, 0x93},
+{0x71D6, 0x40},
+{0x71D7, 0x22},
+{0x71D8, 0x8C},
+{0x71D9, 0xF6},
+{0x71DA, 0x98},
+{0x71DB, 0xF9},
+{0x71DC, 0xA1},
+{0x71DD, 0x00},
+{0x71DE, 0x64},
+{0x71DF, 0x1C},
+{0x71E0, 0x70},
+{0x71E1, 0x50},
+{0x71E2, 0x04},
+{0x71E3, 0x2C},
+{0x71E4, 0xDB},
+{0x71E5, 0xD3},
+{0x71E6, 0x14},
+{0x71E7, 0x4D},
+{0x71E8, 0x00},
+{0x71E9, 0x24},
+{0x71EA, 0x0B},
+{0x71EB, 0x98},
+{0x71EC, 0x67},
+{0x71ED, 0x00},
+{0x71EE, 0xC0},
+{0x71EF, 0x5B},
+{0x71F0, 0x2A},
+{0x71F1, 0x46},
+{0x71F2, 0x40},
+{0x71F3, 0x21},
+{0x71F4, 0x8C},
+{0x71F5, 0xF6},
+{0x71F6, 0x9A},
+{0x71F7, 0xF9},
+{0x71F8, 0x05},
+{0x71F9, 0x99},
+{0x71FA, 0x0E},
+{0x71FB, 0x4A},
+{0x71FC, 0xC8},
+{0x71FD, 0x53},
+{0x71FE, 0xA7},
+{0x71FF, 0x00},
+{0x7200, 0xF0},
+{0x7201, 0x59},
+{0x7202, 0x40},
+{0x7203, 0x21},
+{0x7204, 0x8C},
+{0x7205, 0xF6},
+{0x7206, 0x7B},
+{0x7207, 0xF9},
+{0x7208, 0x04},
+{0x7209, 0x99},
+{0x720A, 0x64},
+{0x720B, 0x1C},
+{0x720C, 0xC8},
+{0x720D, 0x51},
+{0x720E, 0x04},
+{0x720F, 0x2C},
+{0x7210, 0xEB},
+{0x7211, 0xD3},
+{0x7212, 0x0F},
+{0x7213, 0xB0},
+{0x7214, 0xF0},
+{0x7215, 0xBD},
+{0x7216, 0x00},
+{0x7217, 0x00},
+{0x7218, 0x76},
+{0x7219, 0x69},
+{0x721A, 0x18},
+{0x721B, 0x00},
+{0x721C, 0xEC},
+{0x721D, 0x58},
+{0x721E, 0x18},
+{0x721F, 0x00},
+{0x7220, 0x38},
+{0x7221, 0x36},
+{0x7222, 0x18},
+{0x7223, 0x00},
+{0x7224, 0x00},
+{0x7225, 0x35},
+{0x7226, 0x18},
+{0x7227, 0x00},
+{0x7228, 0x00},
+{0x7229, 0x20},
+{0x722A, 0x18},
+{0x722B, 0x00},
+{0x722C, 0xFF},
+{0x722D, 0xFF},
+{0x722E, 0xFF},
+{0x722F, 0x3F},
+{0x7230, 0xFF},
+{0x7231, 0x07},
+{0x7232, 0x00},
+{0x7233, 0x00},
+{0x7234, 0xFF},
+{0x7235, 0xFF},
+{0x7236, 0x07},
+{0x7237, 0x00},
+{0x7238, 0xFF},
+{0x7239, 0x1F},
+{0x723A, 0x00},
+{0x723B, 0x00},
+{0x723C, 0x01},
+{0x723D, 0xF6},
+{0x723E, 0x45},
+{0x723F, 0x12},
+{0x0000, 0x00},
+};
diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c
index d01acdc..88eab02 100644
--- a/drivers/media/i2c/soc_camera/max9286.c
+++ b/drivers/media/i2c/soc_camera/max9286.c
@@ -17,10 +17,8 @@
 #include <linux/of_graph.h>
 #include <linux/videodev2.h>
 
-#include <media/v4l2-async.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
-#include <media/v4l2-fwnode.h>
 #include <media/v4l2-subdev.h>
 
 #include "max9286.h"
@@ -45,6 +43,7 @@ struct max9286_priv {
 	int			csi_rate;
 	const char		*fsync_mode;
 	int			fsync_period;
+	int			pclk;
 	char			pclk_rising_edge;
 	int			gpio_resetb;
 	int			active_low_resetb;
@@ -53,12 +52,26 @@ struct max9286_priv {
 	int			vsync;
 	int			timeout;
 	int			poc_delay;
+	int			bws;
+	int			dbl;
+	int			dt;
+	int			hsgen;
+	int			hts;
+	int			vts;
+	int			hts_delay;
+	int			imager_width;
 	atomic_t		use_count;
 	u32			csi2_outord;
+	u32			switchin;
 	struct i2c_client	*client;
 	int			max9271_addr_map[4];
 	int			ser_id;
 	struct gpio_desc	*poc_gpio[4]; /* PoC power supply */
+
+	/* link statistic */
+	int			prbserr[4];
+	int			deterr[4];
+	int			correrr[4];
 };
 
 static char fsync_mode_default[20] = "manual"; /* manual, automatic, semi-automatic, external */
@@ -95,9 +108,57 @@ static int active_low_resetb;
 module_param(active_low_resetb, int, 0644);
 MODULE_PARM_DESC(active_low_resetb, " Serializer GPIO reset level (default: 0 - active high)");
 
-static int poc_delay;
+static int poc_delay = 50;
 module_param(poc_delay, int, 0644);
-MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms)");
+MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 50 ms)");
+
+static int bws;
+module_param(bws, int, 0644);
+MODULE_PARM_DESC(bws, " BWS mode (default: 0 - 24-bit gmsl packets)");
+
+static int dbl = 1;
+module_param(dbl, int, 0644);
+MODULE_PARM_DESC(dbl, " DBL mode (default: 1 - DBL mode enabled)");
+
+static int dt = 3;
+module_param(dt, int, 0644);
+MODULE_PARM_DESC(dt, " DataType (default: 3 - YUV8), 0 - RGB888, 5 - RAW8, 6 - RAW10, 7 - RAW12, 8 - RAW14");
+
+static int hsgen;
+module_param(hsgen, int, 0644);
+MODULE_PARM_DESC(hsgen, " Enable HS embedded generator (default: 0 - disabled)");
+
+static int pclk = 100;
+module_param(pclk, int, 0644);
+MODULE_PARM_DESC(pclk, " PCLK rate (default: 100MHz)");
+
+static int switchin = 0;
+module_param(switchin, int, 0644);
+MODULE_PARM_DESC(switchin, " COAX SWITCH IN+ and IN- (default: 0 - not switched)");
+
+enum {
+	RGB888_DT = 0,
+	RGB565_DT,
+	RGB666_DT,
+	YUV8_DT, /* default */
+	YUV10_DT,
+	RAW8_DT,
+	RAW10_DT,
+	RAW12_DT,
+	RAW14_DT,
+};
+
+static int dt2bpp [9] = {
+	24,	/* RGB888 */
+	16,	/* RGB565 */
+	18,	/* RGB666 */
+	8,	/* YUV8 - default */
+	10,	/* YUV10 */
+	8,	/* RAW8/RAW16 */
+	10,	/* RAW10 */
+	12,	/* RAW12 */
+	14,	/* RAW14 */
+};
 
 static char* ser_name(int id)
 {
@@ -106,11 +167,42 @@ static char* ser_name(int id)
 		return "MAX9271";
 	case MAX96705_ID:
 		return "MAX96705";
+	case MAX96707_ID:
+		return "MAX96707";
 	default:
 		return "unknown";
 	}
 }
 
+static void max9286_write_remote_verify(struct i2c_client *client, int idx, u8 reg, u8 val)
+{
+	struct max9286_priv *priv = i2c_get_clientdata(client);
+	int timeout;
+
+	for (timeout = 0; timeout < 10; timeout++) {
+		int tmp_addr;
+		u8 sts = 0;
+		u8 val2 = 0;
+
+		reg8_write(client, reg, val);
+
+		tmp_addr = client->addr;
+		client->addr = priv->des_addr;			/* MAX9286-CAMx I2C */
+		reg8_read(client, 0x70, &sts);
+		client->addr = tmp_addr;
+		if (sts & BIT(idx)) /* if ACKed */ {
+			reg8_read(client, reg, &val2);
+			if (val2 == val)
+				break;
+		}
+
+		usleep_range(1000, 1500);
+	}
+
+	if (timeout >= 10)
+		dev_err(&client->dev, "timeout remote write acked\n");
+}
+
 static void max9286_preinit(struct i2c_client *client, int addr)
 {
 	struct max9286_priv *priv = i2c_get_clientdata(client);
@@ -118,8 +210,9 @@ static void max9286_preinit(struct i2c_client *client, int addr)
 	client->addr = addr;			/* MAX9286-CAMx I2C */
 	reg8_write(client, 0x0a, 0x00);		/* disable reverse control for all cams */
 	reg8_write(client, 0x00, 0x00);		/* disable all GMSL links [0:3] */
-	usleep_range(2000, 2500);		/* wait 2ms after any change of reverse channel settings */
-	reg8_write(client, 0x1c, priv->him ? 0xf4 : 0x04); /* high-immunity or legacy mode */
+//	usleep_range(2000, 2500);		/* wait 2ms after any change of reverse channel settings */
+	reg8_write(client, 0x1b, priv->switchin); /* coax polarity (default - normal) */
+	reg8_write(client, 0x1c, priv->him ? 0xf4 : 0x04); /* high-immunity/legacy mode, BWS: 24-bit */
 }
 
 static void max9286_sensor_reset(struct i2c_client *client, int addr, int reset_on)
@@ -142,11 +235,16 @@ static void max9286_postinit(struct i2c_client *client, int addr)
 	int idx;
 
 	for (idx = 0; idx < priv->links; idx++) {
+		if (priv->ser_id == MAX96705_ID || priv->ser_id == MAX96707_ID)
+			continue;
+
 		client->addr = priv->des_addr;			/* MAX9286 I2C */
+		reg8_write(client, 0x00, 0xe0 | BIT(idx));	/* enable GMSL link for CAMx */
 		reg8_write(client, 0x0a, 0x11 << idx);		/* enable reverse/forward control for CAMx */
+		usleep_range(5000, 5500);			/* wait 2ms after any change of reverse channel settings */
 
 		client->addr = priv->max9271_addr_map[idx];	/* MAX9271-CAMx I2C */
-		max9286_sensor_reset(client, client->addr, 0); /* sensor unreset */
+		max9286_sensor_reset(client, client->addr, 0);	/* sensor unreset using gpios. TODO: should be in imager driver */
 	}
 
 	client->addr = addr;					/* MAX9286 I2C */
@@ -154,7 +252,9 @@ static void max9286_postinit(struct i2c_client *client, int addr)
 	reg8_write(client, 0x00, 0xe0 | priv->links_mask);	/* enable GMSL link for CAMs */
 	reg8_write(client, 0x0b, priv->csi2_outord);		/* CSI2 output order */
 	reg8_write(client, 0x15, 0x9b);				/* enable CSI output, VC is set accordingly to Link number, BIT7 magic must be set */
-	reg8_write(client, 0x1b, priv->links_mask);		/* enable equalizer for CAMs */
+	reg8_write(client, 0x1b, priv->switchin | priv->links_mask); /* coax polarity, enable equalizer for CAMs */
+	reg8_write(client, 0x1c, (priv->him ? 0xf0 : 0x00) |
+				 (priv->bws ? 0x05 : 0x04));	/* high-immunity/legacy mode, BWS 24/32-bit */
 	usleep_range(5000, 5500);				/* wait 2ms after any change of reverse channel settings */
 
 	if (strcmp(priv->fsync_mode, "manual") == 0) {
@@ -178,7 +278,6 @@ static int max9286_reverse_channel_setup(struct i2c_client *client, int idx)
 
 	/* Reverse channel enable */
 	client->addr = priv->des_addr;				/* MAX9286-CAMx I2C */
-	reg8_write(client, 0x3f, 0x4f);				/* enable custom reverse channel & first pulse length */
 	reg8_write(client, 0x34, 0xa2 | MAXIM_I2C_I2C_SPEED);	/* enable artificial ACKs, I2C speed set */
 	usleep_range(2000, 2500);				/* wait 2ms after any change of reverse channel settings */
 	reg8_write(client, 0x00, 0xe0 | BIT(idx));		/* enable GMSL link for CAMx */
@@ -186,24 +285,35 @@ static int max9286_reverse_channel_setup(struct i2c_client *client, int idx)
 	usleep_range(2000, 2500);				/* wait 2ms after any change of reverse channel settings */
 
 	for (;;) {
-		client->addr = priv->des_addr;			/* MAX9286-CAMx I2C */
-		reg8_write(client, 0x3b, 0x1e);			/* first pulse length rise time changed from 300ns to 200ns, amplitude 100mV */
-		usleep_range(2000, 2500);			/* wait 2ms after any change of reverse channel settings */
+		if (priv->him) {
+			/* HIM mode setup */
+			client->addr = 0x40;			/* MAX9271-CAMx I2C */
+			reg8_write(client, 0x4d, 0xc0);
+			usleep_range(2000, 2500);		/* wait 2ms after any change of reverse channel settings */
+			reg8_write(client, 0x04, 0x43);		/* wake-up, enable reverse_control/conf_link */
+			usleep_range(2000, 2500);		/* wait 2ms after any change of reverse channel settings */
+		} else {
+			/* Legacy mode setup */
+			client->addr = priv->des_addr;		/* MAX9286-CAMx I2C */
+			reg8_write(client, 0x3f, 0x4f);		/* enable custom reverse channel & first pulse length */
+			reg8_write(client, 0x3b, 0x1e);		/* first pulse length rise time changed from 300ns to 200ns, amplitude 100mV */
+			usleep_range(2000, 2500);		/* wait 2ms after any change of reverse channel settings */
 
-		client->addr = 0x40;				/* MAX9271-CAMx I2C */
-		reg8_write(client, 0x04, 0x43);			/* wake-up, enable reverse_control/conf_link */
-		usleep_range(2000, 2500);			/* wait 2ms after any change of reverse channel settings */
-		reg8_write(client, 0x08, 0x01);			/* reverse channel receiver high threshold enable */
-		reg8_write(client, 0x97, priv->him ? 0xaf : 0x5f); /* enable reverse control channel programming (MAX96705-MAX96711 only) */
-		usleep_range(2000, 2500);			/* wait 2ms after any change of reverse channel settings */
+			client->addr = 0x40;			/* MAX9271-CAMx I2C */
+			reg8_write(client, 0x04, 0x43);		/* wake-up, enable reverse_control/conf_link */
+			usleep_range(2000, 2500);		/* wait 2ms after any change of reverse channel settings */
+			reg8_write(client, 0x08, 0x01);		/* reverse channel receiver high threshold enable */
+			reg8_write(client, 0x97, 0x5f);		/* enable reverse control channel programming (MAX96705-MAX96711 only) */
+			usleep_range(2000, 2500);		/* wait 2ms after any change of reverse channel settings */
 
-		client->addr = priv->des_addr;			/* MAX9286-CAMx I2C */
-		reg8_write(client, 0x3b, 0x19);			/* reverse channel increase amplitude 170mV to compensate high threshold enabled */
-		usleep_range(2000, 2500);			/* wait 2ms after any change of reverse channel settings */
+			client->addr = priv->des_addr;		/* MAX9286-CAMx I2C */
+			reg8_write(client, 0x3b, 0x19);		/* reverse channel increase amplitude 170mV to compensate high threshold enabled */
+			usleep_range(2000, 2500);		/* wait 2ms after any change of reverse channel settings */
+		}
 
 		client->addr = 0x40;				/* MAX9271-CAMx I2C */
 		reg8_read(client, 0x1e, &val);			/* read max9271 ID */
-		if (val == MAX9271_ID || val == MAX96705_ID || --timeout == 0) {
+		if (val == MAX9271_ID || val == MAX96705_ID || val == MAX96707_ID || --timeout == 0) {
 			priv->ser_id = val;
 			break;
 		}
@@ -211,7 +321,7 @@ static int max9286_reverse_channel_setup(struct i2c_client *client, int idx)
 		/* Check if already initialized (after reboot/reset ?) */
 		client->addr = priv->max9271_addr_map[idx];	/* MAX9271-CAMx I2C */
 		reg8_read(client, 0x1e, &val);			/* read max9271 ID */
-		if (val == MAX9271_ID || val == MAX96705_ID) {
+		if (val == MAX9271_ID || val == MAX96705_ID || val == MAX96707_ID) {
 			priv->ser_id = val;
 			reg8_write(client, 0x04, 0x43);		/* enable reverse_control/conf_link */
 			usleep_range(2000, 2500);		/* wait 2ms after any change of reverse channel settings */
@@ -258,22 +368,9 @@ static void max9286_initial_setup(struct i2c_client *client)
 	client->addr = priv->des_addr;				/* MAX9286-CAMx I2C */
 	reg8_write(client, 0x15, 0x13);				/* disable CSI output, VC is set accordingly to Link number */
 	reg8_write(client, 0x69, 0x0f);				/* mask CSI forwarding from all links */
-	switch (priv->lanes) {
-	case 1:
-		reg8_write(client, 0x12, 0x33);			/* enable CSI-2 Lane D0, DBL mode, YUV422 8-bit*/
-		break;
-	case 2:
-		reg8_write(client, 0x12, 0x73);			/* enable CSI-2 Lanes D0,D1, DBL mode, YUV422 8-bit*/
-		break;
-	case 3:
-		reg8_write(client, 0x12, 0xd3);			/* enable CSI-2 Lanes D0-D2, DBL mode, YUV422 8-bit*/
-		break;
-	case 4:
-		reg8_write(client, 0x12, 0xf3);			/* enable CSI-2 Lanes D0-D3, DBL mode, YUV422 8-bit*/
-		break;
-	default:
-		dev_err(&client->dev, "CSI2 lanes number is invalid (%d)\n", priv->lanes);
-	}
+	reg8_write(client, 0x12, ((priv->lanes - 1) << 6) |
+				 (priv->dbl ? 0x30 : 0) |
+				 (priv->dt & 0xf));		/* setup lanes, DBL mode, DataType */
 
 	/* Start GMSL initialization with FSYNC disabled. This is required for some odd LVDS cameras */
 	reg8_write(client, 0x01, 0xc0);				/* ECU (aka MCU) based FrameSync using GPI-to-GPO */
@@ -294,30 +391,96 @@ static void max9286_gmsl_link_setup(struct i2c_client *client, int idx)
 	/* GMSL setup */
 	client->addr = 0x40;					/* MAX9271-CAMx I2C */
 	reg8_write(client, 0x0d, 0x22 | MAXIM_I2C_I2C_SPEED);	/* disable artificial ACK, I2C speed set */
-	reg8_write(client, 0x07, 0x84 | (priv->pclk_rising_edge ? 0 : 0x10)); /* RAW/YUV, PCLK edge, HS/VS encoding enabled */
+	reg8_write(client, 0x07, 0x04 | (priv->pclk_rising_edge ? 0 : 0x10) | (priv->dbl ? 0x80 : 0)); /* RAW/YUV, PCLK edge, HS/VS encoding enabled, DBL mode, BWS 24-bit */
 	usleep_range(2000, 2500);				/* wait 2ms */
 	reg8_write(client, 0x02, 0xff);				/* spread spectrum +-4%, pclk range automatic, Gbps automatic  */
 	usleep_range(2000, 2500);				/* wait 2ms */
 
-	if (priv->ser_id == MAX96705_ID) {
-		/* setup crossbar in DBL mode: reverse DVP bus */
-		reg8_write(client, 0x20, 0x07);
-		reg8_write(client, 0x21, 0x06);
-		reg8_write(client, 0x22, 0x05);
-		reg8_write(client, 0x23, 0x04);
-		reg8_write(client, 0x24, 0x03);
-		reg8_write(client, 0x25, 0x02);
-		reg8_write(client, 0x26, 0x01);
-		reg8_write(client, 0x27, 0x00);
-
-		reg8_write(client, 0x30, 0x17);
-		reg8_write(client, 0x31, 0x16);
-		reg8_write(client, 0x32, 0x15);
-		reg8_write(client, 0x33, 0x14);
-		reg8_write(client, 0x34, 0x13);
-		reg8_write(client, 0x35, 0x12);
-		reg8_write(client, 0x36, 0x11);
-		reg8_write(client, 0x37, 0x10);
+	if (priv->ser_id == MAX96705_ID || priv->ser_id == MAX96707_ID) {
+		switch (priv->dt) {
+		case YUV8_DT:
+			/* setup crossbar for YUV8/RAW8: reverse DVP bus */
+			reg8_write(client, 0x20, 7);
+			reg8_write(client, 0x21, 6);
+			reg8_write(client, 0x22, 5);
+			reg8_write(client, 0x23, 4);
+			reg8_write(client, 0x24, 3);
+			reg8_write(client, 0x25, 2);
+			reg8_write(client, 0x26, 1);
+			reg8_write(client, 0x27, 0);
+
+			/* this is second byte if DBL=1 */
+			reg8_write(client, 0x30, 23);
+			reg8_write(client, 0x31, 22);
+			reg8_write(client, 0x32, 21);
+			reg8_write(client, 0x33, 20);
+			reg8_write(client, 0x34, 19);
+			reg8_write(client, 0x35, 18);
+			reg8_write(client, 0x36, 17);
+			reg8_write(client, 0x37, 16);
+
+			break;
+		case RAW12_DT:
+			/* setup crossbar for RAW12: reverse DVP bus */
+			reg8_write(client, 0x20, 11);
+			reg8_write(client, 0x21, 10);
+			reg8_write(client, 0x22, 9);
+			reg8_write(client, 0x23, 8);
+			reg8_write(client, 0x24, 7);
+			reg8_write(client, 0x25, 6);
+			reg8_write(client, 0x26, 5);
+			reg8_write(client, 0x27, 4);
+			reg8_write(client, 0x28, 3);
+			reg8_write(client, 0x29, 2);
+			reg8_write(client, 0x2a, 1);
+			reg8_write(client, 0x2b, 0);
+
+			/* this is second byte if DBL=1 */
+			reg8_write(client, 0x30, 27);
+			reg8_write(client, 0x31, 26);
+			reg8_write(client, 0x32, 25);
+			reg8_write(client, 0x33, 24);
+			reg8_write(client, 0x34, 23);
+			reg8_write(client, 0x35, 22);
+			reg8_write(client, 0x36, 21);
+			reg8_write(client, 0x37, 20);
+			reg8_write(client, 0x38, 19);
+			reg8_write(client, 0x39, 18);
+			reg8_write(client, 0x3a, 17);
+			reg8_write(client, 0x3b, 16);
+
+			if (!priv->bws && priv->dbl)
+				dev_err(&client->dev, " BWS must be 27/32-bit for RAW12 in DBL mode\n");
+
+			break;
+		}
+
+		if (priv->hsgen) {
+			/* HS/VS pins map */
+			reg8_write(client, 0x3f, 0x10);			/* HS (NC) */
+			reg8_write(client, 0x41, 0x10);			/* DE (NC) */
+			if (priv->ser_id == MAX96705_ID)
+				reg8_write(client, 0x40, 15);		/* VS (DIN13) */
+			if (priv->ser_id == MAX96707_ID)
+				reg8_write(client, 0x40, 13);		/* VS (DIN13) */
+#if 0
+			/* following must come from imager */
+#define SENSOR_WIDTH	(1280*2)
+#define HTS		(1288*2)
+#define VTS		960
+#define HTS_DELAY	0x9
+			reg8_write(client, 0x4e, HTS_DELAY >> 16);	/* HS delay */
+			reg8_write(client, 0x4f, (HTS_DELAY >> 8) & 0xff);
+			reg8_write(client, 0x50, HTS_DELAY & 0xff);
+			reg8_write(client, 0x54, SENSOR_WIDTH >> 8);	/* HS high period */
+			reg8_write(client, 0x55, SENSOR_WIDTH & 0xff);
+			reg8_write(client, 0x56, (HTS - SENSOR_WIDTH) >> 8); /* HS low period */
+			reg8_write(client, 0x57, (HTS - SENSOR_WIDTH) & 0xff);
+			reg8_write(client, 0x58, VTS >> 8);		/* HS count */
+			reg8_write(client, 0x59, VTS & 0xff );
+#endif
+			reg8_write(client, 0x43, 0x15);			/* enable HS generator */
+		}
 	}
 
 	client->addr = priv->des_addr;				/* MAX9286-CAMx I2C */
@@ -344,6 +507,9 @@ static void max9286_gmsl_link_setup(struct i2c_client *client, int idx)
 	client->addr = priv->max9271_addr_map[idx];		/* MAX9271-CAMx I2C new */
 	maxim_max927x_dump_regs(client);
 #endif
+	reg8_write(client, 0x07, 0x04 | (priv->pclk_rising_edge ? 0 : 0x10) |
+					(priv->dbl ? 0x80 : 0) |
+					(priv->bws ? 0x20 : 0)); /* RAW/YUV, PCLK edge, HS/VS encoding enabled, DBL mode, BWS 24/32-bit */
 }
 
 static int max9286_initialize(struct i2c_client *client)
@@ -439,8 +605,8 @@ static int max9286_registered_async(struct v4l2_subdev *sd)
 	reg8_write(client, 0x0a, 0x11 << idx);			/* enable reverse/forward control for CAMx */
 
 	client->addr = priv->max9271_addr_map[idx];		/* MAX9271-CAMx */
-	reg8_write(client, 0x04, conf_link ? 0x43 : 0x83);	/* enable serial_link */
-	usleep_range(2000, 2500);				/* wait 2ms after changing reverse_control */
+	max9286_write_remote_verify(client, idx, 0x04, conf_link ? 0x43 : 0x83);
+//	usleep_range(2000, 2500);				/* wait 2ms after changing reverse_control */
 
 	client->addr = priv->des_addr;				/* MAX9286 I2C */
 	reg8_write(client, 0x0a, (priv->links_mask << 4) | priv->links_mask); /* enable reverse/forward control for all CAMs */
@@ -491,7 +657,7 @@ static int max9286_parse_dt(struct i2c_client *client)
 
 	for (i = 0; i < 4; i++) {
 		sprintf(poc_name, "POC%d", i);
-		priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, poc_name, 0);
+		priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, kstrdup(poc_name, GFP_KERNEL), 0);
 	}
 
 	reg8_read(client, 0x1e, &val);				/* read max9286 ID */
@@ -536,6 +702,19 @@ static int max9286_parse_dt(struct i2c_client *client)
 		priv->vsync = 1;
 	if (of_property_read_u32(np, "maxim,poc-delay", &priv->poc_delay))
 		priv->poc_delay = 50;
+	if (of_property_read_u32(np, "maxim,bws", &priv->bws))
+		priv->bws = 0;
+	if (of_property_read_u32(np, "maxim,dbl", &priv->dbl))
+		priv->dbl = 1;
+	if (of_property_read_u32(np, "maxim,dt", &priv->dt))
+		priv->dt = 3;
+	if (of_property_read_u32(np, "maxim,hsgen", &priv->hsgen))
+		priv->hsgen = 0;
+	if (of_property_read_u32(np, "maxim,pclk", &priv->pclk))
+		priv->pclk = pclk;
+	if (of_property_read_u32(np, "maxim,switchin", &priv->switchin))
+		priv->switchin = 0;
+
 
 	/* module params override dts */
 	if (him)
@@ -554,6 +733,18 @@ static int max9286_parse_dt(struct i2c_client *client)
 		priv->active_low_resetb = active_low_resetb;
 	if (poc_delay)
 		priv->poc_delay = poc_delay;
+	if (bws)
+		priv->bws = bws;
+	if (!dbl)
+		priv->dbl = dbl;
+	if (dt != 3)
+		priv->dt = dt;
+	if (hsgen)
+		priv->hsgen = hsgen;
+	if (pclk != 100)
+		priv->pclk = pclk;
+	if (switchin)
+		priv->switchin = switchin;
 
 	for (i = 0; i < priv->links; i++) {
 		endpoint = of_graph_get_next_endpoint(np, endpoint);
@@ -592,8 +783,8 @@ static void max9286_setup_remote_endpoint(struct i2c_client *client)
 
 		csi_rate_prop = of_find_property(endpoint, "csi-rate", NULL);
 		if (csi_rate_prop) {
-			/* CSI2_RATE = PCLK*sizeof(YUV8)*links/lanes */
-			priv->csi_rate = cpu_to_be32(100 * 8 * hweight8(priv->links_mask) / priv->lanes);
+			/* CSI2_RATE = PCLK*bpp*links/lanes */
+			priv->csi_rate = cpu_to_be32(priv->pclk * dt2bpp[priv->dt] * hweight8(priv->links_mask) / priv->lanes);
 			csi_rate_prop->value = &priv->csi_rate;
 			of_update_property(rendpoint, csi_rate_prop);
 		}
@@ -606,6 +797,86 @@ static void max9286_setup_remote_endpoint(struct i2c_client *client)
 	of_node_put(endpoint);
 }
 
+static const char *line_status[] =
+{
+	"BAT",
+	"GND",
+	"NORMAL",
+	"OPEN"
+};
+
+static ssize_t max9286_link_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	int i = -1;
+	u8 val = 0;
+	bool lenghterr, linebuffof, hlocked, prbsok, vsyncdet, configdet, videodet;
+	int lf;
+	u8 prbserr = 0, deterr = 0, correrr = 0;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max9286_priv *priv = i2c_get_clientdata(client);
+
+	if (!sscanf(attr->attr.name, "link_%d", &i))
+                return -EINVAL;
+
+	if ((i < 0) || (i > 3))
+		return -EINVAL;
+
+	reg8_read(client, 0x20, &val);
+	lf = (val >> (2 * i)) & 0x03;
+
+	reg8_read(client, 0x21, &val);
+	hlocked = !!(val & (1 << i));
+	prbsok = !!(val & (1 << (i + 4)));
+
+	reg8_read(client, 0x22, &val);
+	lenghterr = !!(val & (1 << i));
+	linebuffof = !!(val & (1 << (i + 4)));
+
+	reg8_read(client, 0x23 + i, &prbserr);
+	priv->prbserr[i] += prbserr;
+
+	reg8_read(client, 0x27, &val);
+	vsyncdet = !!(val & (1 << i));
+
+	reg8_read(client, 0x28 + i, &deterr);
+	priv->deterr[i] += deterr;
+
+	reg8_read(client, 0x2c + i, &correrr);
+	priv->correrr[i] += correrr;
+
+	reg8_read(client, 0x49, &val);
+	configdet = !!(val & (1 << i));
+	videodet = !!(val & (1 << (i + 4)));
+
+	return sprintf(buf, "LINK:%d LF:%s HLOCKED:%d PRBSOK:%d LINBUFFOF:%d"
+		" LENGHTERR:%d VSYNCDET:%d CONFIGDET:%d VIDEODET:%d"
+		" PRBSERR:%d(%d) DETEERR:%d(%d) CORRERR:%d(%d)\n",
+		i, line_status[lf], hlocked, prbsok, lenghterr,
+		linebuffof, vsyncdet, configdet, videodet,
+		priv->prbserr[i], prbserr,
+		priv->deterr[i], deterr,
+		priv->correrr[i], correrr);
+	return 0;
+}
+
+static DEVICE_ATTR(link_0, S_IRUGO, max9286_link_show, NULL);
+static DEVICE_ATTR(link_1, S_IRUGO, max9286_link_show, NULL);
+static DEVICE_ATTR(link_2, S_IRUGO, max9286_link_show, NULL);
+static DEVICE_ATTR(link_3, S_IRUGO, max9286_link_show, NULL);
+
+static struct attribute *max9286_attributes_links[] = {
+        &dev_attr_link_0.attr,
+        &dev_attr_link_1.attr,
+        &dev_attr_link_2.attr,
+        &dev_attr_link_3.attr,
+        NULL
+};
+
+static const struct attribute_group max9286_group = {
+        .attrs = max9286_attributes_links,
+};
+
 static int max9286_probe(struct i2c_client *client,
 				 const struct i2c_device_id *did)
 {
@@ -648,6 +919,11 @@ static int max9286_probe(struct i2c_client *client,
 		if (err < 0)
 			goto out;
 	}
+
+	err = sysfs_create_group(&client->dev.kobj,
+                                &max9286_group);
+        if (err < 0)
+                dev_err(&client->dev, "Sysfs registration failed\n");
 out:
 	return err;
 }
@@ -657,6 +933,8 @@ static int max9286_remove(struct i2c_client *client)
 	struct max9286_priv *priv = i2c_get_clientdata(client);
 	int i;
 
+	sysfs_remove_group(&client->dev.kobj,  &max9286_group);
+
 	for (i = 0; i < 4; i++) {
 		v4l2_async_unregister_subdev(&priv->sd[i]);
 		v4l2_device_unregister_subdev(&priv->sd[i]);
diff --git a/drivers/media/i2c/soc_camera/max9286.h b/drivers/media/i2c/soc_camera/max9286.h
index 6c2a9e0..2875b3c 100644
--- a/drivers/media/i2c/soc_camera/max9286.h
+++ b/drivers/media/i2c/soc_camera/max9286.h
@@ -24,6 +24,7 @@
 #define REG16_NUM_RETRIES	10 /* number of read/write retries */
 #define MAX9271_ID		0x9
 #define MAX96705_ID		0x41
+#define MAX96707_ID		0x45 /* MAX96715: there is no HS pin */
 #define MAX9286_ID		0x40
 #define BROADCAST		0x6f
 
diff --git a/drivers/media/i2c/soc_camera/ov10635.c b/drivers/media/i2c/soc_camera/ov10635.c
index 8289b76..916173c 100644
--- a/drivers/media/i2c/soc_camera/ov10635.c
+++ b/drivers/media/i2c/soc_camera/ov10635.c
@@ -19,7 +19,6 @@
 #include <media/soc_camera.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
-#include <media/v4l2-fwnode.h>
 
 #include "max9286.h"
 #include "ov10635.h"
@@ -44,8 +43,7 @@ struct ov10635_priv {
 	/* serializers */
 	int				max9286_addr;
 	int				max9271_addr;
-	int				ti964_addr;
-	int				ti954_addr;
+	int				ti9x4_addr;
 	int				ti9x3_addr;
 	int				port;
 	int				gpio_resetb;
@@ -429,13 +427,11 @@ static int ov10635_s_ctrl(struct v4l2_ctrl *ctrl)
 		break;
 	case V4L2_CID_HFLIP:
 		ret = reg16_read(client, 0x381d, &val);
-		if (ret < 0)
-			goto out;
 		if (ctrl->val)
 			val |= 0x3;
 		else
 			val &= ~0x3;
-		ret = reg16_write(client, 0x381d, val);
+		ret |= reg16_write(client, 0x381d, val);
 		break;
 	case V4L2_CID_VFLIP:
 		ret = reg16_read(client, 0x381c, &val);
@@ -443,14 +439,13 @@ static int ov10635_s_ctrl(struct v4l2_ctrl *ctrl)
 			val |= 0xc0;
 		else
 			val &= ~0xc0;
-		ret = reg16_write(client, 0x381c, val);
+		ret |= reg16_write(client, 0x381c, val);
 		break;
 	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
 		ret = 0;
 		break;
 	}
 
-out:
 	return ret;
 }
 
@@ -567,21 +562,15 @@ static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv)
 			break;
 
 		if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) &&
-		    !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti964-ti9x3") &&
-		    !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti964_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,ti954-ti9x3") &&
-		    !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti954_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->ti964_addr && !priv->ti954_addr) {
+	if (!priv->max9286_addr && !priv->ti9x4_addr) {
 		dev_err(&client->dev, "deserializer does not present for OV10635\n");
 		return -EINVAL;
 	}
@@ -598,19 +587,8 @@ static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv)
 		usleep_range(2000, 2500);				/* wait 2ms */
 	};
 
-	if (priv->ti964_addr) {
-		client->addr = priv->ti964_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, OV10635_I2C_ADDR << 1);	/* Sensor native I2C address */
-
-		reg8_write(client, 0x6e, 0xa9);				/* GPIO0 - resetb, GPIO1 - fsin */
-	}
-
-	if (priv->ti954_addr) {
-		client->addr = priv->ti954_addr;			/* Deserializer I2C address */
+	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 */
diff --git a/drivers/media/i2c/soc_camera/ov10635.h b/drivers/media/i2c/soc_camera/ov10635.h
index a0e510d..a74f360 100644
--- a/drivers/media/i2c/soc_camera/ov10635.h
+++ b/drivers/media/i2c/soc_camera/ov10635.h
@@ -17,13 +17,13 @@
 #define OV10635_MAX_WIDTH		1280
 #define OV10635_MAX_HEIGHT		800
 
-//#define OV10635_PCLK_96MHZ
-#define OV10635_PCLK_88MHZ
+#define OV10635_PCLK_96MHZ
+//#define OV10635_PCLK_88MHZ
 
 #if defined(OV10635_PCLK_96MHZ)
-/* VTS=PCLK/FPS/HTS/2 (=96MHz/30/1600/2) */
- #define OV10635_HTS			1600
- #define OV10635_VTS			1000 /* fps=30 */
+/* VTS=PCLK/FPS/HTS/2 (=96MHz/30/1750/2) */
+ #define OV10635_HTS			1750
+ #define OV10635_VTS			914 /* fps=30 */
 #elif defined(OV10635_PCLK_88MHZ)
 /* VTS=PCLK/FPS/HTS/2 (=88MHz/1572/30/2) */
  #define OV10635_HTS			1572
diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c
index fa775ae..c7bd92e 100644
--- a/drivers/media/i2c/soc_camera/ov106xx.c
+++ b/drivers/media/i2c/soc_camera/ov106xx.c
@@ -13,18 +13,32 @@
 #include "ov490_ov10640.c"
 #include "ov495_ov2775.c"
 #include "ar0132.c"
+#include "ar0140.c"
+#include "ar0143.c"
 #include "ar0220.c"
+#include "ar0231.c"
+#include "ar0233.c"
 #include "ap0101_ar014x.c"
+#include "gw4200_ar014x.c"
 #include "ov2775.c"
+#include "imx390.c"
+#include "ox03a.c"
 
 static enum {
 	ID_OV10635,
 	ID_OV490_OV10640,
 	ID_OV495_OV2775,
 	ID_AR0132,
+	ID_AR0140,
+	ID_AR0143,
 	ID_AR0220,
+	ID_AR0231,
+	ID_AR0233,
 	ID_AP0101_AR014X,
+	ID_GW4200_AR014X,
 	ID_OV2775,
+	ID_IMX390,
+	ID_OX03A,
 } chip_id;
 
 static int ov106xx_probe(struct i2c_client *client,
@@ -57,24 +71,66 @@ static int ov106xx_probe(struct i2c_client *client,
 		goto out;
 	}
 
+	ret = ar0140_probe(client, did);
+	if (!ret) {
+		chip_id = ID_AR0140;
+		goto out;
+	}
+
+	ret = ar0143_probe(client, did);
+	if (!ret) {
+		chip_id = ID_AR0143;
+		goto out;
+	}
+
 	ret = ar0220_probe(client, did);
 	if (!ret) {
 		chip_id = ID_AR0220;
 		goto out;
 	}
 
+	ret = ar0233_probe(client, did);
+	if (!ret) {
+		chip_id = ID_AR0233;
+		goto out;
+	}
+
+	ret = ar0231_probe(client, did);
+	if (!ret) {
+		chip_id = ID_AR0231;
+		goto out;
+	}
+
 	ret = ap0101_probe(client, did);
 	if (!ret) {
 		chip_id = ID_AP0101_AR014X;
 		goto out;
 	}
 
+	ret = gw4200_probe(client, did);
+	if (!ret) {
+		chip_id = ID_GW4200_AR014X;
+		goto out;
+	}
+
 	ret = ov2775_probe(client, did);
 	if (!ret) {
 		chip_id = ID_OV2775;
 		goto out;
 	}
 
+	ret = imx390_probe(client, did);
+	if (!ret) {
+		chip_id = ID_IMX390;
+		goto out;
+	}
+
+	ret = ox03a_probe(client, did);
+	if (!ret) {
+		chip_id = ID_OX03A;
+		goto out;
+	}
+
 	v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
 			client->addr, client->adapter->name);
 out:
@@ -96,15 +152,36 @@ static int ov106xx_remove(struct i2c_client *client)
 	case ID_AR0132:
 		ar0132_remove(client);
 		break;
+	case ID_AR0140:
+		ar0140_remove(client);
+		break;
+	case ID_AR0143:
+		ar0143_remove(client);
+		break;
 	case ID_AR0220:
 		ar0220_remove(client);
 		break;
+	case ID_AR0231:
+		ar0231_remove(client);
+		break;
+	case ID_AR0233:
+		ar0233_remove(client);
+		break;
 	case ID_AP0101_AR014X:
 		ap0101_remove(client);
 		break;
+	case ID_GW4200_AR014X:
+		gw4200_remove(client);
+		break;
 	case ID_OV2775:
 		ov2775_remove(client);
 		break;
+	case ID_IMX390:
+		imx390_remove(client);
+		break;
+	case ID_OX03A:
+		ox03a_remove(client);
+		break;
 	};
 
 	return 0;
@@ -134,6 +211,6 @@ static struct i2c_driver ov106xx_i2c_driver = {
 
 module_i2c_driver(ov106xx_i2c_driver);
 
-MODULE_DESCRIPTION("SoC Camera driver for OV10635, OV490/OV10640, OV495/OV2775, AR0132, AR0220, AP0101/AR014X");
+MODULE_DESCRIPTION("SoC Camera driver for OV10635, OV490+OV10640, OV495+OV2775, AR0132/140/143/220/223, AP0101+AR014X");
 MODULE_AUTHOR("Vladimir Barinov");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/soc_camera/ov2775.c b/drivers/media/i2c/soc_camera/ov2775.c
index cb41764..2022d47 100644
--- a/drivers/media/i2c/soc_camera/ov2775.c
+++ b/drivers/media/i2c/soc_camera/ov2775.c
@@ -19,7 +19,6 @@
 #include <media/soc_camera.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
-#include <media/v4l2-fwnode.h>
 
 #include "ov2775.h"
 
@@ -29,7 +28,7 @@
 #define OV2775_VER		0x300b
 #define OV2775_VERSION_REG	0x2770
 
-#define OV2775_MEDIA_BUS_FMT	MEDIA_BUS_FMT_SBGGR8_1X8
+#define OV2775_MEDIA_BUS_FMT	MEDIA_BUS_FMT_SBGGR12_1X12
 
 struct ov2775_priv {
 	struct v4l2_subdev		sd;
@@ -319,6 +318,7 @@ static int ov2775_initialize(struct i2c_client *client)
 	u8 val = 0;
 	u16 pid;
 	int ret = 0;
+	int tmp_addr;
 
 	/* check and show model ID */
 	reg16_read(client, OV2775_PID, &val);
@@ -332,6 +332,16 @@ static int ov2775_initialize(struct i2c_client *client)
 		goto err;
 	}
 
+	/* setup XCLK */
+	tmp_addr = client->addr;
+	if (priv->ti9x4_addr) {
+		/* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=25MHz: CLKDIV=4, M=7, N=253: 22.5792*160/4*7/253=24.989MHz=CLK_OUT */
+		client->addr = priv->ti9x3_addr;			/* Serializer I2C address */
+		reg8_write(client, 0x06, 0x47);				/* Set CLKDIV and M */
+		reg8_write(client, 0x07, 0xfd);				/* Set N */
+	}
+	client->addr = tmp_addr;
+
 	/* Program wizard registers */
 	ov2775_set_regs(client, ov2775_regs_wizard, ARRAY_SIZE(ov2775_regs_wizard));
 	/* Read OTP IDs */
diff --git a/drivers/media/i2c/soc_camera/ov2775.h b/drivers/media/i2c/soc_camera/ov2775.h
index 1cdfb50..7e1ee31 100644
--- a/drivers/media/i2c/soc_camera/ov2775.h
+++ b/drivers/media/i2c/soc_camera/ov2775.h
@@ -1,5 +1,5 @@
 /*
- * OmniVision OV2775 sensor camera wizard 1928x1088@30/RGGB/MIPI
+ * OmniVision OV2775 sensor camera wizard 1920x1080@30/BGGR/MIPI
  *
  * Copyright (C) 2018 Cogent Embedded, Inc.
  *
@@ -9,29 +9,29 @@
  * option) any later version.
  */
 
-//#define OV2775_DISPLAY_PATTERN_COLOR_BAR
+#define OV2775_DISPLAY_PATTERN_COLOR_BAR
 
-#define OV2775_MAX_WIDTH	2880 // (1928*1.5=2892) <- must be multiple of 16 - requred by R-CAR VIN
-#define OV2775_MAX_HEIGHT	1088
+#define OV2775_MAX_WIDTH	1920
+#define OV2775_MAX_HEIGHT	1080
 
 #define OV2775_DELAY		0xffff
-#define OV2775_DT		0x2c // MIPI Data Type
+#define OV2775_DT		0x2c /* MIPI Data Type RAW12 */
 
 struct ov2775_reg {
 	u16	reg;
 	u8	val;
 };
 
-/* wizard: MIPI 1928x1088 RAW12 Linear 30fps 960Mbps */
+/* wizard: MIPI 1920x1080 RAW12 Linear 30fps 600Mbps XCLK=25MHz  */
 static const struct ov2775_reg ov2775_regs_wizard[] = {
 {0x3013, 0x01}, // s/w reset
 {OV2775_DELAY, 10}, // Wait 10ms
-{0x3000, 0x02},
-{0x3001, 0x28},
-{0x3002, 0x03},
+{0x3000, 0x03},
+{0x3001, 0x18},
+{0x3002, 0x01},
 {0x3003, 0x01},
-{0x3004, 0x02},
-{0x3005, 0x26},
+{0x3004, 0x03},
+{0x3005, 0x1c},
 {0x3006, 0x00},
 {0x3007, 0x07},
 {0x3008, 0x01},
@@ -41,7 +41,7 @@ static const struct ov2775_reg ov2775_regs_wizard[] = {
 {0x300f, 0x00},
 {0x3012, 0x00},
 {0x3013, 0x00},
-{0x3014, 0xc4},
+{0x3014, 0x44},
 {0x3015, 0x00},
 {0x3017, 0x00},
 {0x3018, 0x00},
@@ -328,7 +328,7 @@ static const struct ov2775_reg ov2775_regs_wizard[] = {
 {0x320d, 0x1e},
 {0x320e, 0x30},
 {0x320f, 0x2d},
-{0x3210, OV2775_DT},
+{0x3210, 0x2c},
 {0x3211, 0x2b},
 {0x3212, 0x2a},
 {0x3213, 0x24},
@@ -358,7 +358,7 @@ static const struct ov2775_reg ov2775_regs_wizard[] = {
 {0x3251, 0x00},
 {0x3252, 0x20},
 #ifdef OV2775_DISPLAY_PATTERN_COLOR_BAR
-{0x3253, 0x80},
+{0x3253, 0xC0},
 #else
 {0x3253, 0x00},
 #endif
@@ -1822,9 +1822,9 @@ static const struct ov2775_reg ov2775_regs_wizard[] = {
 {0x30a9, 0x04},
 {0x30aa, 0x00},
 {0x30ab, 0x04},
-{0x30ac, 0x07},
+{0x30ac, 0x07}, /* OV2775_MAX_WIDTH */
 {0x30ad, 0x88},
-{0x30ae, 0x04},
+{0x30ae, 0x04}, /* OV2775_MAX_HEIGHT */
 {0x30af, 0x40},
 {0x30b0, 0x0d},
 {0x30b1, 0xde},
diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.c b/drivers/media/i2c/soc_camera/ov490_ov10640.c
index 4b51a92..1c8aac8 100644
--- a/drivers/media/i2c/soc_camera/ov490_ov10640.c
+++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c
@@ -19,7 +19,6 @@
 #include <media/soc_camera.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
-#include <media/v4l2-fwnode.h>
 
 #include "max9286.h"
 #include "ov490_ov10640.h"
diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.c b/drivers/media/i2c/soc_camera/ov495_ov2775.c
index 32b5078..34b2f46 100644
--- a/drivers/media/i2c/soc_camera/ov495_ov2775.c
+++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c
@@ -19,7 +19,6 @@
 #include <media/soc_camera.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
-#include <media/v4l2-fwnode.h>
 
 #include "ov495_ov2775.h"
 
@@ -403,6 +402,7 @@ static int ov495_initialize(struct i2c_client *client)
 	struct ov495_priv *priv = to_ov495(client);
 	u8 pid = 0, ver = 0;
 	int ret = 0;
+//	int tmp_addr;
 
 	/* check and show product ID and manufacturer ID */
 	reg16_write(client, 0xFFFD, 0x80);
@@ -417,6 +417,18 @@ static int ov495_initialize(struct i2c_client *client)
 		goto err;
 	}
 
+#if 0
+	/* setup XCLK */
+	tmp_addr = client->addr;
+	if (priv->ti9x4_addr) {
+		/* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=25MHz: CLKDIV=4, M=7, N=253: 22.5792*160/4*7/253=24.989MHz=CLK_OUT */
+		client->addr = priv->ti9x3_addr;			/* Serializer I2C address */
+		reg8_write(client, 0x06, 0x47);				/* Set CLKDIV and M */
+		reg8_write(client, 0x07, 0xfd);				/* Set N */
+	}
+	client->addr = tmp_addr;
+#endif
+
 	if (unlikely(force_conf_link))
 		goto out;
 
@@ -439,7 +451,7 @@ static int ov495_initialize(struct i2c_client *client)
 #endif
 
 	/* set virtual channel */
-	ov495_regs_wizard[3].val = 0x1e | (priv->port << 6);
+//	ov495_regs_wizard[3].val = 0x1e | (priv->port << 6);
 	/* Program wizard registers */
 	ov495_set_regs(client, ov495_regs_wizard, ARRAY_SIZE(ov495_regs_wizard));
 	/* Read OTP IDs */
diff --git a/drivers/media/i2c/soc_camera/ox03a.c b/drivers/media/i2c/soc_camera/ox03a.c
new file mode 100644
index 0000000..162c75b
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ox03a.c
@@ -0,0 +1,589 @@
+/*
+ * OmniVision OX03A sensor camera driver
+ *
+ * Copyright (C) 2018 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 "ox03a.h"
+
+#define OX03A_I2C_ADDR		0x36
+
+#define OX03A_PID		0x300A
+#define OX03A_VER		0x300B
+#define OX03A_VERSION_REG	0x5803
+
+#define OX03A_MEDIA_BUS_FMT	MEDIA_BUS_FMT_SBGGR16_1X16
+
+struct ox03a_priv {
+	struct v4l2_subdev		sd;
+	struct v4l2_ctrl_handler	hdl;
+	struct media_pad		pad;
+	struct v4l2_rect		rect;
+	int				init_complete;
+	u8				id[6];
+	int				exposure;
+	int				gain;
+	int				autogain;
+	/* serializers */
+	int				ti9x4_addr;
+	int				ti9x3_addr;
+	int				port;
+	int				gpio_resetb;
+	int				gpio_fsin;
+};
+
+static inline struct ox03a_priv *to_ox03a(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct ox03a_priv, sd);
+}
+
+static int ox03a_set_regs(struct i2c_client *client,
+			  const struct ox03a_reg *regs, int nr_regs)
+{
+	int i;
+
+	for (i = 0; i < nr_regs; i++) {
+		if (regs[i].reg == OX03A_DELAY) {
+			mdelay(regs[i].val);
+			continue;
+		}
+
+		reg16_write(client, regs[i].reg, regs[i].val);
+	}
+
+	return 0;
+}
+
+static int ox03a_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	return 0;
+}
+
+static int ox03a_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 ox03a_priv *priv = to_ox03a(client);
+
+	if (format->pad)
+		return -EINVAL;
+
+	mf->width = priv->rect.width;
+	mf->height = priv->rect.height;
+	mf->code = OX03A_MEDIA_BUS_FMT;
+	mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	mf->field = V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int ox03a_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 = OX03A_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 ox03a_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 = OX03A_MEDIA_BUS_FMT;
+
+	return 0;
+}
+
+static int ox03a_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ox03a_priv *priv = to_ox03a(client);
+
+	memcpy(edid->edid, priv->id, 6);
+
+	edid->edid[6] = 0xff;
+	edid->edid[7] = client->addr;
+	edid->edid[8] = OX03A_VERSION_REG >> 8;
+	edid->edid[9] = OX03A_VERSION_REG & 0xff;
+
+	return 0;
+}
+
+static int ox03a_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 ox03a_priv *priv = to_ox03a(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 > OX03A_MAX_WIDTH) ||
+	    (rect->top + rect->height > OX03A_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;
+
+	return 0;
+}
+
+static int ox03a_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 ox03a_priv *priv = to_ox03a(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 = OX03A_MAX_WIDTH;
+		sel->r.height = OX03A_MAX_HEIGHT;
+		return 0;
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		sel->r.left = 0;
+		sel->r.top = 0;
+		sel->r.width = OX03A_MAX_WIDTH;
+		sel->r.height = OX03A_MAX_HEIGHT;
+		return 0;
+	case V4L2_SEL_TGT_CROP:
+		sel->r = priv->rect;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ox03a_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 ox03a_g_register(struct v4l2_subdev *sd,
+			    struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+	u8 val = 0;
+
+	ret = reg16_read(client, (u16)reg->reg, &val);
+	if (ret < 0)
+		return ret;
+
+	reg->val = val;
+	reg->size = sizeof(u8);
+
+	return 0;
+}
+
+static int ox03a_s_register(struct v4l2_subdev *sd,
+			    const struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return reg16_write(client, (u16)reg->reg, (u8)reg->val);
+}
+#endif
+
+static struct v4l2_subdev_core_ops ox03a_core_ops = {
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = ox03a_g_register,
+	.s_register = ox03a_s_register,
+#endif
+};
+
+static int ox03a_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ox03a_priv *priv = to_ox03a(client);
+	int ret = -EINVAL;
+	u8 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:
+		/* start recording group3 */
+		ret = reg16_write(client, 0x3208, 0x03);
+		/* HCG real gain */
+		ret |= reg16_write(client, 0x3508, ctrl->val >> 8);
+		ret |= reg16_write(client, 0x3509, ctrl->val & 0xff);
+		/* HCG digital gain */
+		ret |= reg16_write(client, 0x350a, ctrl->val >> 8);
+		ret |= reg16_write(client, 0x350b, ctrl->val & 0xff);
+		/* LCG real gain */
+		ret |= reg16_write(client, 0x3548, ctrl->val >> 8);
+		ret |= reg16_write(client, 0x3549, ctrl->val & 0xff);
+		/* LCG digital gain */
+		ret |= reg16_write(client, 0x354a, ctrl->val >> 8);
+		ret |= reg16_write(client, 0x354b, ctrl->val & 0xff);
+		/* VS real gain */
+		ret |= reg16_write(client, 0x3588, ctrl->val >> 8);
+		ret |= reg16_write(client, 0x3589, ctrl->val & 0xff);
+		/* VS digital gain */
+		ret |= reg16_write(client, 0x358a, ctrl->val >> 8);
+		ret |= reg16_write(client, 0x358b, ctrl->val & 0xff);
+		/* stop recording and launch group3 */
+		ret |= reg16_write(client, 0x3208, 0x13);
+		ret |= reg16_write(client, 0x3208, 0xe3);
+		break;
+	case V4L2_CID_EXPOSURE:
+		/* start recording group3 */
+		ret = reg16_write(client, 0x3208, 0x03);
+		/* HCG (long) exposure time */
+		ret |= reg16_write(client, 0x3501, ctrl->val >> 8);
+		ret |= reg16_write(client, 0x3502, ctrl->val & 0xff);
+		/* VS exposure time */
+//		ret |= reg16_write(client, 0x3581, ctrl->val >> 8);
+//		ret |= reg16_write(client, 0x3582, ctrl->val & 0xff);
+		/* stop recording and launch group3 */
+		ret |= reg16_write(client, 0x3208, 0x13);
+		ret |= reg16_write(client, 0x3208, 0xe3);
+		break;
+	case V4L2_CID_HFLIP:
+		/* start recording group3 */
+		ret = reg16_write(client, 0x3208, 0x03);
+		ret = reg16_read(client, 0x3821, &val);
+		if (ctrl->val)
+			val |= 0x04;
+		else
+			val &= ~0x04;
+		ret |= reg16_write(client, 0x3821, val);
+		/* hflip channges CFA, hence compensate it by moving crop window over bayer matrix */
+		ret |= reg16_read(client, 0x3811, &val);
+		if (ctrl->val)
+			val++;
+		else
+			val--;
+		ret |= reg16_write(client, 0x3811, val);
+		/* stop recording and launch group3 */
+		ret |= reg16_write(client, 0x3208, 0x13);
+		ret |= reg16_write(client, 0x3208, 0xe3);
+		break;
+	case V4L2_CID_VFLIP:
+		ret = reg16_read(client, 0x3820, &val);
+		if (ctrl->val)
+			val |= 0x44;
+		else
+			val &= ~0x44;
+		ret |= reg16_write(client, 0x3820, val);
+		break;
+	}
+
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops ox03a_ctrl_ops = {
+	.s_ctrl = ox03a_s_ctrl,
+};
+
+static struct v4l2_subdev_video_ops ox03a_video_ops = {
+	.s_stream	= ox03a_s_stream,
+	.g_mbus_config	= ox03a_g_mbus_config,
+};
+
+static const struct v4l2_subdev_pad_ops ox03a_subdev_pad_ops = {
+	.get_edid	= ox03a_get_edid,
+	.enum_mbus_code	= ox03a_enum_mbus_code,
+	.get_selection	= ox03a_get_selection,
+	.set_selection	= ox03a_set_selection,
+	.get_fmt	= ox03a_get_fmt,
+	.set_fmt	= ox03a_set_fmt,
+};
+
+static struct v4l2_subdev_ops ox03a_subdev_ops = {
+	.core	= &ox03a_core_ops,
+	.video	= &ox03a_video_ops,
+	.pad	= &ox03a_subdev_pad_ops,
+};
+
+static void ox03a_otp_id_read(struct i2c_client *client)
+{
+}
+
+static ssize_t ox03a_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 ox03a_priv *priv = to_ox03a(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_ox03a, S_IRUGO, ox03a_otp_id_show, NULL);
+
+static int ox03a_initialize(struct i2c_client *client)
+{
+	struct ox03a_priv *priv = to_ox03a(client);
+	u8 val = 0;
+	u16 pid;
+	int ret = 0;
+
+	/* check and show model ID */
+	reg16_read(client, OX03A_PID, &val);
+	pid = val;
+	reg16_read(client, OX03A_VER, &val);
+	pid = (pid << 8) | val;
+
+	if (pid != OX03A_VERSION_REG) {
+		dev_dbg(&client->dev, "Product ID error %x\n", pid);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	/* Program wizard registers */
+	ox03a_set_regs(client, ox03a_regs_wizard_r1a, ARRAY_SIZE(ox03a_regs_wizard_r1a));
+	/* Read OTP IDs */
+	ox03a_otp_id_read(client);
+
+	dev_info(&client->dev, "ox03a PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n",
+		 pid, OX03A_MAX_WIDTH, OX03A_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
+err:
+	return ret;
+}
+
+static int ox03a_parse_dt(struct device_node *np, struct ox03a_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, "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->ti9x4_addr) {
+		dev_err(&client->dev, "deserializer does not present\n");
+		return -EINVAL;
+	}
+
+	/* setup I2C translator address */
+	tmp_addr = client->addr;
+	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, OX03A_I2C_ADDR << 1);		/* Sensor native I2C address */
+//		reg8_write(client, 0x6e, 0xa9);				/* GPIO0 - reset, GPIO1 - fsin */
+
+		client->addr = priv->ti9x3_addr;			/* Serializer I2C address */
+		reg8_write(client, 0x0d, 0x03);				/* unreset gpios */
+		reg8_write(client, 0x0e, 0xf0);				/* unreset gpios */
+	}
+	client->addr = tmp_addr;
+
+	mdelay(10);
+
+	return 0;
+}
+
+static int ox03a_probe(struct i2c_client *client,
+		       const struct i2c_device_id *did)
+{
+	struct ox03a_priv *priv;
+	int ret;
+
+	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&priv->sd, client, &ox03a_subdev_ops);
+	priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	priv->exposure = 0x880;
+	priv->gain = 0x600;
+	priv->autogain = 1;
+	v4l2_ctrl_handler_init(&priv->hdl, 4);
+	v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, 0, 16, 1, 7);
+	v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops,
+			  V4L2_CID_CONTRAST, 0, 16, 1, 7);
+	v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops,
+			  V4L2_CID_SATURATION, 0, 7, 1, 2);
+	v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops,
+			  V4L2_CID_HUE, 0, 23, 1, 12);
+	v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops,
+			  V4L2_CID_GAMMA, -128, 128, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops,
+			  V4L2_CID_SHARPNESS, 0, 10, 1, 3);
+	v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops,
+			  V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain);
+	v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops,
+			  V4L2_CID_GAIN, 1, 0xfff, 1, priv->gain);
+	v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops,
+			  V4L2_CID_EXPOSURE, 1, 0xffff, 1, priv->exposure);
+	v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops,
+			  V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops,
+			  V4L2_CID_VFLIP, 0, 1, 1, 1);
+	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 = ox03a_parse_dt(client->dev.of_node, priv);
+	if (ret)
+		goto cleanup;
+
+	ret = ox03a_initialize(client);
+	if (ret < 0)
+		goto cleanup;
+
+	priv->rect.left = 0;
+	priv->rect.top = 0;
+	priv->rect.width = OX03A_MAX_WIDTH;
+	priv->rect.height = OX03A_MAX_HEIGHT;
+
+	ret = v4l2_async_register_subdev(&priv->sd);
+	if (ret)
+		goto cleanup;
+
+	if (device_create_file(&client->dev, &dev_attr_otp_id_ox03a) != 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_OX03A
+	v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
+		client->addr, client->adapter->name);
+#endif
+	return ret;
+}
+
+static int ox03a_remove(struct i2c_client *client)
+{
+	struct ox03a_priv *priv = i2c_get_clientdata(client);
+
+	device_remove_file(&client->dev, &dev_attr_otp_id_ox03a);
+	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_OX03A
+static const struct i2c_device_id ox03a_id[] = {
+	{ "ox03a", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ox03a_id);
+
+static const struct of_device_id ox03a_of_ids[] = {
+	{ .compatible = "ovti,ox03a", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ox03a_of_ids);
+
+static struct i2c_driver ox03a_i2c_driver = {
+	.driver	= {
+		.name		= "ox03a",
+		.of_match_table	= ox03a_of_ids,
+	},
+	.probe		= ox03a_probe,
+	.remove		= ox03a_remove,
+	.id_table	= ox03a_id,
+};
+
+module_i2c_driver(ox03a_i2c_driver);
+
+MODULE_DESCRIPTION("SoC Camera driver for OX03A");
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/media/i2c/soc_camera/ox03a.h b/drivers/media/i2c/soc_camera/ox03a.h
new file mode 100644
index 0000000..4c20374
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ox03a.h
@@ -0,0 +1,1766 @@
+/*
+ * OmniVision OX03A sensor camera wizard 1920x1080@30/BGGR/MIPI
+ *
+ * Copyright (C) 2018 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 OX03A_DISPLAY_PATTERN_COLOR_BAR
+
+#define OX03A_MAX_WIDTH		1632
+#define OX03A_MAX_HEIGHT	1280
+
+#define OX03A_DELAY		0xffff
+//#define OX03A_DT		0x2c /* MIPI Data Type RAW12 */
+//#define DCG16_ONLY
+
+struct ox03a_reg {
+	u16	reg;
+	u8	val;
+};
+
+/* wizard: MIPI 1632x1280 16DCG+12VS 30fps 575MBPS R1A */
+static const struct ox03a_reg ox03a_regs_wizard_r1a[] = {
+{0x0103, 0x01}, // s/w reset
+{OX03A_DELAY, 10}, // Wait 10ms
+{0x4d09, 0x5f},
+{0x0100, 0x00},
+{0x0102, 0x00},
+{0x0103, 0x00},
+{0x0104, 0x04},
+{0x0105, 0x02},
+{0x0106, 0x00},
+{0x0107, 0x00},
+{0x0109, 0x00},
+{0x0300, 0x00},
+{0x0301, 0x01},
+{0x0302, 0x00},
+{0x0303, 0x02},
+{0x0304, 0x00},
+{0x0305, 0x2e},
+{0x0306, 0x00},
+{0x0307, 0x00},
+{0x0308, 0x04},
+{0x0309, 0x02},
+{0x030a, 0x00},
+{0x030c, 0x00},
+{0x030d, 0x00},
+{0x0310, 0x00},
+{0x0311, 0x00},
+{0x0312, 0x00},
+{0x0313, 0x00},
+{0x0314, 0x00},
+{0x0315, 0x00},
+{0x0316, 0x00},
+{0x0317, 0x12},
+{0x0318, 0x01},
+{0x0320, 0x00},
+{0x0321, 0x01},
+{0x0322, 0x00},
+{0x0323, 0x02},
+{0x0324, 0x00},
+{0x0325, 0x6c},
+{0x0326, 0x00},
+{0x0327, 0x05},
+{0x0328, 0x05},
+{0x0329, 0x01},
+{0x032a, 0x02},
+{0x032b, 0x00},
+{0x032c, 0x00},
+{0x0400, 0xe7},
+{0x0401, 0xff},
+{0x0404, 0x2b},
+{0x0405, 0x32},
+{0x0406, 0x33},
+{0x0407, 0x8f},
+{0x0408, 0x0c},
+{0x040a, 0x00},
+{0x0410, 0xe7},
+{0x0411, 0xff},
+{0x0414, 0x2b},
+{0x0415, 0x32},
+{0x0416, 0x33},
+{0x0417, 0x8f},
+{0x0418, 0x0c},
+{0x041a, 0x00},
+{0x2803, 0x00},
+{0x3000, 0x00},
+{0x3001, 0x03},
+{0x3002, 0x03},
+{0x3003, 0x00},
+{0x3004, 0x04},
+{0x3005, 0x00},
+{0x3006, 0x00},
+{0x3007, 0x04},
+{0x3008, 0x00},
+{0x3009, 0x06},
+{0x300d, 0x11},
+{0x300e, 0x11},
+{0x300f, 0x11},
+{0x3012, 0x41},
+{0x3016, 0xf0},
+{0x3017, 0xf0},
+{0x3018, 0xf0},
+{0x3019, 0xf0},
+{0x301a, 0xf0},
+{0x301b, 0xb4},
+{0x301c, 0x01},
+{0x301d, 0x02},
+{0x301e, 0xb8},
+{0x301f, 0xe1},
+{0x3020, 0x01},
+{0x3021, 0x00},
+{0x3022, 0xf8},
+{0x3023, 0xf0},
+{0x3024, 0xf0},
+{0x3025, 0x02},
+{0x3026, 0x00},
+{0x3027, 0x00},
+{0x3028, 0xf0},
+{0x3029, 0x80},
+{0x3035, 0x6c},
+{0x3036, 0x42},
+{0x3037, 0x20},
+{0x3038, 0x00},
+{0x3700, 0x26},
+{0x3701, 0x1e},
+{0x3702, 0x25},
+{0x3703, 0x28},
+{0x3704, 0x0f},
+{0x3705, 0x00},
+{0x3706, 0x39},
+{0x3707, 0x0a},
+{0x3708, 0x36},
+{0x3709, 0x41},
+{0x370a, 0x00},
+{0x370b, 0xa3},
+{0x370c, 0x0f},
+{0x370d, 0x00},
+{0x370e, 0xa6},
+{0x370f, 0x95},
+{0x3710, 0x15},
+{0x3711, 0x72},
+{0x3712, 0x12},
+{0x3713, 0x00},
+{0x3714, 0x22},
+{0x3715, 0x00},
+{0x3716, 0x04},
+{0x3717, 0x02},
+{0x3718, 0x09},
+{0x3719, 0x1f},
+{0x371a, 0x0c},
+{0x371b, 0x16},
+{0x371c, 0x00},
+{0x371d, 0x08},
+{0x371e, 0x00},
+{0x371f, 0x02},
+{0x3720, 0x03},
+{0x3721, 0x1c},
+{0x3722, 0x87},
+{0x3723, 0x08},
+{0x3724, 0x0d},
+{0x3725, 0x08},
+{0x3726, 0x0d},
+{0x3727, 0x08},
+{0x3728, 0x04},
+{0x3729, 0x0c},
+{0x372a, 0x01},
+{0x372b, 0x01},
+{0x372c, 0x17},
+{0x372d, 0x01},
+{0x372e, 0x35},
+{0x372f, 0x43},
+{0x3730, 0x04},
+{0x3731, 0x06},
+{0x3732, 0x01},
+{0x3733, 0x41},
+{0x3734, 0x0a},
+{0x3735, 0x11},
+{0x3736, 0x11},
+{0x3737, 0x00},
+{0x3738, 0x54},
+{0x3739, 0x54},
+{0x373a, 0x54},
+{0x373b, 0x54},
+{0x373c, 0x11},
+{0x373d, 0x11},
+{0x373e, 0x00},
+{0x373f, 0x4c},
+{0x3740, 0x4c},
+{0x3741, 0x44},
+{0x3742, 0x34},
+{0x3743, 0x01},
+{0x3744, 0x16},
+{0x3745, 0x08},
+{0x3746, 0x03},
+{0x3747, 0x01},
+{0x3748, 0x07},
+{0x3749, 0x01},
+{0x374a, 0x07},
+{0x374b, 0x03},
+{0x374c, 0xb1},
+{0x374d, 0x01},
+{0x374e, 0x01},
+{0x374f, 0x01},
+{0x3750, 0x07},
+{0x3751, 0x02},
+{0x3752, 0x03},
+{0x3753, 0xd0},
+{0x3754, 0x08},
+{0x3755, 0x00},
+{0x3758, 0xdd},
+{0x3759, 0x50},
+{0x375a, 0x49},
+{0x375b, 0x02},
+{0x375c, 0x2f},
+{0x375d, 0x00},
+{0x375e, 0x0f},
+{0x375f, 0x03},
+{0x3760, 0x13},
+{0x3761, 0x12},
+{0x3762, 0x1c},
+{0x3763, 0x03},
+{0x3764, 0x0d},
+{0x3765, 0x25},
+{0x3766, 0x08},
+{0x3767, 0x08},
+{0x3768, 0x21},
+{0x3769, 0x01},
+{0x376a, 0x01},
+{0x376b, 0x00},
+{0x376c, 0x15},
+{0x376d, 0x08},
+{0x376e, 0x08},
+{0x376f, 0x08},
+{0x3770, 0x91},
+{0x3771, 0x00},
+{0x3772, 0x00},
+{0x3773, 0x00},
+{0x3774, 0x82},
+{0x3775, 0x00},
+{0x3776, 0x00},
+{0x3777, 0x00},
+{0x3778, 0x00},
+{0x3779, 0x22},
+{0x377a, 0x00},
+{0x377b, 0x00},
+{0x377c, 0x48},
+{0x377d, 0x00},
+{0x377e, 0x00},
+{0x377f, 0x07},
+{0x3780, 0x00},
+{0x3781, 0x02},
+{0x3782, 0x04},
+{0x3783, 0x02},
+{0x3784, 0x08},
+{0x3785, 0x08},
+{0x3786, 0x00},
+{0x3787, 0x04},
+{0x3788, 0x02},
+{0x3789, 0x02},
+{0x378a, 0x04},
+{0x378b, 0x00},
+{0x378c, 0x00},
+{0x378d, 0x00},
+{0x378e, 0x00},
+{0x378f, 0x00},
+{0x3790, 0x10},
+{0x3791, 0x05},
+{0x3792, 0x31},
+#ifdef DCG16_ONLY
+{0x3793, 0x04}, /* DCG16 only */
+#else
+{0x3793, 0x00}, /* DCG16 + VS12*/
+#endif
+{0x3795, 0x00},
+{0x3796, 0x00},
+{0x3797, 0x00},
+{0x3798, 0x00},
+{0x3799, 0x00},
+{0x379a, 0x00},
+{0x379b, 0x10},
+{0x379c, 0x01},
+{0x379d, 0x00},
+{0x379e, 0x0d},
+{0x379f, 0x03},
+{0x37a0, 0x08},
+{0x37a1, 0x80},
+{0x37a2, 0x03},
+{0x37a3, 0x05},
+{0x37a4, 0x04},
+{0x37a5, 0x14},
+{0x37a6, 0x17},
+{0x37a7, 0x14},
+{0x37a8, 0x05},
+{0x37a9, 0x08},
+{0x37aa, 0x05},
+{0x37ab, 0x06},
+{0x37ac, 0x05},
+{0x37ad, 0x0d},
+{0x37ae, 0x0d},
+{0x37af, 0x01},
+{0x37b0, 0x0c},
+{0x37b1, 0x05},
+{0x37b2, 0x08},
+{0x37b3, 0x0a},
+{0x37b4, 0x08},
+{0x37b5, 0x08},
+{0x37b6, 0x08},
+{0x37b7, 0x08},
+{0x37b8, 0xff},
+{0x37b9, 0x01},
+{0x37ba, 0x08},
+{0x37bb, 0x08},
+{0x37bd, 0x01},
+{0x37be, 0xe0},
+{0x37bf, 0x00},
+{0x37c0, 0x01},
+{0x37c1, 0x11},
+{0x37c2, 0x11},
+{0x37c3, 0x00},
+{0x37c4, 0x63},
+{0x37c5, 0x63},
+{0x37c6, 0x48},
+{0x37c7, 0x38},
+{0x37c8, 0x21},
+{0x37c9, 0x00},
+{0x37ca, 0x08},
+{0x37cb, 0x00},
+{0x37cc, 0x40},
+{0x37cd, 0x00},
+{0x37ce, 0x01},
+{0x37cf, 0x08},
+{0x37d0, 0x00},
+{0x37d1, 0x39},
+{0x37d2, 0x00},
+{0x37d3, 0xa3},
+{0x37d4, 0x00},
+{0x37d5, 0x39},
+{0x37d6, 0x00},
+{0x37d7, 0xa3},
+{0x37da, 0x00},
+{0x37db, 0x00},
+{0x37dc, 0x00},
+{0x37dd, 0x00},
+{0x37de, 0x00},
+{0x37df, 0x00},
+{0x37e0, 0x00},
+{0x37e1, 0x00},
+{0x37e2, 0x00},
+{0x37e3, 0x00},
+{0x37e4, 0x00},
+{0x37e5, 0x00},
+{0x37e6, 0x00},
+{0x37e7, 0x00},
+{0x37e8, 0x00},
+{0x37e9, 0x00},
+{0x37ea, 0x00},
+{0x37eb, 0x00},
+{0x37ec, 0x00},
+{0x37ed, 0x00},
+{0x37ee, 0x00},
+{0x37ef, 0x00},
+{0x37f0, 0x00},
+{0x37f1, 0x00},
+{0x37f2, 0x00},
+{0x37f3, 0x00},
+{0x37f4, 0x00},
+{0x37f5, 0x00},
+{0x37f6, 0x00},
+{0x37f7, 0x00},
+{0x37f8, 0x00},
+{0x37f9, 0x00},
+{0x37fa, 0x00},
+{0x37fb, 0x00},
+{0x37fc, 0x00},
+{0x37fd, 0x00},
+{0x37fe, 0x00},
+{0x37ff, 0x00},
+{0x3c00, 0x00},
+{0x3c01, 0x11},
+{0x3c02, 0x20},
+{0x3c03, 0x04},
+{0x3c04, 0x04},
+{0x3c05, 0x00},
+{0x3c06, 0x29},
+{0x3c07, 0x01},
+{0x3c08, 0x05},
+{0x3c09, 0x0c},
+{0x3c0a, 0x04},
+{0x3c0b, 0xa8},
+{0x3c0c, 0x11},
+{0x3c0d, 0x08},
+{0x3c0e, 0x03},
+{0x3c0f, 0x02},
+{0x3c10, 0x01},
+{0x3c11, 0x08},
+{0x3c12, 0x89},
+{0x3c13, 0x21},
+{0x3c14, 0x81},
+{0x3c15, 0x21},
+{0x3c16, 0x11},
+{0x3c17, 0x01},
+{0x3c18, 0x0c},
+{0x3c19, 0x00},
+{0x3c1a, 0x16},
+{0x3c1b, 0x81},
+{0x3c1c, 0x04},
+{0x3c1d, 0x16},
+{0x3c1e, 0x11},
+{0x3c1f, 0x3a},
+{0x3c20, 0x20},
+{0x3c21, 0x00},
+{0x3c22, 0x17},
+{0x3c23, 0x07},
+{0x3c24, 0x1a},
+{0x3c25, 0x1e},
+{0x3c26, 0x24},
+{0x3c27, 0x37},
+{0x3c28, 0x0a},
+{0x3c29, 0x14},
+{0x3c2a, 0xd1},
+{0x3c2b, 0x27},
+{0x3c2c, 0x33},
+{0x3c2d, 0x0c},
+{0x3c2e, 0x12},
+{0x3c2f, 0x08},
+{0x3c30, 0x16},
+{0x3c31, 0x24},
+{0x3c32, 0x35},
+{0x3c33, 0x29},
+{0x3c34, 0x31},
+{0x3c35, 0x21},
+{0x3c36, 0x11},
+{0x3c37, 0x12},
+{0x3c38, 0x11},
+{0x3c39, 0x11},
+{0x3c3a, 0x08},
+{0x3c3b, 0x38},
+{0x3c3c, 0x03},
+{0x3c3d, 0x23},
+{0x3c3e, 0x05},
+{0x3c3f, 0x0a},
+{0x3c40, 0xc1},
+{0x3c41, 0x04},
+{0x3c42, 0x01},
+{0x3c43, 0x18},
+{0x3c44, 0x21},
+{0x3c45, 0x20},
+{0x3c46, 0x0b},
+{0x3c47, 0x11},
+{0x3c48, 0x11},
+{0x3c4a, 0x02},
+{0x3c4b, 0x63},
+{0x3c4c, 0x02},
+{0x3c4d, 0x63},
+{0x3c4e, 0x00},
+{0x3c4f, 0x2a},
+{0x3c50, 0x2a},
+{0x3c51, 0x2a},
+{0x3c52, 0x2a},
+{0x3c53, 0x08},
+{0x3c54, 0x1d},
+{0x3c55, 0xeb},
+{0x3c56, 0x24},
+{0x3c57, 0x10},
+{0x3c58, 0x10},
+{0x3c59, 0x16},
+{0x3c5a, 0x55},
+{0x3c5b, 0x25},
+{0x3c5c, 0x8e},
+{0x3ce0, 0x00},
+{0x3ce1, 0x00},
+{0x3ce2, 0x00},
+{0x3ce3, 0x00},
+{0x3ce4, 0x00},
+{0x3ce5, 0x00},
+{0x3ce6, 0x00},
+{0x3ce7, 0x00},
+{0x3ce8, 0x00},
+{0x3ce9, 0x00},
+{0x3cea, 0x00},
+{0x3ceb, 0x00},
+{0x3cec, 0x00},
+{0x3ced, 0x00},
+{0x3cee, 0x00},
+{0x3cef, 0x00},
+{0x3cf0, 0x00},
+{0x3cf1, 0x00},
+{0x3cf2, 0x00},
+{0x3cf3, 0x00},
+{0x3cf4, 0x00},
+{0x3cf5, 0x00},
+{0x3cf6, 0x00},
+{0x3cf7, 0x00},
+{0x3cf8, 0x00},
+{0x3cf9, 0x00},
+{0x3cfa, 0x00},
+{0x3cfb, 0x00},
+{0x3cfc, 0x00},
+{0x3cfd, 0x00},
+{0x3cfe, 0x00},
+{0x3cff, 0x00},
+{0x3100, 0x00},
+{0x3101, 0x32},
+{0x3102, 0x00},
+{0x3103, 0x25},
+{0x3104, 0x01},
+{0x3105, 0x11},
+{0x3106, 0x10},
+{0x3107, 0x01},
+{0x3108, 0x01},
+{0x3109, 0x00},
+{0x3182, 0x10},
+{0x3183, 0xff},
+{0x3184, 0xff},
+{0x3187, 0xff},
+{0x3189, 0x00},
+{0x318a, 0x00},
+{0x318b, 0x00},
+{0x318c, 0x00},
+{0x318d, 0x00},
+{0x318e, 0x00},
+{0x318f, 0x00},
+{0x3190, 0x00},
+{0x3191, 0x00},
+{0x3192, 0x00},
+{0x3193, 0x00},
+{0x3194, 0x00},
+{0x3200, 0x00},
+{0x3201, 0x08},
+{0x3202, 0x10},
+{0x3203, 0x18},
+{0x3204, 0x20},
+{0x3205, 0x30},
+{0x3206, 0xc0},
+{0x3209, 0x00},
+{0x320a, 0x00},
+{0x320b, 0x00},
+{0x320c, 0x00},
+{0x320d, 0x01},
+{0x3216, 0x02},
+{0x3217, 0x00},
+{0x3218, 0xf7},
+{0x3219, 0x55},
+{0x321b, 0x00},
+{0x3220, 0x1c},
+{0x3221, 0x00},
+{0x3304, 0x04},
+{0x3305, 0x00},
+{0x3306, 0x03},
+{0x3307, 0x00},
+{0x3308, 0x00},
+{0x3309, 0x00},
+{0x330a, 0x00},
+{0x330b, 0x00},
+{0x330c, 0x00},
+{0x330d, 0x00},
+{0x330e, 0x00},
+{0x330f, 0x00},
+{0x3310, 0x06},
+{0x3311, 0x05},
+{0x3312, 0x55},
+{0x3313, 0x0a},
+{0x3314, 0xaa},
+{0x3315, 0x0f},
+{0x3316, 0xf0},
+{0x3317, 0x00},
+{0x3400, 0x08},
+{0x3401, 0x00},
+{0x3402, 0x00},
+{0x3403, 0xb1},
+{0x3404, 0x00},
+{0x3405, 0x0f},
+{0x3406, 0x08},
+{0x3407, 0x08},
+{0x3408, 0x01},
+{0x3409, 0x02},
+{0x340a, 0x02},
+{0x340c, 0x10},
+{0x340d, 0x00},
+{0x3410, 0x00},
+{0x3412, 0x00},
+{0x3413, 0x00},
+{0x3414, 0x00},
+{0x3415, 0x00},
+{0x3416, 0x00},
+{0x3417, 0x00},
+{0x3420, 0x00},
+{0x3421, 0x00},
+{0x3422, 0x00},
+{0x3423, 0x00},
+{0x3424, 0x00},
+{0x3425, 0x00},
+{0x3426, 0x00},
+{0x3427, 0x00},
+{0x3428, 0x00},
+{0x3429, 0x00},
+{0x342a, 0x00},
+{0x342b, 0x00},
+{0x3501, 0x00},
+{0x3502, 0x24},
+{0x3503, 0xa8},
+{0x3504, 0x08},
+{0x3506, 0x00},
+{0x3507, 0x00},
+{0x3508, 0x01},
+{0x3509, 0x00},
+{0x350a, 0x01},
+{0x350b, 0x00},
+{0x350c, 0x00},
+{0x350d, 0x00},
+{0x3541, 0x00},
+{0x3542, 0x40},
+{0x3543, 0xa8},
+{0x3544, 0x08},
+{0x3546, 0x00},
+{0x3547, 0x00},
+{0x3548, 0x01},
+{0x3549, 0x00},
+{0x354a, 0x01},
+{0x354b, 0x00},
+{0x354c, 0x00},
+{0x354d, 0x00},
+{0x3581, 0x00},
+{0x3582, 0x24},
+{0x3583, 0xa8},
+{0x3584, 0x08},
+{0x3586, 0x00},
+{0x3587, 0x00},
+{0x3588, 0x01},
+{0x3589, 0x00},
+{0x358a, 0x01},
+{0x358b, 0x00},
+{0x358c, 0x00},
+{0x358d, 0x00},
+{0x3600, 0x00},
+{0x3601, 0x70},
+{0x3602, 0x42},
+{0x3603, 0xe3},
+{0x3604, 0x93},
+{0x3605, 0xff},
+{0x3606, 0x80},
+{0x3607, 0x4a},
+{0x3608, 0x98},
+{0x3609, 0x70},
+{0x360a, 0x90},
+{0x360b, 0x0a},
+{0x360c, 0x40},
+{0x360d, 0x88},
+{0x360e, 0x88},
+{0x360f, 0x88},
+{0x3610, 0x89},
+{0x3611, 0x4d},
+{0x3612, 0x4f},
+{0x3613, 0xba},
+{0x3614, 0x99},
+{0x3615, 0x99},
+{0x3616, 0x00},
+{0x3617, 0x00},
+{0x3618, 0x18},
+{0x3619, 0x00},
+{0x3620, 0x02},
+{0x3621, 0x80},
+{0x3622, 0x00},
+{0x3623, 0x00},
+{0x3624, 0x00},
+{0x3625, 0x00},
+{0x3626, 0x0e},
+{0x3627, 0x0f},
+{0x3628, 0x0a},
+{0x3629, 0x0a},
+{0x362a, 0x0e},
+{0x362b, 0x0e},
+{0x362c, 0x0e},
+{0x362d, 0x12},
+{0x362e, 0x00},
+{0x362f, 0x00},
+{0x3630, 0x00},
+{0x3631, 0x00},
+{0x3632, 0x99},
+{0x3633, 0x99},
+{0x3634, 0x30},
+{0x3635, 0x30},
+{0x3636, 0x30},
+{0x3637, 0x30},
+{0x3638, 0x00},
+{0x3639, 0x00},
+{0x363a, 0x00},
+{0x363b, 0x0f},
+{0x363c, 0x0f},
+{0x363d, 0x0a},
+{0x363e, 0x0a},
+{0x363f, 0x0a},
+{0x3640, 0x0a},
+{0x3641, 0x0a},
+{0x3642, 0x0a},
+{0x3643, 0x0e},
+{0x3644, 0x00},
+{0x3645, 0x10},
+{0x3646, 0x16},
+{0x3647, 0x0e},
+{0x3648, 0x00},
+{0x3649, 0x13},
+{0x364a, 0x13},
+{0x364b, 0x00},
+{0x364c, 0x0e},
+{0x364d, 0x0e},
+{0x364e, 0x0e},
+{0x364f, 0x0e},
+{0x3650, 0x00},
+{0x3651, 0x00},
+{0x3652, 0xc5},
+{0x3653, 0x00},
+{0x3654, 0x40},
+{0x3655, 0x00},
+{0x3656, 0xcf},
+{0x3657, 0x2b},
+{0x3658, 0x09},
+{0x3659, 0x00},
+{0x365a, 0x00},
+{0x365b, 0x00},
+{0x365c, 0x00},
+{0x365d, 0x00},
+{0x3660, 0x01},
+{0x3661, 0x07},
+{0x3662, 0x00},
+{0x3663, 0x20},
+{0x3664, 0x00},
+{0x3665, 0x12},
+{0x3666, 0x13},
+{0x3667, 0x54},
+{0x3668, 0x95},
+{0x3669, 0x16},
+{0x366a, 0x00},
+{0x366b, 0x00},
+{0x366c, 0x00},
+{0x366d, 0x00},
+{0x366e, 0x00},
+{0x366f, 0xf4},
+{0x3670, 0x6f},
+{0x3671, 0x0f},
+{0x3672, 0x1d},
+{0x3673, 0x6a},
+{0x3674, 0x6f},
+{0x3675, 0x1d},
+{0x3676, 0x6f},
+{0x3677, 0x1d},
+{0x3678, 0x80},
+{0x3679, 0x04},
+{0x367a, 0x00},
+{0x367b, 0x04},
+{0x367c, 0x00},
+{0x367d, 0x00},
+{0x367e, 0x00},
+{0x367f, 0x00},
+{0x3680, 0x00},
+/* window start */
+{0x3800, 0x00},
+{0x3801, 0x00},
+{0x3802, 0x00},
+{0x3803, 0x04},
+{0x3804, 0x07},
+{0x3805, 0x8f},
+{0x3806, 0x05},
+{0x3807, 0x0d},
+{0x3808, OX03A_MAX_WIDTH >> 8},
+{0x3809, OX03A_MAX_WIDTH & 0xff},
+{0x380a, OX03A_MAX_HEIGHT >> 8},
+{0x380b, OX03A_MAX_HEIGHT & 0xff},
+{0x380c, 0x06},
+{0x380d, 0xce},
+{0x380e, 0x05},
+{0x380f, 0x37},
+{0x3810, 0x00},
+{0x3811, 0x9c},
+{0x3812, 0x00},
+{0x3813, 0x04},
+/* window end */
+{0x3814, 0x01},
+{0x3815, 0x01},
+{0x3816, 0x01},
+{0x3817, 0x01},
+{0x3818, 0x00},
+{0x3819, 0x00},
+{0x381a, 0x00},
+{0x381b, 0x01},
+{0x381c, 0x08},
+{0x381d, 0x00},
+{0x3820, 0x44}, /* VPLIP on */
+{0x3821, 0x20}, /* HFLIP off */
+{0x3822, 0x14},
+{0x3823, 0x08},
+{0x3824, 0x00},
+{0x3825, 0x20},
+{0x3826, 0x00},
+{0x3827, 0x08},
+{0x3828, 0x38},
+{0x382a, 0x00},
+{0x382b, 0x00},
+{0x382c, 0x00},
+{0x382d, 0x00},
+{0x3832, 0x00},
+{0x3833, 0x00},
+{0x3834, 0x00},
+{0x3838, 0x00},
+{0x3839, 0x00},
+{0x383a, 0x00},
+{0x383b, 0x00},
+{0x383c, 0x48},
+{0x383d, 0x20},
+{0x383e, 0x00},
+{0x3842, 0x00},
+{0x3843, 0x00},
+{0x3844, 0x00},
+{0x384c, 0x03},
+{0x384d, 0xc2},
+{0x384e, 0x00},
+{0x384f, 0x40},
+{0x3850, 0x00},
+{0x3851, 0x42},
+{0x3852, 0x00},
+{0x3853, 0x40},
+{0x3854, 0x00},
+{0x3855, 0x05},
+{0x3856, 0x04},
+{0x3857, 0x6b},
+{0x3858, 0x3c},
+{0x3859, 0x00},
+{0x385a, 0x03},
+{0x385b, 0x04},
+{0x385c, 0x6a},
+{0x385d, 0x00},
+{0x385e, 0x12},
+{0x385f, 0x00},
+{0x3860, 0x10},
+{0x3861, 0x00},
+{0x3862, 0x40},
+{0x3863, 0x00},
+{0x3864, 0x40},
+{0x3865, 0x00},
+{0x3866, 0x40},
+{0x3881, 0x02},
+{0x3882, 0x00},
+{0x3883, 0x08},
+{0x3b40, 0x3e},
+{0x3b41, 0x00},
+{0x3b42, 0x02},
+{0x3b43, 0x00},
+{0x3b44, 0x03},
+{0x3b45, 0x00},
+{0x3b46, 0x03},
+{0x3b47, 0x00},
+{0x3b80, 0x00},
+{0x3b81, 0x00},
+{0x3b82, 0x07},
+{0x3b83, 0x87},
+{0x3b84, 0x36},
+{0x3b85, 0x00},
+{0x3b86, 0x00},
+{0x3b87, 0x04},
+{0x3b88, 0x00},
+{0x3b89, 0x04},
+{0x3b8a, 0x00},
+{0x3b8b, 0x0a},
+{0x3b8c, 0x00},
+{0x3b8d, 0x01},
+{0x3b8e, 0x03},
+{0x3b8f, 0xe8},
+{0x3d82, 0xbc},
+{0x3d83, 0x08},
+{0x3d84, 0x00},
+{0x3d85, 0x0b},
+{0x3d86, 0x02},
+{0x3d87, 0x0a},
+{0x3d88, 0x00},
+{0x3d89, 0x00},
+{0x3d8a, 0x03},
+{0x3d8b, 0xff},
+{0x3d8c, 0x70},
+{0x3d8d, 0x10},
+{0x3d90, 0x00},
+{0x3d91, 0x00},
+{0x3d92, 0xe2},
+{0x3d93, 0x46},
+{0x3d94, 0x14},
+{0x3d95, 0x06},
+{0x3d96, 0x01},
+{0x3d97, 0x00},
+{0x3d98, 0x00},
+{0x3d99, 0x00},
+{0x3d9a, 0x00},
+{0x3d9b, 0x00},
+{0x3d9c, 0x00},
+{0x3d9d, 0x00},
+{0x3d9e, 0x00},
+{0x3d9f, 0x00},
+{0x3da0, 0x00},
+{0x3da1, 0x00},
+{0x3da2, 0x00},
+{0x3da4, 0x00},
+{0x3e00, 0x00},
+{0x3e01, 0x00},
+{0x3e02, 0x0f},
+{0x3e03, 0xdb},
+{0x3e04, 0x14},
+{0x3e05, 0x00},
+{0x3e06, 0x03},
+{0x3e07, 0x40},
+{0x3e08, 0x00},
+{0x3e09, 0x00},
+{0x3e0a, 0x00},
+{0x3e0b, 0x00},
+{0x3e0c, 0x00},
+{0x3e0d, 0x00},
+{0x3e0e, 0x00},
+{0x3f00, 0x04},
+{0x3f01, 0x00},
+{0x3f02, 0x00},
+{0x3f03, 0x01},
+{0x4000, 0xf8},
+{0x4001, 0x2b},
+{0x4004, 0x00},
+{0x4005, 0x40},
+{0x4006, 0x00},
+{0x4007, 0x10},
+{0x4008, 0x02},
+{0x4009, 0x0d},
+{0x400a, 0x08},
+{0x400b, 0x00},
+{0x400c, 0x00},
+{0x400d, 0x10},
+{0x400e, 0x00},
+{0x400f, 0xa0},
+{0x4010, 0x10},
+{0x4011, 0xff},
+{0x4012, 0x08},
+{0x4013, 0x02},
+{0x4014, 0x02},
+{0x4015, 0x02},
+{0x4016, 0x00},
+{0x4017, 0x10},
+{0x4018, 0x18},
+{0x4019, 0x04},
+{0x401a, 0x58},
+{0x4020, 0x00},
+{0x4021, 0x00},
+{0x4022, 0x00},
+{0x4023, 0x00},
+{0x4024, 0x00},
+{0x4025, 0x00},
+{0x4026, 0x00},
+{0x4027, 0x00},
+{0x4028, 0x4f},
+{0x4029, 0x01},
+{0x402a, 0x00},
+{0x402b, 0x00},
+{0x402c, 0x00},
+{0x402d, 0x00},
+{0x402e, 0x00},
+{0x402f, 0x40},
+{0x4030, 0x00},
+{0x4031, 0x40},
+{0x4032, 0x9f},
+{0x4033, 0x00},
+{0x4034, 0x00},
+{0x4035, 0x80},
+{0x4036, 0x00},
+{0x4037, 0x80},
+{0x4038, 0x00},
+{0x4039, 0x80},
+{0x403a, 0x00},
+{0x403b, 0x80},
+{0x403c, 0x00},
+{0x403d, 0x00},
+{0x4040, 0x00},
+{0x4041, 0x00},
+{0x4042, 0x00},
+{0x4043, 0x00},
+{0x4044, 0x00},
+{0x4045, 0x00},
+{0x4046, 0x00},
+{0x4047, 0x00},
+{0x4048, 0x00},
+{0x4049, 0x00},
+{0x404a, 0x00},
+{0x404b, 0x00},
+{0x404c, 0x00},
+{0x404d, 0x00},
+{0x404e, 0x00},
+{0x404f, 0x00},
+{0x4050, 0x00},
+{0x4051, 0x05},
+{0x4052, 0x00},
+{0x4053, 0x80},
+{0x4054, 0x00},
+{0x4055, 0x80},
+{0x4056, 0x00},
+{0x4057, 0x80},
+{0x4058, 0x00},
+{0x4059, 0x80},
+{0x405a, 0x30},
+{0x405b, 0x18},
+{0x405c, 0x00},
+{0x405d, 0x00},
+{0x405e, 0x00},
+{0x405f, 0x00},
+{0x4060, 0x00},
+{0x4065, 0x00},
+{0x4066, 0x02},
+{0x406d, 0x00},
+{0x406e, 0x00},
+{0x406f, 0x00},
+{0x40a0, 0x00},
+{0x40a1, 0x00},
+{0x40a2, 0x00},
+{0x40a3, 0x00},
+{0x40a4, 0x00},
+{0x40a5, 0x00},
+{0x40a6, 0x00},
+{0x40a7, 0x00},
+{0x40c0, 0x00},
+{0x40c1, 0x00},
+{0x40c2, 0x00},
+{0x40c3, 0x00},
+{0x40c4, 0x00},
+{0x40c5, 0x00},
+{0x40c6, 0x00},
+{0x40c7, 0x00},
+{0x40c8, 0x00},
+{0x40c9, 0x00},
+{0x40ca, 0x00},
+{0x40cb, 0x00},
+{0x40cc, 0x00},
+{0x40cd, 0x00},
+{0x40ce, 0x00},
+{0x40cf, 0x00},
+{0x4200, 0x00},
+{0x4201, 0x00},
+{0x4202, 0x00},
+{0x4203, 0x00},
+{0x4204, 0x00},
+{0x4205, 0x00},
+{0x4206, 0x00},
+{0x4207, 0x00},
+{0x4208, 0x00},
+{0x4300, 0x00},
+{0x4301, 0x00},
+{0x4302, 0x00},
+{0x4303, 0x00},
+{0x4304, 0x00},
+{0x4305, 0x00},
+{0x4306, 0x00},
+{0x4307, 0x00},
+{0x4308, 0x00},
+{0x4309, 0x00},
+{0x430a, 0x00},
+{0x430b, 0xff},
+{0x430c, 0xff},
+{0x430d, 0x00},
+{0x430e, 0x00},
+{0x430f, 0x02},
+{0x4500, 0x16},
+{0x4501, 0x18},
+{0x4502, 0x00},
+{0x4503, 0x00},
+{0x4504, 0x01},
+{0x4505, 0x00},
+{0x4506, 0x32},
+{0x4507, 0x16},
+{0x4508, 0x1a},
+{0x4580, 0x68},
+{0x4581, 0xc7},
+{0x4582, 0x07},
+{0x4583, 0x07},
+{0x4584, 0xec},
+{0x4585, 0x09},
+{0x4586, 0xae},
+{0x4587, 0x04},
+{0x4588, 0x52},
+{0x4589, 0x05},
+{0x458a, 0x47},
+{0x458b, 0x02},
+{0x458c, 0xe2},
+{0x458d, 0x03},
+{0x458e, 0x85},
+{0x458f, 0x00},
+{0x4590, 0x20},
+{0x4591, 0x09},
+{0x4592, 0x60},
+{0x45a6, 0x18},
+{0x4600, 0x00},
+{0x4601, 0x30},
+{0x4602, 0x02},
+{0x4603, 0x01},
+{0x4604, 0x00},
+{0x4605, 0x03},
+{0x4609, 0x00},
+{0x460a, 0x36},
+{0x460b, 0x00},
+{0x460c, 0x60},
+{0x460d, 0x01},
+{0x460e, 0x00},
+{0x4700, 0x2a},
+{0x4702, 0x00},
+{0x4703, 0x80},
+{0x4704, 0x00},
+{0x4705, 0x10},
+{0x4706, 0xaa},
+{0x4707, 0x55},
+{0x4708, 0x99},
+{0x4709, 0x66},
+{0x470a, 0x08},
+{0x470b, 0x88},
+{0x470c, 0x00},
+{0x470d, 0x02},
+{0x470e, 0x00},
+{0x470f, 0x00},
+{0x4710, 0x00},
+{0x4711, 0x00},
+{0x4712, 0x00},
+{0x4713, 0x00},
+{0x4800, 0x04},
+{0x4802, 0x00},
+{0x4803, 0x00},
+{0x4804, 0x08},
+{0x4805, 0x00},
+{0x4806, 0x00},
+{0x4807, 0x03},
+{0x4808, 0x18},
+{0x480e, 0x04},
+{0x4810, 0xff},
+{0x4811, 0xff},
+{0x4813, 0x12}, // 0xVC
+{0x4814, 0x2a},
+{0x4815, 0x2b},
+{0x4816, 0x2b},
+{0x4818, 0x00},
+{0x4819, 0x70},
+{0x481a, 0x00},
+{0x481b, 0x3c},
+{0x481c, 0x01},
+{0x481d, 0x2c},
+{0x481e, 0x5f},
+{0x481f, 0x26},
+{0x4820, 0x00},
+{0x4821, 0x3c},
+{0x4822, 0x00},
+{0x4823, 0x3c},
+{0x4824, 0x00},
+{0x4825, 0x32},
+{0x4826, 0x32},
+{0x4827, 0x55},
+{0x4828, 0x00},
+{0x4829, 0x64},
+{0x482a, 0x06},
+{0x482b, 0x04},
+{0x482c, 0x00},
+{0x482d, 0x00},
+{0x482e, 0x34},
+{0x482f, 0x00},
+{0x4830, 0x00},
+{0x4831, 0x64},
+{0x4832, 0x00},
+{0x4833, 0x10},
+{0x4837, 0x18},
+{0x4838, 0x00},
+{0x4839, 0x00},
+{0x483c, 0x10},
+{0x483d, 0x00},
+{0x484a, 0x3f},
+{0x484b, 0x27},
+{0x484c, 0x00},
+{0x484e, 0x10},
+{0x4850, 0x40},
+{0x4851, 0xaa},
+{0x4852, 0xff},
+{0x4853, 0x8a},
+{0x4854, 0x08},
+{0x4855, 0x30},
+{0x4856, 0x01},
+{0x4860, 0x00},
+{0x4861, 0xa0},
+{0x4862, 0x01},
+{0x4863, 0x01},
+{0x4864, 0x02},
+{0x4865, 0x66},
+{0x4866, 0x99},
+{0x4867, 0x88},
+{0x4868, 0xaa},
+{0x4869, 0xff},
+{0x486a, 0x3f},
+{0x486b, 0x84},
+{0x486c, 0x36},
+{0x486d, 0x00},
+{0x486e, 0x84},
+{0x486f, 0x36},
+{0x4870, 0x00},
+{0x4880, 0x00},
+{0x4881, 0x00},
+{0x4882, 0x00},
+{0x4883, 0x00},
+{0x4884, 0x08},
+{0x4885, 0x00},
+{0x4886, 0x00},
+{0x4900, 0x08},
+{0x4901, 0x00},
+{0x4902, 0x00},
+{0x4903, 0x80},
+{0x4f00, 0xff},
+{0x4f01, 0xff},
+{0x4f04, 0x00},
+{0x4f05, 0x01},
+{0x5180, 0x04},
+{0x5181, 0x00},
+{0x5182, 0x04},
+{0x5183, 0x00},
+{0x5184, 0x04},
+{0x5185, 0x00},
+{0x5186, 0x04},
+{0x5187, 0x00},
+{0x5188, 0x00},
+{0x5189, 0x00},
+{0x518a, 0x00},
+{0x518b, 0x10},
+{0x51a0, 0x04},
+{0x51a1, 0x00},
+{0x51a2, 0x04},
+{0x51a3, 0x00},
+{0x51a4, 0x04},
+{0x51a5, 0x00},
+{0x51a6, 0x04},
+{0x51a7, 0x00},
+{0x51a8, 0x00},
+{0x51a9, 0x00},
+{0x51aa, 0x00},
+{0x51ab, 0x10},
+{0x51c0, 0x04},
+{0x51c1, 0x00},
+{0x51c2, 0x04},
+{0x51c3, 0x00},
+{0x51c4, 0x04},
+{0x51c5, 0x00},
+{0x51c6, 0x04},
+{0x51c7, 0x00},
+{0x51c8, 0x00},
+{0x51c9, 0x00},
+{0x51ca, 0x00},
+{0x51cb, 0x10},
+{0x5380, 0x19},
+{0x5381, 0x94},
+{0x5382, 0x2e},
+{0x5383, 0x24},
+{0x5384, 0x12},
+{0x5385, 0x41},
+{0x5386, 0x48},
+{0x5387, 0x84},
+{0x5388, 0x40},
+{0x5389, 0x00},
+{0x538a, 0x00},
+{0x538b, 0x03},
+{0x538c, 0x00},
+{0x538d, 0x0f},
+{0x538e, 0x00},
+{0x538f, 0x3f},
+{0x5390, 0x0f},
+{0x5391, 0xfd},
+{0x5392, 0xf5},
+{0x5393, 0xf5},
+{0x5394, 0x02},
+{0x5395, 0xff},
+{0x5396, 0x00},
+{0x5397, 0x00},
+{0x53a0, 0x41},
+{0x53a2, 0x04},
+{0x53a3, 0x00},
+{0x53a4, 0x04},
+{0x53a5, 0x00},
+{0x53a6, 0x04},
+{0x53a7, 0x00},
+{0x53ac, 0x04},
+{0x53ad, 0x00},
+{0x53ae, 0x04},
+{0x53af, 0x00},
+{0x53b0, 0x04},
+{0x53b1, 0x00},
+{0x5400, 0x19},
+{0x5401, 0x94},
+{0x5402, 0x2e},
+{0x5403, 0x24},
+{0x5404, 0x12},
+{0x5405, 0x41},
+{0x5406, 0x48},
+{0x5407, 0x84},
+{0x5408, 0x40},
+{0x5409, 0x00},
+{0x540a, 0x00},
+{0x540b, 0x03},
+{0x540c, 0x00},
+{0x540d, 0x0f},
+{0x540e, 0x00},
+{0x540f, 0x3f},
+{0x5410, 0x0f},
+{0x5411, 0xfd},
+{0x5412, 0xf5},
+{0x5413, 0xf5},
+{0x5414, 0x02},
+{0x5415, 0xff},
+{0x5416, 0x00},
+{0x5417, 0x00},
+{0x5420, 0x41},
+{0x5422, 0x04},
+{0x5423, 0x00},
+{0x5424, 0x04},
+{0x5425, 0x00},
+{0x5426, 0x04},
+{0x5427, 0x00},
+{0x542c, 0x04},
+{0x542d, 0x00},
+{0x542e, 0x04},
+{0x542f, 0x00},
+{0x5430, 0x04},
+{0x5431, 0x00},
+{0x5480, 0x19},
+{0x5481, 0x94},
+{0x5482, 0x2e},
+{0x5483, 0x24},
+{0x5484, 0x12},
+{0x5485, 0x41},
+{0x5486, 0x48},
+{0x5487, 0x84},
+{0x5488, 0x40},
+{0x5489, 0x00},
+{0x548a, 0x00},
+{0x548b, 0x03},
+{0x548c, 0x00},
+{0x548d, 0x0f},
+{0x548e, 0x00},
+{0x548f, 0x3f},
+{0x5490, 0x0f},
+{0x5491, 0xfd},
+{0x5492, 0xf5},
+{0x5493, 0xf5},
+{0x5494, 0x02},
+{0x5495, 0xff},
+{0x5496, 0x00},
+{0x5497, 0x00},
+{0x54a0, 0x41},
+{0x54a2, 0x04},
+{0x54a3, 0x00},
+{0x54a4, 0x04},
+{0x54a5, 0x00},
+{0x54a6, 0x04},
+{0x54a7, 0x00},
+{0x54ac, 0x04},
+{0x54ad, 0x00},
+{0x54ae, 0x04},
+{0x54af, 0x00},
+{0x54b0, 0x04},
+{0x54b1, 0x00},
+{0x5800, 0x39},
+{0x5801, 0x03},
+{0x5802, 0x60},
+{0x5803, 0xf0},
+{0x5804, 0x00},
+{0x5805, 0x40},
+{0x5806, 0x01},
+{0x5807, 0x00},
+{0x5808, 0x60},
+{0x5809, 0xf0},
+{0x580a, 0x33},
+{0x580b, 0x10},
+{0x580c, 0x04},
+{0x580d, 0x00},
+{0x580e, 0x10},
+{0x580f, 0x10},
+{0x5810, 0x02},
+{0x5811, 0x08},
+{0x5812, 0x38},
+{0x5813, 0x00},
+{0x5814, 0x00},
+{0x5815, 0x00},
+{0x5816, 0x00},
+{0x5000, 0x81},
+{0x5001, 0x42},
+{0x5002, 0x1b},
+{0x5003, 0xfe},
+{0x5004, 0x02},
+{0x5005, 0x00},
+{0x5006, 0x01},
+{0x5007, 0x00},
+{0x5008, 0x00},
+{0x5009, 0x40},
+{0x500a, 0x00},
+{0x500b, 0x00},
+{0x500c, 0x00},
+{0x500d, 0x00},
+{0x500e, 0x00},
+{0x500f, 0x00},
+{0x5010, 0x07},
+{0x5011, 0x8f},
+{0x5012, 0x05},
+{0x5013, 0x0f},
+{0x5014, 0x01},
+{0x5015, 0x01},
+{0x5016, 0x01},
+{0x5017, 0x01},
+{0x5018, 0x00},
+{0x5019, 0x00},
+{0x501a, 0x00},
+{0x501b, 0x10},
+{0x501c, 0x00},
+{0x501d, 0x10},
+{0x501e, 0x00},
+{0x501f, 0x10},
+{0x5020, 0x04},
+{0x5021, 0x00},
+{0x5022, 0x04},
+{0x5023, 0x00},
+{0x5024, 0x04},
+{0x5025, 0x00},
+{0x5026, 0x00},
+{0x5027, 0x10},
+{0x5028, 0x00},
+{0x5029, 0x10},
+{0x502a, 0x00},
+{0x502b, 0x10},
+{0x502c, 0x00},
+{0x502d, 0x10},
+{0x502e, 0x00},
+{0x502f, 0x10},
+{0x5030, 0x00},
+{0x5031, 0x10},
+{0x5032, 0x04},
+{0x5033, 0x00},
+{0x5034, 0x04},
+{0x5035, 0x00},
+{0x5036, 0x04},
+{0x5037, 0x00},
+{0x5038, 0x00},
+{0x5039, 0x10},
+{0x503a, 0x00},
+{0x503b, 0x10},
+{0x503c, 0x00},
+{0x503d, 0x10},
+{0x503e, 0x00},
+{0x503f, 0x00},
+{0x5040, 0x00},
+{0x5041, 0x01},
+{0x5042, 0x00},
+{0x5043, 0x00},
+{0x5600, 0x0f},
+{0x5601, 0xab},
+{0x5602, 0x02},
+{0x5603, 0x58},
+{0x5604, 0x03},
+{0x5605, 0x20},
+{0x5606, 0x02},
+{0x5607, 0x58},
+{0x5608, 0x03},
+{0x5609, 0x20},
+{0x560a, 0x02},
+{0x560b, 0x58},
+{0x560c, 0x03},
+{0x560d, 0x20},
+{0x560e, 0x02},
+{0x560f, 0x58},
+{0x5610, 0x03},
+{0x5611, 0x20},
+{0x5612, 0x02},
+{0x5613, 0x58},
+{0x5614, 0x03},
+{0x5615, 0x20},
+{0x5616, 0x02},
+{0x5617, 0x58},
+{0x5618, 0x03},
+{0x5619, 0x20},
+{0x5640, 0x0f},
+{0x5641, 0xab},
+{0x5642, 0x02},
+{0x5643, 0x58},
+{0x5644, 0x03},
+{0x5645, 0x20},
+{0x5646, 0x02},
+{0x5647, 0x58},
+{0x5648, 0x03},
+{0x5649, 0x20},
+{0x564a, 0x02},
+{0x564b, 0x58},
+{0x564c, 0x03},
+{0x564d, 0x20},
+{0x564e, 0x02},
+{0x564f, 0x58},
+{0x5650, 0x03},
+{0x5651, 0x20},
+{0x5652, 0x02},
+{0x5653, 0x58},
+{0x5654, 0x03},
+{0x5655, 0x20},
+{0x5656, 0x02},
+{0x5657, 0x58},
+{0x5658, 0x03},
+{0x5659, 0x20},
+{0x5680, 0x0f},
+{0x5681, 0xab},
+{0x5682, 0x02},
+{0x5683, 0x58},
+{0x5684, 0x03},
+{0x5685, 0x20},
+{0x5686, 0x02},
+{0x5687, 0x58},
+{0x5688, 0x03},
+{0x5689, 0x20},
+{0x568a, 0x02},
+{0x568b, 0x58},
+{0x568c, 0x03},
+{0x568d, 0x20},
+{0x568e, 0x02},
+{0x568f, 0x58},
+{0x5690, 0x03},
+{0x5691, 0x20},
+{0x5692, 0x02},
+{0x5693, 0x58},
+{0x5694, 0x03},
+{0x5695, 0x20},
+{0x5696, 0x02},
+{0x5697, 0x58},
+{0x5698, 0x03},
+{0x5699, 0x20},
+{0x5700, 0x00},
+{0x5701, 0x00},
+{0x5702, 0x00},
+{0x5703, 0x00},
+{0x5704, 0x02},
+{0x5705, 0x80},
+{0x5706, 0x01},
+{0x5707, 0xe0},
+{0x5708, 0x00},
+{0x5709, 0x0f},
+{0x5740, 0x00},
+{0x5741, 0x00},
+{0x5742, 0x00},
+{0x5743, 0x00},
+{0x5744, 0x02},
+{0x5745, 0x80},
+{0x5746, 0x01},
+{0x5747, 0xe0},
+{0x5748, 0x00},
+{0x5749, 0x0f},
+{0x5780, 0x00},
+{0x5781, 0x00},
+{0x5782, 0x00},
+{0x5783, 0x00},
+{0x5784, 0x02},
+{0x5785, 0x80},
+{0x5786, 0x01},
+{0x5787, 0xe0},
+{0x5788, 0x00},
+{0x5789, 0x0f},
+{0x5200, 0x70},
+{0x5201, 0x70},
+{0x5202, 0x73},
+{0x5203, 0xff},
+{0x5204, 0x02},
+{0x5205, 0x6c},
+{0x5206, 0x00},
+{0x5207, 0x00},
+{0x5209, 0x08},
+{0x520a, 0x00},
+{0x520b, 0x07},
+{0x520c, 0x01},
+{0x520d, 0x01},
+{0x520e, 0x01},
+{0x520f, 0x01},
+{0x5210, 0x00},
+{0x5211, 0x00},
+{0x5212, 0x00},
+{0x5213, 0x00},
+{0x5214, 0x00},
+{0x5215, 0x00},
+{0x5216, 0x07},
+{0x5217, 0x8b},
+{0x5218, 0x00},
+{0x5219, 0x00},
+{0x5280, 0x00},
+{0x5281, 0x00},
+{0x5282, 0xff},
+{0x5283, 0xff},
+{0x5284, 0x02},
+{0x5285, 0x6c},
+{0x5286, 0x00},
+{0x5287, 0x00},
+{0x5289, 0x08},
+{0x528a, 0x00},
+{0x528b, 0x07},
+{0x528c, 0x01},
+{0x528d, 0x01},
+{0x528e, 0x01},
+{0x528f, 0x01},
+{0x5290, 0x00},
+{0x5291, 0x00},
+{0x5292, 0x00},
+{0x5293, 0x00},
+{0x5294, 0x00},
+{0x5295, 0x00},
+{0x5296, 0x07},
+{0x5297, 0x8b},
+{0x5298, 0x00},
+{0x5299, 0x00},
+{0x5300, 0x00},
+{0x5301, 0x00},
+{0x5302, 0xff},
+{0x5303, 0xff},
+{0x5304, 0x02},
+{0x5305, 0x6c},
+{0x5306, 0x00},
+{0x5307, 0x00},
+{0x5309, 0x08},
+{0x530a, 0x00},
+{0x530b, 0x07},
+{0x530c, 0x01},
+{0x530d, 0x01},
+{0x530e, 0x01},
+{0x530f, 0x01},
+{0x5310, 0x00},
+{0x5311, 0x00},
+{0x5312, 0x00},
+{0x5313, 0x00},
+{0x5314, 0x00},
+{0x5315, 0x00},
+{0x5316, 0x07},
+{0x5317, 0x8b},
+{0x5318, 0x00},
+{0x5319, 0x00},
+#ifdef OX03A_DISPLAY_PATTERN_COLOR_BAR
+{0x5080, 0xc0}, /* Rolling test pattern for HCG */
+#else
+{0x5080, 0x00},
+#endif
+{0x5081, 0x01},
+{0x5082, 0xb0},
+{0x5083, 0x0f},
+{0x5084, 0x00},
+{0x5085, 0x00},
+{0x5086, 0x00},
+{0x5087, 0x01},
+{0x5088, 0x00},
+{0x5089, 0x00},
+{0x508a, 0x00},
+{0x508b, 0x00},
+{0x508c, 0x00},
+{0x508d, 0x00},
+{0x508e, 0x00},
+{0x508f, 0x00},
+{0x5090, 0x00},
+{0x5091, 0x00},
+{0x5092, 0x00},
+{0x5093, 0x00},
+{0x5094, 0x00},
+{0x5095, 0x00},
+{0x5096, 0x00},
+{0x5097, 0x00},
+#ifdef OX03A_DISPLAY_PATTERN_COLOR_BAR
+{0x50c0, 0xc0}, /* Rolling test pattern for LCG */
+#else
+{0x50c0, 0x00},
+#endif
+{0x50c1, 0x01},
+{0x50c2, 0xb0},
+{0x50c3, 0x0f},
+{0x50c4, 0x00},
+{0x50c5, 0x00},
+{0x50c6, 0x00},
+{0x50c7, 0x01},
+{0x50c8, 0x00},
+{0x50c9, 0x00},
+{0x50ca, 0x00},
+{0x50cb, 0x00},
+{0x50cc, 0x00},
+{0x50cd, 0x00},
+{0x50ce, 0x00},
+{0x50cf, 0x00},
+{0x50d0, 0x00},
+{0x50d1, 0x00},
+{0x50d2, 0x00},
+{0x50d3, 0x00},
+{0x50d4, 0x00},
+{0x50d5, 0x00},
+{0x50d6, 0x00},
+{0x50d7, 0x00},
+#ifdef OX03A_DISPLAY_PATTERN_COLOR_BAR
+{0x5100, 0xc0}, /* Rolling test pattern for VS */
+#else
+{0x5100, 0x00},
+#endif
+{0x5101, 0x01},
+{0x5102, 0xb0},
+{0x5103, 0x0f},
+{0x5104, 0x00},
+{0x5105, 0x00},
+{0x5106, 0x00},
+{0x5107, 0x01},
+{0x5108, 0x00},
+{0x5109, 0x00},
+{0x510a, 0x00},
+{0x510b, 0x00},
+{0x510c, 0x00},
+{0x510d, 0x00},
+{0x510e, 0x00},
+{0x510f, 0x00},
+{0x5110, 0x00},
+{0x5111, 0x00},
+{0x5112, 0x00},
+{0x5113, 0x00},
+{0x5114, 0x00},
+{0x5115, 0x00},
+{0x5116, 0x00},
+{0x5117, 0x00},
+/* patch start */
+{0x0325, 0x68},
+{0x0400, 0xe8},
+{0x0401, 0x00},
+{0x0406, 0x35},
+{0x0407, 0x8a},
+{0x0410, 0xe8},
+{0x0411, 0x00},
+{0x0416, 0x35},
+{0x0417, 0x8a},
+{0x3501, 0x01},
+{0x3502, 0x90},
+{0x3508, 0x04},
+{0x3549, 0x80},
+{0x3674, 0x7b},
+{0x3675, 0xb8},
+{0x3676, 0x3e},
+{0x3677, 0xa8},
+{0x384c, 0x03},
+{0x384d, 0xc2},
+{0x4d0e, 0x20},
+{0x3208, 0x04},
+{0x3501, 0x02},
+{0x3508, 0x04},
+{0x3208, 0x14},
+{0x3208, 0x05},
+{0x3501, 0x02},
+{0x3508, 0x04},
+{0x3208, 0x15},
+/* patch end */
+/* patch2 start */
+//{0x3208, 0x03}, // start recording group3
+{0x3501, 0x08}, // HCG exposure integration time MSB
+{0x3502, 0x80}, // HCG exposure integration time LSB
+{0x3508, 0x06}, // HCG real gain
+{0x350a, 0x06}, // HCG digital gain
+{0x3548, 0x06}, // LCG real gain
+{0x354a, 0x06}, // LCG digital gain
+{0x3588, 0x06}, // VS real gain
+{0x358a, 0x06}, // VS digital gain
+//{0x3208, 0x13}, // stop recording group3
+//{0x3208, 0xe3}, // launch group3
+/* patch2 end */
+{0x0100, 0x01},
+};
diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c
index 7704bfa..e36ecdb 100644
--- a/drivers/media/i2c/soc_camera/ti9x4.c
+++ b/drivers/media/i2c/soc_camera/ti9x4.c
@@ -17,10 +17,9 @@
 #include <linux/of_graph.h>
 #include <linux/videodev2.h>
 
-#include <media/v4l2-async.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-clk.h>
 #include <media/v4l2-device.h>
-#include <media/v4l2-fwnode.h>
 #include <media/v4l2-subdev.h>
 
 #include "ti9x4.h"
@@ -43,7 +42,11 @@ struct ti9x4_priv {
 	int			ti9x3_addr_map[4];
 	char			chip_id[6];
 	int			ser_id;
+	int			vc_map;
+	int			csi_map;
+	struct gpio_desc	*pwen; /* chip power en */
 	struct gpio_desc	*poc_gpio[4]; /* PoC power supply */
+	struct v4l2_clk		*ref_clk; /* ref clock */
 };
 
 static int ser_id;
@@ -70,6 +73,14 @@ static int poc_delay;
 module_param(poc_delay, int, 0644);
 MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms)");
 
+static int vc_map = 0x3210;
+module_param(vc_map, int, 0644);
+MODULE_PARM_DESC(vc_map, " CSI VC MAP (default: 0xe4 - linear map VCx=LINKx)");
+
+static int csi_map = 0;
+module_param(csi_map, int, 0644);
+MODULE_PARM_DESC(csi_map, " CSI TX MAP (default: 0 - forwarding of all links to CSI0)");
+
 #ifdef TI954_SILICON_ERRATA
 static int indirect_write(struct i2c_client *client, unsigned int page, u8 reg, u8 val)
 {
@@ -121,29 +132,35 @@ static void ti9x4_initial_setup(struct i2c_client *client)
 	reg8_write(client, 0x0d, 0xb9);				/* VDDIO 3.3V */
 	switch (priv->csi_rate) {
 	case 1600: /* REFCLK = 25MHZ */
+	case 1500: /* REFCLK = 23MHZ */
 	case 1450: /* REFCLK = 22.5MHZ */
 		reg8_write(client, 0x1f, 0x00);			/* CSI rate 1.5/1.6Gbps */
 		break;
+	case 1200: /* REFCLK = 25MHZ */
+	case 1100: /* REFCLK = 22.5MHZ */
+		reg8_write(client, 0x1f, 0x01);			/* CSI rate 1.1/1.2Gbps */
+		break;
 	case 800: /* REFCLK = 25MHZ */
 	case 700: /* REFCLK = 22.5MHZ */
 		reg8_write(client, 0x1f, 0x02);			/* CSI rate 700/800Mbps */
 		break;
 	case 400: /* REFCLK = 25MHZ */
-		reg8_write(client, 0x1f, 0x03);			/* CSI rate 400Mbps */
+	case 350: /* REFCLK = 22.5MHZ */
+		reg8_write(client, 0x1f, 0x03);			/* CSI rate 350/400Mbps */
 		break;
 	default:
 		dev_err(&client->dev, "unsupported CSI rate %d\n", priv->csi_rate);
 	}
 
 	if (strcmp(priv->forwarding_mode, "round-robin") == 0) {
-		reg8_write(client, 0x21, 0x01);			/* Round Robin forwarding enable */
+		reg8_write(client, 0x21, 0x03);			/* Round Robin forwarding enable for CSI0/CSI1 */
 	} else if (strcmp(priv->forwarding_mode, "synchronized") == 0) {
-		reg8_write(client, 0x21, 0x44);			/* Basic Syncronized forwarding enable (FrameSync must be enabled!!) */
+		reg8_write(client, 0x21, 0x54);			/* Basic Syncronized forwarding enable (FrameSync must be enabled!!) for CSI0/CSI1 */
 	}
 
-	reg8_write(client, 0x32, 0x01);				/* Select TX (CSI) port 0 */
+	reg8_write(client, 0x32, 0x03);				/* Select TX for CSI0/CSI1, RX for CSI0 */
 	reg8_write(client, 0x33, ((priv->lanes - 1) ^ 0x3) << 4); /* disable CSI output, set CSI lane count, non-continuous CSI mode */
-	reg8_write(client, 0x20, 0xf0);				/* disable port forwarding */
+	reg8_write(client, 0x20, 0xf0 | priv->csi_map);		/* disable port forwarding */
 #if 0
 	/* FrameSync setup for REFCLK=25MHz,   FPS=30: period_counts=1/2/FPS*25MHz  =1/2/30*25Mhz  =416666 -> FS_TIME=416666 */
 	/* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/2/FPS*22.5Mhz=1/2/30*22.5Mhz=375000 -> FS_TIME=375000 */
@@ -156,12 +173,15 @@ static void ti9x4_initial_setup(struct i2c_client *client)
 #else
 	/* FrameSync setup for REFCLK=25MHz,   FPS=30: period_counts=1/FPS/12mks=1/30/12e-6=2777 -> HI=2, LO=2775 */
 	/* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/FPS/13.333mks=1/30/13.333e-6=2500 -> HI=2, LO=2498 */
- #define FS_TIME (priv->csi_rate == 1450 ? (2498+15) : (2775+15))
+// #define FS_TIME (priv->csi_rate == 1450 ? (2498+15) : (2775+15))
+// #define FS_TIME (2498+15)
+ #define FS_TIME (2498+15)
 	reg8_write(client, 0x19, 2 >> 8);			/* FrameSync high time MSB */
 	reg8_write(client, 0x1a, 2 & 0xff);			/* FrameSync high time LSB */
 	reg8_write(client, 0x1b, FS_TIME >> 8);			/* FrameSync low time MSB */
 	reg8_write(client, 0x1c, FS_TIME & 0xff);		/* FrameSync low time LSB */
 	reg8_write(client, 0x18, 0x01);				/* Enable FrameSync, HI/LO mode, Frame clock from port0 */
+//	reg8_write(client, 0x18, 0x80);				/* Enable FrameSync, HI/LO mode, Frame clock from port0 */
 #endif
 }
 
@@ -220,10 +240,11 @@ static void ti9x4_fpdlink3_setup(struct i2c_client *client, int idx)
 
 	reg8_write(client, 0x6d, port_config);
 	reg8_write(client, 0x7c, port_config2);
-	reg8_write(client, 0x70, (idx << 6) | 0x1e);		/* CSI data type: yuv422 8-bit, assign VC */
-	reg8_write(client, 0x71, (idx << 6) | 0x2a);		/* CSI data type: RAW8, assign VC */
+	reg8_write(client, 0x70, ((priv->vc_map >> (idx * 4)) << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */
+	reg8_write(client, 0x71, ((priv->vc_map >> (idx * 4)) << 6) | 0x2c); /* CSI data type: RAW12, assign VC */
 	reg8_write(client, 0xbc, 0x00);				/* Setup minimal time between FV and LV to 3 PCLKs */
 	reg8_write(client, 0x6e, 0x88);				/* Sensor reset: backchannel GPIO0/GPIO1 set low */
+	reg8_write(client, 0x72, priv->vc_map >> (idx * 4));	/* CSI VC MAP */
 }
 
 static int ti9x4_initialize(struct i2c_client *client)
@@ -286,10 +307,10 @@ static int ti9x4_s_power(struct v4l2_subdev *sd, int on)
 
 	if (on) {
 		if (atomic_inc_return(&priv->use_count) == 1)
-			reg8_write(client, 0x20, 0x00);		/* enable port forwarding to CSI */
+			reg8_write(client, 0x20, 0x00 | priv->csi_map); /* enable port forwarding to CSI */
 	} else {
 		if (atomic_dec_return(&priv->use_count) == 0)
-			reg8_write(client, 0x20, 0xf0);		/* disable port forwarding to CSI */
+			reg8_write(client, 0x20, 0xf0 | priv->csi_map); /* disable port forwarding to CSI */
 	}
 
 	return 0;
@@ -324,7 +345,7 @@ static int ti9x4_parse_dt(struct i2c_client *client)
 	struct device_node *np = client->dev.of_node;
 	struct device_node *endpoint = NULL, *rendpoint = NULL;
 	struct property *prop;
-	int err, pwen, i;
+	int i;
 	int sensor_delay;
 	char forwarding_mode_default[20] = "round-robin"; /* round-robin, synchronized */
 	struct property *csi_rate_prop, *dvp_order_prop;
@@ -337,18 +358,22 @@ static int ti9x4_parse_dt(struct i2c_client *client)
 	if (of_property_read_u32(np, "ti,lanes", &priv->lanes))
 		priv->lanes = 4;
 
-	pwen = of_get_gpio(np, 0);
-	if (pwen > 0) {
-		err = devm_gpio_request_one(&client->dev, pwen, GPIOF_OUT_INIT_LOW, dev_name(&client->dev));
-		if (err)
-			dev_err(&client->dev, "cannot request PWEN gpio %d: %d\n", pwen, err);
-		else
-			mdelay(250);
+	priv->ref_clk = v4l2_clk_get(&client->dev, "ref_clk");
+	if (!IS_ERR(priv->ref_clk)) {
+		dev_info(&client->dev, "ref_clk = %luKHz", v4l2_clk_get_rate(priv->ref_clk) / 1000);
+		v4l2_clk_enable(priv->ref_clk);
+	}
+
+	priv->pwen = devm_gpiod_get(&client->dev, NULL, GPIOF_OUT_INIT_HIGH);
+	if (!IS_ERR(priv->pwen)) {
+		mdelay(5);
+		gpiod_direction_output(priv->pwen, 0);
+		mdelay(5);
 	}
 
 	for (i = 0; i < 4; i++) {
 		sprintf(poc_name, "POC%d", i);
-		priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, poc_name, 0);
+		priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, kstrdup(poc_name, GFP_KERNEL), 0);
 	}
 
 	reg8_read(client, 0x00, &val);				/* read TI9x4 I2C address */
@@ -379,13 +404,34 @@ static int ti9x4_parse_dt(struct i2c_client *client)
 	if (of_property_read_u32(np, "ti,dvp_bus", &priv->dvp_bus))
 		priv->dvp_bus = 8;
 	if (of_property_read_u32(np, "ti,hsync", &priv->hsync))
-		priv->vsync = 0;
+		priv->hsync = 0;
 	if (of_property_read_u32(np, "ti,vsync", &priv->vsync))
 		priv->vsync = 1;
 	if (of_property_read_u32(np, "ti,ser_id", &priv->ser_id))
 		priv->ser_id = TI913_ID;
 	if (of_property_read_u32(np, "ti,poc-delay", &priv->poc_delay))
 		priv->poc_delay = 50;
+	if (of_property_read_u32(np, "ti,vc-map", &priv->vc_map))
+		priv->vc_map = 0x3210;
+
+	/*
+	 * CSI forwarding of all links is to CSI0 by default.
+	 * Decide if any link will be forwarded to CSI1 instead CSI0
+	 */
+	prop = of_find_property(np, "ti,csi1-links", NULL);
+	if (prop) {
+		const __be32 *link = NULL;
+		u32 v;
+
+		for (i = 0; i < 4; i++) {
+			link = of_prop_next_u32(prop, link, &v);
+			if (!link)
+				break;
+			priv->csi_map |= BIT(v);
+		}
+	} else {
+		priv->csi_map = 0;
+	}
 
 	/* module params override dts */
 	if (is_stp)
@@ -400,6 +446,10 @@ static int ti9x4_parse_dt(struct i2c_client *client)
 		priv->ser_id = ser_id;
 	if (poc_delay)
 		priv->poc_delay = poc_delay;
+	if (vc_map != 0x3210)
+		priv->vc_map = vc_map;
+	if (csi_map)
+		priv->csi_map = csi_map;
 
 	for (i = 0; ; i++) {
 		endpoint = of_graph_get_next_endpoint(np, endpoint);
-- 
2.7.4

