示例#1
0
static int32_t ov10820_match_id(struct msm_sensor_ctrl_t *s_ctrl)
{
    int32_t rc = 0;
    uint16_t chipid = 0;

    if (ov660_check_probe(s_ctrl) >= 0)
        ov660_exists = true;
    if (ov660_exists)
        ov660_set_i2c_bypass(s_ctrl, (int)1);

    /* Query each i2c slave address for the camera to if the
     * part exists since the sensor has two possible i2c slave
     * addresses. */
    rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_read(
             s_ctrl->sensor_i2c_client,
             s_ctrl->sensordata->slave_info->sensor_id_reg_addr,
             &chipid,
             MSM_CAMERA_I2C_WORD_DATA);
    if (rc >= 0)
        goto check_chipid;

    s_ctrl->sensordata->slave_info->sensor_slave_addr =
        OV10820_SECONDARY_I2C_ADDRESS;
    s_ctrl->sensor_i2c_client->cci_client->sid =
        (OV10820_SECONDARY_I2C_ADDRESS >> 1);
    rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_read(
             s_ctrl->sensor_i2c_client,
             s_ctrl->sensordata->slave_info->sensor_id_reg_addr,
             &chipid,
             MSM_CAMERA_I2C_WORD_DATA);
    if (rc < 0) {
        pr_err("ov10820_match_id read failed");
        return rc;
    }

check_chipid:
    if (chipid != s_ctrl->sensordata->slave_info->sensor_id) {
        pr_err("%s: chip id %x does not match expected %x\n", __func__,
               chipid, s_ctrl->sensordata->
               slave_info->sensor_id);
        return -ENODEV;
    }

    /* Check hardware revision */
    rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_read(
             s_ctrl->sensor_i2c_client,
             OV10820_HW_REV_REG,
             &ov10820_hw_rev,
             MSM_CAMERA_I2C_BYTE_DATA);
    if (rc < 0) {
        pr_err("%s: unable to determine hw rev of sensor!\n", __func__);
        return rc;
    }

    pr_info("%s: success addr:0x%x hw:0x%x\n",
            __func__, s_ctrl->sensor_i2c_client->cci_client->sid,
            ov10820_hw_rev);
    return 0;
}
/* TBD: Need to revisit*/
static int32_t ov10820_write_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
		uint16_t gain, uint32_t line, int32_t luma_avg, uint16_t fgain)
{
	uint32_t fl_lines, offset;
	uint8_t int_time[3];

	fl_lines =
		(s_ctrl->curr_frame_length_lines * s_ctrl->fps_divider) / Q10;
	offset = s_ctrl->sensor_exp_gain_info->vert_offset;
	if (line > (fl_lines - offset))
		fl_lines = line + offset;

	fl_lines += (fl_lines & 0x1);

	int_time[0] = line >> 12;
	int_time[1] = line >> 4;
	int_time[2] = line << 4;

	if (allow_asic_control) {
		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
				s_ctrl->sensor_output_reg_addr->
				frame_length_lines, fl_lines,
				MSM_CAMERA_I2C_WORD_DATA);
		ov660_set_i2c_bypass(0);
		ov660_set_exposure_gain(gain, line);
		ov660_set_i2c_bypass(1);
	} else {
		s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
				s_ctrl->sensor_output_reg_addr->
				frame_length_lines, fl_lines,
				MSM_CAMERA_I2C_WORD_DATA);
		msm_camera_i2c_write_seq(s_ctrl->sensor_i2c_client,
				s_ctrl->sensor_exp_gain_info->
				coarse_int_time_addr, &int_time[0], 3);
		msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
				s_ctrl->sensor_exp_gain_info->
				global_gain_addr, gain,
				MSM_CAMERA_I2C_BYTE_DATA);
		s_ctrl->func_tbl->sensor_group_hold_off(s_ctrl);
		if (update_ov660_gain)
			ov660_set_exposure_gain2(gain, line);
	}

	return 0;
}
static int32_t ov10820_check_i2c_configuration(struct msm_sensor_ctrl_t *s_ctrl)
{
	int32_t rc = 0;
	uint16_t chipid = 0;


	ov660_set_i2c_bypass(0);

	rc = msm_camera_i2c_read(
			s_ctrl->sensor_i2c_client,
			s_ctrl->sensor_id_info->sensor_id_reg_addr, &chipid,
			MSM_CAMERA_I2C_BYTE_DATA);

	if (rc < 0) {
		pr_info("%s: I2C is configured through ASIC.\n", __func__);
		allow_asic_control = true;

		rc = ov660_add_blc_firmware(s_ctrl->sensor_i2c_addr);
		if (rc < 0)
			pr_err("%s: Unable to set blc firmware!\n", __func__);

	} else {
		pr_info("%s: I2C is configured around ASIC.\n", __func__);
		allow_asic_control = false;
		rc = ov660_use_work_around_blc();

		if (rc < 0)
			pr_err("%s: unable to set ov660 blc workaround!\n",
					__func__);

		rc = msm_camera_i2c_write_tbl(s_ctrl->sensor_i2c_client,
				ov10820_BLC_work_around_settings,
				ARRAY_SIZE(ov10820_BLC_work_around_settings),
				MSM_CAMERA_I2C_BYTE_DATA);
		if (rc < 0)
			pr_err("%s: unable to write 10MP blc workaround!\n",
					__func__);
	}

	ov660_set_i2c_bypass(1);
	return 0;
}
static int32_t ov10820_check_hw_rev(struct msm_sensor_ctrl_t *s_ctrl)
{
	int32_t rc = 0;

	ov660_set_i2c_bypass(1);

	rc = msm_camera_i2c_read(
			s_ctrl->sensor_i2c_client,
			0x302A, &revision, MSM_CAMERA_I2C_BYTE_DATA);
	if (rc < 0) {
		pr_err("%s: unable to read revision (%d)\n", __func__, rc);
	} else {
		pr_info("%s: revision is 0x%x\n", __func__, revision);
		if (revision == 0xB1) {
			pr_info("%s: new revision, using no BLC fix\n",
					__func__);
			allow_asic_control = false;
			return 0;
		}
	}

	return rc;
}
static int32_t ov10820_match_id(struct msm_sensor_ctrl_t *s_ctrl)
{
	int32_t rc = 0;
	uint16_t chipid = 0;
	struct msm_camera_sensor_info *info = s_ctrl->sensordata;

	if (!info->oem_data) {
		pr_err("%s: oem data NULL in sensor info, aborting",
				__func__);
		return -EINVAL;
	}

	if (ov660_check_probe() >= 0)
		ov660_exists = true;
	if (ov660_exists) {
		ov660_set_i2c_bypass(1);
		if (ov10820_ov660_rev_check == 0x1) {
			ov660_read_revision();
			/* Reset Flag automatically */
			ov10820_ov660_rev_check = 0x0;
			return -EINVAL;
		}
	}

	/* TODO Need to understand if better way to read chip id is
	 * by the OTP or by normal method per below */

	/*Read sensor id*/
	rc = msm_camera_i2c_read(
			s_ctrl->sensor_i2c_client,
			s_ctrl->sensor_id_info->sensor_id_reg_addr, &chipid,
			MSM_CAMERA_I2C_BYTE_DATA);
	if (rc >= 0)
		goto check_chipid;

	/* Need to re-assign i2c address to secondary address of the
	 * sensor to see if the part exists under the second address.
	 */
	s_ctrl->sensor_i2c_addr = OV10820_SECONDARY_I2C_ADDRESS;
	s_ctrl->sensor_i2c_client->client->addr = OV10820_SECONDARY_I2C_ADDRESS;
	rc = msm_camera_i2c_read(
			s_ctrl->sensor_i2c_client,
			s_ctrl->sensor_id_info->sensor_id_reg_addr, &chipid,
			MSM_CAMERA_I2C_BYTE_DATA);

	if (rc < 0) {
		pr_err("%s: read id failed\n", __func__);
		return rc;
	}

check_chipid:
	if (chipid != s_ctrl->sensor_id_info->sensor_id) {
		pr_err("%s: chip id %x does not match expected %x\n", __func__,
				chipid, s_ctrl->sensor_id_info->sensor_id);
		return -ENODEV;
	}

	ov10820_check_hw_rev(s_ctrl);

	if (ov660_exists) {
		ov660_initialize_10MP(revision);
		usleep(10000);
	}

	/* Need to determine when to apply BLC firmware fix
	 * or when to use the old method of blc work around fix */
	if (revision <= 0xB0)
		ov10820_check_i2c_configuration(s_ctrl);

	pr_debug("%s: success and using i2c address of: %x\n", __func__,
			s_ctrl->sensor_i2c_client->client->addr);

	ov10820_init_confs(s_ctrl);

	if ((!ov660_exists) &&
			(info->oem_data->sensor_allow_asic_bypass != 1)) {
		pr_err("%s: detected 10mp, but asic not working!\n",
				__func__);
		return -ENODEV;
	}

	ov660_set_i2c_bypass(1);
	rc = ov10820_read_otp(&ov10820_s_ctrl);
	if (rc < 0) {
		pr_err("%s: unable to read otp data!\n", __func__);
		ov10820_otp_info.size = 0;
	} else {
		ov10820_otp_info.otp_info = (uint8_t *)ov10820_otp;
		ov10820_otp_info.size = OV10820_OTP_SIZE;
	}
	ov10820_otp_info.asic_rev = info->oem_data->sensor_asic_revision;

	return 0;
}