On Wed, Nov 11, 2020 at 02:39:57PM +0800, Bingbu Cao wrote: > OTP data access of ov2740 need enable the streaming mode to load > and it could be done in any time, so driver need allow the OTP > data access during streaming instead of return EBUSY, this patch > try to read the OTP data out in STREAMON if OTP data is not ready > before first time streaming start. > > Signed-off-by: Bingbu Cao <bingbu.cao@xxxxxxxxx> > --- > drivers/media/i2c/ov2740.c | 189 +++++++++++++++++++++++---------------------- > 1 file changed, 96 insertions(+), 93 deletions(-) > Reviewed-by: Tomasz Figa <tfiga@xxxxxxxxxxxx> Best regards, Tomasz > diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c > index 41c17df46f47..d723e0e7adf7 100644 > --- a/drivers/media/i2c/ov2740.c > +++ b/drivers/media/i2c/ov2740.c > @@ -598,13 +598,109 @@ static void ov2740_update_pad_format(const struct ov2740_mode *mode, > fmt->field = V4L2_FIELD_NONE; > } > > +static int ov2740_load_otp_data(struct nvm_data *nvm) > +{ > + struct i2c_client *client = nvm->client; > + struct ov2740 *ov2740 = to_ov2740(i2c_get_clientdata(client)); > + u32 isp_ctrl00 = 0; > + u32 isp_ctrl01 = 0; > + int ret; > + > + if (!nvm) > + return -EINVAL; > + > + if (nvm->nvm_buffer) > + return 0; > + > + nvm->nvm_buffer = kzalloc(CUSTOMER_USE_OTP_SIZE, GFP_KERNEL); > + if (!nvm->nvm_buffer) > + return -ENOMEM; > + > + ret = ov2740_read_reg(ov2740, OV2740_REG_ISP_CTRL00, 1, &isp_ctrl00); > + if (ret) { > + dev_err(&client->dev, "failed to read ISP CTRL00\n"); > + goto err; > + } > + > + ret = ov2740_read_reg(ov2740, OV2740_REG_ISP_CTRL01, 1, &isp_ctrl01); > + if (ret) { > + dev_err(&client->dev, "failed to read ISP CTRL01\n"); > + goto err; > + } > + > + /* Clear bit 5 of ISP CTRL00 */ > + ret = ov2740_write_reg(ov2740, OV2740_REG_ISP_CTRL00, 1, > + isp_ctrl00 & ~BIT(5)); > + if (ret) { > + dev_err(&client->dev, "failed to set ISP CTRL00\n"); > + goto err; > + } > + > + /* Clear bit 7 of ISP CTRL01 */ > + ret = ov2740_write_reg(ov2740, OV2740_REG_ISP_CTRL01, 1, > + isp_ctrl01 & ~BIT(7)); > + if (ret) { > + dev_err(&client->dev, "failed to set ISP CTRL01\n"); > + goto err; > + } > + > + ret = ov2740_write_reg(ov2740, OV2740_REG_MODE_SELECT, 1, > + OV2740_MODE_STREAMING); > + if (ret) { > + dev_err(&client->dev, "failed to set streaming mode\n"); > + goto err; > + } > + > + /* > + * Users are not allowed to access OTP-related registers and memory > + * during the 20 ms period after streaming starts (0x100 = 0x01). > + */ > + msleep(20); > + > + ret = regmap_bulk_read(nvm->regmap, OV2740_REG_OTP_CUSTOMER, > + nvm->nvm_buffer, CUSTOMER_USE_OTP_SIZE); > + if (ret) { > + dev_err(&client->dev, "failed to read OTP data, ret %d\n", ret); > + goto err; > + } > + > + ret = ov2740_write_reg(ov2740, OV2740_REG_MODE_SELECT, 1, > + OV2740_MODE_STANDBY); > + if (ret) { > + dev_err(&client->dev, "failed to set streaming mode\n"); > + goto err; > + } > + > + ret = ov2740_write_reg(ov2740, OV2740_REG_ISP_CTRL01, 1, isp_ctrl01); > + if (ret) { > + dev_err(&client->dev, "failed to set ISP CTRL01\n"); > + goto err; > + } > + > + ret = ov2740_write_reg(ov2740, OV2740_REG_ISP_CTRL00, 1, isp_ctrl00); > + if (ret) { > + dev_err(&client->dev, "failed to set ISP CTRL00\n"); > + goto err; > + } > + > + return 0; > +err: > + kfree(nvm->nvm_buffer); > + nvm->nvm_buffer = NULL; > + > + return ret; > +} > + > static int ov2740_start_streaming(struct ov2740 *ov2740) > { > struct i2c_client *client = v4l2_get_subdevdata(&ov2740->sd); > + struct nvm_data *nvm = ov2740->nvm; > const struct ov2740_reg_list *reg_list; > int link_freq_index; > int ret = 0; > > + ov2740_load_otp_data(nvm); > + > link_freq_index = ov2740->cur_mode->link_freq_index; > reg_list = &link_freq_configs[link_freq_index].reg_list; > ret = ov2740_write_reg_list(ov2740, reg_list); > @@ -934,99 +1030,6 @@ static int ov2740_remove(struct i2c_client *client) > return 0; > } > > -static int ov2740_load_otp_data(struct nvm_data *nvm) > -{ > - struct i2c_client *client = nvm->client; > - struct ov2740 *ov2740 = to_ov2740(i2c_get_clientdata(client)); > - u32 isp_ctrl00 = 0; > - u32 isp_ctrl01 = 0; > - int ret; > - > - if (!nvm) > - return -EINVAL; > - > - if (nvm->nvm_buffer) > - return 0; > - > - nvm->nvm_buffer = kzalloc(CUSTOMER_USE_OTP_SIZE, GFP_KERNEL); > - if (!nvm->nvm_buffer) > - return -ENOMEM; > - > - ret = ov2740_read_reg(ov2740, OV2740_REG_ISP_CTRL00, 1, &isp_ctrl00); > - if (ret) { > - dev_err(&client->dev, "failed to read ISP CTRL00\n"); > - goto err; > - } > - > - ret = ov2740_read_reg(ov2740, OV2740_REG_ISP_CTRL01, 1, &isp_ctrl01); > - if (ret) { > - dev_err(&client->dev, "failed to read ISP CTRL01\n"); > - goto err; > - } > - > - /* Clear bit 5 of ISP CTRL00 */ > - ret = ov2740_write_reg(ov2740, OV2740_REG_ISP_CTRL00, 1, > - isp_ctrl00 & ~BIT(5)); > - if (ret) { > - dev_err(&client->dev, "failed to set ISP CTRL00\n"); > - goto err; > - } > - > - /* Clear bit 7 of ISP CTRL01 */ > - ret = ov2740_write_reg(ov2740, OV2740_REG_ISP_CTRL01, 1, > - isp_ctrl01 & ~BIT(7)); > - if (ret) { > - dev_err(&client->dev, "failed to set ISP CTRL01\n"); > - goto err; > - } > - > - ret = ov2740_write_reg(ov2740, OV2740_REG_MODE_SELECT, 1, > - OV2740_MODE_STREAMING); > - if (ret) { > - dev_err(&client->dev, "failed to set streaming mode\n"); > - goto err; > - } > - > - /* > - * Users are not allowed to access OTP-related registers and memory > - * during the 20 ms period after streaming starts (0x100 = 0x01). > - */ > - msleep(20); > - > - ret = regmap_bulk_read(nvm->regmap, OV2740_REG_OTP_CUSTOMER, > - nvm->nvm_buffer, CUSTOMER_USE_OTP_SIZE); > - if (ret) { > - dev_err(&client->dev, "failed to read OTP data, ret %d\n", ret); > - goto err; > - } > - > - ret = ov2740_write_reg(ov2740, OV2740_REG_MODE_SELECT, 1, > - OV2740_MODE_STANDBY); > - if (ret) { > - dev_err(&client->dev, "failed to set streaming mode\n"); > - goto err; > - } > - > - ret = ov2740_write_reg(ov2740, OV2740_REG_ISP_CTRL01, 1, isp_ctrl01); > - if (ret) { > - dev_err(&client->dev, "failed to set ISP CTRL01\n"); > - goto err; > - } > - > - ret = ov2740_write_reg(ov2740, OV2740_REG_ISP_CTRL00, 1, isp_ctrl00); > - if (ret) { > - dev_err(&client->dev, "failed to set ISP CTRL00\n"); > - goto err; > - } > - > - return 0; > -err: > - kfree(nvm->nvm_buffer); > - nvm->nvm_buffer = NULL; > - > - return ret; > -} > - > static int ov2740_nvmem_read(void *priv, unsigned int off, void *val, > size_t count) > { > -- > 2.7.4 >