/****************************************************************************
* FunctionName: s5k4e1_liteon_affli_add_project_name;
* Description :  add the project name and app_info display;
***************************************************************************/
static int s5k4e1_liteon_affli_add_project_name(struct msm_sensor_ctrl_t *s_ctrl)
{
    /*Todo: check the module before cp project name, when we use two sensors with the same IC*/

    /*add project name for the project menu*/
    strncpy(s_ctrl->sensordata->sensor_info->sensor_project_name, "23060129FA-SAM-L", strlen("23060129FA-SAM-L")+1);

    pr_info("%s %d : s5k4e1_liteon_affli_add_project_name sensor_project_name=%s \n",  __func__, __LINE__,
            s_ctrl->sensordata->sensor_info->sensor_project_name);

    /*add the app_info*/
    app_info_set("camera_main", "s5k4e1_liteon_affli");
        
    pr_info("s5k4e1_liteon_affli_add_project_name OK\n");

    return 0;
}
/****************************************************************************
* FunctionName: ov8850_foxconn_add_project_name;
* Description : add the project name and app_info display;
***************************************************************************/
static int ov8850_foxconn_add_project_name(struct msm_sensor_ctrl_t *s_ctrl)
{
    /*Todo: check the module before cp project name, when we use two sensors with the same IC*/

    /*add project name for the project menu*/
    strncpy(s_ctrl->sensordata->sensor_info->sensor_project_name, "23060108FA-OV-F", strlen("23060108FA-OV-F")+1);

    pr_info("%s %d : ov8850_foxconn_add_project_name sensor_project_name=%s \n",  __func__, __LINE__,
            s_ctrl->sensordata->sensor_info->sensor_project_name);

    /*add the app_info*/
    app_info_set("camera_main", "ov8850_foxconn");
    
    pr_info("ov8850_foxconn_add_project_name OK\n");

    return 0;
}
int32_t msm_sensor_driver_probe(void *setting,
	struct msm_sensor_info_t *probed_info, char *entity_name)
{
	int32_t                              rc = 0;
	struct msm_sensor_ctrl_t            *s_ctrl = NULL;
	struct msm_camera_cci_client        *cci_client = NULL;
	struct msm_camera_sensor_slave_info *slave_info = NULL;
	struct msm_camera_slave_info        *camera_info = NULL;
 
    struct msm_sensor_cam_id_t          *cam_id =NULL;
    
	unsigned long                        mount_pos = 0;
	int32_t index = -1;
	uint32_t                             i = 0;

	/* Validate input parameters */
	if (!setting) {
		pr_err("failed: slave_info %p", setting);
		return -EINVAL;
	}

	/* Allocate memory for slave info */
	slave_info = kzalloc(sizeof(*slave_info), GFP_KERNEL);
	if (!slave_info) {
		pr_err("failed: no memory slave_info %p", slave_info);
		return -ENOMEM;
	}
#ifdef CONFIG_COMPAT
	if (is_compat_task()) {
		struct msm_camera_sensor_slave_info32 setting32;
		if (copy_from_user((void *)&setting32, setting,
			sizeof(setting32))) {
				pr_err("failed: copy_from_user");
				rc = -EFAULT;
				goto free_slave_info;
			}

		strlcpy(slave_info->actuator_name, setting32.actuator_name,
			sizeof(slave_info->actuator_name));

		strlcpy(slave_info->eeprom_name, setting32.eeprom_name,
			sizeof(slave_info->eeprom_name));

		strlcpy(slave_info->sensor_name, setting32.sensor_name,
			sizeof(slave_info->sensor_name));

		strlcpy(slave_info->ois_name, setting32.ois_name,
			sizeof(slave_info->ois_name));

		strlcpy(slave_info->flash_name, setting32.flash_name,
			sizeof(slave_info->flash_name));

		slave_info->addr_type = setting32.addr_type;
		slave_info->camera_id = setting32.camera_id;

		slave_info->i2c_freq_mode = setting32.i2c_freq_mode;
		slave_info->sensor_id_info = setting32.sensor_id_info;

		slave_info->slave_addr = setting32.slave_addr;
		slave_info->power_setting_array.size =
			setting32.power_setting_array.size;
		slave_info->power_setting_array.size_down =
			setting32.power_setting_array.size_down;
		slave_info->power_setting_array.size_down =
			setting32.power_setting_array.size_down;
		slave_info->power_setting_array.power_setting =
			compat_ptr(setting32.power_setting_array.power_setting);
		slave_info->power_setting_array.power_down_setting =
			compat_ptr(setting32.
				power_setting_array.power_down_setting);
		slave_info->is_init_params_valid =
			setting32.is_init_params_valid;
		slave_info->sensor_init_params = setting32.sensor_init_params;
		slave_info->is_flash_supported = setting32.is_flash_supported;
	} else
#endif
	{
		if (copy_from_user(slave_info,
					(void *)setting, sizeof(*slave_info))) {
			pr_err("failed: copy_from_user");
			rc = -EFAULT;
			goto free_slave_info;
		}
	}

	/* Print slave info */
	CDBG("camera id %d", slave_info->camera_id);
	CDBG("slave_addr 0x%x", slave_info->slave_addr);
	CDBG("addr_type %d", slave_info->addr_type);
	CDBG("sensor_id_reg_addr 0x%x",
		slave_info->sensor_id_info.sensor_id_reg_addr);
	CDBG("sensor_id 0x%x", slave_info->sensor_id_info.sensor_id);
	CDBG("size %d", slave_info->power_setting_array.size);
	CDBG("size down %d", slave_info->power_setting_array.size_down);
	/* Print dump reg info */
	CDBG("dump_reg_num:%d \n", slave_info->dump_reg_num);
	for(i = 0; i < slave_info->dump_reg_num; i++)
		CDBG("load dump_reg_addr:0x%X,default value:0x%X \n",
			slave_info->dump_reg_info[i].addr,
			slave_info->dump_reg_info[i].value);

	if (slave_info->is_init_params_valid) {
		CDBG("position %d",
			slave_info->sensor_init_params.position);
		CDBG("mount %d",
			slave_info->sensor_init_params.sensor_mount_angle);
	}

	/* Validate camera id */
	if (slave_info->camera_id >= MAX_CAMERAS) {
		pr_err("failed: invalid camera id %d max %d",
			slave_info->camera_id, MAX_CAMERAS);
		rc = -EINVAL;
		goto free_slave_info;
	}

	/* Extract s_ctrl from camera id */
	s_ctrl = g_sctrl[slave_info->camera_id];
	if (!s_ctrl) {
		pr_err("failed: s_ctrl %p for camera_id %d", s_ctrl,
			slave_info->camera_id);
		rc = -EINVAL;
		goto free_slave_info;
	}

	CDBG("s_ctrl[%d] %p", slave_info->camera_id, s_ctrl);

	if (s_ctrl->is_probe_succeed == 1) {
		/*
		 * Different sensor on this camera slot has been connected
		 * and probe already succeeded for that sensor. Ignore this
		 * probe
		 */
		if (slave_info->sensor_id_info.sensor_id ==
			s_ctrl->sensordata->cam_slave_info->
				sensor_id_info.sensor_id) {
			pr_err("slot%d: sensor id%d already probed\n",
				slave_info->camera_id,
				s_ctrl->sensordata->cam_slave_info->
					sensor_id_info.sensor_id);
			msm_sensor_fill_sensor_info(s_ctrl,
				probed_info, entity_name);
		} else
			pr_err("slot %d has some other sensor\n",
				slave_info->camera_id);

		rc = 0;
		goto free_slave_info;
	}

	if (s_ctrl->sensordata->special_support_size > 0) {
		if (!msm_sensor_driver_is_special_support(s_ctrl,
			slave_info->sensor_name)) {
			pr_err("%s:%s is not support on this board\n",
				__func__, slave_info->sensor_name);
			rc = 0;
			goto free_slave_info;
		}
	}

	rc = msm_sensor_get_power_settings(setting, slave_info,
		&s_ctrl->sensordata->power_info);
	if (rc < 0) {
		pr_err("failed");
		goto free_slave_info;
	}


	camera_info = kzalloc(sizeof(struct msm_camera_slave_info), GFP_KERNEL);
	if (!camera_info) {
		pr_err("failed: no memory slave_info %p", camera_info);
		goto free_slave_info;

	}

	s_ctrl->sensordata->slave_info = camera_info;
	
   	/* used for confirmed MCAM_ID */
	cam_id = kzalloc(sizeof(*cam_id),GFP_KERNEL);
	if(!cam_id){
		pr_err("failed: no memory cam_id %p",cam_id);
		rc = -ENOMEM;
		goto free_camera_info;
	}
	if(slave_info->sensor_cam_id){
		if (copy_from_user(cam_id,(void *)slave_info->sensor_cam_id,sizeof(*cam_id))) {
			pr_err("sensor_cam_id failed: copy_from_user");
			rc = -EFAULT;
			goto free_camera_id;
		}
		camera_info->mcam_id = cam_id->cam_excepted_id;
		CDBG("%s expect camera id %d",slave_info->sensor_name,camera_info->mcam_id);
	}else{
		CDBG("%s no need to match camera id",slave_info->sensor_name);
		camera_info->mcam_id = 2;
	}

