summaryrefslogtreecommitdiffstats
path: root/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch
diff options
context:
space:
mode:
authorVladimir Barinov <vladimir.barinov@cogentembedded.com>2017-11-26 21:50:19 +0300
committerVladimir Barinov <vladimir.barinov@cogentembedded.com>2017-11-26 21:50:19 +0300
commita741482ab005ed90c717af54d41f4626420224dc (patch)
tree9e53deca6f1629f1762f54051480e0c6ed27390d /meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch
parentcfc23e64c7675214f15461a4e533d8ecc2e948f8 (diff)
LVDS stability update
1) use POC regulators in driver and power cameras one after one 2) set sensors reset during POC channels setup 3) fix wizard setup for ov490 based caemras by waiting it's firmware start all internal apps 4) support AR0132 with MAX9286 5) due to stability fixed then increase i2c bus speed on Videobox Mini 6) support MAX96705 serializer with MAX9286
Diffstat (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch')
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch239
1 files changed, 179 insertions, 60 deletions
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 aca7198..781e456 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
@@ -11,20 +11,20 @@ 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/ar0132.c | 548 +++++++++++
+ drivers/media/i2c/soc_camera/ar0132.c | 581 +++++++++++
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/max9286_max9271.c | 607 ++++++++++++
+ drivers/media/i2c/soc_camera/max9286_max9271.h | 244 +++++
+ drivers/media/i2c/soc_camera/ov10635.c | 758 ++++++++++++++
drivers/media/i2c/soc_camera/ov10635.h | 1139 ++++++++++++++++++++++
drivers/media/i2c/soc_camera/ov10635_debug.h | 54 +
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/ov490_ov10640.c | 1064 ++++++++++++++++++++
+ drivers/media/i2c/soc_camera/ov490_ov10640.h | 93 ++
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/ti954_ti9x3.c | 431 ++++++++
+ drivers/media/i2c/soc_camera/ti964_ti9x3.c | 399 ++++++++
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 | 174 +++-
@@ -32,7 +32,7 @@ Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
drivers/media/platform/soc_camera/soc_mediabus.c | 16 +
include/media/drv-intf/soc_mediabus.h | 3 +
include/media/soc_camera.h | 1 +
- 23 files changed, 6852 insertions(+), 109 deletions(-)
+ 23 files changed, 6976 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
@@ -129,10 +129,10 @@ index 6f994f9..7d4c1ab 100644
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
+index 0000000..decbf5f
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ar0132.c
-@@ -0,0 +1,548 @@
+@@ -0,0 +1,581 @@
+/*
+ * Aptina AR0132 sensor camera driver
+ *
@@ -177,6 +177,8 @@ index 0000000..284c522
+ int autogain;
+ int dvp_order;
+ /* serializers */
++ int max9286_addr;
++ int max9271_addr;
+ int ti964_addr;
+ int ti954_addr;
+ int ti9x3_addr;
@@ -191,6 +193,19 @@ index 0000000..284c522
+ return container_of(i2c_get_clientdata(client), struct ar0132_priv, sd);
+}
+
++static void ar0132_s_port(struct i2c_client *client, int fwd_en)
++{
++ struct ar0132_priv *priv = to_ar0132(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 */
++ client->addr = tmp_addr;
++ };
++}
++
+static int ar0132_set_regs(struct i2c_client *client,
+ const struct ar0132_reg *regs, int nr_regs)
+{
@@ -456,6 +471,8 @@ index 0000000..284c522
+ u16 pid = 0;
+ int ret = 0;
+
++ ar0132_s_port(client, 1);
++
+ /* check and show model ID */
+ reg16_read16(client, AR0132_PID, &pid);
+
@@ -479,6 +496,8 @@ index 0000000..284c522
+ 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:
++ ar0132_s_port(client, 0);
++
+ return ret;
+}
+
@@ -502,6 +521,11 @@ index 0000000..284c522
+ 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,ti964-ti9x3") &&
+ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti964_addr) &&
@@ -515,13 +539,22 @@ index 0000000..284c522
+ break;
+ }
+
-+ if (!priv->ti964_addr && !priv->ti954_addr) {
-+ dev_err(&client->dev, "deserializer does not present\n");
++ if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) {
++ dev_err(&client->dev, "deserializer does not present for AR0132\n");
+ return -EINVAL;
+ }
+
++ ar0132_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, AR0132_I2C_ADDR << 1); /* Sensor native I2C address */
++ usleep_range(2000, 2500); /* wait 2ms */
++ };
+ if (priv->ti964_addr) {
+ client->addr = priv->ti964_addr; /* Deserializer I2C address */
+
@@ -902,10 +935,10 @@ index 0000000..055841d
+};
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..9797d24
+index 0000000..91223a0
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/max9286_max9271.c
-@@ -0,0 +1,567 @@
+@@ -0,0 +1,607 @@
+/*
+ * MAXIM max9286-max9271 GMSL driver
+ *
@@ -920,9 +953,10 @@ index 0000000..9797d24
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
++#include <linux/notifier.h>
+#include <linux/of_gpio.h>
++#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
-+#include <linux/notifier.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
@@ -959,10 +993,12 @@ index 0000000..9797d24
+ u32 csi2_outord;
+ struct i2c_client *client;
+ int max9271_addr_map[4];
++ struct regulator *poc_supply[4]; /* PoC power supply */
+};
+
+static int force_conf_link;
-+
++static int force_poc_trig;
++#ifndef MODULE
+static __init int max9286_max9271_force_conf_link(char *str)
+{
+ /* force configuration link */
@@ -972,6 +1008,16 @@ index 0000000..9797d24
+}
+early_param("force_conf_link", max9286_max9271_force_conf_link);
+
++static __init int max9286_max9271_force_poc_trig(char *str)
++{
++ /* force PoC triggering during reverse channel setup */
++ /* to be used on systems with dedicated PoC and unstable ser-des lock */
++ force_poc_trig = 1;
++ return 0;
++}
++early_param("force_poc_trig", max9286_max9271_force_poc_trig);
++#endif
++
+static void max9286_max9271_preinit(struct i2c_client *client, int addr)
+{
+ client->addr = addr; /* MAX9286-CAMx I2C */
@@ -980,27 +1026,32 @@ index 0000000..9797d24
+ 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)
++static void max9286_max9271_sensor_reset(struct i2c_client *client, int addr, int reset_on)
+{
+ struct max9286_max9271_priv *priv = i2c_get_clientdata(client);
+
+ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5)
+ return;
+
-+ /* get out from sensor reset */
++ /* sensor reset/unreset */
+ 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, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | /* set GPIOn value to reset/unreset */
++ ((priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0) ^ reset_on));
+ 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);
++ int idx;
++
++ for (idx = 0; idx < priv->links; idx++) {
++ client->addr = priv->des_addr; /* MAX9286 I2C */
++ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */
++
++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */
++ max9286_max9271_sensor_reset(client, client->addr, 0); /* sensor unreset */
++ }
+
+ client->addr = addr; /* MAX9286 I2C */
+ reg8_write(client, 0x0a, 0x00); /* disable reverse control for all cams */
@@ -1016,6 +1067,7 @@ index 0000000..9797d24
+ struct max9286_max9271_priv *priv = i2c_get_clientdata(client);
+ u8 val = 0;
+ int timeout = priv->timeout;
++ char timeout_str[10];
+ int ret = 0;
+
+ /* Reverse channel enable */
@@ -1033,7 +1085,10 @@ index 0000000..9797d24
+ 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, 0x1); /* 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 */
@@ -1041,26 +1096,32 @@ index 0000000..9797d24
+ 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 */
-+
-+ client->addr = 0x40; /* MAX9271-CAMx I2C */
+ reg8_read(client, 0x1e, &val); /* read max9271 ID */
-+ if (val == MAX9271_ID || --timeout == 0)
++ if (val == MAX9271_ID || val == MAX96705_ID || --timeout == 0)
+ break;
+
+ /* 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) {
++ if (val == MAX9271_ID || val == MAX96705_ID) {
+ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */
+ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */
+ ret = -EADDRINUSE;
+ break;
+ }
++
++ if (timeout == priv->timeout / 2 && force_poc_trig) {
++ if (!IS_ERR(priv->poc_supply[idx])) {
++ if (regulator_disable(priv->poc_supply[idx]))
++ dev_err(&client->dev, "fail to disable POC%d regulator\n", idx);
++ mdelay(200);
++ if (regulator_enable(priv->poc_supply[idx]))
++ dev_err(&client->dev, "fail to enable POC%d regulator\n", idx);
++ }
++ }
+ }
+
-+ max9286_max9271_sensor_reset(client, client->addr); /* sensor reset */
++ max9286_max9271_sensor_reset(client, client->addr, 1); /* sensor reset */
+
+ if (!timeout) {
+ ret = -ETIMEDOUT;
@@ -1072,9 +1133,11 @@ index 0000000..9797d24
+ priv->csi2_outord |= ((hweight8(priv->links_mask) - 1) << (idx * 2));
+
+out:
-+ dev_info(&client->dev, "link%d MAX9271 %sat 0x%x %s\n", idx,
++ sprintf(timeout_str, "retries=%d", priv->timeout - timeout);
++ dev_info(&client->dev, "link%d MAX9271 %sat 0x%x %s %s\n", idx,
+ ret == -EADDRINUSE ? "already " : "", priv->max9271_addr_map[idx],
-+ ret == -ETIMEDOUT ? "not found: timeout GMSL link establish" : "");
++ ret == -ETIMEDOUT ? "not found: timeout GMSL link establish" : "",
++ priv->timeout - timeout? timeout_str : "");
+
+ return ret;
+}
@@ -1176,6 +1239,11 @@ index 0000000..9797d24
+ max9286_max9271_initial_setup(client);
+
+ for (idx = 0; idx < priv->links; idx++) {
++ if (!IS_ERR(priv->poc_supply[idx])) {
++ if (regulator_enable(priv->poc_supply[idx]))
++ dev_err(&client->dev, "fail to enable POC%d regulator\n", idx);
++ }
++
+ ret = max9286_max9271_reverse_channel_setup(client, idx);
+ if (ret)
+ continue;
@@ -1391,6 +1459,7 @@ index 0000000..9797d24
+{
+ struct max9286_max9271_priv *priv;
+ int err, i;
++ char supply_name[10];
+
+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
@@ -1406,6 +1475,11 @@ index 0000000..9797d24
+ if (err)
+ goto out;
+
++ for (i = 0; i < 4; i++) {
++ sprintf(supply_name, "POC%d", i);
++ priv->poc_supply[i] = devm_regulator_get_optional(&client->dev, supply_name);
++ }
++
+ err = max9286_max9271_initialize(client);
+ if (err < 0)
+ goto out;
@@ -1428,7 +1502,6 @@ index 0000000..9797d24
+ if (err < 0)
+ goto out;
+ }
-+
+out:
+ return err;
+}
@@ -1475,10 +1548,10 @@ index 0000000..9797d24
+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..0016f28a
+index 0000000..6c2a9e0
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/max9286_max9271.h
-@@ -0,0 +1,243 @@
+@@ -0,0 +1,244 @@
+/*
+ * MAXIM max9286-max9271 GMSL driver include file
+ *
@@ -1504,6 +1577,7 @@ index 0000000..0016f28a
+#define REG8_NUM_RETRIES 1 /* number of read/write retries */
+#define REG16_NUM_RETRIES 10 /* number of read/write retries */
+#define MAX9271_ID 0x9
++#define MAX96705_ID 0x41
+#define MAX9286_ID 0x40
+#define BROADCAST 0x6f
+
@@ -1724,10 +1798,10 @@ index 0000000..0016f28a
+#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..45169de
+index 0000000..6296647
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov10635.c
-@@ -0,0 +1,759 @@
+@@ -0,0 +1,758 @@
+/*
+ * OmniVision ov10635 sensor camera driver
+ *
@@ -1798,7 +1872,7 @@ index 0000000..45169de
+
+ if (priv->max9286_addr) {
+ tmp_addr = client->addr;
-+ client->addr = priv->max9286_addr; /* Deserializer I2C address */
++ 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 */
+ client->addr = tmp_addr;
+ };
@@ -2265,7 +2339,6 @@ index 0000000..45169de
+
+ dev_info(&client->dev, "ov10635 Product ID %x Manufacturer ID %x OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n",
+ pid, ver, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
-+
+out:
+ ov10635_s_port(client, 0);
+
@@ -2311,7 +2384,7 @@ index 0000000..45169de
+ }
+
+ if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) {
-+ dev_err(&client->dev, "deserializer does not present\n");
++ dev_err(&client->dev, "deserializer does not present for OV10635\n");
+ return -EINVAL;
+ }
+
@@ -2489,7 +2562,7 @@ index 0000000..45169de
+#endif
diff --git a/drivers/media/i2c/soc_camera/ov10635.h b/drivers/media/i2c/soc_camera/ov10635.h
new file mode 100644
-index 0000000..66cc490
+index 0000000..a0e510d
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov10635.h
@@ -0,0 +1,1139 @@
@@ -3806,10 +3879,10 @@ index 0000000..f2bb706
+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..15acc51
+index 0000000..bee9293
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c
-@@ -0,0 +1,1046 @@
+@@ -0,0 +1,1064 @@
+/*
+ * OmniVision ov490-ov10640 sensor camera driver
+ *
@@ -4553,10 +4626,28 @@ index 0000000..15acc51
+ reg16_write(client, 0xFFFD, 0x80);
+ reg16_write(client, 0xFFFE, 0x29);
+ usleep_range(100, 150); /* wait 100 us */
-+ timeout = 300;
-+ for (;;) {
++ for (timeout = 300; timeout > 0; timeout--) {
+ reg16_read(client, 0xd000, &val);
-+ if (val == 0x0c || --timeout == 0)
++ if (val == 0x0c)
++ break;
++ mdelay(1);
++ }
++
++ /* wait firmware apps started by reading OV10640 ID */
++ for (;timeout > 0; timeout--) {
++ reg16_write(client, 0xFFFD, 0x80);
++ reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0x5000, 0x01);
++ reg16_write(client, 0x5001, 0x30);
++ reg16_write(client, 0x5002, 0x0a);
++ reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0xC0, 0xc1);
++ reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(1000, 1500); /* wait 1 ms */
++ reg16_read(client, 0x5000, &val);
++ if (val == 0xa6)
+ break;
+ mdelay(1);
+ }
@@ -4658,7 +4749,7 @@ index 0000000..15acc51
+ }
+
+ if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) {
-+ dev_err(&client->dev, "deserializer does not present\n");
++ dev_err(&client->dev, "deserializer does not present for OV490\n");
+ return -EINVAL;
+ }
+
@@ -4858,7 +4949,7 @@ index 0000000..15acc51
+#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..d3290c7
+index 0000000..8c9ecf1
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov490_ov10640.h
@@ -0,0 +1,93 @@
@@ -4957,7 +5048,7 @@ index 0000000..d3290c7
+};
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..881615e
+index 0000000..6dc0675
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c
@@ -0,0 +1,658 @@
@@ -5447,7 +5538,7 @@ index 0000000..881615e
+ }
+
+ if (!priv->ti960_addr && !priv->ti954_addr) {
-+ dev_err(&client->dev, "deserializer does not present\n");
++ dev_err(&client->dev, "deserializer does not present for OV495\n");
+ return -EINVAL;
+ }
+
@@ -5650,10 +5741,10 @@ 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..fc7ccda
+index 0000000..1672173
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ti954_ti9x3.c
-@@ -0,0 +1,417 @@
+@@ -0,0 +1,431 @@
+/*
+ * TI ti954-(ti913/ti953) FPDLinkIII driver
+ *
@@ -5668,9 +5759,10 @@ index 0000000..fc7ccda
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
++#include <linux/notifier.h>
+#include <linux/of_gpio.h>
++#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
-+#include <linux/notifier.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
@@ -5692,6 +5784,7 @@ index 0000000..fc7ccda
+ struct i2c_client *client;
+ int ti9x3_addr_map[4];
+ char chip_id[6];
++ struct regulator *poc_supply[4]; /* PoC power supply */
+ int xtal_gpio;
+};
+
@@ -5824,8 +5917,14 @@ index 0000000..fc7ccda
+
+ ti954_ti9x3_initial_setup(client);
+
-+ for (idx = 0; idx < priv->links; idx++)
++ for (idx = 0; idx < priv->links; idx++) {
++ if (!IS_ERR(priv->poc_supply[idx])) {
++ if (regulator_enable(priv->poc_supply[idx]))
++ dev_err(&client->dev, "fail to enable POC%d regulator\n", idx);
++ }
++
+ ti954_ti9x3_fpdlink3_setup(client, idx);
++ }
+
+ client->addr = priv->des_addr;
+
@@ -5992,6 +6091,7 @@ index 0000000..fc7ccda
+{
+ struct ti954_ti9x3_priv *priv;
+ int err, i;
++ char supply_name[10];
+
+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
@@ -6006,6 +6106,11 @@ index 0000000..fc7ccda
+ if (err)
+ goto out;
+
++ for (i = 0; i < 4; i++) {
++ sprintf(supply_name, "POC%d", i);
++ priv->poc_supply[i] = devm_regulator_get_optional(&client->dev, supply_name);
++ }
++
+ err = ti954_ti9x3_initialize(client);
+ if (err < 0)
+ goto out;
@@ -6073,10 +6178,10 @@ index 0000000..fc7ccda
+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..8dd0f99
+index 0000000..770d306
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ti964_ti9x3.c
-@@ -0,0 +1,385 @@
+@@ -0,0 +1,399 @@
+/*
+ * TI (ti964/ti960)-(ti913/ti953) FPDLinkIII driver
+ *
@@ -6091,9 +6196,10 @@ index 0000000..8dd0f99
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
++#include <linux/notifier.h>
+#include <linux/of_gpio.h>
++#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
-+#include <linux/notifier.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
@@ -6115,6 +6221,7 @@ index 0000000..8dd0f99
+ struct i2c_client *client;
+ int ti9x3_addr_map[4];
+ char chip_id[6];
++ struct regulator *poc_supply[4]; /* PoC power supply */
+};
+
+static void ti964_ti9x3_read_chipid(struct i2c_client *client)
@@ -6220,8 +6327,14 @@ index 0000000..8dd0f99
+
+ ti964_ti9x3_initial_setup(client);
+
-+ for (idx = 0; idx < priv->links; idx++)
++ for (idx = 0; idx < priv->links; idx++) {
++ if (!IS_ERR(priv->poc_supply[idx])) {
++ if (regulator_enable(priv->poc_supply[idx]))
++ dev_err(&client->dev, "fail to enable POC%d regulator\n", idx);
++ }
++
+ ti964_ti9x3_fpdlink3_setup(client, idx);
++ }
+
+ client->addr = priv->des_addr;
+
@@ -6383,6 +6496,7 @@ index 0000000..8dd0f99
+{
+ struct ti964_ti9x3_priv *priv;
+ int err, i;
++ char supply_name[10];
+
+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
@@ -6397,6 +6511,11 @@ index 0000000..8dd0f99
+ if (err)
+ goto out;
+
++ for (i = 0; i < 4; i++) {
++ sprintf(supply_name, "POC%d", i);
++ priv->poc_supply[i] = devm_regulator_get_optional(&client->dev, supply_name);
++ }
++
+ err = ti964_ti9x3_initialize(client);
+ if (err < 0)
+ goto out;