summaryrefslogtreecommitdiffstats
path: root/meta-rcar-gen3-adas/recipes-kernel
diff options
context:
space:
mode:
authorGrigory Kletsko <grigory.kletsko@cogentembedded.com>2017-09-18 16:41:13 +0300
committerGrigory Kletsko <grigory.kletsko@cogentembedded.com>2017-09-18 16:41:13 +0300
commit2212d4e5596911054210a6a3e1bdb6e079de6ed8 (patch)
tree9d0a08c44731595d0298c05a0fab9e03d9fcaaee /meta-rcar-gen3-adas/recipes-kernel
parentc167cd68d5af35436864294330e101b615454522 (diff)
parent076bb2986c9446a76fd0ca93ce36197e789388f1 (diff)
Merge branch 'v2.19.0' of git://github.com/CogentEmbedded/meta-rcar into v2.19.0
Diffstat (limited to 'meta-rcar-gen3-adas/recipes-kernel')
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend2
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch6
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch1181
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch71
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg1
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg32
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend16
7 files changed, 1196 insertions, 113 deletions
diff --git a/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend
new file mode 100644
index 0000000..cf50bc8
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend
@@ -0,0 +1,2 @@
+MMNGR_CFG_eagle = "MMNGR_SALVATORX_X"
+MMNGR_CFG_v3msk = "MMNGR_SALVATORX_X"
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch
index 6209ed0..0cb8cc6 100644
--- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch
@@ -1609,11 +1609,11 @@ index ecae864..42eb45c 100644
- pllcr = LVDPLLCR_PLLDIVCNT_148M;
+ if (soc_device_match(r8a7797)) {
+ if (freq < 39000)
-+ pllcr = LVDPLLCR_PLLDLYCNT_38M;
++ pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
+ else if (freq < 61000)
-+ pllcr = LVDPLLCR_PLLDLYCNT_60M;
++ pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
+ else if (freq < 121000)
-+ pllcr = LVDPLLCR_PLLDLYCNT_121M;
++ pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
+ else
+ pllcr = LVDPLLCR_PLLDLYCNT_150M;
+ } else {
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch
index 2782272..96c1601 100644
--- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch
@@ -4,33 +4,37 @@ Date: Sun, 14 May 2017 15:20:01 +0300
Subject: [PATCH] Gen3: LVDS cameras
This add Gen3 LVDS cameras support:
-- deserializers: MAX9286, TI964, TI953, TI960
-- cameras: 10635, ov490+ov10640, ov495+OV2775
+- deserializers: MAX9286, TI964, TI954, TI960
+- cameras: ov10635, ov490+ov10640, ov495+OV2775, ar0132
Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
---
drivers/media/i2c/soc_camera/Kconfig | 47 +
drivers/media/i2c/soc_camera/Makefile | 7 +
- drivers/media/i2c/soc_camera/max9286_max9271.c | 562 +++++++++++
- drivers/media/i2c/soc_camera/max9286_max9271.h | 196 ++++
- drivers/media/i2c/soc_camera/ov10635.c | 751 ++++++++++++++
+ drivers/media/i2c/soc_camera/ar0132.c | 548 +++++++++++
+ drivers/media/i2c/soc_camera/ar0132.h | 213 ++++
+ drivers/media/i2c/soc_camera/max9286_max9271.c | 567 +++++++++++
+ drivers/media/i2c/soc_camera/max9286_max9271.h | 243 +++++
+ drivers/media/i2c/soc_camera/ov10635.c | 759 ++++++++++++++
drivers/media/i2c/soc_camera/ov10635.h | 1139 ++++++++++++++++++++++
drivers/media/i2c/soc_camera/ov10635_debug.h | 54 +
- drivers/media/i2c/soc_camera/ov106xx.c | 95 ++
- drivers/media/i2c/soc_camera/ov490_ov10640.c | 961 ++++++++++++++++++
- drivers/media/i2c/soc_camera/ov490_ov10640.h | 82 ++
- drivers/media/i2c/soc_camera/ov495_ov2775.c | 650 ++++++++++++
+ drivers/media/i2c/soc_camera/ov106xx.c | 106 ++
+ drivers/media/i2c/soc_camera/ov490_ov10640.c | 1046 ++++++++++++++++++++
+ drivers/media/i2c/soc_camera/ov490_ov10640.h | 88 ++
+ drivers/media/i2c/soc_camera/ov495_ov2775.c | 658 +++++++++++++
drivers/media/i2c/soc_camera/ov495_ov2775.h | 23 +
drivers/media/i2c/soc_camera/ti954_ti9x3.c | 417 ++++++++
drivers/media/i2c/soc_camera/ti964_ti9x3.c | 385 ++++++++
- drivers/media/i2c/soc_camera/ti9x4_ti9x3.h | 108 ++
+ drivers/media/i2c/soc_camera/ti9x4_ti9x3.h | 153 +++
drivers/media/platform/soc_camera/rcar_csi2.c | 297 ++++--
- drivers/media/platform/soc_camera/rcar_vin.c | 159 ++-
+ drivers/media/platform/soc_camera/rcar_vin.c | 174 +++-
drivers/media/platform/soc_camera/soc_camera.c | 17 +-
drivers/media/platform/soc_camera/soc_mediabus.c | 16 +
include/media/drv-intf/soc_mediabus.h | 3 +
include/media/soc_camera.h | 1 +
- 21 files changed, 5861 insertions(+), 109 deletions(-)
+ 23 files changed, 6852 insertions(+), 109 deletions(-)
+ create mode 100644 drivers/media/i2c/soc_camera/ar0132.c
+ create mode 100644 drivers/media/i2c/soc_camera/ar0132.h
create mode 100644 drivers/media/i2c/soc_camera/max9286_max9271.c
create mode 100644 drivers/media/i2c/soc_camera/max9286_max9271.h
create mode 100644 drivers/media/i2c/soc_camera/ov10635.c
@@ -123,12 +127,785 @@ index 6f994f9..7d4c1ab 100644
obj-$(CONFIG_SOC_CAMERA_OV2640) += ov2640.o
obj-$(CONFIG_SOC_CAMERA_OV5642) += ov5642.o
obj-$(CONFIG_SOC_CAMERA_OV6650) += ov6650.o
+diff --git a/drivers/media/i2c/soc_camera/ar0132.c b/drivers/media/i2c/soc_camera/ar0132.c
+new file mode 100644
+index 0000000..284c522
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/ar0132.c
+@@ -0,0 +1,548 @@
++/*
++ * Aptina AR0132 sensor camera driver
++ *
++ * Copyright (C) 2017 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/videodev2.h>
++
++#include <media/soc_camera.h>
++#include <media/v4l2-common.h>
++#include <media/v4l2-ctrls.h>
++#include <media/v4l2-of.h>
++
++#include "ar0132.h"
++
++#define AR0132_I2C_ADDR 0x18
++//#define AR0132_I2C_ADDR 0x50 // eeprom
++
++#define AR0132_PID 0x3000
++#define AR0132_VERSION_REG 0x2400
++
++#define AR0132_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR12_1X12
++
++struct ar0132_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;
++ int dvp_order;
++ /* serializers */
++ int ti964_addr;
++ int ti954_addr;
++ int ti9x3_addr;
++ int port;
++ int gpio_resetb;
++ int gpio_fsin;
++
++};
++
++static inline struct ar0132_priv *to_ar0132(const struct i2c_client *client)
++{
++ return container_of(i2c_get_clientdata(client), struct ar0132_priv, sd);
++}
++
++static int ar0132_set_regs(struct i2c_client *client,
++ const struct ar0132_reg *regs, int nr_regs)
++{
++ int i;
++
++ for (i = 0; i < nr_regs; i++) {
++ if (regs[i].reg == AR0132_DELAY) {
++ mdelay(regs[i].val);
++ continue;
++ }
++
++ reg16_write16(client, regs[i].reg, regs[i].val);
++ }
++
++ return 0;
++}
++
++static int ar0132_s_stream(struct v4l2_subdev *sd, int enable)
++{
++ return 0;
++}
++
++static int ar0132_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 ar0132_priv *priv = to_ar0132(client);
++
++ if (format->pad)
++ return -EINVAL;
++
++ mf->width = priv->rect.width;
++ mf->height = priv->rect.height;
++ mf->code = AR0132_MEDIA_BUS_FMT;
++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
++ mf->field = V4L2_FIELD_NONE;
++
++ return 0;
++}
++
++static int ar0132_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 = AR0132_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 ar0132_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 = AR0132_MEDIA_BUS_FMT;
++
++ return 0;
++}
++
++static int ar0132_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ar0132_priv *priv = to_ar0132(client);
++
++ memcpy(edid->edid, priv->id, 6);
++
++ edid->edid[6] = 0xff;
++ edid->edid[7] = client->addr;
++ edid->edid[8] = AR0132_VERSION_REG >> 8;
++ edid->edid[9] = AR0132_VERSION_REG & 0xff;
++
++ return 0;
++}
++
++static int ar0132_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 ar0132_priv *priv = to_ar0132(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 > AR0132_MAX_WIDTH) ||
++ (rect->top + rect->height > AR0132_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 ar0132_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 ar0132_priv *priv = to_ar0132(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 = AR0132_MAX_WIDTH;
++ sel->r.height = AR0132_MAX_HEIGHT;
++ return 0;
++ case V4L2_SEL_TGT_CROP_DEFAULT:
++ sel->r.left = 0;
++ sel->r.top = 0;
++ sel->r.width = AR0132_MAX_WIDTH;
++ sel->r.height = AR0132_MAX_HEIGHT;
++ return 0;
++ case V4L2_SEL_TGT_CROP:
++ sel->r = priv->rect;
++ return 0;
++ default:
++ return -EINVAL;
++ }
++}
++
++static int ar0132_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 ar0132_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 ar0132_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 ar0132_core_ops = {
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++ .g_register = ar0132_g_register,
++ .s_register = ar0132_s_register,
++#endif
++};
++
++static int ar0132_s_ctrl(struct v4l2_ctrl *ctrl)
++{
++ struct v4l2_subdev *sd = to_sd(ctrl);
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ar0132_priv *priv = to_ar0132(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 ar0132_ctrl_ops = {
++ .s_ctrl = ar0132_s_ctrl,
++};
++
++static struct v4l2_subdev_video_ops ar0132_video_ops = {
++ .s_stream = ar0132_s_stream,
++ .g_mbus_config = ar0132_g_mbus_config,
++};
++
++static const struct v4l2_subdev_pad_ops ar0132_subdev_pad_ops = {
++ .get_edid = ar0132_get_edid,
++ .enum_mbus_code = ar0132_enum_mbus_code,
++ .get_selection = ar0132_get_selection,
++ .set_selection = ar0132_set_selection,
++ .get_fmt = ar0132_get_fmt,
++ .set_fmt = ar0132_set_fmt,
++};
++
++static struct v4l2_subdev_ops ar0132_subdev_ops = {
++ .core = &ar0132_core_ops,
++ .video = &ar0132_video_ops,
++ .pad = &ar0132_subdev_pad_ops,
++};
++
++static void ar0132_otp_id_read(struct i2c_client *client)
++{
++}
++
++static ssize_t ar0132_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 ar0132_priv *priv = to_ar0132(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_ar0132, S_IRUGO, ar0132_otp_id_show, NULL);
++
++static int ar0132_initialize(struct i2c_client *client)
++{
++ struct ar0132_priv *priv = to_ar0132(client);
++ u16 val = 0;
++ u16 pid = 0;
++ int ret = 0;
++
++ /* check and show model ID */
++ reg16_read16(client, AR0132_PID, &pid);
++
++ if (pid != AR0132_VERSION_REG) {
++ dev_dbg(&client->dev, "Product ID error %x\n", pid);
++ ret = -ENODEV;
++ goto err;
++ }
++
++ /* Program wizard registers */
++ ar0132_set_regs(client, ar0132_regs_wizard, ARRAY_SIZE(ar0132_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 */
++ ar0132_otp_id_read(client);
++
++ dev_info(&client->dev, "ar0132 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n",
++ pid, AR0132_MAX_WIDTH, AR0132_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 ar0132_parse_dt(struct device_node *np, struct ar0132_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;
++
++ of_node_put(endpoint);
++
++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order);
++
++ 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,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) &&
++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port))
++ break;
++ }
++
++ if (!priv->ti964_addr && !priv->ti954_addr) {
++ dev_err(&client->dev, "deserializer does not present\n");
++ return -EINVAL;
++ }
++
++ /* setup I2C translator address */
++ tmp_addr = client->addr;
++ 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, AR0132_I2C_ADDR << 1); /* Sensor native I2C address */
++
++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */
++ }
++ if (priv->ti954_addr) {
++ client->addr = priv->ti954_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, AR0132_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 ar0132_probe(struct i2c_client *client,
++ const struct i2c_device_id *did)
++{
++ struct ar0132_priv *priv;
++ int ret;
++
++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ v4l2_i2c_subdev_init(&priv->sd, client, &ar0132_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, &ar0132_ctrl_ops,
++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops,
++ V4L2_CID_CONTRAST, 0, 16, 1, 7);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops,
++ V4L2_CID_SATURATION, 0, 7, 1, 2);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops,
++ V4L2_CID_HUE, 0, 23, 1, 12);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops,
++ V4L2_CID_GAMMA, -128, 128, 1, 0);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops,
++ V4L2_CID_SHARPNESS, 0, 10, 1, 3);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops,
++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops,
++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops,
++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops,
++ V4L2_CID_HFLIP, 0, 1, 1, 1);
++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_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 = ar0132_parse_dt(client->dev.of_node, priv);
++ if (ret)
++ goto cleanup;
++
++ ret = ar0132_initialize(client);
++ if (ret < 0)
++ goto cleanup;
++
++ priv->rect.left = 0;
++ priv->rect.top = 0;
++ priv->rect.width = AR0132_MAX_WIDTH;
++ priv->rect.height = AR0132_MAX_HEIGHT;
++
++ ret = v4l2_async_register_subdev(&priv->sd);
++ if (ret)
++ goto cleanup;
++
++ if (device_create_file(&client->dev, &dev_attr_otp_id_ar0132) != 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_AR0132
++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
++ client->addr, client->adapter->name);
++#endif
++ return ret;
++}
++
++static int ar0132_remove(struct i2c_client *client)
++{
++ struct ar0132_priv *priv = i2c_get_clientdata(client);
++
++ device_remove_file(&client->dev, &dev_attr_otp_id_ar0132);
++ 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_AR0132
++static const struct i2c_device_id ar0132_id[] = {
++ { "ar0132", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, ar0132_id);
++
++static const struct of_device_id ar0132_of_ids[] = {
++ { .compatible = "aptina,ar0132", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, ar0132_of_ids);
++
++static struct i2c_driver ar0132_i2c_driver = {
++ .driver = {
++ .name = "ar0132",
++ .of_match_table = ar0132_of_ids,
++ },
++ .probe = ar0132_probe,
++ .remove = ar0132_remove,
++ .id_table = ar0132_id,
++};
++
++module_i2c_driver(ar0132_i2c_driver);
++
++MODULE_DESCRIPTION("SoC Camera driver for AR0132");
++MODULE_AUTHOR("Vladimir Barinov");
++MODULE_LICENSE("GPL");
++#endif
+diff --git a/drivers/media/i2c/soc_camera/ar0132.h b/drivers/media/i2c/soc_camera/ar0132.h
+new file mode 100644
+index 0000000..055841d
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/ar0132.h
+@@ -0,0 +1,213 @@
++/*
++ * OmniVision ar0132 sensor camera wizard 1110x620@30/BGGR/BT601/12bit
++ *
++ * Copyright (C) 2017 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 AR0132_DISPLAY_PATTERN_FIXED
++//#define AR0132_DISPLAY_PATTERN_COLOR_BAR
++
++#define AR0132_EMBEDDED_LINE
++
++#define AR0132_MAX_WIDTH 1665 // (1110*3/2)
++#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_Y 620 // AR0132_MAX_HEIGHT
++
++#define AR0132_ROI_Y_START 0x00AE
++#define AR0132_ROI_X_START 0x005C
++#define AR0132_ROI_Y_END AR0132_ROI_Y_START+AR0132_ROI_DIM_Y-1
++#define AR0132_ROI_X_END AR0132_ROI_X_START+AR0132_ROI_DIM_X-1
++
++#define AR0132_FrameLength_Lines 0x029E
++#define AR0132_LineLength_Ticks 0x06B6
++
++#define AR0132_PLL_VT_Pix_Clk_Div 0x0008
++#define AR0132_PLL_VT_Sys_Clk_Div 0x0001
++#define AR0132_PLL_Pre_Clk_Div 0x0004
++#define AR0132_PLL_Multiplier 0x003C
++
++#define AR0132_DigitalTest 0x2002
++
++struct ar0132_reg {
++ u16 reg;
++ u16 val;
++};
++
++static const struct ar0132_reg ar0132_regs_wizard[] = {
++{0x301A, 0x0001}, // reset
++{AR0132_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 AR0132_DISPLAY_PATTERN_FIXED
++{0x3070, 0x0001},
++{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
++{AR0132_DELAY, 250},
++// patch begin
++{0x3088, 0x8000},
++{0x3086, 0x0025}, {0x3086, 0x5050}, {0x3086, 0x2D26}, {0x3086, 0x0828}, {0x3086, 0x0D17}, {0x3086, 0x0926}, {0x3086, 0x0028}, {0x3086, 0x0526},
++{0x3086, 0xA728}, {0x3086, 0x0725}, {0x3086, 0x8080}, {0x3086, 0x2925}, {0x3086, 0x0040}, {0x3086, 0x2702}, {0x3086, 0x1616}, {0x3086, 0x2706},
++{0x3086, 0x1736}, {0x3086, 0x26A6}, {0x3086, 0x1703}, {0x3086, 0x26A4}, {0x3086, 0x171F}, {0x3086, 0x2805}, {0x3086, 0x2620}, {0x3086, 0x2804},
++{0x3086, 0x2520}, {0x3086, 0x2027}, {0x3086, 0x0017}, {0x3086, 0x1D25}, {0x3086, 0x0020}, {0x3086, 0x1F17}, {0x3086, 0x1028}, {0x3086, 0x0519},
++{0x3086, 0x1703}, {0x3086, 0x2706}, {0x3086, 0x1703}, {0x3086, 0x1741}, {0x3086, 0x2660}, {0x3086, 0x17AE}, {0x3086, 0x2500}, {0x3086, 0x9027},
++{0x3086, 0x0026}, {0x3086, 0x1828}, {0x3086, 0x002E}, {0x3086, 0x2A28}, {0x3086, 0x081C}, {0x3086, 0x1470}, {0x3086, 0x7003}, {0x3086, 0x1470},
++{0x3086, 0x7004}, {0x3086, 0x1470}, {0x3086, 0x7005}, {0x3086, 0x1470}, {0x3086, 0x7009}, {0x3086, 0x170C}, {0x3086, 0x0014}, {0x3086, 0x0020},
++{0x3086, 0x2300}, {0x3086, 0x1400}, {0x3086, 0x5003}, {0x3086, 0x1400}, {0x3086, 0x2003}, {0x3086, 0x1400}, {0x3086, 0x5022}, {0x3086, 0x0414},
++{0x3086, 0x0020}, {0x3086, 0x0414}, {0x3086, 0x0050}, {0x3086, 0x0514}, {0x3086, 0x0020}, {0x3086, 0x2405}, {0x3086, 0x1400}, {0x3086, 0x5001},
++{0x3086, 0x2550}, {0x3086, 0x502D}, {0x3086, 0x2608}, {0x3086, 0x280D}, {0x3086, 0x1709}, {0x3086, 0x2600}, {0x3086, 0x2805}, {0x3086, 0x26A7},
++{0x3086, 0x2807}, {0x3086, 0x2580}, {0x3086, 0x8029}, {0x3086, 0x2500}, {0x3086, 0x4027}, {0x3086, 0x0216}, {0x3086, 0x1627}, {0x3086, 0x0617},
++{0x3086, 0x3626}, {0x3086, 0xA617}, {0x3086, 0x0326}, {0x3086, 0xA417}, {0x3086, 0x1F28}, {0x3086, 0x0526}, {0x3086, 0x2028}, {0x3086, 0x0425},
++{0x3086, 0x2020}, {0x3086, 0x2700}, {0x3086, 0x171D}, {0x3086, 0x2500}, {0x3086, 0x2020}, {0x3086, 0x1710}, {0x3086, 0x2805}, {0x3086, 0x1A17},
++{0x3086, 0x0327}, {0x3086, 0x0617}, {0x3086, 0x0317}, {0x3086, 0x4126}, {0x3086, 0x6017}, {0x3086, 0xAE25}, {0x3086, 0x0090}, {0x3086, 0x2700},
++{0x3086, 0x2618}, {0x3086, 0x2800}, {0x3086, 0x2E2A}, {0x3086, 0x2808}, {0x3086, 0x1D05}, {0x3086, 0x1470}, {0x3086, 0x7009}, {0x3086, 0x1720},
++{0x3086, 0x1400}, {0x3086, 0x2024}, {0x3086, 0x1400}, {0x3086, 0x5002}, {0x3086, 0x2550}, {0x3086, 0x502D}, {0x3086, 0x2608}, {0x3086, 0x280D},
++{0x3086, 0x1709}, {0x3086, 0x2600}, {0x3086, 0x2805}, {0x3086, 0x26A7}, {0x3086, 0x2807}, {0x3086, 0x2580}, {0x3086, 0x8029}, {0x3086, 0x2500},
++{0x3086, 0x4027}, {0x3086, 0x0216}, {0x3086, 0x1627}, {0x3086, 0x0617}, {0x3086, 0x3626}, {0x3086, 0xA617}, {0x3086, 0x0326}, {0x3086, 0xA417},
++{0x3086, 0x1F28}, {0x3086, 0x0526}, {0x3086, 0x2028}, {0x3086, 0x0425}, {0x3086, 0x2020}, {0x3086, 0x2700}, {0x3086, 0x171D}, {0x3086, 0x2500},
++{0x3086, 0x2021}, {0x3086, 0x1710}, {0x3086, 0x2805}, {0x3086, 0x1B17}, {0x3086, 0x0327}, {0x3086, 0x0617}, {0x3086, 0x0317}, {0x3086, 0x4126},
++{0x3086, 0x6017}, {0x3086, 0xAE25}, {0x3086, 0x0090}, {0x3086, 0x2700}, {0x3086, 0x2618}, {0x3086, 0x2800}, {0x3086, 0x2E2A}, {0x3086, 0x2808},
++{0x3086, 0x1E17}, {0x3086, 0x0A05}, {0x3086, 0x1470}, {0x3086, 0x7009}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616},
++{0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616},
++{0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1400}, {0x3086, 0x2024}, {0x3086, 0x1400}, {0x3086, 0x502B},
++{0x3086, 0x302C}, {0x3086, 0x2C2C}, {0x3086, 0x2C00}, {0x3086, 0x0225}, {0x3086, 0x5050}, {0x3086, 0x2D26}, {0x3086, 0x0828}, {0x3086, 0x0D17},
++{0x3086, 0x0926}, {0x3086, 0x0028}, {0x3086, 0x0526}, {0x3086, 0xA728}, {0x3086, 0x0725}, {0x3086, 0x8080}, {0x3086, 0x2917}, {0x3086, 0x0525},
++{0x3086, 0x0040}, {0x3086, 0x2702}, {0x3086, 0x1616}, {0x3086, 0x2706}, {0x3086, 0x1736}, {0x3086, 0x26A6}, {0x3086, 0x1703}, {0x3086, 0x26A4},
++{0x3086, 0x171F}, {0x3086, 0x2805}, {0x3086, 0x2620}, {0x3086, 0x2804}, {0x3086, 0x2520}, {0x3086, 0x2027}, {0x3086, 0x0017}, {0x3086, 0x1E25},
++{0x3086, 0x0020}, {0x3086, 0x2117}, {0x3086, 0x1028}, {0x3086, 0x051B}, {0x3086, 0x1703}, {0x3086, 0x2706}, {0x3086, 0x1703}, {0x3086, 0x1747},
++{0x3086, 0x2660}, {0x3086, 0x17AE}, {0x3086, 0x2500}, {0x3086, 0x9027}, {0x3086, 0x0026}, {0x3086, 0x1828}, {0x3086, 0x002E}, {0x3086, 0x2A28},
++{0x3086, 0x081E}, {0x3086, 0x0831}, {0x3086, 0x1440}, {0x3086, 0x4014}, {0x3086, 0x2020}, {0x3086, 0x1410}, {0x3086, 0x1034}, {0x3086, 0x1400},
++{0x3086, 0x1014}, {0x3086, 0x0020}, {0x3086, 0x1400}, {0x3086, 0x4013}, {0x3086, 0x1802}, {0x3086, 0x1470}, {0x3086, 0x7004}, {0x3086, 0x1470},
++{0x3086, 0x7003}, {0x3086, 0x1470}, {0x3086, 0x7017}, {0x3086, 0x2002}, {0x3086, 0x1400}, {0x3086, 0x2002}, {0x3086, 0x1400}, {0x3086, 0x5004},
++{0x3086, 0x1400}, {0x3086, 0x2004}, {0x3086, 0x1400}, {0x3086, 0x5022}, {0x3086, 0x0314}, {0x3086, 0x0020}, {0x3086, 0x0314}, {0x3086, 0x0050},
++{0x3086, 0x2C2C}, {0x3086, 0x2C2C},
++{0x309E, 0x0186},
++{0x309E, 0x0186},
++// patch end
++{AR0132_DELAY, 250},
++{0x301A, 0x10D8}, // WR= RESET_REGISTER, 0x10D8 - stop streaming
++{0x3082, 0x0028}, // Set HiDy OPERATION_MODE_CTRL(A) Requested integration time ratio (T2 to T3): 8 & (T1 t0 T2): 16
++{0x3084, 0x0028}, // Set HiDy OPERATION_MODE_CTRL(B) Requested integration time ratio (T2 to T3): 16 & (T1 t0 T2): 16
++{0x301E, 0x00C8}, // set datapedestal to 200 to avoid clipping near saturation
++{0x3EDA, 0x0F03}, // Set vln_dac to 0x3 as recommended by Sergey
++{0x3EDE, 0xC007},
++{0x3ED8, 0x01EF}, // Vrst_low = +1
++{0x3EE2, 0xA46B},
++{0x3EE0, 0x067D}, // enable anti eclipse and adjust setting for high conversion gain
++{0x3EDC, 0x0070}, // adjust anti eclipse setting for low conversion gain
++{0x3044, 0x0404}, // disable digital row noise correction and cancels TX during column correction
++{0x3EE6, 0x4303}, // Helps with column noise at low light
++{0x3EE4, 0xD208}, // enable analog row noise correction
++{0x3ED6, 0x00BD},
++{0x3EE6, 0x8303}, // improves low light FPN
++{0x30E4, 0x6372}, // ADC settings to improve noise performance
++{0x30E2, 0x7253},
++{0x30E0, 0x5470},
++{0x30E6, 0xC4CC},
++{0x30E8, 0x8050},
++{AR0132_DELAY, 250},
++{0x3058, 0x003F}, // WR= BLUE_GAIN, 0x003F
++{0x3014, 0}, // Fine_IT_Time(A)
++{0x3002, AR0132_ROI_Y_START}, // WR= Y_ADDR_START_(A)
++{0x3004, AR0132_ROI_X_START}, // WR= X_ADDR_START_(A)
++{0x3006, AR0132_ROI_Y_END}, // WR= Y_ADDR_END_(A)
++{0x3008, AR0132_ROI_X_END}, // WR= X_ADDR_END_(A)
++{0x300A, AR0132_FrameLength_Lines}, // WR= FRAME_LENGTH_LINES_(A)
++{0x3018, 0}, // Fine_IT_Time(B)
++{0x308C, AR0132_ROI_Y_START}, // Y_ADDR_START_(B)
++{0x308A, AR0132_ROI_X_START}, // X_ADDR_START_(B)
++{0x3090, AR0132_ROI_Y_END}, // Y_ADDR_END_(B)
++{0x308E, AR0132_ROI_X_END}, // X_ADDR_END_(B)
++{0x30AA, AR0132_FrameLength_Lines}, // FRAME_LENGTH_LINES_(B)
++{0x300C, AR0132_LineLength_Ticks}, // Line Length
++{0x301A, 0x10D8}, // Disable Streaming and setup parallel
++{0x31D0, 0x0001}, // Set to 12 bits
++{0x3028, 0x0010}, // ROW_SPEED = 16
++{0x302A, AR0132_PLL_VT_Pix_Clk_Div},
++{0x302C, AR0132_PLL_VT_Sys_Clk_Div},
++{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
++{0x3044, 0x0404}, // Dark Control = 1028
++{0x30A6, 0x0001}, // Y Odd Inc. (A) = 1
++{0x30A8, 0x0001}, // Y Odd Inc. (B) = 1
++{0x30B0, AR0132_DigitalTest},
++{AR0132_DELAY, 100},
++#ifdef AR0132_EMBEDDED_LINE
++{0x3064, 0x1982}, // Embedded Data on
++#else
++{0x3064, 0x1802}, // Embedded Data off
++#endif
++{0x3100, 0x0084}, // WR= AECTRLREG,
++{0x3190, 0x6BA0},
++{0x3194, 0x0E74},
++{0x3196, 0x0ED8},
++{0x3198, 0x0FA0},
++{0x319E, 0x5040}, // resetvalue
++{0x31A2, 0x0FA0},
++//FrontCamera Specific Section
++//Common
++#ifdef AR0132_EMBEDDED_LINE
++{0x3064, 0x1982},
++#else
++{0x3064, 0x1802},
++#endif
++{0x30B4, 0x0011},
++{0x30ba, 0x0008},
++{0x3180, 0xE000},
++{0x3182, 0x012C},
++{0x3190, 0x6BA0},
++{0x3194, 0x0E74},
++{0x3196, 0x0ED8},
++{0x3198, 0x0FA0},
++{0x319E, 0x5040},
++{0x31A2, 0x0FA0},
++//Context A:0
++{0x3012, 0x0021},
++{0x3014, 0x0000},
++{0x30A6, 0x0001},
++{0x3056, 0x0008},
++{0x3058, 0x0008},
++{0x305A, 0x0008},
++{0x305C, 0x0008},
++{0x305E, 0x0008},
++{0x3082, 0x0014},
++//Context B:0
++{0x3016, 0x007F},
++{0x3018, 0x0000},
++{0x30A8, 0x0001},
++{0x30BC, 0x0020},
++{0x30BE, 0x0020},
++{0x30C0, 0x0020},
++{0x30C2, 0x0020},
++{0x30C4, 0x0020},
++{0x3084, 0x0028},
++//not covered
++{0x301E, 0x00C8},
++{0x3044, 0x0404},
++{0x31D0, 0x0001},
++{0x30B0, 0x2002},
++};
diff --git a/drivers/media/i2c/soc_camera/max9286_max9271.c b/drivers/media/i2c/soc_camera/max9286_max9271.c
new file mode 100644
-index 0000000..1261e45
+index 0000000..9797d24
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/max9286_max9271.c
-@@ -0,0 +1,562 @@
+@@ -0,0 +1,567 @@
+/*
+ * MAXIM max9286-max9271 GMSL driver
+ *
@@ -203,6 +980,24 @@ index 0000000..1261e45
+ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */
+}
+
++static void max9286_max9271_sensor_reset(struct i2c_client *client, int addr)
++{
++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client);
++
++ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5)
++ return;
++
++ /* get out from sensor reset */
++ client->addr = addr; /* MAX9271-CAMx I2C */
++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) |
++ (priv->active_low_resetb ? 0 : BIT(priv->gpio_resetb))); /* set GPIOn value to reset */
++ reg8_write(client, 0x0e, 0x42 | BIT(priv->gpio_resetb)); /* set GPIOn direction output */
++ usleep_range(2000, 2500); /* wait 2ms */
++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) |
++ (priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0)); /* set GPIOn value to un-reset */
++ usleep_range(2000, 2500); /* wait 2ms */
++}
++
+static void max9286_max9271_postinit(struct i2c_client *client, int addr)
+{
+ struct max9286_max9271_priv *priv = i2c_get_clientdata(client);
@@ -214,10 +1009,6 @@ index 0000000..1261e45
+ 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 */
+ usleep_range(5000, 5500); /* wait 2ms after any change of reverse channel settings */
-+
-+ /* wait for sensor firmware up (f.e. ov490) if we did sensor reset */
-+ if (priv->gpio_resetb >= 1 && priv->gpio_resetb <= 5)
-+ mdelay(300);
+}
+
+static int max9286_max9271_reverse_channel_setup(struct i2c_client *client, int idx)
@@ -269,6 +1060,8 @@ index 0000000..1261e45
+ }
+ }
+
++ max9286_max9271_sensor_reset(client, client->addr); /* sensor reset */
++
+ if (!timeout) {
+ ret = -ETIMEDOUT;
+ goto out;
@@ -365,17 +1158,6 @@ index 0000000..1261e45
+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */
+ maxim_max927x_dump_regs(client);
+#endif
-+ if (priv->gpio_resetb >= 1 && priv->gpio_resetb <= 5) {
-+ /* get out from sensor reset */
-+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */
-+ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) |
-+ (priv->active_low_resetb ? 0 : BIT(priv->gpio_resetb))); /* set GPIOn value to reset */
-+ reg8_write(client, 0x0e, 0x42 | BIT(priv->gpio_resetb)); /* set GPIOn direction output */
-+ usleep_range(2000, 2500); /* wait 2ms */
-+ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) |
-+ (priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0)); /* set GPIOn value to un-reset */
-+ usleep_range(2000, 2500); /* wait 2ms */
-+ }
+}
+
+static int max9286_max9271_initialize(struct i2c_client *client)
@@ -512,10 +1294,10 @@ index 0000000..1261e45
+ err = gpio_request_one(pwen, GPIOF_OUT_INIT_HIGH, dev_name(&client->dev));
+ if (err)
+ dev_err(&client->dev, "cannot request PWEN gpio %d: %d\n", pwen, err);
-+ else
-+ mdelay(250);
+ }
+
++ mdelay(250);
++
+ reg8_read(client, 0x1e, &val); /* read max9286 ID */
+ if (val != MAX9286_ID) {
+ prop = of_find_property(np, "reg", NULL);
@@ -693,10 +1475,10 @@ index 0000000..1261e45
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/soc_camera/max9286_max9271.h b/drivers/media/i2c/soc_camera/max9286_max9271.h
new file mode 100644
-index 0000000..87c040b
+index 0000000..0016f28a
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/max9286_max9271.h
-@@ -0,0 +1,196 @@
+@@ -0,0 +1,243 @@
+/*
+ * MAXIM max9286-max9271 GMSL driver include file
+ *
@@ -828,6 +1610,53 @@ index 0000000..87c040b
+ return ret < 0 ? ret : 0;
+}
+
++
++static inline int reg16_read16(struct i2c_client *client, u16 reg, u16 *val)
++{
++ int ret, retries;
++ u8 buf[2] = {reg >> 8, reg & 0xff};
++
++ for (retries = REG8_NUM_RETRIES; retries; retries--) {
++ ret = i2c_master_send(client, buf, 2);
++ if (ret == 2) {
++ ret = i2c_master_recv(client, buf, 2);
++ if (ret == 2)
++ break;
++ }
++ }
++
++ if (ret < 0) {
++ dev_err(&client->dev,
++ "read fail: chip 0x%x register 0x%x: %d\n",
++ client->addr, reg, ret);
++ } else {
++ *val = ((u16)buf[0] << 8) | buf[1];
++ }
++
++ return ret < 0 ? ret : 0;
++}
++
++static inline int reg16_write16(struct i2c_client *client, u16 reg, u16 val)
++{
++ int ret, retries;
++ u8 buf[4] = {reg >> 8, reg & 0xff, val >> 8, val & 0xff};
++
++ for (retries = REG8_NUM_RETRIES; retries; retries--) {
++ ret = i2c_master_send(client, buf, 4);
++ if (ret == 4)
++ break;
++ }
++
++ if (ret < 0) {
++ dev_err(&client->dev,
++ "write fail: chip 0x%x register 0x%x: %d\n",
++ client->addr, reg, ret);
++ }
++
++ return ret < 0 ? ret : 0;
++}
++
++
+#ifdef MAXIM_DUMP
+static void maxim_ovsensor_dump_regs(struct i2c_client *client)
+{
@@ -895,10 +1724,10 @@ index 0000000..87c040b
+#endif /* _MAX9286_MAX9271_H */
diff --git a/drivers/media/i2c/soc_camera/ov10635.c b/drivers/media/i2c/soc_camera/ov10635.c
new file mode 100644
-index 0000000..fd72396
+index 0000000..45169de
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov10635.c
-@@ -0,0 +1,751 @@
+@@ -0,0 +1,759 @@
+/*
+ * OmniVision ov10635 sensor camera driver
+ *
@@ -1344,6 +2173,9 @@ index 0000000..fd72396
+ val &= ~0xc0;
+ ret = reg16_write(client, 0x381c, val);
+ break;
++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
++ ret = 0;
++ break;
+ }
+
+out:
@@ -1504,7 +2336,6 @@ index 0000000..fd72396
+ reg8_write(client, 0x5d, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */
+
+ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */
-+ udelay(100);
+ }
+
+ if (priv->ti954_addr) {
@@ -1516,10 +2347,11 @@ index 0000000..fd72396
+ reg8_write(client, 0x5d, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */
+
+ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */
-+ udelay(100);
+ }
+ client->addr = tmp_addr;
+
++ udelay(100);
++
+ return 0;
+}
+
@@ -1527,6 +2359,7 @@ index 0000000..fd72396
+ const struct i2c_device_id *did)
+{
+ struct ov10635_priv *priv;
++ struct v4l2_ctrl *ctrl;
+ int ret;
+
+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
@@ -1562,6 +2395,10 @@ index 0000000..fd72396
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops,
++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9);
++ if (ctrl)
++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
+ priv->sd.ctrl_handler = &priv->hdl;
+
+ ret = priv->hdl.error;
@@ -2634,10 +3471,10 @@ index 0000000..66cc490
+{0x6F00, 0x03},
+{0x6F00, 0x43},
+/* enable FSIN (FRAMESYNC input) functionality */
-+{0x3832, 0x00},
-+{0x3833, 0x10},
-+{0x3834, 0x00},
-+{0x3835, 0x10},
++{0x3832, (0x0d+2*0x20+0x15+38) >> 8},
++{0x3833, (0x0d+2*0x20+0x15+38) & 0xff},
++{0x3834, OV10635_VTS >> 8},
++{0x3835, OV10635_VTS & 0xff},
+{0x302E, 0x01},
+};
+
@@ -2857,10 +3694,10 @@ index 0000000..4c3515a
+#endif
diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c
new file mode 100644
-index 0000000..0079bb2
+index 0000000..f2bb706
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov106xx.c
-@@ -0,0 +1,95 @@
+@@ -0,0 +1,106 @@
+/*
+ * OmniVision ov10635/ov490-ov10640/ov495-ov2775 sensor camera driver
+ *
@@ -2875,11 +3712,13 @@ index 0000000..0079bb2
+#include "ov10635.c"
+#include "ov490_ov10640.c"
+#include "ov495_ov2775.c"
++#include "ar0132.c"
+
+static enum {
+ ID_OV10635,
+ ID_OV490_OV10640,
+ ID_OV495_OV2775,
++ ID_AR0132,
+} chip_id;
+
+static int ov106xx_probe(struct i2c_client *client,
@@ -2906,6 +3745,12 @@ index 0000000..0079bb2
+ goto out;
+ }
+
++ ret = ar0132_probe(client, did);
++ if (!ret) {
++ chip_id = ID_AR0132;
++ goto out;
++ }
++
+ v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
+ client->addr, client->adapter->name);
+out:
@@ -2924,6 +3769,9 @@ index 0000000..0079bb2
+ case ID_OV495_OV2775:
+ ov495_remove(client);
+ break;
++ case ID_AR0132:
++ ar0132_remove(client);
++ break;
+ };
+
+ return 0;
@@ -2953,15 +3801,15 @@ index 0000000..0079bb2
+
+module_i2c_driver(ov106xx_i2c_driver);
+
-+MODULE_DESCRIPTION("SoC Camera driver for OV10635 or OV490/OV10640 or OV495/OV2775");
++MODULE_DESCRIPTION("SoC Camera driver for OV10635 or OV490/OV10640 or OV495/OV2775 or AR0132");
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.c b/drivers/media/i2c/soc_camera/ov490_ov10640.c
new file mode 100644
-index 0000000..308fe1b
+index 0000000..15acc51
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c
-@@ -0,0 +1,961 @@
+@@ -0,0 +1,1046 @@
+/*
+ * OmniVision ov490-ov10640 sensor camera driver
+ *
@@ -3021,8 +3869,8 @@ index 0000000..308fe1b
+ int ti9x3_addr;
+ int port;
+ int gpio_resetb;
++ int active_low_resetb;
+ int gpio_fsin;
-+
+};
+
+static int force_conf_link;
@@ -3055,6 +3903,48 @@ index 0000000..308fe1b
+ };
+}
+
++static void ov490_reset(struct i2c_client *client)
++{
++ struct ov490_priv *priv = to_ov490(client);
++ int tmp_addr;
++
++ if (priv->max9286_addr) {
++ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5)
++ return;
++
++ tmp_addr = client->addr;
++ /* get out from sensor reset */
++ client->addr = priv->max9271_addr; /* MAX9271 I2C address */
++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) |
++ (priv->active_low_resetb ? 0 : BIT(priv->gpio_resetb))); /* set GPIOn value to reset */
++ usleep_range(2000, 2500); /* wait 2ms */
++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) |
++ (priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0)); /* set GPIOn value to un-reset */
++ usleep_range(2000, 2500); /* wait 2ms */
++ client->addr = tmp_addr;
++ }
++
++ if (priv->ti964_addr) {
++ client->addr = priv->ti964_addr; /* TI964 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, 0x6e, 0x8a); /* set GPIO1 value to reset */
++ usleep_range(2000, 2500); /* wait 2ms */
++ reg8_write(client, 0x6e, 0x9a); /* set GPIO1 value to un-reset */
++ }
++
++ if (priv->ti954_addr) {
++ client->addr = priv->ti954_addr; /* TI964 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, 0x6e, 0x8a); /* set GPIO1 value to reset */
++ usleep_range(2000, 2500); /* wait 2ms */
++ reg8_write(client, 0x6e, 0x9a); /* set GPIO1 value to un-reset */
++ }
++}
++
+static int ov490_set_regs(struct i2c_client *client,
+ const struct ov490_reg *regs, int nr_regs)
+{
@@ -3534,6 +4424,9 @@ index 0000000..308fe1b
+ ret |= reg16_write(client, 0x00C0, 0xc1);
+#endif
+ break;
++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
++ ret = 0;
++ break;
+ }
+
+ return ret;
@@ -3630,7 +4523,7 @@ index 0000000..308fe1b
+ struct ov490_priv *priv = to_ov490(client);
+ u8 val = 0;
+ u8 pid = 0, ver = 0;
-+ int ret = 0;
++ int ret = 0, timeout, retry_timeout = 3;
+
+ if (priv->is_fixed_sensor) {
+ dev_info(&client->dev, "ov490/ov10640 fixed-sensor res %dx%d\n", priv->max_width, priv->max_height);
@@ -3655,6 +4548,36 @@ index 0000000..308fe1b
+ if (unlikely(force_conf_link))
+ goto out;
+
++again:
++ /* Check if firmware booted by reading stream-on status */
++ reg16_write(client, 0xFFFD, 0x80);
++ reg16_write(client, 0xFFFE, 0x29);
++ usleep_range(100, 150); /* wait 100 us */
++ timeout = 300;
++ for (;;) {
++ reg16_read(client, 0xd000, &val);
++ if (val == 0x0c || --timeout == 0)
++ break;
++ mdelay(1);
++ }
++
++ if (!timeout) {
++ dev_err(&client->dev, "Timeout firmware boot wait, retrying\n");
++ /* reset OV10640 using RESETB pin controlled by OV490 GPIO0 */
++ reg16_write(client, 0xFFFD, 0x80);
++ reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0x0050, 0x01);
++ reg16_write(client, 0x0054, 0x01);
++ reg16_write(client, 0x0058, 0x00);
++ mdelay(10);
++ reg16_write(client, 0x0058, 0x01);
++ /* reset OV490 using RESETB pin controlled by serializer */
++ ov490_reset(client);
++ if (retry_timeout--)
++ goto again;
++ }
++
+ /* read resolution used by current firmware */
+ reg16_write(client, 0xFFFD, 0x80);
+ reg16_write(client, 0xFFFE, 0x82);
@@ -3709,8 +4632,17 @@ index 0000000..308fe1b
+
+ 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))
++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) {
++ if (of_property_read_u32(rendpoint->parent->parent, "maxim,resetb-gpio", &priv->gpio_resetb)) {
++ priv->gpio_resetb = -1;
++ } else {
++ if (of_property_read_bool(rendpoint->parent->parent, "maxim,resetb-active-high"))
++ priv->active_low_resetb = false;
++ else
++ priv->active_low_resetb = true;
++ }
+ break;
++ }
+
+ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) &&
+ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti964-ti9x3") &&
@@ -3750,8 +4682,6 @@ index 0000000..308fe1b
+ reg8_write(client, 0x5d, OV490_I2C_ADDR << 1); /* Sensor native I2C address */
+
+ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */
-+ /* TODO: why too long? move logic to workqueue? */
-+ mdelay(350); /* time needed to boot all sensor IPs */
+ }
+ if (priv->ti954_addr) {
+ client->addr = priv->ti954_addr; /* Deserializer I2C address */
@@ -3762,8 +4692,6 @@ index 0000000..308fe1b
+ reg8_write(client, 0x5d, OV490_I2C_ADDR << 1); /* Sensor native I2C address */
+
+ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */
-+ /* TODO: why too long? move logic to workqueue? */
-+ mdelay(350); /* time needed to boot all sensor IPs */
+ }
+ client->addr = tmp_addr;
+
@@ -3795,6 +4723,7 @@ index 0000000..308fe1b
+ const struct i2c_device_id *did)
+{
+ struct ov490_priv *priv;
++ struct v4l2_ctrl *ctrl;
+ int ret;
+
+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
@@ -3830,6 +4759,10 @@ index 0000000..308fe1b
+ V4L2_CID_HFLIP, 0, 1, 1, 1);
+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops,
++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9);
++ if (ctrl)
++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
+ priv->sd.ctrl_handler = &priv->hdl;
+
+ ret = priv->hdl.error;
@@ -3925,7 +4858,7 @@ index 0000000..308fe1b
+#endif
diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.h b/drivers/media/i2c/soc_camera/ov490_ov10640.h
new file mode 100644
-index 0000000..dde81ef
+index 0000000..d3290c7
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov490_ov10640.h
@@ -0,0 +1,88 @@
@@ -4019,10 +4952,10 @@ index 0000000..dde81ef
+};
diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.c b/drivers/media/i2c/soc_camera/ov495_ov2775.c
new file mode 100644
-index 0000000..56891ff
+index 0000000..881615e
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c
-@@ -0,0 +1,650 @@
+@@ -0,0 +1,658 @@
+/*
+ * OmniVision ov495-ov2775 sensor camera driver
+ *
@@ -4337,6 +5270,9 @@ index 0000000..56891ff
+ ret |= reg16_write(client, 0x30C0, 0xdc);
+ ret |= reg16_write(client, 0x3516, 0x01);
+ break;
++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
++ ret = 0;
++ break;
+ }
+
+ return ret;
@@ -4545,6 +5481,7 @@ index 0000000..56891ff
+ const struct i2c_device_id *did)
+{
+ struct ov495_priv *priv;
++ struct v4l2_ctrl *ctrl;
+ int ret;
+
+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
@@ -4580,6 +5517,10 @@ index 0000000..56891ff
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops,
++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9);
++ if (ctrl)
++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
+ priv->sd.ctrl_handler = &priv->hdl;
+
+ ret = priv->hdl.error;
@@ -4704,7 +5645,7 @@ index 0000000..3f53689
+};
diff --git a/drivers/media/i2c/soc_camera/ti954_ti9x3.c b/drivers/media/i2c/soc_camera/ti954_ti9x3.c
new file mode 100644
-index 0000000..f94208d
+index 0000000..fc7ccda
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ti954_ti9x3.c
@@ -0,0 +1,417 @@
@@ -4865,7 +5806,7 @@ index 0000000..f94208d
+ }
+ reg8_write(client, 0x70, (idx << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */
+ reg8_write(client, 0x7c, 0x81); /* BIT(7) - magic to Use RAW10 as 8-bit mode */
-+ reg8_write(client, 0x6e, 0x99); /* Backchannel GPIO0/GPIO1 set high */
++ reg8_write(client, 0x6e, 0x88); /* Sensor reset: backchannel GPIO0/GPIO1 set low */
+}
+
+static int ti954_ti9x3_initialize(struct i2c_client *client)
@@ -5127,7 +6068,7 @@ index 0000000..f94208d
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/soc_camera/ti964_ti9x3.c b/drivers/media/i2c/soc_camera/ti964_ti9x3.c
new file mode 100644
-index 0000000..567def1
+index 0000000..8dd0f99
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ti964_ti9x3.c
@@ -0,0 +1,385 @@
@@ -5261,7 +6202,7 @@ index 0000000..567def1
+ }
+ reg8_write(client, 0x70, (idx << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */
+ reg8_write(client, 0x7c, 0x81); /* BIT(7) - magic to Use RAW10 as 8-bit mode */
-+ reg8_write(client, 0x6e, 0x99); /* Backchannel GPIO0/GPIO1 set high */
++ reg8_write(client, 0x6e, 0x88); /* Sensor reset: backchannel GPIO0/GPIO1 set low */
+}
+
+static int ti964_ti9x3_initialize(struct i2c_client *client)
@@ -5518,10 +6459,10 @@ index 0000000..567def1
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/soc_camera/ti9x4_ti9x3.h b/drivers/media/i2c/soc_camera/ti9x4_ti9x3.h
new file mode 100644
-index 0000000..0cee5f1
+index 0000000..69d3728
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ti9x4_ti9x3.h
-@@ -0,0 +1,108 @@
+@@ -0,0 +1,153 @@
+/*
+ * TI FPDLinkIII driver include file
+ *
@@ -5629,9 +6570,54 @@ index 0000000..0cee5f1
+
+ return ret < 0 ? ret : 0;
+}
++
++static inline int reg16_read16(struct i2c_client *client, u16 reg, u16 *val)
++{
++ int ret, retries;
++ u8 buf[2] = {reg >> 8, reg & 0xff};
++
++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) {
++ ret = i2c_master_send(client, buf, 2);
++ if (ret == 2) {
++ ret = i2c_master_recv(client, buf, 2);
++ if (ret == 2)
++ break;
++ }
++ }
++
++ if (ret < 0) {
++ dev_err(&client->dev,
++ "read fail: chip 0x%x register 0x%x: %d\n",
++ client->addr, reg, ret);
++ } else {
++ *val = ((u16)buf[0] << 8) | buf[1];
++ }
++
++ return ret < 0 ? ret : 0;
++}
++
++static inline int reg16_write16(struct i2c_client *client, u16 reg, u16 val)
++{
++ int ret, retries;
++ u8 buf[4] = {reg >> 8, reg & 0xff, val >> 8, val & 0xff};
++
++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) {
++ ret = i2c_master_send(client, buf, 4);
++ if (ret == 4)
++ break;
++ }
++
++ if (ret < 0) {
++ dev_err(&client->dev,
++ "write fail: chip 0x%x register 0x%x: %d\n",
++ client->addr, reg, ret);
++ }
++
++ return ret < 0 ? ret : 0;
++}
+#endif /* _TI9X4_H */
diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c
-index 5faac64..cf70414 100644
+index 4d95da6..2ef27e8 100644
--- a/drivers/media/platform/soc_camera/rcar_csi2.c
+++ b/drivers/media/platform/soc_camera/rcar_csi2.c
@@ -37,8 +37,9 @@
@@ -6117,7 +7103,7 @@ index 5faac64..cf70414 100644
return 0;
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
-index 74fb005..f5c2528 100644
+index 74fb005..496a8bd 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -106,6 +106,7 @@
@@ -6158,17 +7144,18 @@ index 74fb005..f5c2528 100644
/* Synchronous probing compatibility */
struct platform_device *csi2_pdev;
-@@ -989,6 +995,9 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
+@@ -989,6 +995,10 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
input_is_yuv = true;
break;
+ case MEDIA_BUS_FMT_SBGGR8_1X8:
++ case MEDIA_BUS_FMT_SBGGR12_1X12:
+ vnmc |= VNMC_INF_RAW8 | VNMC_BPS;
+ break;
default:
break;
}
-@@ -1021,6 +1030,10 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
+@@ -1021,6 +1031,10 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
dmr = 0;
output_is_yuv = true;
break;
@@ -6179,27 +7166,29 @@ index 74fb005..f5c2528 100644
case V4L2_PIX_FMT_ARGB555:
dmr = VNDMR_DTMD_ARGB;
break;
-@@ -1043,6 +1056,9 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
+@@ -1043,6 +1057,10 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB;
break;
+ case V4L2_PIX_FMT_SBGGR8:
++ case V4L2_PIX_FMT_SBGGR12:
+ dmr = 0;
+ break;
default:
goto e_format;
}
-@@ -1061,7 +1077,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
+@@ -1061,7 +1079,9 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
else
vnmc |= VNMC_DPINE;
- if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12)
+ if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) &&
-+ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8)
++ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8) &&
++ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR12)
&& is_scaling(cam))
vnmc |= VNMC_SCLE;
}
-@@ -1211,6 +1228,10 @@ static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
+@@ -1211,6 +1231,10 @@ static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
*/
static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv)
{
@@ -6210,7 +7199,7 @@ index 74fb005..f5c2528 100644
while (priv->state != STOPPED) {
/* issue stop if running */
if (priv->state == RUNNING)
-@@ -1361,6 +1382,31 @@ static struct v4l2_subdev *find_csi2(struct rcar_vin_priv *pcdev)
+@@ -1361,6 +1385,31 @@ static struct v4l2_subdev *find_csi2(struct rcar_vin_priv *pcdev)
return NULL;
}
@@ -6242,7 +7231,7 @@ index 74fb005..f5c2528 100644
static int rcar_vin_add_device(struct soc_camera_device *icd)
{
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-@@ -1375,7 +1421,8 @@ static int rcar_vin_add_device(struct soc_camera_device *icd)
+@@ -1375,7 +1424,8 @@ static int rcar_vin_add_device(struct soc_camera_device *icd)
if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
priv->chip == RCAR_V3M) {
struct v4l2_subdev *csi2_sd = find_csi2(priv);
@@ -6252,7 +7241,7 @@ index 74fb005..f5c2528 100644
if (csi2_sd) {
csi2_sd->grp_id = soc_camera_grp_id(icd);
-@@ -1390,6 +1437,18 @@ static int rcar_vin_add_device(struct soc_camera_device *icd)
+@@ -1390,6 +1440,18 @@ static int rcar_vin_add_device(struct soc_camera_device *icd)
if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
return ret;
}
@@ -6271,7 +7260,7 @@ index 74fb005..f5c2528 100644
/*
* -ENODEV is special:
* either csi2_sd == NULL or the CSI-2 driver
-@@ -1417,6 +1476,7 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd)
+@@ -1417,6 +1479,7 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd)
struct rcar_vin_priv *priv = ici->priv;
struct vb2_v4l2_buffer *vbuf;
struct v4l2_subdev *csi2_sd = find_csi2(priv);
@@ -6279,7 +7268,7 @@ index 74fb005..f5c2528 100644
int i;
/* disable capture, disable interrupts */
-@@ -1443,6 +1503,8 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd)
+@@ -1443,6 +1506,8 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd)
if ((csi2_sd) && (priv->csi_sync))
v4l2_subdev_call(csi2_sd, core, s_power, 0);
@@ -6288,27 +7277,29 @@ index 74fb005..f5c2528 100644
dev_dbg(icd->parent, "R-Car VIN driver detached from camera %d\n",
icd->devnum);
-@@ -1621,13 +1683,17 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd)
+@@ -1621,13 +1686,19 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd)
if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
priv->chip == RCAR_V3M) {
- if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12)
+ if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) &&
-+ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8)
++ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8) &&
++ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR12)
&& is_scaling(cam)) {
ret = rcar_vin_uds_set(priv, cam);
if (ret < 0)
return ret;
}
- if (is_scaling(cam) ||
-+ if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_SBGGR8)
++ if ((icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_SBGGR8) ||
++ (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_SBGGR12))
+ iowrite32(ALIGN(cam->out_width / 2, 0x10),
+ priv->base + VNIS_REG);
+ else if (is_scaling(cam) ||
(icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV16) ||
(icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV12))
iowrite32(ALIGN(cam->out_width, 0x20),
-@@ -1868,6 +1934,14 @@ static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt)
+@@ -1868,6 +1939,14 @@ static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt)
.layout = SOC_MBUS_LAYOUT_PACKED,
},
{
@@ -6323,7 +7314,7 @@ index 74fb005..f5c2528 100644
.fourcc = V4L2_PIX_FMT_RGB565,
.name = "RGB565",
.bits_per_sample = 16,
-@@ -1899,6 +1973,14 @@ static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt)
+@@ -1899,6 +1978,22 @@ static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt)
.order = SOC_MBUS_ORDER_LE,
.layout = SOC_MBUS_LAYOUT_PACKED,
},
@@ -6335,18 +7326,27 @@ index 74fb005..f5c2528 100644
+ .order = SOC_MBUS_ORDER_LE,
+ .layout = SOC_MBUS_LAYOUT_PACKED,
+ },
++ {
++ .fourcc = V4L2_PIX_FMT_SBGGR12,
++ .name = "Bayer 12 BGGR",
++ .bits_per_sample = 8,
++ .packing = SOC_MBUS_PACKING_NONE,
++ .order = SOC_MBUS_ORDER_LE,
++ .layout = SOC_MBUS_LAYOUT_PACKED,
++ },
};
static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx,
-@@ -2012,6 +2094,7 @@ static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx,
+@@ -2012,6 +2107,8 @@ static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx,
case MEDIA_BUS_FMT_YUYV8_2X8:
case MEDIA_BUS_FMT_YUYV10_2X10:
case MEDIA_BUS_FMT_RGB888_1X24:
+ case MEDIA_BUS_FMT_SBGGR8_1X8:
++ case MEDIA_BUS_FMT_SBGGR12_1X12:
if (cam->extra_fmt)
break;
-@@ -2218,12 +2301,14 @@ static int rcar_vin_set_fmt(struct soc_camera_device *icd,
+@@ -2218,12 +2315,15 @@ static int rcar_vin_set_fmt(struct soc_camera_device *icd,
case V4L2_PIX_FMT_ABGR32:
case V4L2_PIX_FMT_UYVY:
case V4L2_PIX_FMT_YUYV:
@@ -6358,10 +7358,11 @@ index 74fb005..f5c2528 100644
break;
case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_SBGGR8:
++ case V4L2_PIX_FMT_SBGGR12:
default:
can_scale = false;
break;
-@@ -2316,7 +2401,8 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd,
+@@ -2316,7 +2416,8 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd,
/* odd number clipping by pixel post clip processing, */
/* it is outputted to a memory per even pixels. */
if ((pixfmt == V4L2_PIX_FMT_NV16) || (pixfmt == V4L2_PIX_FMT_NV12) ||
@@ -6371,7 +7372,7 @@ index 74fb005..f5c2528 100644
v4l_bound_align_image(&pix->width, 5, priv->max_width, 1,
&pix->height, 2, priv->max_height, 0, 0);
else
-@@ -2486,6 +2572,19 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd,
+@@ -2486,6 +2587,19 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd,
}
#endif
@@ -6391,7 +7392,7 @@ index 74fb005..f5c2528 100644
static struct soc_camera_host_ops rcar_vin_host_ops = {
.owner = THIS_MODULE,
.add = rcar_vin_add_device,
-@@ -2504,6 +2603,7 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd,
+@@ -2504,6 +2618,7 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd,
.get_selection = rcar_vin_get_selection,
.cropcap = rcar_vin_cropcap,
#endif
@@ -6399,7 +7400,7 @@ index 74fb005..f5c2528 100644
};
#ifdef CONFIG_OF
-@@ -2524,7 +2624,7 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd,
+@@ -2524,7 +2639,7 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd,
MODULE_DEVICE_TABLE(of, rcar_vin_of_table);
#endif
@@ -6408,7 +7409,7 @@ index 74fb005..f5c2528 100644
static DECLARE_BITMAP(device_map, MAP_MAX_NUM);
static DEFINE_MUTEX(list_lock);
-@@ -2714,7 +2814,11 @@ static int rcar_vin_probe(struct platform_device *pdev)
+@@ -2714,7 +2829,11 @@ static int rcar_vin_probe(struct platform_device *pdev)
const char *str;
unsigned int i;
struct device_node *epn = NULL, *ren = NULL;
@@ -6420,7 +7421,7 @@ index 74fb005..f5c2528 100644
match = of_match_device(of_match_ptr(rcar_vin_of_table), &pdev->dev);
-@@ -2741,13 +2845,27 @@ static int rcar_vin_probe(struct platform_device *pdev)
+@@ -2741,13 +2860,27 @@ static int rcar_vin_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "node name:%s\n",
of_node_full_name(ren->parent));
@@ -6452,7 +7453,7 @@ index 74fb005..f5c2528 100644
}
ret = v4l2_of_parse_endpoint(np, &ep);
-@@ -2799,6 +2917,7 @@ static int rcar_vin_probe(struct platform_device *pdev)
+@@ -2799,6 +2932,7 @@ static int rcar_vin_probe(struct platform_device *pdev)
priv->ici.drv_name = dev_name(&pdev->dev);
priv->ici.ops = &rcar_vin_host_ops;
priv->csi_sync = false;
@@ -6460,7 +7461,7 @@ index 74fb005..f5c2528 100644
priv->pdata_flags = pdata_flags;
if (!match) {
-@@ -2983,7 +3102,25 @@ static int rcar_vin_probe(struct platform_device *pdev)
+@@ -2983,7 +3117,25 @@ static int rcar_vin_probe(struct platform_device *pdev)
goto cleanup;
if (csi_use) {
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch
index 661d02c..4acd0f1 100644
--- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch
@@ -18,18 +18,19 @@ Videobox board on R8A7795 ES1.x SoC
Videobox board on R8A7795 SoC
Eagle board on R8A7797 SoC
V3MSK board on R8A7797 SoC
-Kingfisher board on V3M SoC
+Kingfisher board on R8A7797 SoC
Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
---
- arch/arm64/boot/dts/renesas/Makefile | 15 +
- arch/arm64/boot/dts/renesas/legacy/Makefile | 7 +
+ arch/arm64/boot/dts/renesas/Makefile | 16 +
+ arch/arm64/boot/dts/renesas/legacy/Makefile | 8 +
.../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1717 +++++++++++++++++++
.../renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts | 441 +++++
.../dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts | 1724 +++++++++++++++++++
.../dts/renesas/legacy/r8a7795-h3ulcb-kf-v1.dts | 465 +++++
.../dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts | 1214 +++++++++++++
.../dts/renesas/legacy/r8a7796-m3ulcb-kf-v1.dts | 465 +++++
+ .../dts/renesas/legacy/r8a7797-v3msk-kf-v0.dts | 20 +
.../boot/dts/renesas/legacy/ulcb-kf-cmos.dtsi | 75 +
.../arm64/boot/dts/renesas/legacy/ulcb-kf-rpi.dtsi | 77 +
.../dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts | 22 +
@@ -54,9 +55,9 @@ Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 294 ++++
arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 518 ++++++
arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi | 46 +
- arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1523 +++++++++++++++++
+ arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1520 +++++++++++++++++
arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi | 515 ++++++
- 34 files changed, 17221 insertions(+)
+ 35 files changed, 17240 insertions(+)
create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile
create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts
create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts
@@ -64,6 +65,7 @@ Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v1.dts
create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts
create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7796-m3ulcb-kf-v1.dts
+ create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7797-v3msk-kf-v0.dts
create mode 100644 arch/arm64/boot/dts/renesas/legacy/ulcb-kf-cmos.dtsi
create mode 100644 arch/arm64/boot/dts/renesas/legacy/ulcb-kf-rpi.dtsi
create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts
@@ -92,10 +94,10 @@ Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi
diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
-index 32fb4d9..de2770e 100644
+index 32fb4d9..fd17456 100644
--- a/arch/arm64/boot/dts/renesas/Makefile
+++ b/arch/arm64/boot/dts/renesas/Makefile
-@@ -4,5 +4,20 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x.dtb r8a7795-es1-h3ulcb.dtb
+@@ -4,5 +4,21 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x.dtb r8a7795-es1-h3ulcb.dtb
dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x.dtb r8a7796-m3ulcb.dtb
dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb
@@ -110,6 +112,7 @@ index 32fb4d9..de2770e 100644
+dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vb.dtb r8a7795-es1-h3ulcb-vb.dtb
+dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-eagle.dtb
+dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk.dtb
++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-kf.dtb
+
+# ADAS legacy boards
+subdir-y := legacy
@@ -118,14 +121,15 @@ index 32fb4d9..de2770e 100644
clean-files := *.dtb
diff --git a/arch/arm64/boot/dts/renesas/legacy/Makefile b/arch/arm64/boot/dts/renesas/legacy/Makefile
new file mode 100644
-index 0000000..f7de935
+index 0000000..7f25079
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/legacy/Makefile
-@@ -0,0 +1,7 @@
+@@ -0,0 +1,8 @@
+# Legacy KF board: V0, V1 (V2 is the same as V1), V3 is latest and deployed in default directory
+dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-kf-v0.dtb r8a7795-es1-h3ulcb-kf-v1.dtb
+dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-kf-v0.dtb r8a7796-m3ulcb-kf-v1.dtb
+dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-kf-v0.dtb r8a7795-h3ulcb-kf-v1.dtb
++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-kf-v0.dtb
+
+always := $(dtb-y)
+clean-files := *.dtb
@@ -220,7 +224,7 @@ index 0000000..cd23797
+ regulator-name = "lvds_on";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
-+ gpio = <&gpio1 24 0>;
++ /* gpio = <&gpio1 24 0>; */
+ enable-active-high;
+ regulator-always-on;
+ };
@@ -2390,7 +2394,7 @@ index 0000000..f640350
+ regulator-name = "lvds_on";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
-+ gpio = <&gpio1 24 0>;
++ /* gpio = <&gpio1 24 0>; */
+ enable-active-high;
+ regulator-always-on;
+ };
@@ -4591,7 +4595,7 @@ index 0000000..7be2370
+ regulator-name = "lvds_on";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
-+ gpio = <&gpio1 24 0>;
++ /* gpio = <&gpio1 24 0>; */
+ enable-active-high;
+ regulator-always-on;
+ };
@@ -6191,6 +6195,32 @@ index 0000000..637c840
+ pcie3v3-supply = <&mpcie_3v3>;
+ pcie1v8-supply = <&mpcie_1v8>;
+};
+diff --git a/arch/arm64/boot/dts/renesas/legacy/r8a7797-v3msk-kf-v0.dts b/arch/arm64/boot/dts/renesas/legacy/r8a7797-v3msk-kf-v0.dts
+new file mode 100644
+index 0000000..cc04429
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/legacy/r8a7797-v3msk-kf-v0.dts
+@@ -0,0 +1,20 @@
++/*
++ * Device Tree Source for the V3MSK Kingfisher V0 board on r8a7797
++ *
++ * Copyright (C) 2017 Renesas Electronics Corp.
++ * Copyright (C) 2017 Cogent Embedded, Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include "../r8a7797-v3msk-kf.dts"
++
++/ {
++ model = "Renesas V3MSK Kingfisher V0 board based on r8a7797";
++};
++
++&i2cswitch4 {
++ reg = <0x74>;
++};
diff --git a/arch/arm64/boot/dts/renesas/legacy/ulcb-kf-cmos.dtsi b/arch/arm64/boot/dts/renesas/legacy/ulcb-kf-cmos.dtsi
new file mode 100644
index 0000000..2145f5e
@@ -12826,7 +12856,7 @@ new file mode 100644
index 0000000..730cd2a
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts
-@@ -0,0 +1,36 @@
+@@ -0,0 +1,40 @@
+/*
+ * Device Tree Source for the M3ULCB Kingfisher board on r8a7796
+ *
@@ -12863,6 +12893,10 @@ index 0000000..730cd2a
+&hsusb {
+ status = "okay";
+};
++
++&xhci0 {
++ status = "disabled";
++};
diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts
new file mode 100644
index 0000000..1ac0041
@@ -14049,7 +14083,7 @@ index 0000000..f71addf
+
diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts
new file mode 100644
-index 0000000..903d73e
+index 0000000..9837e17
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts
@@ -0,0 +1,541 @@
@@ -15475,7 +15509,7 @@ new file mode 100644
index 0000000..4ead97a
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi
-@@ -0,0 +1,1523 @@
+@@ -0,0 +1,1520 @@
+/*
+ * Device Tree Source for the ULCB Kingfisher board
+ *
@@ -15636,7 +15670,7 @@ index 0000000..4ead97a
+ /delete-node/sound;
+
+ rsnd_ak4613: sound@1 {
-+ pinctrl-0 = <&sound_1_pins>;
++ pinctrl-0 = <&sound_pins>;
+ pinctrl-names = "default";
+ compatible = "simple-audio-card";
+
@@ -15812,10 +15846,7 @@ index 0000000..4ead97a
+ function = "ssi";
+ };
+
-+ sound_1_pins: sound1 {
-+ groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data_a";
-+ function = "ssi";
-+ };
++ /* sound_pins defined in H3 or M3 ulsb file */
+
+ sound_2_pins: sound2 {
+ groups = "ssi6_ctrl", "ssi6_data";
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg
index c0f4237..333b917 100644
--- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg
@@ -25,3 +25,4 @@ CONFIG_VIDEO_RENESAS_IMR=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_PROPERTIES=y
CONFIG_HID_MULTITOUCH=y
+CONFIG_SERIAL_SH_SCI_DMA=y
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg
new file mode 100644
index 0000000..ffc54dc
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg
@@ -0,0 +1,32 @@
+CONFIG_ARCH_R8A7797=y
+CONFIG_CAN=y
+CONFIG_CAN_PEAK_USB=y
+CONFIG_CAN_BCM=y
+CONFIG_CAN_RAW=y
+CONFIG_CAN_DEV=y
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_RCAR=y
+CONFIG_CANFD_RCAR=y
+CONFIG_DUMMY=y
+CONFIG_DRM_I2C_ADV7511=y
+CONFIG_GPIO_MAX732X=y
+CONFIG_GPIO_MAX732X_IRQ=y
+CONFIG_GPIO_PCA953X=y
+CONFIG_GPIO_PCA953X_IRQ=y
+CONFIG_VIDEO_ADV_DEBUG=y
+CONFIG_VIDEO_RCAR_VIN_LEGACY=y
+CONFIG_VIDEO_RCAR_CSI2_LEGACY=y
+# CONFIG_VIDEO_RCAR_VIN is not set
+# CONFIG_VIDEO_RCAR_CSI2 is not set
+CONFIG_SOC_CAMERA=y
+CONFIG_SOC_CAMERA_SCALE_CROP=y
+CONFIG_SOC_CAMERA_PLATFORM=y
+CONFIG_SOC_CAMERA_MAX9286_MAX9271=y
+CONFIG_SOC_CAMERA_TI964_TI9X3=y
+CONFIG_SOC_CAMERA_TI954_TI9X3=y
+CONFIG_SOC_CAMERA_OV106XX=y
+CONFIG_VIDEO_RENESAS_IMR=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_PROPERTIES=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_SERIAL_SH_SCI_DMA=y
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend
index 7e4738a..43c9e10 100644
--- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend
@@ -1,5 +1,8 @@
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+COMPATIBLE_MACHINE_eagle = "eagle"
+COMPATIBLE_MACHINE_v3msk = "v3msk"
+
SRC_URI_append = " \
${@bb.utils.contains('MACHINE_FEATURES', 'h3ulcb-had', ' file://hyperflash.cfg', '', d)} \
${@base_conditional("SDHI_SEQ", "1", " file://sdhi_seq.cfg", "", d)} \
@@ -61,6 +64,7 @@ SRC_URI_append_h3ulcb = " file://ulcb.cfg"
SRC_URI_append_m3ulcb = " file://ulcb.cfg"
SRC_URI_append_salvator-x = " file://salvator-x.cfg"
SRC_URI_append_eagle = " file://eagle.cfg"
+SRC_URI_append_v3msk = " file://v3msk.cfg"
KERNEL_DEVICETREE_append_h3ulcb = " \
renesas/r8a7795-es1-h3ulcb-view.dtb \
@@ -73,11 +77,17 @@ KERNEL_DEVICETREE_append_h3ulcb = " \
renesas/r8a7795-h3ulcb-had-beta.dtb \
renesas/r8a7795-h3ulcb-kf.dtb \
renesas/r8a7795-h3ulcb-vb.dtb \
+ renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dtb \
+ renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dtb \
+ renesas/legacy/r8a7795-h3ulcb-kf-v0.dtb \
+ renesas/legacy/r8a7795-h3ulcb-kf-v1.dtb \
"
KERNEL_DEVICETREE_append_m3ulcb = " \
renesas/r8a7796-m3ulcb-view.dtb \
renesas/r8a7796-m3ulcb-kf.dtb \
+ renesas/legacy/r8a7796-m3ulcb-kf-v0.dtb \
+ renesas/legacy/r8a7796-m3ulcb-kf-v1.dtb \
"
KERNEL_DEVICETREE_append_salvator-x = " \
@@ -89,3 +99,9 @@ KERNEL_DEVICETREE_append_salvator-x = " \
KERNEL_DEVICETREE_append_eagle = " \
renesas/r8a7797-eagle.dtb \
"
+
+KERNEL_DEVICETREE_append_v3msk = " \
+ renesas/r8a7797-v3msk.dtb \
+ renesas/r8a7797-v3msk-kf.dtb \
+ renesas/legacy/r8a7797-v3msk-kf-v0.dtb \
+"