Commit 3ecb8664 authored by Sakari Ailus's avatar Sakari Ailus Committed by Mauro Carvalho Chehab
Browse files

[media] smiapp: Merge smiapp_init() with smiapp_probe()



The smiapp_probe() is the sole caller of smiapp_init(). Unify the two.

Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: default avatarSebastian Reichel <sre@kernel.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 99769540
Loading
Loading
Loading
Loading
+204 −219
Original line number Diff line number Diff line
@@ -2622,223 +2622,6 @@ static void smiapp_create_subdev(struct smiapp_sensor *sensor,
	v4l2_set_subdevdata(&ssd->sd, client);
}

static int smiapp_init(struct smiapp_sensor *sensor)
{
	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
	struct smiapp_pll *pll = &sensor->pll;
	unsigned int i;
	int rval;

	sensor->vana = devm_regulator_get(&client->dev, "vana");
	if (IS_ERR(sensor->vana)) {
		dev_err(&client->dev, "could not get regulator for vana\n");
		return PTR_ERR(sensor->vana);
	}

	sensor->ext_clk = devm_clk_get(&client->dev, NULL);
	if (IS_ERR(sensor->ext_clk)) {
		dev_err(&client->dev, "could not get clock (%ld)\n",
			PTR_ERR(sensor->ext_clk));
		return -EPROBE_DEFER;
	}

	rval = clk_set_rate(sensor->ext_clk,
			    sensor->hwcfg->ext_clk);
	if (rval < 0) {
		dev_err(&client->dev,
			"unable to set clock freq to %u\n",
			sensor->hwcfg->ext_clk);
		return rval;
	}

	sensor->xshutdown = devm_gpiod_get_optional(&client->dev, "xshutdown",
						    GPIOD_OUT_LOW);
	if (IS_ERR(sensor->xshutdown))
		return PTR_ERR(sensor->xshutdown);

	rval = smiapp_power_on(sensor);
	if (rval)
		return -ENODEV;

	rval = smiapp_identify_module(sensor);
	if (rval) {
		rval = -ENODEV;
		goto out_power_off;
	}

	rval = smiapp_get_all_limits(sensor);
	if (rval) {
		rval = -ENODEV;
		goto out_power_off;
	}

	/*
	 * Handle Sensor Module orientation on the board.
	 *
	 * The application of H-FLIP and V-FLIP on the sensor is modified by
	 * the sensor orientation on the board.
	 *
	 * For SMIAPP_BOARD_SENSOR_ORIENT_180 the default behaviour is to set
	 * both H-FLIP and V-FLIP for normal operation which also implies
	 * that a set/unset operation for user space HFLIP and VFLIP v4l2
	 * controls will need to be internally inverted.
	 *
	 * Rotation also changes the bayer pattern.
	 */
	if (sensor->hwcfg->module_board_orient ==
	    SMIAPP_MODULE_BOARD_ORIENT_180)
		sensor->hvflip_inv_mask = SMIAPP_IMAGE_ORIENTATION_HFLIP |
					  SMIAPP_IMAGE_ORIENTATION_VFLIP;

	rval = smiapp_call_quirk(sensor, limits);
	if (rval) {
		dev_err(&client->dev, "limits quirks failed\n");
		goto out_power_off;
	}

	if (sensor->limits[SMIAPP_LIMIT_BINNING_CAPABILITY]) {
		u32 val;

		rval = smiapp_read(sensor,
				   SMIAPP_REG_U8_BINNING_SUBTYPES, &val);
		if (rval < 0) {
			rval = -ENODEV;
			goto out_power_off;
		}
		sensor->nbinning_subtypes = min_t(u8, val,
						  SMIAPP_BINNING_SUBTYPES);

		for (i = 0; i < sensor->nbinning_subtypes; i++) {
			rval = smiapp_read(
				sensor, SMIAPP_REG_U8_BINNING_TYPE_n(i), &val);
			if (rval < 0) {
				rval = -ENODEV;
				goto out_power_off;
			}
			sensor->binning_subtypes[i] =
				*(struct smiapp_binning_subtype *)&val;

			dev_dbg(&client->dev, "binning %xx%x\n",
				sensor->binning_subtypes[i].horizontal,
				sensor->binning_subtypes[i].vertical);
		}
	}
	sensor->binning_horizontal = 1;
	sensor->binning_vertical = 1;

	if (device_create_file(&client->dev, &dev_attr_ident) != 0) {
		dev_err(&client->dev, "sysfs ident entry creation failed\n");
		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) {
			dev_err(&client->dev, "nvm buf allocation failed\n");
			rval = -ENOMEM;
			goto out_cleanup;
		}

		if (device_create_file(&client->dev, &dev_attr_nvm) != 0) {
			dev_err(&client->dev, "sysfs nvm entry failed\n");
			rval = -EBUSY;
			goto out_cleanup;
		}
	}

	/* We consider this as profile 0 sensor if any of these are zero. */
	if (!sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV] ||
	    !sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV] ||
	    !sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV] ||
	    !sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV]) {
		sensor->minfo.smiapp_profile = SMIAPP_PROFILE_0;
	} else if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
		   != SMIAPP_SCALING_CAPABILITY_NONE) {
		if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
		    == SMIAPP_SCALING_CAPABILITY_HORIZONTAL)
			sensor->minfo.smiapp_profile = SMIAPP_PROFILE_1;
		else
			sensor->minfo.smiapp_profile = SMIAPP_PROFILE_2;
		sensor->scaler = &sensor->ssds[sensor->ssds_used];
		sensor->ssds_used++;
	} else if (sensor->limits[SMIAPP_LIMIT_DIGITAL_CROP_CAPABILITY]
		   == SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP) {
		sensor->scaler = &sensor->ssds[sensor->ssds_used];
		sensor->ssds_used++;
	}
	sensor->binner = &sensor->ssds[sensor->ssds_used];
	sensor->ssds_used++;
	sensor->pixel_array = &sensor->ssds[sensor->ssds_used];
	sensor->ssds_used++;

	sensor->scale_m = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];

	/* prepare PLL configuration input values */
	pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
	pll->csi2.lanes = sensor->hwcfg->lanes;
	pll->ext_clk_freq_hz = sensor->hwcfg->ext_clk;
	pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
	/* Profile 0 sensors have no separate OP clock branch. */
	if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
		pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;

	smiapp_create_subdev(sensor, sensor->scaler, "scaler", 2);
	smiapp_create_subdev(sensor, sensor->binner, "binner", 2);
	smiapp_create_subdev(sensor, sensor->pixel_array, "pixel_array", 1);

	dev_dbg(&client->dev, "profile %d\n", sensor->minfo.smiapp_profile);

	sensor->pixel_array->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;

	/* final steps */
	smiapp_read_frame_fmt(sensor);
	rval = smiapp_init_controls(sensor);
	if (rval < 0)
		goto out_cleanup;

	rval = smiapp_call_quirk(sensor, init);
	if (rval)
		goto out_cleanup;

	rval = smiapp_get_mbus_formats(sensor);
	if (rval) {
		rval = -ENODEV;
		goto out_cleanup;
	}

	rval = smiapp_init_late_controls(sensor);
	if (rval) {
		rval = -ENODEV;
		goto out_cleanup;
	}

	mutex_lock(&sensor->mutex);
	rval = smiapp_update_mode(sensor);
	mutex_unlock(&sensor->mutex);
	if (rval) {
		dev_err(&client->dev, "update mode failed\n");
		goto out_cleanup;
	}

	sensor->streaming = false;
	sensor->dev_init_done = true;

	smiapp_power_off(sensor);

	return 0;

