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

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
Loading
Loading
Loading
Loading
+50 −53
Original line number Diff line number Diff line
@@ -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;
	int rval;
	u32 s;

	*status = 0;

	rval = smiapp_write(sensor,
			    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)
	if (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] &
	    SMIAPP_DATA_TRANSFER_IF_CAPABILITY_POLL) {
		for (i = 1000; i > 0; i--) {
			u32 s;
			if (s & SMIAPP_DATA_TRANSFER_IF_1_STATUS_RD_READY)
				break;

			rval = smiapp_read(
				sensor,
@@ -998,10 +1013,6 @@ static int smiapp_read_nvm_page(struct smiapp_sensor *sensor, u32 p, u8 *nvm)

			if (rval)
				return rval;

			if (s & SMIAPP_DATA_TRANSFER_IF_1_STATUS_RD_READY)
				break;

		}

		if (!i)
@@ -1023,23 +1034,27 @@ static int smiapp_read_nvm_page(struct smiapp_sensor *sensor, u32 p, u8 *nvm)
	return 0;
}

static int smiapp_read_nvm(struct smiapp_sensor *sensor,
			   unsigned char *nvm)
static int smiapp_read_nvm(struct smiapp_sensor *sensor, unsigned char *nvm,
			   size_t nvm_size)
{
	u32 p, np;
	u8 status = 0;
	u32 p;
	int rval = 0, rval2;

	np = sensor->nvm_size / SMIAPP_NVM_PAGE_SIZE;
	for (p = 0; p < np && !rval; p++) {
		rval = smiapp_read_nvm_page(sensor, p, nvm);
	for (p = 0; p < nvm_size / SMIAPP_NVM_PAGE_SIZE && !rval; p++) {
		rval = smiapp_read_nvm_page(sensor, p, nvm, &status);
		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);
	if (rval < 0)
		return rval;
	else
		return rval2;
		return rval2 ?: p * SMIAPP_NVM_PAGE_SIZE;
}

/*
@@ -2326,17 +2341,11 @@ smiapp_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,
	struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev));
	struct i2c_client *client = v4l2_get_subdevdata(subdev);
	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
	unsigned int nbytes;
	int rval;

	if (!sensor->dev_init_done)
		return -EBUSY;

	if (!sensor->nvm_size) {
		int rval;

		/* NVM not read yet - read it now */
		sensor->nvm_size = sensor->hwcfg->nvm_size;

	rval = pm_runtime_get_sync(&client->dev);
	if (rval < 0) {
		if (rval != -EBUSY && rval != -EAGAIN)
@@ -2345,7 +2354,8 @@ smiapp_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,
		return -ENODEV;
	}

		if (smiapp_read_nvm(sensor, sensor->nvm)) {
	rval = smiapp_read_nvm(sensor, buf, PAGE_SIZE);
	if (rval < 0) {
		pm_runtime_put(&client->dev);
		dev_err(&client->dev, "nvm read failed\n");
		return -ENODEV;
@@ -2353,15 +2363,12 @@ smiapp_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,

	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
	 * assume this for now.
	 */
	nbytes = min_t(unsigned int, sensor->nvm_size, PAGE_SIZE);
	memcpy(buf, sensor->nvm, nbytes);

	return nbytes;
	return rval;
}
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)
		}
	}

	/* 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",
					&hwcfg->ext_clk);
	if (rval)
		dev_info(dev, "can't get clock-frequency\n");

	dev_dbg(dev, "nvm %d, clk %d, mode %d\n",
		hwcfg->nvm_size, hwcfg->ext_clk, hwcfg->csi_signalling_mode);
	dev_dbg(dev, "clk %d, mode %d\n", hwcfg->ext_clk,
		hwcfg->csi_signalling_mode);

	if (!bus_cfg.nr_of_link_frequencies) {
		dev_warn(dev, "no link frequencies defined\n");
@@ -3018,17 +3022,10 @@ static int smiapp_probe(struct i2c_client *client)
		rval = -ENOENT;
		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) {
			dev_err(&client->dev, "sysfs nvm entry failed\n");
			rval = -EBUSY;
+0 −3
Original line number Diff line number Diff line
@@ -208,9 +208,6 @@ struct smiapp_sensor {
	bool dev_init_done;
	u8 compressed_min_bpp;

	u8 *nvm;		/* nvm memory buffer */
	unsigned int nvm_size;	/* bytes */

	struct smiapp_module_info minfo;

	struct smiapp_pll pll;
+0 −1
Original line number Diff line number Diff line
@@ -49,7 +49,6 @@ struct smiapp_hwconfig {
	unsigned short i2c_addr_dfl;	/* Default i2c addr */
	unsigned short i2c_addr_alt;	/* Alternate i2c addr */

	uint32_t nvm_size;		/* bytes */
	uint32_t ext_clk;		/* sensor external clk */

	unsigned int lanes;		/* Number of CSI-2 lanes */