From 805e485b11c5aafacd2ab16a2d699c904ba13372 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 19 Dec 2018 00:02:17 +0300 Subject: [PATCH 085/122] lvds: AR0233 add different vendor This adds possibility to setup cameras with different gpio connection using dts or command line: ti9x4.gpioX --- drivers/media/i2c/soc_camera/ar0233.c | 36 ++++++++++++++++++---------- drivers/media/i2c/soc_camera/ov106xx.c | 12 +++++----- drivers/media/i2c/soc_camera/ti9x4.c | 44 +++++++++++++++++++++++++++------- 3 files changed, 64 insertions(+), 28 deletions(-) diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c index 7c1141c..74ecc85 100644 --- a/drivers/media/i2c/soc_camera/ar0233.c +++ b/drivers/media/i2c/soc_camera/ar0233.c @@ -22,7 +22,7 @@ #include "ar0233.h" -#define AR0233_I2C_ADDR 0x10 +static const int ar0233_i2c_addr[] = {0x10, 0x20}; #define AR0233_PID 0x3000 #define AR0233_VERSION_REG 0x0354 @@ -380,9 +380,23 @@ static int ar0233_initialize(struct i2c_client *client) u16 pid = 0; int ret = 0; int tmp_addr; + int i; + + for (i = 0; i < ARRAY_SIZE(ar0233_i2c_addr); i++) { + tmp_addr = client->addr; + if (priv->ti9x4_addr) { + client->addr = priv->ti9x4_addr;/* Deserializer I2C address */ + reg8_write(client, 0x5d, ar0233_i2c_addr[i] << 1); /* Sensor native I2C address */ + usleep_range(2000, 2500); /* wait 2ms */ + } + client->addr = tmp_addr; - /* check and show model ID */ - reg16_read16(client, AR0233_PID, &pid); + /* check model ID */ + reg16_read16(client, AR0233_PID, &pid); + + if (pid == AR0233_VERSION_REG) + break; + } if (pid != AR0233_VERSION_REG) { dev_dbg(&client->dev, "Product ID error %x\n", pid); @@ -395,12 +409,16 @@ static int ar0233_initialize(struct i2c_client *client) if (priv->ti9x4_addr) { /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=27MHz: CLKDIV=2, M=15, N=251: 22.5792*160/8*15/251=26.987MHz=CLK_OUT */ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ +#if 0 reg8_write(client, 0x06, 0x6f); /* Set CLKDIV and M */ reg8_write(client, 0x07, 0xfb); /* Set N */ - reg8_write(client, 0x0e, 0x1f); /* Set FSIN GPIO to output */ +#endif + reg8_write(client, 0x0e, 0xf0); /* Enable all remote gpios */ } client->addr = tmp_addr; + /* Read OTP IDs */ + ar0233_otp_id_read(client); /* Program wizard registers */ ar0233_set_regs(client, ar0233_regs_wizard, ARRAY_SIZE(ar0233_regs_wizard)); @@ -409,9 +427,6 @@ static int ar0233_initialize(struct i2c_client *client) val |= (1 << 2); // Set streamOn bit reg16_write16(client, 0x301a, val); // Start Streaming - /* Read OTP IDs */ - ar0233_otp_id_read(client); - dev_info(&client->dev, "ar0233 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", pid, AR0233_MAX_WIDTH, AR0233_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); err: @@ -444,7 +459,7 @@ static int ar0233_parse_dt(struct device_node *np, struct ar0233_priv *priv) of_node_put(endpoint); if (!priv->ti9x4_addr) { - dev_err(&client->dev, "deserializer does not present\n"); + dev_dbg(&client->dev, "deserializer does not present\n"); return -EINVAL; } @@ -456,14 +471,9 @@ static int ar0233_parse_dt(struct device_node *np, struct ar0233_priv *priv) reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ usleep_range(2000, 2500); /* wait 2ms */ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ - reg8_write(client, 0x5d, AR0233_I2C_ADDR << 1); /* Sensor native I2C address */ - - reg8_write(client, 0x6e, 0x8a); /* GPIO0 - fsin, GPIO1 - NC */ } client->addr = tmp_addr; - mdelay(10); - return 0; } diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c index d6df193..e5d6b67 100644 --- a/drivers/media/i2c/soc_camera/ov106xx.c +++ b/drivers/media/i2c/soc_camera/ov106xx.c @@ -51,6 +51,12 @@ static int ov106xx_probe(struct i2c_client *client, int ret; chip_id = -EINVAL; + ret = ar0233_probe(client, did); + if (!ret) { + chip_id = ID_AR0233; + goto out; + } + ret = ov10635_probe(client, did); if (!ret) { chip_id = ID_OV10635; @@ -93,12 +99,6 @@ static int ov106xx_probe(struct i2c_client *client, goto out; } - ret = ar0233_probe(client, did); - if (!ret) { - chip_id = ID_AR0233; - goto out; - } - ret = ar0323_probe(client, did); if (!ret) { chip_id = ID_AR0323; diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c index effcf6c..d03c0f9 100644 --- a/drivers/media/i2c/soc_camera/ti9x4.c +++ b/drivers/media/i2c/soc_camera/ti9x4.c @@ -44,6 +44,7 @@ struct ti9x4_priv { int ser_id; int vc_map; int csi_map; + int gpio[4]; struct gpio_desc *pwen; /* chip power en */ struct gpio_desc *poc_gpio[4]; /* PoC power supply */ struct v4l2_clk *ref_clk; /* ref clock */ @@ -81,6 +82,16 @@ static int csi_map = 0; module_param(csi_map, int, 0644); MODULE_PARM_DESC(csi_map, " CSI TX MAP (default: 0 - forwarding of all links to CSI0)"); +static int gpio0 = 0, gpio1 = 0, gpio2 = 0, gpio3 = 0; +module_param(gpio0, int, 0644); +MODULE_PARM_DESC(gpio0, " GPIO0 function select (default: GPIO0 low level)"); +module_param(gpio1, int, 0644); +MODULE_PARM_DESC(gpio1, " GPIO1 function select (default: GPIO1 low level)"); +module_param(gpio2, int, 0644); +MODULE_PARM_DESC(gpio2, " GPIO2 function select (default: GPIO2 low level)"); +module_param(gpio3, int, 0644); +MODULE_PARM_DESC(gpio3, " GPIO3 function select (default: GPIO3 low level)"); + #ifdef TI954_SILICON_ERRATA static int indirect_write(struct i2c_client *client, unsigned int page, u8 reg, u8 val) { @@ -204,9 +215,6 @@ static void ti9x4_initial_setup(struct i2c_client *client) #endif } -//#define SENSOR_ID 0x30 // ov10635 -//#define SENSOR_ID 0x24 // ov490 - static void ti9x4_fpdlink3_setup(struct i2c_client *client, int idx) { struct ti9x4_priv *priv = i2c_get_clientdata(client); @@ -230,7 +238,7 @@ static void ti9x4_fpdlink3_setup(struct i2c_client *client, int idx) } reg8_write(client, 0x5c, priv->ti9x3_addr_map[idx] << 1); /* TI9X3 I2C addr */ -// reg8_write(client, 0x5d, SENSOR_ID << 1); /* SENSOR I2C native - must be set by sensor driver */ +// reg8_write(client, 0x5d, 0x30 << 1); /* SENSOR I2C native - must be set by sensor driver */ // reg8_write(client, 0x65, (0x60 + idx) << 1); /* SENSOR I2C translated - must be set by sensor driver */ if (priv->is_coax) @@ -262,7 +270,8 @@ static void ti9x4_fpdlink3_setup(struct i2c_client *client, int idx) reg8_write(client, 0x70, ((priv->vc_map >> (idx * 4)) << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */ reg8_write(client, 0x71, ((priv->vc_map >> (idx * 4)) << 6) | 0x2c); /* CSI data type: RAW12, assign VC */ reg8_write(client, 0xbc, 0x00); /* Setup minimal time between FV and LV to 3 PCLKs */ - reg8_write(client, 0x6e, 0x88); /* Sensor reset: backchannel GPIO0/GPIO1 set low */ + reg8_write(client, 0x6e, 0x88 | (priv->gpio[1] << 4) | priv->gpio[0]); /* Remote GPIO1/GPIO0 setup */ + reg8_write(client, 0x6f, 0x88 | (priv->gpio[3] << 4) | priv->gpio[2]); /* Remote GPIO3/GPIO2 setup */ reg8_write(client, 0x72, priv->vc_map >> (idx * 4)); /* CSI VC MAP */ } @@ -285,6 +294,10 @@ static int ti9x4_initialize(struct i2c_client *client) ti9x4_fpdlink3_setup(client, idx); } + /* extra delay to wait imager power up */ + if (priv->poc_delay) + mdelay(350); + client->addr = priv->des_addr; return 0; @@ -369,7 +382,7 @@ static int ti9x4_parse_dt(struct i2c_client *client) char forwarding_mode_default[20] = "round-robin"; /* round-robin, synchronized */ struct property *csi_rate_prop, *dvp_order_prop; u8 val = 0; - char poc_name[10]; + char name[10]; if (of_property_read_u32(np, "ti,links", &priv->links)) priv->links = 4; @@ -391,8 +404,8 @@ static int ti9x4_parse_dt(struct i2c_client *client) } for (i = 0; i < 4; i++) { - sprintf(poc_name, "POC%d", i); - priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, kstrdup(poc_name, GFP_KERNEL), 0); + sprintf(name, "POC%d", i); + priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, kstrdup(name, GFP_KERNEL), 0); } reg8_read(client, 0x00, &val); /* read TI9x4 I2C address */ @@ -429,9 +442,14 @@ static int ti9x4_parse_dt(struct i2c_client *client) if (of_property_read_u32(np, "ti,ser_id", &priv->ser_id)) priv->ser_id = TI913_ID; if (of_property_read_u32(np, "ti,poc-delay", &priv->poc_delay)) - priv->poc_delay = 50; + priv->poc_delay = 10; if (of_property_read_u32(np, "ti,vc-map", &priv->vc_map)) priv->vc_map = 0x3210; + for (i = 0; i < 4; i++) { + sprintf(name, "ti,gpio%d", i); + if (of_property_read_u32(np, name, &priv->gpio[i])) + priv->gpio[i] = 0; + } /* * CSI forwarding of all links is to CSI0 by default. @@ -469,6 +487,14 @@ static int ti9x4_parse_dt(struct i2c_client *client) priv->vc_map = vc_map; if (csi_map) priv->csi_map = csi_map; + if (gpio0) + priv->gpio[0] = gpio0; + if (gpio1) + priv->gpio[1] = gpio1; + if (gpio2) + priv->gpio[2] = gpio2; + if (gpio3) + priv->gpio[3] = gpio3; for (i = 0; ; i++) { endpoint = of_graph_get_next_endpoint(np, endpoint); -- 2.7.4