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

Commit 59b7004f authored by Jeyaprakash Soundrapandian's avatar Jeyaprakash Soundrapandian Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: Add QUP i2c burst and sequential write support" into dev/msm-4.9-camx

parents 75d5415e 75fd4253
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -163,4 +163,18 @@ int32_t cam_qup_i2c_poll(struct i2c_client *client,
int32_t cam_qup_i2c_write_table(
	struct camera_io_master *client,
	struct cam_sensor_i2c_reg_setting *write_setting);

/**
 * cam_qup_i2c_write_continuous_write: QUP based I2C write continuous(Burst/Seq)
 * @client: QUP I2C client structure
 * @write_setting: I2C register setting
 * @cam_sensor_i2c_write_flag: burst or seq write
 *
 * This API handles QUP continuous write
 */
int32_t cam_qup_i2c_write_continuous_table(
	struct camera_io_master *client,
	struct cam_sensor_i2c_reg_setting *write_setting,
	uint8_t cam_sensor_i2c_write_flag);

#endif /*_CAM_SENSOR_I2C_H*/
+2 −2
Original line number Diff line number Diff line
@@ -129,8 +129,8 @@ int32_t camera_io_dev_write_continuous(struct camera_io_master *io_master_info,
		return cam_cci_i2c_write_continuous_table(io_master_info,
			write_setting, cam_sensor_i2c_write_flag);
	} else if (io_master_info->master_type == I2C_MASTER) {
		return cam_qup_i2c_write_table(io_master_info,
			write_setting);
		return cam_qup_i2c_write_continuous_table(io_master_info,
			write_setting, cam_sensor_i2c_write_flag);
	} else if (io_master_info->master_type == SPI_MASTER) {
		return cam_spi_write_table(io_master_info,
			write_setting);
+171 −0
Original line number Diff line number Diff line
@@ -353,3 +353,174 @@ int32_t cam_qup_i2c_write_table(struct camera_io_master *client,

	return rc;
}

static int32_t cam_qup_i2c_write_seq(struct camera_io_master *client,
	struct cam_sensor_i2c_reg_setting *write_setting)
{
	int i;
	int32_t rc = 0;
	struct cam_sensor_i2c_reg_array *reg_setting;

	reg_setting = write_setting->reg_setting;

	for (i = 0; i < write_setting->size; i++) {
		reg_setting->reg_addr += i;
		rc = cam_qup_i2c_write(client, reg_setting,
			write_setting->addr_type, write_setting->data_type);
		if (rc < 0) {
			CAM_ERR(CAM_SENSOR,
				"Sequential i2c write failed: rc: %d", rc);
			break;
		}
		reg_setting++;
	}

	if (write_setting->delay > 20)
		msleep(write_setting->delay);
	else if (write_setting->delay)
		usleep_range(write_setting->delay * 1000, (write_setting->delay
			* 1000) + 1000);

	return rc;
}

static int32_t cam_qup_i2c_write_burst(struct camera_io_master *client,
	struct cam_sensor_i2c_reg_setting *write_setting)
{
	int i;
	int32_t rc = 0;
	uint32_t len = 0;
	unsigned char *buf = NULL;
	struct cam_sensor_i2c_reg_array *reg_setting;
	enum camera_sensor_i2c_type addr_type;
	enum camera_sensor_i2c_type data_type;

	buf = kzalloc((write_setting->addr_type +
			(write_setting->size * write_setting->data_type)),
			GFP_KERNEL);

	if (!buf) {
		CAM_ERR(CAM_SENSOR, "BUF is NULL");
		return -ENOMEM;
	}

	reg_setting = write_setting->reg_setting;
	addr_type = write_setting->addr_type;
	data_type = write_setting->data_type;

	CAM_DBG(CAM_SENSOR, "reg addr = 0x%x data type: %d",
			reg_setting->reg_addr, data_type);
	if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) {
		buf[0] = reg_setting->reg_addr;
		CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]);
		len = 1;
	} else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) {
		buf[0] = reg_setting->reg_addr >> 8;
		buf[1] = reg_setting->reg_addr;
		CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]);
		CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len+1, buf[len+1]);
		len = 2;
	} else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) {
		buf[0] = reg_setting->reg_addr >> 16;
		buf[1] = reg_setting->reg_addr >> 8;
		buf[2] = reg_setting->reg_addr;
		len = 3;
	} else if (addr_type == CAMERA_SENSOR_I2C_TYPE_DWORD) {
		buf[0] = reg_setting->reg_addr >> 24;
		buf[1] = reg_setting->reg_addr >> 16;
		buf[2] = reg_setting->reg_addr >> 8;
		buf[3] = reg_setting->reg_addr;
		len = 4;
	} else {
		CAM_ERR(CAM_SENSOR, "Invalid I2C addr type");
		rc = -EINVAL;
		goto free_res;
	}

	for (i = 0; i < write_setting->size; i++) {
		if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) {
			buf[len] = reg_setting->reg_data;
			CAM_DBG(CAM_SENSOR,
				"Byte %d: 0x%x", len, buf[len]);
			len += 1;
		} else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) {
			buf[len] = reg_setting->reg_data >> 8;
			buf[len+1] = reg_setting->reg_data;
			CAM_DBG(CAM_SENSOR,
				"Byte %d: 0x%x", len, buf[len]);
			CAM_DBG(CAM_SENSOR,
				"Byte %d: 0x%x", len+1, buf[len+1]);
			len += 2;
		} else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) {
			buf[len] = reg_setting->reg_data >> 16;
			buf[len + 1] = reg_setting->reg_data >> 8;
			buf[len + 2] = reg_setting->reg_data;
			CAM_DBG(CAM_SENSOR,
				"Byte %d: 0x%x", len, buf[len]);
			CAM_DBG(CAM_SENSOR,
				"Byte %d: 0x%x", len+1, buf[len+1]);
			CAM_DBG(CAM_SENSOR,
				"Byte %d: 0x%x", len+2, buf[len+2]);
			len += 3;
		} else if (data_type == CAMERA_SENSOR_I2C_TYPE_DWORD) {
			buf[len] = reg_setting->reg_data >> 24;
			buf[len + 1] = reg_setting->reg_data >> 16;
			buf[len + 2] = reg_setting->reg_data >> 8;
			buf[len + 3] = reg_setting->reg_data;
			CAM_DBG(CAM_SENSOR,
				"Byte %d: 0x%x", len, buf[len]);
			CAM_DBG(CAM_SENSOR,
				"Byte %d: 0x%x", len+1, buf[len+1]);
			CAM_DBG(CAM_SENSOR,
				"Byte %d: 0x%x", len+2, buf[len+2]);
			CAM_DBG(CAM_SENSOR,
				"Byte %d: 0x%x", len+3, buf[len+3]);
			len += 4;
		} else {
			CAM_ERR(CAM_SENSOR, "Invalid Data Type");
			rc = -EINVAL;
			goto free_res;
		}
		reg_setting++;
	}

	if (len > (write_setting->addr_type +
		(write_setting->size * write_setting->data_type))) {
		CAM_ERR(CAM_SENSOR, "Invalid Length: %u | Expected length: %u",
			len, (write_setting->addr_type +
			(write_setting->size * write_setting->data_type)));
		rc = -EINVAL;
		goto free_res;
	}

	rc = cam_qup_i2c_txdata(client, buf, len);
	if (rc < 0)
		CAM_ERR(CAM_SENSOR, "failed rc: %d", rc);

