Commit 5e6fd339 authored by Bingbu Cao's avatar Bingbu Cao Committed by Mauro Carvalho Chehab

media: ov2740: allow OTP data access during streaming

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: default avatarBingbu Cao <bingbu.cao@intel.com>
Signed-off-by: default avatarQingwu Zhang <qingwu.zhang@intel.com>
Reviewed-by: default avatarTomasz Figa <tfiga@chromium.org>
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 798f1a6b
...@@ -598,13 +598,109 @@ static void ov2740_update_pad_format(const struct ov2740_mode *mode, ...@@ -598,13 +598,109 @@ static void ov2740_update_pad_format(const struct ov2740_mode *mode,
fmt->field = V4L2_FIELD_NONE; 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) static int ov2740_start_streaming(struct ov2740 *ov2740)
{ {
struct i2c_client *client = v4l2_get_subdevdata(&ov2740->sd); struct i2c_client *client = v4l2_get_subdevdata(&ov2740->sd);
struct nvm_data *nvm = ov2740->nvm;
const struct ov2740_reg_list *reg_list; const struct ov2740_reg_list *reg_list;
int link_freq_index; int link_freq_index;
int ret = 0; int ret = 0;
ov2740_load_otp_data(nvm);
link_freq_index = ov2740->cur_mode->link_freq_index; link_freq_index = ov2740->cur_mode->link_freq_index;
reg_list = &link_freq_configs[link_freq_index].reg_list; reg_list = &link_freq_configs[link_freq_index].reg_list;
ret = ov2740_write_reg_list(ov2740, reg_list); ret = ov2740_write_reg_list(ov2740, reg_list);
...@@ -934,99 +1030,6 @@ static int ov2740_remove(struct i2c_client *client) ...@@ -934,99 +1030,6 @@ static int ov2740_remove(struct i2c_client *client)
return 0; 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, static int ov2740_nvmem_read(void *priv, unsigned int off, void *val,
size_t count) size_t count)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment