diff options
Diffstat (limited to 'bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0168-lvds-ISX019-fix-add-address-intf-fix-read-write.patch')
-rw-r--r-- | bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0168-lvds-ISX019-fix-add-address-intf-fix-read-write.patch | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0168-lvds-ISX019-fix-add-address-intf-fix-read-write.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0168-lvds-ISX019-fix-add-address-intf-fix-read-write.patch new file mode 100644 index 00000000..efe99fbd --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0168-lvds-ISX019-fix-add-address-intf-fix-read-write.patch @@ -0,0 +1,228 @@ +From 95a48f63ed8839cce6d91c53a72f67551c2f7a92 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Mon, 13 May 2019 16:38:48 +0300 +Subject: [PATCH 117/122] lvds: ISX019: fix add address intf, fix read/write + +- Add command/address register access interfaces +- fix endianess of data +- read resolution from registers +--- + drivers/media/i2c/soc_camera/isx019.c | 112 ++++++++++++++++++++-------------- + drivers/media/i2c/soc_camera/isx019.h | 9 ++- + 2 files changed, 73 insertions(+), 48 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/isx019.c b/drivers/media/i2c/soc_camera/isx019.c +index 650b533..c2f5a4a 100644 +--- a/drivers/media/i2c/soc_camera/isx019.c ++++ b/drivers/media/i2c/soc_camera/isx019.c +@@ -25,7 +25,7 @@ + static const int isx019_i2c_addr[] = {0x1a}; + + #define ISX019_PID 0x0000 +-#define ISX019_VERSION_REG 0x0740 ++#define ISX019_VERSION_REG 0x4000 + + #define ISX019_MEDIA_BUS_FMT MEDIA_BUS_FMT_YUYV8_2X8 + +@@ -51,6 +51,10 @@ struct isx019_priv { + int gpio_fsin; + }; + ++static char *intf = "command"; ++module_param(intf, charp, 0644); ++MODULE_PARM_DESC(intf, " Registers access interface command,address (default: command)"); ++ + static inline struct isx019_priv *to_isx019(const struct i2c_client *client) + { + return container_of(i2c_get_clientdata(client), struct isx019_priv, sd); +@@ -72,31 +76,40 @@ static void isx019_s_port(struct i2c_client *client, int fwd_en) + + static int isx019_read16(struct i2c_client *client, u8 category, u16 reg, u16 *val) + { +- int ret; ++ int ret = -1; ++ ++ if (strcmp(intf, "command") == 0) { + #define R_NUM_BYTES 9 + #define R_NUM_CMDS 1 + #define R_NUM_CMD_BYTES 6 + #define R_CMD 1 + #define R_BYTES 2 +- u8 buf[R_NUM_BYTES] = {R_NUM_BYTES, R_NUM_CMDS, +- R_NUM_CMD_BYTES, R_CMD, +- category, reg >> 8, reg & 0xff, +- R_BYTES, 0x00}; +- +- /* calculate checksum */ +- buf[8] = R_NUM_BYTES + R_NUM_CMDS + R_NUM_CMD_BYTES + R_CMD + +- category + (reg >> 8) + (reg & 0xff) + R_BYTES; +- +- ret = i2c_master_send(client, buf, R_NUM_BYTES); +- if (ret == R_NUM_BYTES) +- ret = i2c_master_recv(client, buf, R_NUM_BYTES - 2); +- +- if (ret < 0) { +- dev_err(&client->dev, +- "read fail: chip 0x%x register 0x%x: %d\n", +- client->addr, reg, ret); ++ u8 buf[R_NUM_BYTES] = {R_NUM_BYTES, R_NUM_CMDS, ++ R_NUM_CMD_BYTES, R_CMD, ++ category, reg >> 8, reg & 0xff, ++ R_BYTES, 0x00}; ++ ++ /* calculate checksum */ ++ buf[8] = R_NUM_BYTES + R_NUM_CMDS + R_NUM_CMD_BYTES + R_CMD + ++ category + (reg >> 8) + (reg & 0xff) + R_BYTES; ++ ++ ret = i2c_master_send(client, buf, R_NUM_BYTES); ++ if (ret == R_NUM_BYTES) ++ ret = i2c_master_recv(client, buf, R_NUM_BYTES - 2); ++ ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = buf[4] | ((u16)buf[5] << 8); ++ } ++ } else if (strcmp(intf, "address") == 0) { ++ reg16_write(client, 0xFFFF, category); ++ ret = reg16_read16(client, reg, val); ++ *val = swab16p(val); + } else { +- *val = ((u16)buf[4] << 8) | buf[5]; ++ dev_err(&client->dev, "invalid register access interface %s\n", intf); + } + + return ret < 0 ? ret : 0; +@@ -104,26 +117,35 @@ static int isx019_read16(struct i2c_client *client, u8 category, u16 reg, u16 *v + + static int isx019_write16(struct i2c_client *client, u8 category, u16 reg, u16 val) + { +- int ret; ++ int ret = -1; ++ ++ if (strcmp(intf, "command") == 0) { + #define W_NUM_BYTES 10 + #define W_NUM_CMDS 1 + #define W_NUM_CMD_BYTES 7 + #define W_CMD 2 +- u8 buf[W_NUM_BYTES] = {W_NUM_BYTES, W_NUM_CMDS, +- W_NUM_CMD_BYTES, W_CMD, +- category, reg >> 8, reg & 0xff, +- val >> 8, val & 0xff}; ++ u8 buf[W_NUM_BYTES] = {W_NUM_BYTES, W_NUM_CMDS, ++ W_NUM_CMD_BYTES, W_CMD, ++ category, reg >> 8, reg & 0xff, ++ val & 0xff, val >> 8}; + +- /* calculate checksum */ +- buf[9] = W_NUM_BYTES + W_NUM_CMDS + W_NUM_CMD_BYTES + W_CMD + +- category + (reg >> 8) + (reg & 0xff) + (val >> 8) + (val & 0xff); ++ /* calculate checksum */ ++ buf[9] = W_NUM_BYTES + W_NUM_CMDS + W_NUM_CMD_BYTES + W_CMD + ++ category + (reg >> 8) + (reg & 0xff) + (val >> 8) + (val & 0xff); + +- ret = i2c_master_send(client, buf, W_NUM_BYTES); ++ ret = i2c_master_send(client, buf, W_NUM_BYTES); + +- if (ret < 0) { +- dev_err(&client->dev, +- "write fail: chip 0x%x register 0x%x: %d\n", +- client->addr, reg, ret); ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } ++ } else if (strcmp(intf, "address") == 0) { ++ val = swab16(val); ++ reg16_write(client, 0xFFFF, category); ++ ret = reg16_write16(client, reg, val); ++ } else { ++ dev_err(&client->dev, "invalid register acces interface %s\n", intf); + } + + return ret < 0 ? ret : 0; +@@ -404,13 +426,11 @@ static DEVICE_ATTR(otp_id_isx019, S_IRUGO, isx019_otp_id_show, NULL); + static int isx019_initialize(struct i2c_client *client) + { + struct isx019_priv *priv = to_isx019(client); +- u16 pid = 0; ++ u16 pid = 0, val = 0; + int ret = 0; + int tmp_addr; + int i; + +- isx019_s_port(client, 1); +- + for (i = 0; i < ARRAY_SIZE(isx019_i2c_addr); i++) { + tmp_addr = client->addr; + if (priv->max9286_addr) { +@@ -423,26 +443,28 @@ static int isx019_initialize(struct i2c_client *client) + /* check model ID */ + isx019_read16(client, 0, ISX019_PID, &pid); + +- if (pid == ISX019_VERSION_REG) ++ if ((pid & 0xff00) == ISX019_VERSION_REG) + break; + } + +- if (pid != ISX019_VERSION_REG) { +- dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ if ((pid & 0xff00) != ISX019_VERSION_REG) { ++ dev_err(&client->dev, "Product ID error %x\n", pid); + ret = -ENODEV; + goto err; + } + +- priv->max_width = ISX019_MAX_WIDTH; +- priv->max_height = ISX019_MAX_HEIGHT; +- + /* Read OTP IDs */ + isx019_otp_id_read(client); + /* Program wizard registers */ + isx019_set_regs(client, isx019_regs_wizard, ARRAY_SIZE(isx019_regs_wizard)); +- +- dev_info(&client->dev, "isx019 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", +- pid, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ /* read resolution used by current firmware */ ++ isx019_read16(client, 86, 0x8, &val); ++ priv->max_width = val; ++ isx019_read16(client, 86, 0xa, &val); ++ priv->max_height = val; ++ ++ dev_info(&client->dev, "isx019 PID %x (rev %x), res %dx%d, if=%s, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid & 0xff00, pid & 0xff, priv->max_width, priv->max_height, intf, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); + err: + isx019_s_port(client, 0); + +diff --git a/drivers/media/i2c/soc_camera/isx019.h b/drivers/media/i2c/soc_camera/isx019.h +index edaa767..c7072a3 100644 +--- a/drivers/media/i2c/soc_camera/isx019.h ++++ b/drivers/media/i2c/soc_camera/isx019.h +@@ -9,8 +9,8 @@ + * option) any later version. + */ + +-#define ISX019_MAX_WIDTH 1280 +-#define ISX019_MAX_HEIGHT 800 ++//#define ISX019_MAX_WIDTH 1280 ++//#define ISX019_MAX_HEIGHT 960 + + #define ISX019_DELAY 0xffff + +@@ -22,6 +22,9 @@ struct isx019_reg { + static const struct isx019_reg isx019_regs_wizard[] = { + #if 0 + /* enable FSIN */ +-#endif + {ISX019_DELAY, 100}, ++#endif ++/* disable embedded data */ ++{0x504c, 0x0}, ++{0x504e, 0x0}, + }; +-- +2.7.4 + |