Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f93358ce authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: Add power down sequence separately for camera"

parents 423b0f31 8107b2ea
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -66,6 +66,8 @@ struct msm_camera_power_ctrl_t {
	struct device *dev;
	struct msm_sensor_power_setting *power_setting;
	uint16_t power_setting_size;
	struct msm_sensor_power_setting *power_down_setting;
	uint16_t power_down_setting_size;
	struct msm_camera_gpio_conf *gpio_conf;
	struct camera_vreg_t *cam_vreg;
	int num_vreg;
+1 −1
Original line number Diff line number Diff line
@@ -597,7 +597,7 @@ static int msm_eeprom_get_dt_data(struct msm_eeprom_ctrl_t *e_ctrl)

	rc = msm_camera_get_dt_power_setting_data(of_node,
		power_info->cam_vreg, power_info->num_vreg,
		&power_info->power_setting, &power_info->power_setting_size);
		power_info);
	if (rc < 0)
		goto ERROR1;

+79 −33
Original line number Diff line number Diff line
@@ -347,8 +347,7 @@ ERROR:

int msm_camera_get_dt_power_setting_data(struct device_node *of_node,
	struct camera_vreg_t *cam_vreg, int num_vreg,
	struct msm_sensor_power_setting **power_setting,
	uint16_t *power_setting_size)
	struct msm_camera_power_ctrl_t *power_info)
{
	int rc = 0, i, j;
	int count = 0;
@@ -356,11 +355,18 @@ int msm_camera_get_dt_power_setting_data(struct device_node *of_node,
	uint32_t *array = NULL;
	struct msm_sensor_power_setting *ps;

	if (!power_setting || !power_setting_size)
	struct msm_sensor_power_setting *power_setting;
	uint16_t *power_setting_size;

	if (!power_info)
		return -EINVAL;

	power_setting = power_info->power_setting;
	power_setting_size = &power_info->power_setting_size;

	count = of_property_count_strings(of_node, "qcom,cam-power-seq-type");
	*power_setting_size = count;

	CDBG("%s qcom,cam-power-seq-type count %d\n", __func__, count);

	if (count <= 0)
@@ -371,7 +377,7 @@ int msm_camera_get_dt_power_setting_data(struct device_node *of_node,
		pr_err("%s failed %d\n", __func__, __LINE__);
		return -ENOMEM;
	}
	*power_setting = ps;
	power_setting = ps;

	for (i = 0; i < count; i++) {
		rc = of_property_read_string_index(of_node,
@@ -502,7 +508,6 @@ int msm_camera_get_dt_power_setting_data(struct device_node *of_node,
	}
	kfree(array);
	return rc;

ERROR2:
	kfree(array);
ERROR1:
@@ -1038,6 +1043,7 @@ power_up_failed:
		power_setting = &ctrl->power_setting[index];
		CDBG("%s type %d\n", __func__, power_setting->seq_type);
		switch (power_setting->seq_type) {

		case SENSOR_CLK:
			msm_cam_clk_enable(ctrl->dev,
				&ctrl->clk_info[0],
@@ -1081,12 +1087,34 @@ power_up_failed:
	return rc;
}

static struct msm_sensor_power_setting*
msm_camera_get_power_settings(struct msm_camera_power_ctrl_t *ctrl,
				enum msm_sensor_power_seq_type_t seq_type,
				uint16_t seq_val)
{
	struct msm_sensor_power_setting *power_setting, *ps = NULL;
	int idx;

	for (idx = 0; idx < ctrl->power_setting_size; idx++) {
		power_setting = &ctrl->power_setting[idx];
		if (power_setting->seq_type == seq_type &&
			power_setting->seq_val ==  seq_val) {
			ps = power_setting;
			return ps;
		}

	}
	return ps;
}

int msm_camera_power_down(struct msm_camera_power_ctrl_t *ctrl,
	enum msm_camera_device_type_t device_type,
	struct msm_camera_i2c_client *sensor_i2c_client)
{
	int index = 0;
	struct msm_sensor_power_setting *power_setting = NULL;
	struct msm_sensor_power_setting *pd = NULL;
	struct msm_sensor_power_setting *ps;


	CDBG("%s:%d\n", __func__, __LINE__);
	if (!ctrl || !sensor_i2c_client) {
@@ -1099,46 +1127,64 @@ int msm_camera_power_down(struct msm_camera_power_ctrl_t *ctrl,
		sensor_i2c_client->i2c_func_tbl->i2c_util(
			sensor_i2c_client, MSM_CCI_RELEASE);

	for (index = (ctrl->power_setting_size - 1); index >= 0; index--) {
	for (index = 0; index < ctrl->power_down_setting_size; index++) {
		CDBG("%s index %d\n", __func__, index);
		power_setting = &ctrl->power_setting[index];
		CDBG("%s type %d\n", __func__, power_setting->seq_type);
		switch (power_setting->seq_type) {
		pd = &ctrl->power_down_setting[index];
		ps = NULL;
		CDBG("%s type %d\n", __func__, pd->seq_type);
		switch (pd->seq_type) {
		case SENSOR_CLK:

			ps = msm_camera_get_power_settings(ctrl,
						pd->seq_type,
						pd->seq_val);
			if (ps)
				msm_cam_clk_enable(ctrl->dev,
					&ctrl->clk_info[0],
				(struct clk **)&power_setting->data[0],
					(struct clk **)&ps->data[0],
					ctrl->clk_info_size,
					0);
			else
				pr_err("%s error in power up/down seq data\n",
								__func__);
				break;
		case SENSOR_GPIO:
			if (power_setting->seq_val >= SENSOR_GPIO_MAX ||
			if (pd->seq_val >= SENSOR_GPIO_MAX ||
				!ctrl->gpio_conf->gpio_num_info) {
				pr_err("%s gpio index %d >= max %d\n", __func__,
					power_setting->seq_val,
					pd->seq_val,
					SENSOR_GPIO_MAX);
				continue;
			}
			if (!ctrl->gpio_conf->gpio_num_info->valid
				[power_setting->seq_val])
				[pd->seq_val])
				continue;
			gpio_set_value_cansleep(
				ctrl->gpio_conf->gpio_num_info->gpio_num
				[power_setting->seq_val],
				[pd->seq_val],
				ctrl->gpio_conf->gpio_num_info->gpio_num
				[power_setting->config_val]);
				[pd->config_val]);
			break;
		case SENSOR_VREG:
			if (power_setting->seq_val >= CAM_VREG_MAX) {
			if (pd->seq_val >= CAM_VREG_MAX) {
				pr_err("%s vreg index %d >= max %d\n", __func__,
					power_setting->seq_val,
					pd->seq_val,
					SENSOR_GPIO_MAX);
				continue;
			}

			ps = msm_camera_get_power_settings(ctrl,
						pd->seq_type,
						pd->seq_val);

			if (ps)
				msm_camera_config_single_vreg(ctrl->dev,
				&ctrl->cam_vreg[power_setting->seq_val],
				(struct regulator **)&power_setting->data[0],
					&ctrl->cam_vreg[pd->seq_val],
					(struct regulator **)&ps->data[0],
					0);
			else
				pr_err("%s error in power up/down seq data\n",
								__func__);
			break;
		case SENSOR_I2C_MUX:
			if (ctrl->i2c_conf && ctrl->i2c_conf->use_i2c_mux)
@@ -1146,14 +1192,14 @@ int msm_camera_power_down(struct msm_camera_power_ctrl_t *ctrl,
			break;
		default:
			pr_err("%s error power seq type %d\n", __func__,
				power_setting->seq_type);
				pd->seq_type);
			break;
		}
		if (power_setting->delay > 20) {
			msleep(power_setting->delay);
		} else if (power_setting->delay) {
			usleep_range(power_setting->delay * 1000,
				(power_setting->delay * 1000) + 1000);
		if (pd->delay > 20) {
			msleep(pd->delay);
		} else if (pd->delay) {
			usleep_range(pd->delay * 1000,
				(pd->delay * 1000) + 1000);
		}
	}
	msm_camera_request_gpio_table(
+1 −2
Original line number Diff line number Diff line
@@ -29,8 +29,7 @@ int msm_sensor_get_dt_csi_data(struct device_node *of_node,

int msm_camera_get_dt_power_setting_data(struct device_node *of_node,
	struct camera_vreg_t *cam_vreg, int num_vreg,
	struct msm_sensor_power_setting **power_setting,
	uint16_t *power_setting_size);
	struct msm_camera_power_ctrl_t *power_info);

int msm_camera_get_dt_gpio_req_tbl(struct device_node *of_node,
	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+96 −13
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ static int32_t msm_camera_get_power_settimgs_from_sensor_lib(
	int32_t rc = 0;
	uint32_t size;
	struct msm_sensor_power_setting *ps;
	bool need_reverse = 0;

	if ((NULL == power_info->power_setting) ||
		(0 == power_info->power_setting_size)) {
@@ -60,7 +61,42 @@ static int32_t msm_camera_get_power_settimgs_from_sensor_lib(
		power_info->power_setting_size = size;
	}

	ps = power_setting_array->power_down_setting;
	size = power_setting_array->size_down;
	if (NULL == ps || 0 == size) {
		ps = power_info->power_setting;
		size = power_info->power_setting_size;
		need_reverse = 1;
	}

	power_info->power_down_setting =
	kzalloc(sizeof(*ps) * size, GFP_KERNEL);
	if (!power_info->power_down_setting) {
		pr_err("%s failed %d\n", __func__, __LINE__);
		goto FREE_UP;
	}
	memcpy(power_info->power_down_setting,
		ps,
		sizeof(*ps) * size);
	power_info->power_down_setting_size = size;

	if (need_reverse) {
		int c, end = size - 1;
		struct msm_sensor_power_setting power_down_setting_t;
		for (c = 0; c < size/2; c++) {
			power_down_setting_t =
				power_info->power_down_setting[c];
			power_info->power_down_setting[c] =
				power_info->power_down_setting[end];
			power_info->power_down_setting[end] =
				power_down_setting_t;
			end--;
		}
	}

	return 0;
FREE_UP:
	kfree(power_info->power_setting);
FAILED_1:
	return rc;
}
@@ -159,8 +195,7 @@ static int32_t msm_sensor_get_dt_data(struct device_node *of_node,
	rc = msm_camera_get_dt_power_setting_data(of_node,
			sensordata->power_info.cam_vreg,
			sensordata->power_info.num_vreg,
			&sensordata->power_info.power_setting,
			&sensordata->power_info.power_setting_size);
			&sensordata->power_info);


	if (rc < 0) {
@@ -277,6 +312,7 @@ FREE_GPIO_CONF:
	kfree(s_ctrl->sensordata->power_info.gpio_conf);
FREE_PS:
	kfree(s_ctrl->sensordata->power_info.power_setting);
	kfree(s_ctrl->sensordata->power_info.power_down_setting);
FREE_VREG:
	kfree(s_ctrl->sensordata->power_info.cam_vreg);
FREE_CSI:
@@ -566,7 +602,7 @@ int msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void __user *argp)
		struct msm_camera_sensor_slave_info sensor_slave_info;
		struct msm_camera_power_ctrl_t *p_ctrl;
		uint16_t size;
		int slave_index = 0;
		int s_index = 0;
		if (copy_from_user(&sensor_slave_info,
				(void *)cdata->cfg.setting,
				sizeof(sensor_slave_info))) {
@@ -583,9 +619,9 @@ int msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void __user *argp)
		/* Update sensor address type */
		s_ctrl->sensor_i2c_client->addr_type =
			sensor_slave_info.addr_type;

		/* Update power up / down sequence */
		p_ctrl = &s_ctrl->sensordata->power_info;

		/* Update power up sequence */
		size = sensor_slave_info.power_setting_array.size;
		if (p_ctrl->power_setting_size < size) {
			struct msm_sensor_power_setting *tmp;
@@ -619,15 +655,62 @@ int msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void __user *argp)
			sensor_slave_info.sensor_id_info.sensor_id_reg_addr);
		CDBG("%s sensor id %x\n", __func__,
			sensor_slave_info.sensor_id_info.sensor_id);
		for (slave_index = 0; slave_index <
			p_ctrl->power_setting_size; slave_index++) {
			CDBG("%s i %d power setting %d %d %ld %d\n", __func__,
				slave_index,
				p_ctrl->power_setting[slave_index].seq_type,
				p_ctrl->power_setting[slave_index].seq_val,
				p_ctrl->power_setting[slave_index].config_val,
				p_ctrl->power_setting[slave_index].delay);
		for (s_index = 0; s_index <
			p_ctrl->power_setting_size; s_index++) {
			CDBG("%s i %d power up setting %d %d %ld %d\n",
				__func__,
				s_index,
				p_ctrl->power_setting[s_index].seq_type,
				p_ctrl->power_setting[s_index].seq_val,
				p_ctrl->power_setting[s_index].config_val,
				p_ctrl->power_setting[s_index].delay);
		}

		/* Update power down sequence */
		if (!sensor_slave_info.power_setting_array.power_down_setting ||
			0 == size) {
			pr_err("%s: Missing dedicated power down sequence\n",
				__func__);
			break;
		}
		size = sensor_slave_info.power_setting_array.size_down;

		if (p_ctrl->power_down_setting_size < size) {
			struct msm_sensor_power_setting *tmp;
			tmp = kmalloc(sizeof(*tmp) * size, GFP_KERNEL);
			if (!tmp) {
				pr_err("%s: failed to alloc mem\n", __func__);
				rc = -ENOMEM;
				break;
			}
			kfree(p_ctrl->power_down_setting);
			p_ctrl->power_down_setting = tmp;
		}
		p_ctrl->power_down_setting_size = size;


		rc = copy_from_user(p_ctrl->power_down_setting, (void *)
			sensor_slave_info.power_setting_array.
			power_down_setting,
			size * sizeof(struct msm_sensor_power_setting));
		if (rc) {
			pr_err("%s:%d failed\n", __func__, __LINE__);
			kfree(sensor_slave_info.power_setting_array.
				power_down_setting);
			rc = -EFAULT;
			break;
		}
		for (s_index = 0; s_index <
			p_ctrl->power_down_setting_size; s_index++) {
			CDBG("%s i %d power DOWN setting %d %d %ld %d\n",
				__func__,
				s_index,
				p_ctrl->power_down_setting[s_index].seq_type,
				p_ctrl->power_down_setting[s_index].seq_val,
				p_ctrl->power_down_setting[s_index].config_val,
				p_ctrl->power_down_setting[s_index].delay);
		}

		break;
	}
	case CFG_WRITE_I2C_ARRAY: {
Loading