void hisi_mclk_config(struct hisi_sensor_ctrl_t *s_ctrl,
	struct sensor_power_setting *power_setting, int state)
{
	int sensor_index;

	cam_debug("%s enter.state:%d", __func__, state);
	if (SENSOR_INDEX_INVALID != power_setting->sensor_index) {
		sensor_index = power_setting->sensor_index;
	} else {
		sensor_index = s_ctrl->sensor->sensor_info->sensor_index;
	}

	if (is_fpga_board())
		return;

	if (POWER_ON == state) {
		/* mclk */
		if (CAMERA_SENSOR_PRIMARY == sensor_index) {
			SETREG8(REG_ISP_CLK_DIVIDER, 0x44);
		} else {
			SETREG8(REG_ISP_CLK_DIVIDER, 0x44);
		}
	} else {
		//SETREG8(REG_ISP_CLK_DIVIDER, 0);
	}

	if (0 != power_setting->delay) {
		camdrv_msleep(power_setting->delay);
	}

	return;
}
int hisi_sensor_ldo_config(ldo_index_t ldo, struct hisi_sensor_info *sensor_info,
	struct sensor_power_setting *power_setting, int state)
{
	int index;
	int rc = -1;
	const char *ldo_names[LDO_MAX]
		= {"dvdd", "dvdd2", "avdd", "avdd2", "vcm", "vcm2", "iopw"};

	cam_debug("%s enter, ldo: %d", __func__, ldo);

	if (is_fpga_board())
		return 0;

	for(index = 0; index < sensor_info->ldo_num; index++) {
		if(!strcmp(sensor_info->ldo[index].supply, ldo_names[ldo]))
			break;
	}

	if(index == sensor_info->ldo_num) {
		cam_notice("ldo [%s] is not actived", ldo_names[ldo]);
		return 0;
	}

	if (POWER_ON == state) {
		if(LDO_IOPW != ldo) {
			rc = regulator_set_voltage(sensor_info->ldo[index].consumer, power_setting->config_val, power_setting->config_val);
			if(rc < 0) {
				cam_err("failed to set ldo[%s] to %d V", ldo_names[ldo], power_setting->config_val);
				return rc;
			}
		}
		rc = regulator_bulk_enable(1, &sensor_info->ldo[index]);
		if (rc) {
			cam_err("failed to enable regulators %d\n", rc);
			return rc;
		}
		if (0 != power_setting->delay) {
			camdrv_msleep(power_setting->delay);
		}
	} else {
		regulator_bulk_disable(1, &sensor_info->ldo[index]);
		rc = 0;
	}

	return rc;

}
void hisi_sensor_i2c_config(struct hisi_sensor_ctrl_t *s_ctrl,
	struct sensor_power_setting *power_setting, int state)
{
	cam_debug("enter %s, state:%d", __func__, state);

	if (is_fpga_board())
		return;

	if (POWER_ON == state) {
		isp_config_i2c(&s_ctrl->sensor->sensor_info->i2c_config);

		if (0 != power_setting->delay) {
			camdrv_msleep(power_setting->delay);
		}
	}

	return;
}
int hisi_sensor_gpio_config(gpio_t pin_type, struct hisi_sensor_info *sensor_info,
	struct sensor_power_setting *power_setting, int state)
{
	int rc = -1;

	cam_debug("%s enter, pin_type: %d", __func__, pin_type);

	if (is_fpga_board())
		return 0;

	if(0 == sensor_info->gpios[pin_type].gpio) {
		cam_notice("gpio type[%d] is not actived", pin_type);
		return 0;
	}

	rc = gpio_request(sensor_info->gpios[pin_type].gpio, NULL);
	if(rc < 0) {
		cam_err("failed to request gpio[%d]", sensor_info->gpios[pin_type].gpio);
		return rc;
	}

	if(pin_type == FSIN) {
		cam_info("pin_level: %d", gpio_get_value(sensor_info->gpios[pin_type].gpio));
		rc = 0;
	} else {
		rc = gpio_direction_output(sensor_info->gpios[pin_type].gpio,
			state ? (power_setting->config_val + 1) % 2 : power_setting->config_val);
		if(rc < 0) {
			cam_err("failed to control gpio[%d]", sensor_info->gpios[pin_type].gpio);
		}
	}

	gpio_free(sensor_info->gpios[pin_type].gpio);

	if (0 != power_setting->delay) {
		camdrv_msleep(power_setting->delay);
	}

	return rc;

}
int hisi_sensor_power_up(struct hisi_sensor_ctrl_t *s_ctrl)
{
	struct sensor_power_setting_array *power_setting_array
		= &s_ctrl->sensor->power_setting_array;
	struct sensor_power_setting *power_setting = NULL;
	int index = 0, rc = 0;

	cam_debug("%s enter.", __func__);

	/* fpga board compatibility */

	if (is_fpga_board()) {
		//hisi_sensor_power_up_fpga(s_ctrl);
		return 0;
	}

	for (index = 0; index < power_setting_array->size; index++) {
		power_setting = &power_setting_array->power_setting[index];
		switch(power_setting->seq_type) {
		case SENSOR_DVDD:
			rc = hisi_sensor_ldo_config(LDO_DVDD, s_ctrl->sensor->sensor_info,
				power_setting, POWER_ON);
			break;
		case SENSOR_DVDD2:
			rc = hisi_sensor_ldo_config(LDO_DVDD2, s_ctrl->sensor->sensor_info,
				power_setting, POWER_ON);
			break;
		case SENSOR_IOVDD:
			rc = hisi_sensor_ldo_config(LDO_IOPW, s_ctrl->sensor->sensor_info,
				power_setting, POWER_ON);
			break;
		case SENSOR_AVDD:
			rc = hisi_sensor_ldo_config(LDO_AVDD, s_ctrl->sensor->sensor_info,
				power_setting, POWER_ON);
			break;
		case SENSOR_AVDD2:
			rc = hisi_sensor_ldo_config(LDO_AVDD2, s_ctrl->sensor->sensor_info,
				power_setting, POWER_ON);
			break;
		case SENSOR_VCM_AVDD:
			rc = hisi_sensor_ldo_config(LDO_VCM, s_ctrl->sensor->sensor_info,
				power_setting, POWER_ON);
			break;
		case SENSOR_VCM_AVDD2:
			rc = hisi_sensor_ldo_config(LDO_VCM2, s_ctrl->sensor->sensor_info,
				power_setting, POWER_ON);
			break;

		case SENSOR_MCLK:
			hisi_mclk_config(s_ctrl, power_setting, POWER_ON);
			break;
		case SENSOR_I2C:
			hisi_sensor_i2c_config(s_ctrl, power_setting, POWER_ON);
			break;

		case SENSOR_CHECK_LEVEL:
			rc = hisi_sensor_gpio_config(FSIN, s_ctrl->sensor->sensor_info,
				power_setting, POWER_ON);
			break;
		case SENSOR_RST:
			rc = hisi_sensor_gpio_config(RESETB, s_ctrl->sensor->sensor_info,
				power_setting, POWER_ON);
			break;
		case SENSOR_PWDN:
			rc = hisi_sensor_gpio_config(PWDN, s_ctrl->sensor->sensor_info,
				power_setting, POWER_ON);
			break;
		case SENSOR_VCM_PWDN:
			rc = hisi_sensor_gpio_config(VCM, s_ctrl->sensor->sensor_info,
				power_setting, POWER_ON);
			break;
		case SENSOR_SUSPEND:
			rc = hisi_sensor_gpio_config(SUSPEND, s_ctrl->sensor->sensor_info,
				power_setting, POWER_ON);
			break;

		default:
			cam_err("%s invalid seq_type.", __func__);
			break;
		}

		if(rc) {
			cam_err("%s power up procedure error.", __func__);
			break;
		}
	}
	return rc;
}
int imx214_match_id(struct hisi_sensor_ctrl_t *s_ctrl)
{
	int ret = 0;
	u16 id_h = 0;
	u16 id_l = 0;
	u16 sensor_id = 0;
	int camif_id = -1;
	struct hisi_sensor_info *sensor_info = s_ctrl->sensor->sensor_info;

	cam_info( "%s, sensor_chipid:0x%x\n",
		__func__, sensor_info->sensor_chipid);

	ret = hisi_sensor_power_up(s_ctrl);
	if(ret) {
		cam_err("sensor[%s] power up failed.", sensor_info->name);
		ret = -1;
		goto out;
	}

	/* check sensor id */
	isp_read_sensor_byte(&sensor_info->i2c_config, 0x0016, &id_h);

	isp_read_sensor_byte(&sensor_info->i2c_config, 0x0017, &id_l);

	sensor_id = id_h << 8 | id_l;

	cam_notice( "sensor id:  0x%x", sensor_id);
	if (sensor_id != sensor_info->sensor_chipid) {
		ret =  -1;
		goto out;
	}
	if (!is_fpga_board()) {
		if(0 == sensor_info->gpios[FSIN].gpio) {
			cam_err("%s gpio type[FSIN] is not actived.", __func__);
			ret = -1;
			goto out;
		}

		ret = gpio_request(sensor_info->gpios[FSIN].gpio, "camif_id");
		if(ret < 0) {
			cam_err("failed to request gpio[%d]", sensor_info->gpios[FSIN].gpio);
			goto out;
		}
		ret = gpio_direction_input(sensor_info->gpios[FSIN].gpio);
		if(ret < 0) {
			cam_err("failed to control gpio[%d]", sensor_info->gpios[FSIN].gpio);
			goto out_gpio;
		}

		ret = gpio_get_value(sensor_info->gpios[FSIN].gpio);
		if(ret < 0) {
			cam_err("failed to get gpio[%d]", sensor_info->gpios[FSIN].gpio);
			goto out_gpio;
		} else {
			camif_id = ret;
			cam_notice("%s camif id = %d.", __func__, camif_id);
		}

		if (camif_id != sensor_info->camif_id) {
			cam_notice("%s camera[%s] module is not match.", __func__, sensor_info->name);
			ret = -1;
		} else {
			cam_notice("%s camera[%s] match successfully.", __func__, sensor_info->name);
			ret = 0;
		}

		if (0 == ret) {
			#ifdef IMX214_OTP_FEATURE
			imx214_read_otp(s_ctrl);
			#endif
		}
	}
out_gpio:
	gpio_free(sensor_info->gpios[FSIN].gpio);
out:
	hisi_sensor_power_down(s_ctrl);
	return ret;
}
int hisi_sensor_get_dt_data(struct platform_device *pdev,
	struct hisi_sensor_t *sensor)
{
	struct device_node *of_node = pdev->dev.of_node;
	struct hisi_sensor_info *sensor_info = NULL;
	int rc = 0;
	u32 i, index = 0;
	char *gpio_tag = NULL;
	const char *gpio_ctrl_types[IO_MAX] =
		{"reset", "fsin", "pwdn", "vcm_pwdn", "suspend"};

