summaryrefslogtreecommitdiffstats
path: root/meta-rcar-gen3-adas/recipes-kernel
diff options
context:
space:
mode:
authorVladimir Barinov <vladimir.barinov@cogentembedded.com>2017-08-25 03:15:29 +0300
committerVladimir Barinov <vladimir.barinov@cogentembedded.com>2017-08-25 03:15:29 +0300
commite2409ffe9fca38c9a097070af5cefe3597a3b500 (patch)
tree60baca669c6a1683cda1c1f0478ca4873f2bcaae /meta-rcar-gen3-adas/recipes-kernel
parente26fbcaf761aefe5597b2cc0edb3474cd0fa6aef (diff)
LVDS: fix camera start-up (stability work)
Some cameras with OV10640/OV490 are bad in h/w and does not match start up sequence: PWDN/RESETB that lead to OV10640 hang. This patch fixes that in s/w.
Diffstat (limited to 'meta-rcar-gen3-adas/recipes-kernel')
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch91
1 files changed, 79 insertions, 12 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 3e2138c..461b2c7 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,13 +11,13 @@ 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 | 566 +++++++++++
+ drivers/media/i2c/soc_camera/max9286_max9271.c | 567 +++++++++++
drivers/media/i2c/soc_camera/max9286_max9271.h | 196 ++++
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 | 979 +++++++++++++++++++
+ 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 +
@@ -30,7 +30,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 +
- 21 files changed, 5905 insertions(+), 109 deletions(-)
+ 21 files changed, 5973 insertions(+), 109 deletions(-)
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
@@ -125,7 +125,7 @@ index 6f994f9..7d4c1ab 100644
obj-$(CONFIG_SOC_CAMERA_OV6650) += ov6650.o
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..a663a66
+index 0000000..9797d24
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/max9286_max9271.c
@@ -0,0 +1,567 @@
@@ -215,7 +215,7 @@ index 0000000..a663a66
+ 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 */
-+ mdelay(10);
++ 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 */
@@ -2971,10 +2971,10 @@ index 0000000..0079bb2
+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..71cb68a
+index 0000000..15acc51
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c
-@@ -0,0 +1,979 @@
+@@ -0,0 +1,1046 @@
+/*
+ * OmniVision ov490-ov10640 sensor camera driver
+ *
@@ -3034,8 +3034,8 @@ index 0000000..71cb68a
+ int ti9x3_addr;
+ int port;
+ int gpio_resetb;
++ int active_low_resetb;
+ int gpio_fsin;
-+
+};
+
+static int force_conf_link;
@@ -3068,6 +3068,48 @@ index 0000000..71cb68a
+ };
+}
+
++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)
+{
@@ -3646,7 +3688,7 @@ index 0000000..71cb68a
+ struct ov490_priv *priv = to_ov490(client);
+ u8 val = 0;
+ u8 pid = 0, ver = 0;
-+ int ret = 0, timeout = 1000;
++ 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);
@@ -3671,10 +3713,12 @@ index 0000000..71cb68a
+ 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)
@@ -3682,8 +3726,22 @@ index 0000000..71cb68a
+ mdelay(1);
+ }
+
-+ if (!timeout)
-+ dev_err(&client->dev, "Timeout firmware boot wait\n");
++ 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);
@@ -3739,8 +3797,17 @@ index 0000000..71cb68a
+
+ 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") &&