out_cleanup:
	smiapp_cleanup(sensor);

out_power_off:
	smiapp_power_off(sensor);
	return rval;
}

static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
	struct smiapp_subdev *ssd = to_smiapp_subdev(sd);
@@ -3061,6 +2844,7 @@ static int smiapp_probe(struct i2c_client *client,
{
	struct smiapp_sensor *sensor;
	struct smiapp_hwconfig *hwcfg = smiapp_get_hwconfig(&client->dev);
	unsigned int i;
	int rval;

	if (hwcfg == NULL)
@@ -3081,9 +2865,205 @@ static int smiapp_probe(struct i2c_client *client,
	sensor->src->sensor = sensor;
	sensor->src->pads[0].flags = MEDIA_PAD_FL_SOURCE;

	rval = smiapp_init(sensor);
	sensor->vana = devm_regulator_get(&client->dev, "vana");
	if (IS_ERR(sensor->vana)) {
		dev_err(&client->dev, "could not get regulator for vana\n");
		return PTR_ERR(sensor->vana);
	}

	sensor->ext_clk = devm_clk_get(&client->dev, NULL);
	if (IS_ERR(sensor->ext_clk)) {
		dev_err(&client->dev, "could not get clock (%ld)\n",
			PTR_ERR(sensor->ext_clk));
		return -EPROBE_DEFER;
	}

	rval = clk_set_rate(sensor->ext_clk,
			    sensor->hwcfg->ext_clk);
	if (rval < 0) {
		dev_err(&client->dev,
			"unable to set clock freq to %u\n",
			sensor->hwcfg->ext_clk);
		return rval;
	}

	sensor->xshutdown = devm_gpiod_get_optional(&client->dev, "xshutdown",
						    GPIOD_OUT_LOW);
	if (IS_ERR(sensor->xshutdown))
		return PTR_ERR(sensor->xshutdown);

	rval = smiapp_power_on(sensor);
	if (rval)
		goto out_media_entity_cleanup;
		return -ENODEV;

	rval = smiapp_identify_module(sensor);
	if (rval) {
		rval = -ENODEV;
		goto out_power_off;
	}

	rval = smiapp_get_all_limits(sensor);
	if (rval) {
		rval = -ENODEV;
		goto out_power_off;
	}

	/*
	 * Handle Sensor Module orientation on the board.
	 *
	 * The application of H-FLIP and V-FLIP on the sensor is modified by
	 * the sensor orientation on the board.
	 *
	 * For SMIAPP_BOARD_SENSOR_ORIENT_180 the default behaviour is to set
	 * both H-FLIP and V-FLIP for normal operation which also implies
	 * that a set/unset operation for user space HFLIP and VFLIP v4l2
	 * controls will need to be internally inverted.
	 *
	 * Rotation also changes the bayer pattern.
	 */
	if (sensor->hwcfg->module_board_orient ==
	    SMIAPP_MODULE_BOARD_ORIENT_180)
		sensor->hvflip_inv_mask = SMIAPP_IMAGE_ORIENTATION_HFLIP |
					  SMIAPP_IMAGE_ORIENTATION_VFLIP;

	rval = smiapp_call_quirk(sensor, limits);
	if (rval) {
		dev_err(&client->dev, "limits quirks failed\n");
		goto out_power_off;
	}

	if (sensor->limits[SMIAPP_LIMIT_BINNING_CAPABILITY]) {
		u32 val;

		rval = smiapp_read(sensor,
				   SMIAPP_REG_U8_BINNING_SUBTYPES, &val);
		if (rval < 0) {
			rval = -ENODEV;
			goto out_power_off;
		}
		sensor->nbinning_subtypes = min_t(u8, val,
						  SMIAPP_BINNING_SUBTYPES);

		for (i = 0; i < sensor->nbinning_subtypes; i++) {
			rval = smiapp_read(
				sensor, SMIAPP_REG_U8_BINNING_TYPE_n(i), &val);
			if (rval < 0) {
				rval = -ENODEV;
				goto out_power_off;
			}
			sensor->binning_subtypes[i] =
				*(struct smiapp_binning_subtype *)&val;

			dev_dbg(&client->dev, "binning %xx%x\n",
				sensor->binning_subtypes[i].horizontal,
				sensor->binning_subtypes[i].vertical);
		}
	}
	sensor->binning_horizontal = 1;
	sensor->binning_vertical = 1;

	if (device_create_file(&client->dev, &dev_attr_ident) != 0) {
		dev_err(&client->dev, "sysfs ident entry creation failed\n");
		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) {
			dev_err(&client->dev, "nvm buf allocation failed\n");
			rval = -ENOMEM;
			goto out_cleanup;
		}

		if (device_create_file(&client->dev, &dev_attr_nvm) != 0) {
			dev_err(&client->dev, "sysfs nvm entry failed\n");
			rval = -EBUSY;
			goto out_cleanup;
		}
	}

	/* We consider this as profile 0 sensor if any of these are zero. */
	if (!sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV] ||
	    !sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV] ||
	    !sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV] ||
	    !sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV]) {
		sensor->minfo.smiapp_profile = SMIAPP_PROFILE_0;
	} else if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
		   != SMIAPP_SCALING_CAPABILITY_NONE) {
		if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
		    == SMIAPP_SCALING_CAPABILITY_HORIZONTAL)
			sensor->minfo.smiapp_profile = SMIAPP_PROFILE_1;
		else
			sensor->minfo.smiapp_profile = SMIAPP_PROFILE_2;
		sensor->scaler = &sensor->ssds[sensor->ssds_used];
		sensor->ssds_used++;
	} else if (sensor->limits[SMIAPP_LIMIT_DIGITAL_CROP_CAPABILITY]
		   == SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP) {
		sensor->scaler = &sensor->ssds[sensor->ssds_used];
		sensor->ssds_used++;
	}
	sensor->binner = &sensor->ssds[sensor->ssds_used];
	sensor->ssds_used++;
	sensor->pixel_array = &sensor->ssds[sensor->ssds_used];
	sensor->ssds_used++;

	sensor->scale_m = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];

	/* prepare PLL configuration input values */
	sensor->pll.bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
	sensor->pll.csi2.lanes = sensor->hwcfg->lanes;
	sensor->pll.ext_clk_freq_hz = sensor->hwcfg->ext_clk;
	sensor->pll.scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
	/* Profile 0 sensors have no separate OP clock branch. */
	if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
		sensor->pll.flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;

	smiapp_create_subdev(sensor, sensor->scaler, "scaler", 2);
	smiapp_create_subdev(sensor, sensor->binner, "binner", 2);
	smiapp_create_subdev(sensor, sensor->pixel_array, "pixel_array", 1);

	dev_dbg(&client->dev, "profile %d\n", sensor->minfo.smiapp_profile);

	sensor->pixel_array->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;

	/* final steps */
	smiapp_read_frame_fmt(sensor);
	rval = smiapp_init_controls(sensor);
	if (rval < 0)
		goto out_cleanup;

	rval = smiapp_call_quirk(sensor, init);
	if (rval)
		goto out_cleanup;

	rval = smiapp_get_mbus_formats(sensor);
	if (rval) {
		rval = -ENODEV;
		goto out_cleanup;
	}

	rval = smiapp_init_late_controls(sensor);
	if (rval) {
		rval = -ENODEV;
		goto out_cleanup;
	}

	mutex_lock(&sensor->mutex);
	rval = smiapp_update_mode(sensor);
	mutex_unlock(&sensor->mutex);
	if (rval) {
		dev_err(&client->dev, "update mode failed\n");
		goto out_cleanup;
	}

	sensor->streaming = false;
	sensor->dev_init_done = true;

	smiapp_power_off(sensor);

	rval = media_entity_pads_init(&sensor->src->sd.entity, 2,
				 sensor->src->pads);
@@ -3099,6 +3079,11 @@ static int smiapp_probe(struct i2c_client *client,
out_media_entity_cleanup:
	media_entity_cleanup(&sensor->src->sd.entity);

out_cleanup:
	smiapp_cleanup(sensor);

out_power_off:
	smiapp_power_off(sensor);
	return rval;
}