Commit 941e1d36 authored by Sakari Ailus's avatar Sakari Ailus Committed by Mauro Carvalho Chehab

media: smiapp: Support probing NVM size

The interface supports probing for the NVM size but this was not
implemented in the driver. Do that now.

This will also make nokia,nvm-size property redundant.
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 23fc92fa
...@@ -971,10 +971,14 @@ static int smiapp_update_mode(struct smiapp_sensor *sensor) ...@@ -971,10 +971,14 @@ static int smiapp_update_mode(struct smiapp_sensor *sensor)
* *
*/ */
static int smiapp_read_nvm_page(struct smiapp_sensor *sensor, u32 p, u8 *nvm) static int smiapp_read_nvm_page(struct smiapp_sensor *sensor, u32 p, u8 *nvm,
u8 *status)
{ {
unsigned int i; unsigned int i;
int rval; int rval;
u32 s;
*status = 0;
rval = smiapp_write(sensor, rval = smiapp_write(sensor,
SMIAPP_REG_U8_DATA_TRANSFER_IF_1_PAGE_SELECT, p); SMIAPP_REG_U8_DATA_TRANSFER_IF_1_PAGE_SELECT, p);
...@@ -986,10 +990,21 @@ static int smiapp_read_nvm_page(struct smiapp_sensor *sensor, u32 p, u8 *nvm) ...@@ -986,10 +990,21 @@ static int smiapp_read_nvm_page(struct smiapp_sensor *sensor, u32 p, u8 *nvm)
if (rval) if (rval)
return rval; return rval;
rval = smiapp_read(sensor, SMIAPP_REG_U8_DATA_TRANSFER_IF_1_STATUS,
&s);
if (rval)
return rval;
if (s & SMIAPP_DATA_TRANSFER_IF_1_STATUS_EUSAGE) {
*status = s;
return -ENODATA;
}
if (sensor->limits[SMIAPP_LIMIT_DATA_TRANSFER_IF_CAPABILITY] & if (sensor->limits[SMIAPP_LIMIT_DATA_TRANSFER_IF_CAPABILITY] &
SMIAPP_DATA_TRANSFER_IF_CAPABILITY_POLL) { SMIAPP_DATA_TRANSFER_IF_CAPABILITY_POLL) {
for (i = 1000; i > 0; i--) { for (i = 1000; i > 0; i--) {
u32 s; if (s & SMIAPP_DATA_TRANSFER_IF_1_STATUS_RD_READY)
break;
rval = smiapp_read( rval = smiapp_read(
sensor, sensor,
...@@ -998,10 +1013,6 @@ static int smiapp_read_nvm_page(struct smiapp_sensor *sensor, u32 p, u8 *nvm) ...@@ -998,10 +1013,6 @@ static int smiapp_read_nvm_page(struct smiapp_sensor *sensor, u32 p, u8 *nvm)
if (rval) if (rval)
return rval; return rval;
if (s & SMIAPP_DATA_TRANSFER_IF_1_STATUS_RD_READY)
break;
} }
if (!i) if (!i)
...@@ -1023,23 +1034,27 @@ static int smiapp_read_nvm_page(struct smiapp_sensor *sensor, u32 p, u8 *nvm) ...@@ -1023,23 +1034,27 @@ static int smiapp_read_nvm_page(struct smiapp_sensor *sensor, u32 p, u8 *nvm)
return 0; return 0;
} }
static int smiapp_read_nvm(struct smiapp_sensor *sensor, static int smiapp_read_nvm(struct smiapp_sensor *sensor, unsigned char *nvm,
unsigned char *nvm) size_t nvm_size)
{ {
u32 p, np; u8 status = 0;
u32 p;
int rval = 0, rval2; int rval = 0, rval2;
np = sensor->nvm_size / SMIAPP_NVM_PAGE_SIZE; for (p = 0; p < nvm_size / SMIAPP_NVM_PAGE_SIZE && !rval; p++) {
for (p = 0; p < np && !rval; p++) { rval = smiapp_read_nvm_page(sensor, p, nvm, &status);
rval = smiapp_read_nvm_page(sensor, p, nvm);
nvm += SMIAPP_NVM_PAGE_SIZE; nvm += SMIAPP_NVM_PAGE_SIZE;
} }
if (rval == -ENODATA &&
status & SMIAPP_DATA_TRANSFER_IF_1_STATUS_EUSAGE)
rval = 0;
rval2 = smiapp_write(sensor, SMIAPP_REG_U8_DATA_TRANSFER_IF_1_CTRL, 0); rval2 = smiapp_write(sensor, SMIAPP_REG_U8_DATA_TRANSFER_IF_1_CTRL, 0);
if (rval < 0) if (rval < 0)
return rval; return rval;
else else
return rval2; return rval2 ?: p * SMIAPP_NVM_PAGE_SIZE;
} }
/* /*
...@@ -2326,42 +2341,34 @@ smiapp_sysfs_nvm_read(struct device *dev, struct device_attribute *attr, ...@@ -2326,42 +2341,34 @@ smiapp_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,
struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev)); struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev));
struct i2c_client *client = v4l2_get_subdevdata(subdev); struct i2c_client *client = v4l2_get_subdevdata(subdev);
struct smiapp_sensor *sensor = to_smiapp_sensor(subdev); struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
unsigned int nbytes; int rval;
if (!sensor->dev_init_done) if (!sensor->dev_init_done)
return -EBUSY; return -EBUSY;
if (!sensor->nvm_size) { rval = pm_runtime_get_sync(&client->dev);
int rval; if (rval < 0) {
if (rval != -EBUSY && rval != -EAGAIN)
/* NVM not read yet - read it now */ pm_runtime_set_active(&client->dev);
sensor->nvm_size = sensor->hwcfg->nvm_size; pm_runtime_put_noidle(&client->dev);
return -ENODEV;
}
rval = pm_runtime_get_sync(&client->dev); rval = smiapp_read_nvm(sensor, buf, PAGE_SIZE);
if (rval < 0) { if (rval < 0) {
if (rval != -EBUSY && rval != -EAGAIN) pm_runtime_put(&client->dev);
pm_runtime_set_active(&client->dev); dev_err(&client->dev, "nvm read failed\n");
pm_runtime_put_noidle(&client->dev); return -ENODEV;
return -ENODEV; }
}
if (smiapp_read_nvm(sensor, sensor->nvm)) { pm_runtime_mark_last_busy(&client->dev);
pm_runtime_put(&client->dev); pm_runtime_put_autosuspend(&client->dev);
dev_err(&client->dev, "nvm read failed\n");
return -ENODEV;
}
pm_runtime_mark_last_busy(&client->dev);
pm_runtime_put_autosuspend(&client->dev);
}
/* /*
* NVM is still way below a PAGE_SIZE, so we can safely * NVM is still way below a PAGE_SIZE, so we can safely
* assume this for now. * assume this for now.
*/ */
nbytes = min_t(unsigned int, sensor->nvm_size, PAGE_SIZE); return rval;
memcpy(buf, sensor->nvm, nbytes);
return nbytes;
} }
static DEVICE_ATTR(nvm, S_IRUGO, smiapp_sysfs_nvm_read, NULL); static DEVICE_ATTR(nvm, S_IRUGO, smiapp_sysfs_nvm_read, NULL);
...@@ -2825,16 +2832,13 @@ static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev) ...@@ -2825,16 +2832,13 @@ static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev)
} }
} }
/* NVM size is not mandatory */
fwnode_property_read_u32(fwnode, "nokia,nvm-size", &hwcfg->nvm_size);
rval = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", rval = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
&hwcfg->ext_clk); &hwcfg->ext_clk);
if (rval) if (rval)
dev_info(dev, "can't get clock-frequency\n"); dev_info(dev, "can't get clock-frequency\n");
dev_dbg(dev, "nvm %d, clk %d, mode %d\n", dev_dbg(dev, "clk %d, mode %d\n", hwcfg->ext_clk,
hwcfg->nvm_size, hwcfg->ext_clk, hwcfg->csi_signalling_mode); hwcfg->csi_signalling_mode);
if (!bus_cfg.nr_of_link_frequencies) { if (!bus_cfg.nr_of_link_frequencies) {
dev_warn(dev, "no link frequencies defined\n"); dev_warn(dev, "no link frequencies defined\n");
...@@ -3018,17 +3022,10 @@ static int smiapp_probe(struct i2c_client *client) ...@@ -3018,17 +3022,10 @@ static int smiapp_probe(struct i2c_client *client)
rval = -ENOENT; rval = -ENOENT;
goto out_power_off; goto out_power_off;
} }
/* SMIA++ NVM initialization - it will be read from the sensor
* when it is first requested by userspace.
*/
if (sensor->minfo.smiapp_version && sensor->hwcfg->nvm_size) {
sensor->nvm = devm_kzalloc(&client->dev,
sensor->hwcfg->nvm_size, GFP_KERNEL);
if (sensor->nvm == NULL) {
rval = -ENOMEM;
goto out_cleanup;
}
if (sensor->minfo.smiapp_version &&
sensor->limits[SMIAPP_LIMIT_DATA_TRANSFER_IF_CAPABILITY] &
SMIAPP_DATA_TRANSFER_IF_CAPABILITY_SUPPORTED) {
if (device_create_file(&client->dev, &dev_attr_nvm) != 0) { if (device_create_file(&client->dev, &dev_attr_nvm) != 0) {
dev_err(&client->dev, "sysfs nvm entry failed\n"); dev_err(&client->dev, "sysfs nvm entry failed\n");
rval = -EBUSY; rval = -EBUSY;
......
...@@ -208,9 +208,6 @@ struct smiapp_sensor { ...@@ -208,9 +208,6 @@ struct smiapp_sensor {
bool dev_init_done; bool dev_init_done;
u8 compressed_min_bpp; u8 compressed_min_bpp;
u8 *nvm; /* nvm memory buffer */
unsigned int nvm_size; /* bytes */
struct smiapp_module_info minfo; struct smiapp_module_info minfo;
struct smiapp_pll pll; struct smiapp_pll pll;
......
...@@ -49,7 +49,6 @@ struct smiapp_hwconfig { ...@@ -49,7 +49,6 @@ struct smiapp_hwconfig {
unsigned short i2c_addr_dfl; /* Default i2c addr */ unsigned short i2c_addr_dfl; /* Default i2c addr */
unsigned short i2c_addr_alt; /* Alternate i2c addr */ unsigned short i2c_addr_alt; /* Alternate i2c addr */
uint32_t nvm_size; /* bytes */
uint32_t ext_clk; /* sensor external clk */ uint32_t ext_clk; /* sensor external clk */
unsigned int lanes; /* Number of CSI-2 lanes */ unsigned int lanes; /* Number of CSI-2 lanes */
......
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