From 95a48f63ed8839cce6d91c53a72f67551c2f7a92 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov 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