	/* Fill sensor slave info */
	camera_info->sensor_slave_addr = slave_info->slave_addr;
	camera_info->sensor_id_reg_addr =
		slave_info->sensor_id_info.sensor_id_reg_addr;
	camera_info->sensor_id = slave_info->sensor_id_info.sensor_id;
        camera_info->sensor_id_data_type = slave_info->sensor_id_info.sensor_id_data_type;

	//Fill dump reg info
	if (0 !=  slave_info->dump_reg_num && slave_info->dump_reg_info) {
		camera_info->dump_reg_num = slave_info->dump_reg_num;
		camera_info->dump_reg_info = kzalloc( (sizeof (struct dump_reg_info_t)) *
			slave_info->dump_reg_num, GFP_KERNEL);

		if (!camera_info->dump_reg_info) {
			pr_err("failed: no memory dump reg info %p", camera_info->dump_reg_info);
			return -ENOMEM;
		} else if (copy_from_user(camera_info->dump_reg_info,slave_info->dump_reg_info,
					sizeof(struct dump_reg_info_t) * slave_info->dump_reg_num)) {
			pr_err("failed: copy_dump_reg");
			rc = -EFAULT;
			kfree(camera_info->dump_reg_info);
			return rc;
		} else {
			for(i = 0; i < (camera_info->dump_reg_num); i++)
				CDBG("cam_dump_reg: 0x%X",
				camera_info->dump_reg_info[i].addr);
		}
	} else {
		pr_err("sensor %s have no dump_reg_info",slave_info->sensor_name);
	}

	/* Fill CCI master, slave address and CCI default params */
	if (!s_ctrl->sensor_i2c_client) {
		pr_err("failed: sensor_i2c_client %p",
			s_ctrl->sensor_i2c_client);
		rc = -EINVAL;
		goto free_camera_info;
	}
	/* Fill sensor address type */
	s_ctrl->sensor_i2c_client->addr_type = slave_info->addr_type;
	if (s_ctrl->sensor_i2c_client->client)
		s_ctrl->sensor_i2c_client->client->addr =
			camera_info->sensor_slave_addr;

	cci_client = s_ctrl->sensor_i2c_client->cci_client;
	if (!cci_client) {
		pr_err("failed: cci_client %p", cci_client);
		goto free_camera_info;
	}
	cci_client->cci_i2c_master = s_ctrl->cci_i2c_master;
	cci_client->sid = slave_info->slave_addr >> 1;
	cci_client->retries = 3;
	cci_client->id_map = 0;
	cci_client->i2c_freq_mode = slave_info->i2c_freq_mode;

	/* Parse and fill vreg params for powerup settings */
	rc = msm_camera_fill_vreg_params(
		s_ctrl->sensordata->power_info.cam_vreg,
		s_ctrl->sensordata->power_info.num_vreg,
		s_ctrl->sensordata->power_info.power_setting,
		s_ctrl->sensordata->power_info.power_setting_size);
	if (rc < 0) {
		pr_err("failed: msm_camera_get_dt_power_setting_data rc %d",
			rc);
		goto free_camera_info;
	}

	/* Parse and fill vreg params for powerdown settings*/
	rc = msm_camera_fill_vreg_params(
		s_ctrl->sensordata->power_info.cam_vreg,
		s_ctrl->sensordata->power_info.num_vreg,
		s_ctrl->sensordata->power_info.power_down_setting,
		s_ctrl->sensordata->power_info.power_down_setting_size);
	if (rc < 0) {
		pr_err("failed: msm_camera_fill_vreg_params for PDOWN rc %d",
			rc);
		goto free_camera_info;
	}

	/* Update sensor, actuator and eeprom name in
	*  sensor control structure */
	s_ctrl->sensordata->sensor_name = slave_info->sensor_name;
	s_ctrl->sensordata->eeprom_name = slave_info->eeprom_name;
	s_ctrl->sensordata->actuator_name = slave_info->actuator_name;
	s_ctrl->sensordata->ois_name = slave_info->ois_name;
	/*
	 * Update eeporm subdevice Id by input eeprom name
	 */
	rc = msm_sensor_fill_eeprom_subdevid_by_name(s_ctrl);
	if (rc < 0) {
		pr_err("%s failed %d\n", __func__, __LINE__);
		goto free_camera_info;
	}
	/*
	 * Update actuator subdevice Id by input actuator name
	 */
	rc = msm_sensor_fill_actuator_subdevid_by_name(s_ctrl);
	if (rc < 0) {
		pr_err("%s failed %d\n", __func__, __LINE__);
		goto free_camera_info;
	}

