static int32_t msm_camera_cci_i2c_set_write_mask_data(
	struct msm_camera_i2c_client *client,
	uint32_t addr, uint16_t data, int16_t mask,
	enum msm_camera_i2c_data_type data_type)
{
	int32_t rc;
	uint16_t reg_data;
	CDBG("%s\n", __func__);
	if (mask == -1)
		return 0;
	if (mask == 0) {
		rc = msm_camera_cci_i2c_write(client, addr, data, data_type);
	} else {
		rc = msm_camera_cci_i2c_read(client, addr, &reg_data,
			data_type);
		if (rc < 0) {
			CDBG("%s read fail\n", __func__);
			return rc;
		}
		reg_data &= ~mask;
		reg_data |= (data & mask);
		rc = msm_camera_cci_i2c_write(client, addr, reg_data,
			data_type);
		if (rc < 0)
			CDBG("%s write fail\n", __func__);
	}
	return rc;
}
static int32_t msm_camera_cci_i2c_set_mask(struct msm_camera_i2c_client *client,
	uint32_t addr, uint16_t mask,
	enum msm_camera_i2c_data_type data_type, uint16_t set_mask)
{
	int32_t rc;
	uint16_t reg_data;

	rc = msm_camera_cci_i2c_read(client, addr, &reg_data, data_type);
	if (rc < 0) {
		S_I2C_DBG("%s read fail\n", __func__);
		return rc;
	}
	S_I2C_DBG("%s addr: 0x%x data: 0x%x setmask: 0x%x\n",
			__func__, addr, reg_data, mask);

	if (set_mask)
		reg_data |= mask;
	else
		reg_data &= ~mask;
	S_I2C_DBG("%s write: 0x%x\n", __func__, reg_data);

	rc = msm_camera_cci_i2c_write(client, addr, reg_data, data_type);
	if (rc < 0)
		S_I2C_DBG("%s write fail\n", __func__);

	return rc;
}
int32_t msm_camera_cci_i2c_write_table_w_microdelay(
	struct msm_camera_i2c_client *client,
	struct msm_camera_i2c_reg_tbl *reg_tbl, uint16_t size,
	enum msm_camera_i2c_data_type data_type)
{
	int i;
	int32_t rc = -EFAULT;

	if (!client || !reg_tbl)
		return rc;

	if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
		&& client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
		|| (data_type != MSM_CAMERA_I2C_BYTE_DATA
		&& data_type != MSM_CAMERA_I2C_WORD_DATA))
		return rc;

	for (i = 0; i < size; i++) {
		rc = msm_camera_cci_i2c_write(client, reg_tbl->reg_addr,
			reg_tbl->reg_data, data_type);
		if (rc < 0)
			return rc;
		if (reg_tbl->delay)
			usleep_range(reg_tbl->delay, reg_tbl->delay + 1000);
		reg_tbl++;
	}
	return rc;
}
int32_t msm_camera_cci_i2c_write_table(
	struct msm_camera_i2c_client *client,
	struct msm_camera_i2c_reg_setting *write_setting)
{
	int i;
	int32_t rc = -EFAULT;
	struct msm_camera_i2c_reg_array *reg_setting;
	uint16_t client_addr_type;

	if (!client || !write_setting)
		return rc;

	if ((write_setting->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
		&& write_setting->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
		|| (write_setting->data_type != MSM_CAMERA_I2C_BYTE_DATA
		&& write_setting->data_type != MSM_CAMERA_I2C_WORD_DATA))
		return rc;

	reg_setting = write_setting->reg_setting;
	client_addr_type = client->addr_type;
	client->addr_type = write_setting->addr_type;

	for (i = 0; i < write_setting->size; i++) {
		rc = msm_camera_cci_i2c_write(client, reg_setting->reg_addr,
			reg_setting->reg_data, write_setting->data_type);
		if (rc < 0)
			return rc;
		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);

	client->addr_type = client_addr_type;
	return rc;
}
int32_t msm_camera_cci_i2c_write_conf_tbl(
	struct msm_camera_i2c_client *client,
	struct msm_camera_i2c_reg_conf *reg_conf_tbl, uint16_t size,
	enum msm_camera_i2c_data_type data_type)
{
	int i;
	int32_t rc = -EFAULT;
	for (i = 0; i < size; i++) {
		enum msm_camera_i2c_data_type dt;
		if (reg_conf_tbl->cmd_type == MSM_CAMERA_I2C_CMD_POLL) {
			rc = msm_camera_cci_i2c_poll(client,
				reg_conf_tbl->reg_addr,
				reg_conf_tbl->reg_data,
				reg_conf_tbl->dt);
		} else {
			if (reg_conf_tbl->dt == 0)
				dt = data_type;
			else
				dt = reg_conf_tbl->dt;
			switch (dt) {
			case MSM_CAMERA_I2C_BYTE_DATA:
			case MSM_CAMERA_I2C_WORD_DATA:
				rc = msm_camera_cci_i2c_write(
					client,
					reg_conf_tbl->reg_addr,
					reg_conf_tbl->reg_data, dt);
				break;
			case MSM_CAMERA_I2C_SET_BYTE_MASK:
				rc = msm_camera_cci_i2c_set_mask(client,
					reg_conf_tbl->reg_addr,
					reg_conf_tbl->reg_data,
					MSM_CAMERA_I2C_BYTE_DATA, 1);
				break;
			case MSM_CAMERA_I2C_UNSET_BYTE_MASK:
				rc = msm_camera_cci_i2c_set_mask(client,
					reg_conf_tbl->reg_addr,
					reg_conf_tbl->reg_data,
					MSM_CAMERA_I2C_BYTE_DATA, 0);
				break;
			case MSM_CAMERA_I2C_SET_WORD_MASK:
				rc = msm_camera_cci_i2c_set_mask(client,
					reg_conf_tbl->reg_addr,
					reg_conf_tbl->reg_data,
					MSM_CAMERA_I2C_WORD_DATA, 1);
				break;
			case MSM_CAMERA_I2C_UNSET_WORD_MASK:
				rc = msm_camera_cci_i2c_set_mask(client,
					reg_conf_tbl->reg_addr,
					reg_conf_tbl->reg_data,
					MSM_CAMERA_I2C_WORD_DATA, 0);
				break;
			case MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA:
				rc = msm_camera_cci_i2c_set_write_mask_data(
					client,
					reg_conf_tbl->reg_addr,
					reg_conf_tbl->reg_data,
					reg_conf_tbl->mask,
					MSM_CAMERA_I2C_BYTE_DATA);
				break;
			default:
				pr_err("%s: Unsupport data type: %d\n",
					__func__, dt);
				break;
			}
		}
		if (rc < 0)
			break;
		reg_conf_tbl++;
	}
	return rc;
}
int32_t msm_camera_cci_i2c_write_table(
	struct msm_camera_i2c_client *client,
	struct msm_camera_i2c_reg_setting *write_setting)
{
	int32_t rc = -EFAULT;
	struct msm_camera_cci_ctrl cci_ctrl;
    