free_res:
	kfree(buf);
	return rc;
}

int32_t cam_qup_i2c_write_continuous_table(struct camera_io_master *client,
	struct cam_sensor_i2c_reg_setting *write_settings,
	uint8_t cam_sensor_i2c_write_flag)
{
	int32_t rc = 0;

	if (!client || !write_settings)
		return -EINVAL;

	if ((write_settings->addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID
		|| write_settings->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX
		|| (write_settings->data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID
		|| write_settings->data_type >= CAMERA_SENSOR_I2C_TYPE_MAX)))
		return -EINVAL;

	if (cam_sensor_i2c_write_flag == CAM_SENSOR_I2C_WRITE_BURST)
		rc = cam_qup_i2c_write_burst(client, write_settings);
	else if (cam_sensor_i2c_write_flag == CAM_SENSOR_I2C_WRITE_SEQ)
		rc = cam_qup_i2c_write_seq(client, write_settings);

	return rc;
}
+2 −0
Original line number Diff line number Diff line
@@ -231,6 +231,8 @@ static int32_t cam_sensor_handle_continuous_write(
		cam_cmd_i2c_continuous_wr->header.addr_type;
	i2c_list->i2c_settings.data_type =
		cam_cmd_i2c_continuous_wr->header.data_type;
	i2c_list->i2c_settings.size =
		cam_cmd_i2c_continuous_wr->header.count;

	for (cnt = 0; cnt < (cam_cmd_i2c_continuous_wr->header.count);
		cnt++) {