	rc = msm_sensor_fill_ois_subdevid_by_name(s_ctrl);
	if (rc < 0) {
		pr_err("%s failed %d\n", __func__, __LINE__);
		goto free_camera_info;
	}

	/* Power up and probe sensor */
	rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
	if (rc < 0) {
		pr_err("%s power up failed", slave_info->sensor_name);
		goto free_camera_info;
	}
	if ( is_exist_otp_function(s_ctrl, &index)){
		if(otp_function_lists[index].is_boot_load){
			rc = otp_function_lists[index].sensor_otp_function(s_ctrl, index);
			if (rc < 0){
				pr_err("%s:%d failed rc %d\n", __func__,__LINE__, rc);
			}
		}
	}
	pr_err("%s probe succeeded", slave_info->sensor_name);
	if (0 == slave_info->camera_id){
		rc = app_info_set("camera_main", slave_info->sensor_name);
	}
	else if (1 == slave_info->camera_id){
		rc = app_info_set("camera_slave", slave_info->sensor_name);
	}
	else{
		pr_err("%s app_info_set id err", slave_info->sensor_name);
	}

#ifdef CONFIG_HUAWEI_HW_DEV_DCT
	if(0 == slave_info->camera_id) //detet main senor or sub sensor
	{
		set_hw_dev_flag(DEV_I2C_CAMERA_MAIN);   //set sensor flag
	}
	else if (1 == slave_info->camera_id)       //sub sensor
	{
		set_hw_dev_flag(DEV_I2C_CAMERA_SLAVE);  //set sensor flag
	}
	else
	{
		pr_err("%s set_hw_dev_flag id err", slave_info->sensor_name);
	}
#endif
	/*
	  Set probe succeeded flag to 1 so that no other camera shall
	 * probed on this slot
	 */
	s_ctrl->is_probe_succeed = 1;

	/*
	 * Update the subdevice id of flash-src based on availability in kernel.
	 */
	if (slave_info->is_flash_supported == 0) {
		s_ctrl->sensordata->sensor_info->
			subdev_id[SUB_MODULE_LED_FLASH] = -1;
	}

	/*
	 * Create /dev/videoX node, comment for now until dummy /dev/videoX
	 * node is created and used by HAL
	 */

	if (s_ctrl->sensor_device_type == MSM_CAMERA_PLATFORM_DEVICE)
		rc = msm_sensor_driver_create_v4l_subdev(s_ctrl);
	else
		rc = msm_sensor_driver_create_i2c_v4l_subdev(s_ctrl);
	if (rc < 0) {
		pr_err("failed: camera creat v4l2 rc %d", rc);
		goto camera_power_down;
	}

	/* Power down */
	s_ctrl->func_tbl->sensor_power_down(s_ctrl);

	rc = msm_sensor_fill_slave_info_init_params(
		slave_info,
		s_ctrl->sensordata->sensor_info);
	if (rc < 0) {
		pr_err("%s Fill slave info failed", slave_info->sensor_name);
		goto free_camera_info;
	}
	rc = msm_sensor_validate_slave_info(s_ctrl->sensordata->sensor_info);
	if (rc < 0) {
		pr_err("%s Validate slave info failed",
			slave_info->sensor_name);
		goto free_camera_info;
	}
	/* Update sensor mount angle and position in media entity flag */
	mount_pos = s_ctrl->sensordata->sensor_info->position << 16;
	mount_pos = mount_pos | ((s_ctrl->sensordata->sensor_info->
		sensor_mount_angle / 90) << 8);
	s_ctrl->msm_sd.sd.entity.flags = mount_pos | MEDIA_ENT_FL_DEFAULT;

	/*Save sensor info*/
	s_ctrl->sensordata->cam_slave_info = slave_info;

	msm_sensor_fill_sensor_info(s_ctrl, probed_info, entity_name);

	return rc;

camera_power_down:
	s_ctrl->func_tbl->sensor_power_down(s_ctrl);
free_camera_info:
	kfree(camera_info);
free_camera_id:
	kfree(cam_id);
free_slave_info:
	kfree(slave_info);
	return rc;
}