Hi Tomasz, Thanks for the patch. On Wed, Sep 02, 2020 at 10:48:13PM +0000, Tomasz Figa wrote: > From: Hao He <hao.he@xxxxxxxxxxxxxx> > > The sensor OTP holds values for various configuration registers > deteremined at manufacturing time and dead pixel correction tables. Add > code to load both from the OTP and initialize the sensor appropriately. > > Signed-off-by: Hao He <hao.he@xxxxxxxxxxxxxx> > Signed-off-by: Xingyu Wu <wuxy@xxxxxxxxxxxxxx> > Signed-off-by: Tomasz Figa <tfiga@xxxxxxxxxxxx> > --- > drivers/media/i2c/gc5035.c | 478 +++++++++++++++++++++++++++++++++++++ > 1 file changed, 478 insertions(+) > > diff --git a/drivers/media/i2c/gc5035.c b/drivers/media/i2c/gc5035.c > index 12e1b3a430b5..61645cec6948 100644 > --- a/drivers/media/i2c/gc5035.c > +++ b/drivers/media/i2c/gc5035.c > @@ -81,6 +81,57 @@ > #define GC5035_TEST_PATTERN_ENABLE 0x11 > #define GC5035_TEST_PATTERN_DISABLE 0x10 > > +/* Page 2 registers */ > + > +/* OTP access registers */ > +#define GC5035_REG_OTP_MODE 0xf3 > +#define GC5035_OTP_PRE_READ 0x20 > +#define GC5035_OTP_READ_MODE 0x12 > +#define GC5035_OTP_READ_DONE 0x00 > +#define GC5035_REG_OTP_DATA 0x6c > +#define GC5035_REG_OTP_ACCESS_ADDR_H 0x69 > +#define GC5035_REG_OTP_ACCESS_ADDR_L 0x6a > +#define GC5035_OTP_ACCESS_ADDR_H_MASK 0x1f > +#define GC5035_OTP_ADDR_MASK 0x1fff > +#define GC5035_OTP_ADDR_SHIFT 3 > +#define GC5035_REG_DD_TOTALNUM_H 0x01 > +#define GC5035_REG_DD_TOTALNUM_L 0x02 > +#define GC5035_DD_TOTALNUM_H_MASK 0x07 > +#define GC5035_REG_DD_LOAD_STATUS 0x06 > +#define GC5035_OTP_BIT_LOAD BIT(0) > + > +/* OTP-related definitions */ > + > +#define GC5035_OTP_ID_SIZE 9 > +#define GC5035_OTP_ID_DATA_OFFSET 0x0020 > +#define GC5035_OTP_DATA_LENGTH 1024 > + > +/* OTP DPC parameters */ > +#define GC5035_OTP_DPC_FLAG_OFFSET 0x0068 > +#define GC5035_OTP_DPC_FLAG_MASK 0x03 > +#define GC5035_OTP_FLAG_EMPTY 0x00 > +#define GC5035_OTP_FLAG_VALID 0x01 > +#define GC5035_OTP_DPC_TOTAL_NUMBER_OFFSET 0x0070 > +#define GC5035_OTP_DPC_ERROR_NUMBER_OFFSET 0x0078 > + > +/* OTP register parameters */ > +#define GC5035_OTP_REG_FLAG_OFFSET 0x0880 > +#define GC5035_OTP_REG_DATA_OFFSET 0x0888 > +#define GC5035_OTP_REG_ADDR_OFFSET 1 > +#define GC5035_OTP_REG_VAL_OFFSET 2 > +#define GC5035_OTP_PAGE_FLAG_OFFSET 3 > +#define GC5035_OTP_PER_PAGE_SIZE 4 > +#define GC5035_OTP_REG_PAGE_MASK 0x07 > +#define GC5035_OTP_REG_MAX_GROUP 5 > +#define GC5035_OTP_REG_BYTE_PER_GROUP 5 > +#define GC5035_OTP_REG_PER_GROUP 2 > +#define GC5035_OTP_REG_BYTE_PER_REG 2 > +#define GC5035_OTP_REG_DATA_SIZE 25 > +#define GC5035_OTP_REG_SIZE 10 > + > +#define GC5035_DD_DELAY_US (10 * 1000) > +#define GC5035_DD_TIMEOUT_US (100 * 1000) > + > static const char * const gc5035_supplies[] = { > /* > * Requested separately due to power sequencing needs: > @@ -95,6 +146,21 @@ struct gc5035_regval { > u8 val; > }; > > +struct gc5035_reg { > + u8 page; > + struct gc5035_regval regval; > +}; > + > +struct gc5035_otp_regs { > + unsigned int num_regs; > + struct gc5035_reg regs[GC5035_OTP_REG_SIZE]; > +}; > + > +struct gc5035_dpc { > + bool valid; > + unsigned int total_num; > +}; > + > struct gc5035_mode { > u32 width; > u32 height; > @@ -122,6 +188,11 @@ struct gc5035 { > struct v4l2_ctrl *hblank; > struct v4l2_ctrl *vblank; > > + bool otp_read; > + u8 otp_id[GC5035_OTP_ID_SIZE]; > + struct gc5035_dpc dpc; > + struct gc5035_otp_regs otp_regs; > + > /* > * Serialize control access, get/set format, get selection > * and start streaming. > @@ -136,6 +207,69 @@ static inline struct gc5035 *to_gc5035(struct v4l2_subdev *sd) > return container_of(sd, struct gc5035, subdev); > } > > +static const struct gc5035_regval gc5035_otp_init_regs[] = { > + {0xfc, 0x01}, > + {0xf4, 0x40}, > + {0xf5, 0xe9}, > + {0xf6, 0x14}, > + {0xf8, 0x49}, > + {0xf9, 0x82}, > + {0xfa, 0x00}, > + {0xfc, 0x81}, > + {0xfe, 0x00}, > + {0x36, 0x01}, > + {0xd3, 0x87}, > + {0x36, 0x00}, > + {0x33, 0x00}, > + {0xf7, 0x01}, > + {0xfc, 0x8e}, > + {0xfe, 0x00}, > + {0xee, 0x30}, > + {0xfa, 0x10}, > + {0xf5, 0xe9}, > + {0xfe, 0x02}, > + {0x67, 0xc0}, > + {0x59, 0x3f}, > + {0x55, 0x84}, > + {0x65, 0x80}, > + {0x66, 0x03}, > + {0xfe, 0x00}, > +}; > + > +static const struct gc5035_regval gc5035_otp_exit_regs[] = { > + {0xfe, 0x02}, > + {0x67, 0x00}, > + {0xfe, 0x00}, > + {0xfa, 0x00}, > +}; > + > +static const struct gc5035_regval gc5035_dd_auto_load_regs[] = { > + {0xfe, 0x02}, > + {0xbe, 0x00}, > + {0xa9, 0x01}, > + {0x09, 0x33}, > +}; > + > +static const struct gc5035_regval gc5035_otp_dd_regs[] = { > + {0x03, 0x00}, > + {0x04, 0x80}, > + {0x95, 0x0a}, > + {0x96, 0x30}, > + {0x97, 0x0a}, > + {0x98, 0x32}, > + {0x99, 0x07}, > + {0x9a, 0xa9}, > + {0xf3, 0x80}, > +}; > + > +static const struct gc5035_regval gc5035_otp_dd_enable_regs[] = { > + {0xbe, 0x01}, > + {0x09, 0x00}, > + {0xfe, 0x01}, > + {0x80, 0x02}, > + {0xfe, 0x00}, > +}; > + > /* > * Xclk 24Mhz > * Pclk 87.6Mhz > @@ -763,6 +897,346 @@ static int gc5035_read_reg(struct gc5035 *gc5035, u8 reg, u8 *val) > return 0; > } > > +static int gc5035_otp_read_data(struct gc5035 *gc5035, u16 bit_addr, u8 *data, > + size_t length) > +{ > + size_t i; > + int ret; > + > + if (WARN_ON(bit_addr % 8)) > + return -EINVAL; > + > + if (WARN_ON(bit_addr / 8 + length > GC5035_OTP_DATA_LENGTH)) > + return -EINVAL; > + > + ret = gc5035_write_reg(gc5035, GC5035_PAGE_REG, 2); > + if (ret) > + return ret; > + > + ret = gc5035_write_reg(gc5035, GC5035_REG_OTP_ACCESS_ADDR_H, > + (bit_addr >> 8) & > + GC5035_OTP_ACCESS_ADDR_H_MASK); > + if (ret) > + return ret; > + > + ret = gc5035_write_reg(gc5035, GC5035_REG_OTP_ACCESS_ADDR_L, > + bit_addr & 0xff); > + if (ret) > + return ret; > + > + ret = gc5035_write_reg(gc5035, GC5035_REG_OTP_MODE, > + GC5035_OTP_PRE_READ); > + if (ret) > + goto out_read_done; > + > + ret = gc5035_write_reg(gc5035, GC5035_REG_OTP_MODE, > + GC5035_OTP_READ_MODE); > + if (ret) > + goto out_read_done; > + > + for (i = 0; i < length; i++) { > + ret = gc5035_read_reg(gc5035, GC5035_REG_OTP_DATA, &data[i]); > + if (ret) > + goto out_read_done; > + } > + > +out_read_done: > + gc5035_write_reg(gc5035, GC5035_REG_OTP_MODE, GC5035_OTP_READ_DONE); > + > + return ret; > +} > + > +static int gc5035_read_otp_regs(struct gc5035 *gc5035) > +{ > + struct device *dev = &gc5035->client->dev; > + struct gc5035_otp_regs *otp_regs = &gc5035->otp_regs; > + u8 regs[GC5035_OTP_REG_DATA_SIZE] = {0}; > + unsigned int i, j; > + u8 flag; > + int ret; > + > + ret = gc5035_otp_read_data(gc5035, GC5035_OTP_REG_FLAG_OFFSET, > + &flag, 1); > + if (ret) { > + dev_err(dev, "failed to read otp reg flag\n"); > + return ret; > + } > + > + dev_dbg(dev, "register update flag = 0x%x\n", flag); > + > + gc5035->otp_regs.num_regs = 0; > + if (flag != GC5035_OTP_FLAG_VALID) > + return 0; > + > + ret = gc5035_otp_read_data(gc5035, GC5035_OTP_REG_DATA_OFFSET, > + regs, sizeof(regs)); > + if (ret) { > + dev_err(dev, "failed to read otp reg data\n"); > + return ret; > + } > + > + for (i = 0; i < GC5035_OTP_REG_MAX_GROUP; i++) { > + unsigned int base_group = i * GC5035_OTP_REG_BYTE_PER_GROUP; > + > + for (j = 0; j < GC5035_OTP_REG_PER_GROUP; j++) { > + struct gc5035_reg *reg; > + > + if (!(regs[base_group] & > + BIT((GC5035_OTP_PER_PAGE_SIZE * j + > + GC5035_OTP_PAGE_FLAG_OFFSET)))) > + continue; > + > + reg = &otp_regs->regs[otp_regs->num_regs++]; > + reg->page = (regs[base_group] >> > + (GC5035_OTP_PER_PAGE_SIZE * j)) & > + GC5035_OTP_REG_PAGE_MASK; > + reg->regval.addr = regs[base_group + j * > + GC5035_OTP_REG_BYTE_PER_REG + > + GC5035_OTP_REG_ADDR_OFFSET]; > + reg->regval.val = regs[base_group + j * > + GC5035_OTP_REG_BYTE_PER_REG + > + GC5035_OTP_REG_VAL_OFFSET]; > + } > + } > + > + return 0; > +} > + > +static int gc5035_read_dpc(struct gc5035 *gc5035) > +{ > + struct device *dev = &gc5035->client->dev; > + struct gc5035_dpc *dpc = &gc5035->dpc; > + u8 dpc_flag = 0; > + u8 error_number = 0; > + u8 total_number = 0; > + int ret; > + > + ret = gc5035_otp_read_data(gc5035, GC5035_OTP_DPC_FLAG_OFFSET, > + &dpc_flag, 1); > + if (ret) { > + dev_err(dev, "failed to read dpc flag\n"); > + return ret; > + } > + > + dev_dbg(dev, "dpc flag = 0x%x\n", dpc_flag); > + > + dpc->valid = false; > + > + switch (dpc_flag & GC5035_OTP_DPC_FLAG_MASK) { > + case GC5035_OTP_FLAG_EMPTY: > + dev_dbg(dev, "dpc info is empty!!\n"); > + break; > + > + case GC5035_OTP_FLAG_VALID: > + dev_dbg(dev, "dpc info is valid!\n"); > + ret = gc5035_otp_read_data(gc5035, > + GC5035_OTP_DPC_TOTAL_NUMBER_OFFSET, > + &total_number, 1); > + if (ret) { > + dev_err(dev, "failed to read dpc total number\n"); > + return ret; > + } > + > + ret = gc5035_otp_read_data(gc5035, > + GC5035_OTP_DPC_ERROR_NUMBER_OFFSET, > + &error_number, 1); > + if (ret) { > + dev_err(dev, "failed to read dpc error number\n"); > + return ret; > + } > + > + dpc->total_num = total_number + error_number; > + dpc->valid = true; > + dev_dbg(dev, "total_num = %d\n", dpc->total_num); > + break; > + > + default: > + break; > + } > + > + return ret; > +} > + > +static int gc5035_otp_read_sensor_info(struct gc5035 *gc5035) > +{ > + int ret; > + > + ret = gc5035_read_dpc(gc5035); > + if (ret) > + return ret; > + > + return gc5035_read_otp_regs(gc5035); > +} > + > +static int gc5035_check_dd_load_status(struct gc5035 *gc5035) > +{ > + u8 status; > + int ret; > + > + ret = gc5035_read_reg(gc5035, GC5035_REG_DD_LOAD_STATUS, &status); > + if (ret) > + return ret; > + > + if (status & GC5035_OTP_BIT_LOAD) > + return status; > + else > + return 0; > +} > + > +static int gc5035_otp_update_dd(struct gc5035 *gc5035) > +{ > + struct device *dev = &gc5035->client->dev; > + struct gc5035_dpc *dpc = &gc5035->dpc; > + int val, ret; > + > + if (!dpc->valid) { > + dev_dbg(dev, "DPC table invalid, not updating DD.\n"); > + return 0; > + } > + > + dev_dbg(dev, "DD auto load start\n"); > + > + ret = gc5035_write_array(gc5035, gc5035_dd_auto_load_regs, > + ARRAY_SIZE(gc5035_dd_auto_load_regs)); > + if (ret) { > + dev_err(dev, "failed to write dd auto load reg\n"); > + return ret; > + } > + > + ret = gc5035_write_reg(gc5035, GC5035_REG_DD_TOTALNUM_H, > + (dpc->total_num >> 8) & > + GC5035_DD_TOTALNUM_H_MASK); > + if (ret) > + return ret; > + > + ret = gc5035_write_reg(gc5035, GC5035_REG_DD_TOTALNUM_L, > + dpc->total_num & 0xff); > + if (ret) > + return ret; > + > + ret = gc5035_write_array(gc5035, gc5035_otp_dd_regs, > + ARRAY_SIZE(gc5035_otp_dd_regs)); > + if (ret) > + return ret; > + > + /* Wait for DD to finish loading automatically */ > + ret = readx_poll_timeout(gc5035_check_dd_load_status, gc5035, > + val, val <= 0, GC5035_DD_DELAY_US, > + GC5035_DD_TIMEOUT_US); > + if (ret < 0) { > + dev_err(dev, "DD load timeout\n"); > + return -EFAULT; > + } > + if (val < 0) { > + dev_err(dev, "DD load failure\n"); > + return val; > + } > + > + ret = gc5035_write_array(gc5035, gc5035_otp_dd_enable_regs, > + ARRAY_SIZE(gc5035_otp_dd_enable_regs)); > + if (ret) > + return ret; > + > + return 0; > +} > + > +static int gc5035_otp_update_regs(struct gc5035 *gc5035) > +{ > + struct device *dev = &gc5035->client->dev; > + struct gc5035_otp_regs *otp_regs = &gc5035->otp_regs; > + unsigned int i; > + int ret; > + > + dev_dbg(dev, "reg count = %d\n", otp_regs->num_regs); > + > + for (i = 0; i < otp_regs->num_regs; i++) { > + ret = gc5035_write_reg(gc5035, GC5035_PAGE_REG, > + otp_regs->regs[i].page); > + if (ret) > + return ret; > + > + ret = gc5035_write_reg(gc5035, > + otp_regs->regs[i].regval.addr, > + otp_regs->regs[i].regval.val); > + if (ret) > + return ret; > + } > + > + return 0; > +} > + > +static int gc5035_otp_update(struct gc5035 *gc5035) > +{ > + struct device *dev = &gc5035->client->dev; > + int ret; > + > + ret = gc5035_otp_update_dd(gc5035); > + if (ret) { > + dev_err(dev, "failed to update otp dd\n"); > + return ret; > + } > + > + ret = gc5035_otp_update_regs(gc5035); > + if (ret) { > + dev_err(dev, "failed to update otp regs\n"); > + return ret; > + } > + > + return ret; > +} > + > +static int gc5035_set_otp_config(struct gc5035 *gc5035) > +{ > + struct device *dev = &gc5035->client->dev; > + u8 otp_id[GC5035_OTP_ID_SIZE]; > + int ret; > + > + ret = gc5035_write_array(gc5035, gc5035_otp_init_regs, > + ARRAY_SIZE(gc5035_otp_init_regs)); > + if (ret) { > + dev_err(dev, "failed to write otp init reg\n"); > + return ret; > + } > + > + ret = gc5035_otp_read_data(gc5035, GC5035_OTP_ID_DATA_OFFSET, > + &otp_id[0], GC5035_OTP_ID_SIZE); Is this read needed every time when streaming is about to start? I guess it's not wrong but it seems unnecessary on subsequent times. > + if (ret) { > + dev_err(dev, "failed to read otp id\n"); > + goto out_otp_exit; > + } > + > + if (!gc5035->otp_read || memcmp(gc5035->otp_id, otp_id, sizeof(otp_id))) { > + dev_dbg(dev, "reading OTP configuration\n"); > + > + memset(&gc5035->otp_regs, 0, sizeof(gc5035->otp_regs)); > + memset(&gc5035->dpc, 0, sizeof(gc5035->dpc)); > + > + memcpy(gc5035->otp_id, otp_id, sizeof(gc5035->otp_id)); > + > + ret = gc5035_otp_read_sensor_info(gc5035); > + if (ret < 0) { > + dev_err(dev, "failed to read otp info\n"); > + goto out_otp_exit; > + } > + > + gc5035->otp_read = true; > + } > + > + ret = gc5035_otp_update(gc5035); > + if (ret < 0) > + return ret; > + > +out_otp_exit: > + ret = gc5035_write_array(gc5035, gc5035_otp_exit_regs, > + ARRAY_SIZE(gc5035_otp_exit_regs)); > + if (ret) { > + dev_err(dev, "failed to write otp exit reg\n"); > + return ret; > + } > + > + return ret; > +} > + > static int gc5035_set_fmt(struct v4l2_subdev *sd, > struct v4l2_subdev_pad_config *cfg, > struct v4l2_subdev_format *fmt) > @@ -859,6 +1333,10 @@ static int __gc5035_start_stream(struct gc5035 *gc5035) > if (ret) > return ret; > > + ret = gc5035_set_otp_config(gc5035); > + if (ret) > + return ret; > + > ret = gc5035_write_array(gc5035, gc5035->cur_mode->reg_list, > gc5035->cur_mode->num_regs); > if (ret) -- Kind regards, Sakari Ailus