	int i;
	struct msm_camera_i2c_reg_array *reg_setting;
	uint16_t client_addr_type;
	
	
	int special_delay = 0;
	
	if (!client || !write_setting)
		return rc;

	
	reg_setting = write_setting->reg_setting;
	for (i = 0; i < write_setting->size; i++)
	{
		if (reg_setting->reg_addr == 0xffff)
		{
		    special_delay = 1;
		    break;
		}
		reg_setting++;
	}
	
	if ((write_setting->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
		&& write_setting->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
		|| (write_setting->data_type != MSM_CAMERA_I2C_BYTE_DATA
		&& write_setting->data_type != MSM_CAMERA_I2C_WORD_DATA
		&& write_setting->data_type != MSM_CAMERA_I2C_SET_BYTE_MASK
		&& write_setting->data_type != MSM_CAMERA_I2C_UNSET_BYTE_MASK))
		return rc;

	if (write_setting->size == 0)
		rc = 0;

	reg_setting = write_setting->reg_setting;
	client_addr_type = client->addr_type;
	client->addr_type = write_setting->addr_type;

	if (write_setting->data_type == MSM_CAMERA_I2C_SET_BYTE_MASK) {
		for (i = 0; i < write_setting->size; i++) {
			rc = msm_camera_cci_i2c_set_mask(client, reg_setting->reg_addr,
				reg_setting->reg_data, MSM_CAMERA_I2C_BYTE_DATA, 1);
			if (rc < 0) {
				pr_err("%s:%d failed, i = %d, rc = %d\n", __func__, __LINE__, i, rc);
				return rc;
			}
			reg_setting++;
		}
	} else if (write_setting->data_type == MSM_CAMERA_I2C_UNSET_BYTE_MASK) {
		for (i = 0; i < write_setting->size; i++) {
			rc = msm_camera_cci_i2c_set_mask(client, reg_setting->reg_addr,
				reg_setting->reg_data, MSM_CAMERA_I2C_BYTE_DATA, 0);
			if (rc < 0) {
				pr_err("%s:%d failed, i = %d, rc = %d\n", __func__, __LINE__, i, rc);
				return rc;
			}
			reg_setting++;
		}
	} else {
		
		if(special_delay == 0)
		{
		
		cci_ctrl.cmd = MSM_CCI_I2C_WRITE;
		cci_ctrl.cci_info = client->cci_client;
		cci_ctrl.cfg.cci_i2c_write_cfg.reg_setting =
			write_setting->reg_setting;
		cci_ctrl.cfg.cci_i2c_write_cfg.data_type = write_setting->data_type;
		cci_ctrl.cfg.cci_i2c_write_cfg.addr_type = client->addr_type;
		cci_ctrl.cfg.cci_i2c_write_cfg.size = write_setting->size;
		rc = v4l2_subdev_call(client->cci_client->cci_subdev,
				core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
		if (rc < 0) {
			pr_err("%s: line %d rc = %d\n", __func__, __LINE__, rc);
			return rc;
		}
		rc = cci_ctrl.status;
		
		}
		else
		{
			for (i = 0; i < write_setting->size; i++)
			{
			    if (reg_setting->reg_addr == 0xffff)
			    {
			        int delay = reg_setting->reg_data;
			        msleep(delay);
			        pr_info("%s: delay %d ms\n", __func__,delay);
			    }
			    else
			    {
			        rc = msm_camera_cci_i2c_write(client, reg_setting->reg_addr,
			        reg_setting->reg_data, write_setting->data_type);
			        if (rc < 0)
			        {
			            pr_err("%s: write addr(0x%x) data:0x%x fail\n", __func__,reg_setting->reg_addr, reg_setting->reg_data);
			            return rc;
			        }
			    }
			    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;
}