	cam_debug("enter %s", __func__);
	sensor_info = kzalloc(sizeof(struct hisi_sensor_info),
				GFP_KERNEL);
	if (!sensor_info) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		return -ENOMEM;
	}
	sensor->sensor_info = sensor_info;

	/* ++add mirror & flip disable flag zwx211899++ */
	rc = of_property_read_u32(of_node, "hisi,mirror_flip_disable",
			&sensor_info->mirror_flip_disable);
	if(rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
	}
	/* --add mirror & flip disable flag zwx211899--*/

	rc = of_property_read_string(of_node, "hisi,sensor_name",
		&sensor_info->name);
	cam_debug("%s hisi,sensor_name %s, rc %d\n", __func__,
		sensor_info->name, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,sensor_index",
		&sensor_info->sensor_index);
	cam_debug("%s hisi,sensor_index %d, rc %d\n", __func__,
		sensor_info->sensor_index, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,interface_type",
		&sensor_info->interface_type);
	cam_debug("%s hisi,interface_type %d, rc %d\n", __func__,
		sensor_info->interface_type, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,csi_lane",
		&sensor_info->csi_lane);
	cam_debug("%s hisi,csi_lane %d, rc %d\n", __func__,
		sensor_info->csi_lane, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,csi_mipi_clk",
		&sensor_info->csi_mipi_clk);
	cam_debug("%s hisi,csi_mipi_clk %d, rc %d\n", __func__,
		sensor_info->csi_mipi_clk, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,csi_index",
		&sensor_info->csi_index);
	cam_debug("%s hisi,csi_index %d, rc %d\n", __func__,
		sensor_info->csi_index, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,pd_valid",
		&sensor_info->power_conf.pd_valid);
	cam_debug("%s hisi,pd_valid %d, rc %d\n", __func__,
		sensor_info->power_conf.pd_valid, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,reset_valid",
		&sensor_info->power_conf.reset_valid);
	cam_debug("%s hisi,reset_valid %d, rc %d\n", __func__,
		sensor_info->power_conf.reset_valid, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,vcmpd_valid",
		&sensor_info->power_conf.vcmpd_valid);
	cam_debug("%s hisi,vcmpd_valid %d, rc %d\n", __func__,
		sensor_info->power_conf.vcmpd_valid, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,i2c-index",
		&sensor_info->i2c_config.index);
	cam_debug("%s hisi,i2c-index %d, rc %d\n", __func__,
		sensor_info->i2c_config.index, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,i2c-speed",
		&sensor_info->i2c_config.speed);
	cam_debug("%s hisi,i2c-speed %d, rc %d\n", __func__,
		sensor_info->i2c_config.speed, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,i2c-addr",
		&sensor_info->i2c_config.addr);
	cam_debug("%s hisi,i2c-addr 0x%x, rc %d\n", __func__,
		sensor_info->i2c_config.addr, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,i2c-addr_bits",
		&sensor_info->i2c_config.addr_bits);
	cam_debug("%s hisi,i2c-addr_bits %d, rc %d\n", __func__,
		sensor_info->i2c_config.addr_bits, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,i2c-val_bits",
		&sensor_info->i2c_config.val_bits);
	cam_debug("%s hisi,i2c-val_bits %d, rc %d\n", __func__,
		sensor_info->i2c_config.val_bits, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,sensor_chipid",
		&sensor_info->sensor_chipid);
	cam_debug("%s hisi,sensor_chipid 0x%x, rc %d\n", __func__,
		sensor_info->sensor_chipid, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,camif_id",
		&sensor_info->camif_id);
	cam_debug("%s hisi,camif_id 0x%x, rc %d\n", __func__,
		sensor_info->camif_id, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,vcm_enable",
		&sensor_info->vcm_enable);
	cam_debug("%s hisi,vcm_enable %d, rc %d\n", __func__,
		sensor_info->vcm_enable, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	rc = of_property_read_u32(of_node, "hisi,sensor_type",
		&sensor_info->sensor_type);
	cam_debug("%s hisi,sensor_type %d, rc %d\n", __func__,
		sensor_info->sensor_type, rc);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	if (sensor_info->vcm_enable) {
		rc = of_property_read_string(of_node, "hisi,vcm_name",
			&sensor_info->vcm_name);
		cam_debug("%s hisi,vcm_name %s, rc %d\n", __func__,
			sensor_info->vcm_name, rc);
		if (rc < 0) {
			cam_err("%s failed %d\n", __func__, __LINE__);
			goto fail;
		}
	}

	if (is_fpga_board())
		return rc;

	/* get ldo */
	sensor_info->ldo_num = of_property_count_strings(of_node, "hisi,ldo-names");
	if(sensor_info->ldo_num < 0) {
			cam_err("%s failed %d\n", __func__, __LINE__);
			goto fail;
	}
	cam_debug("ldo num = %d", sensor_info->ldo_num);
	for (i = 0; i < sensor_info->ldo_num; i++) {
		rc = of_property_read_string_index(of_node, "hisi,ldo-names",
			i, &sensor_info->ldo[i].supply);
		if(rc < 0) {
			cam_err("%s failed %d\n", __func__, __LINE__);
			goto fail;
		}
	}

	rc = devm_regulator_bulk_get(&(pdev->dev), sensor_info->ldo_num, sensor_info->ldo);
	if (rc < 0) {
		cam_err("%s failed %d\n", __func__, __LINE__);
		goto fail;
	}

	sensor_info->gpio_num = of_gpio_count(of_node);
	if(sensor_info->gpio_num < 0 ) {
			cam_err("%s failed %d\n", __func__, __LINE__);
			goto fail;
	}
	for(i = 0; i < sensor_info->gpio_num; i++) {
		rc = of_property_read_string_index(of_node, "hisi,gpio-ctrl-types",
			i, (const char **)&gpio_tag);
		if(rc < 0) {
			cam_err("%s failed %d\n", __func__, __LINE__);
			goto fail;
		}
		for(index = 0; index < IO_MAX; index++) {
			if(!strcmp(gpio_ctrl_types[index], gpio_tag))
				sensor_info->gpios[index].gpio = of_get_gpio(of_node, i);
		}
		cam_info("gpio ctrl types: %s\n", gpio_tag);
	}

	return rc;
fail:
	cam_err("%s error exit.\n", __func__);
	kfree(sensor_info);
	sensor_info = NULL;
	return rc;
}