高通 camera 多模组兼容

背景知识

OTP 基本概念

Camera Module一般会采取两种方式来记录该Sensor的一些信息,一种是OTP(One Time Programmable),另外一种是EEPROM (Electrically Erasable Programmable Read - Only Memory)。

OTP存储器的类型

  1. OTP数据烧录在sensor的寄存器中。
  2. OTP数据烧录在EEPROM中:EEPROM是指带电可擦可编程只读存储器,是一种掉电后数据不丢失的存储芯片。

OTP的作用

保证效果一致性, 模组厂会挑选一部分模组作为golden,然后将其他模组的相应参数校准到和这些golden一样

OTP的数据

OTP烧录的数据类型 一般包括:

AF:自动对焦校准数据
AWB:白平衡校准数据
LSC:镜头阴影校准 (Lens Shading Calibration)
Moudle Info:模组信息,包含模组的生产年月日,模组ID等

兼容的思路

利用OTP中的module info 来区分不同的模组

举例 OTP烧录在sensor寄存器

  1. sensor 寄存器说明
    OTP寄存器的说明2. OTP 读写规则
    OTP读写规则3. OTP读写 参考
    读写参考代码

进行兼容

利用读出的OTP数据中的module info 进行区分


\kernel\drivers\media\platform\msm\camera_v2\sensor\msm_sensor.c



int msm_sensor_match_id(struct msm_sensor_ctrl_t *s_ctrl)
{
  int rc = 0;
  uint16_t chipid = 0;
  uint16_t module_id = -1;
  struct msm_camera_i2c_client *sensor_i2c_client;
  struct msm_camera_slave_info *slave_info;
  const char *sensor_name;
   
  if (!s_ctrl) {
      pr_err("%s:%d failed: %pK\n",
          __func__, __LINE__, s_ctrl);
      return -EINVAL;
  }
  sensor_i2c_client = s_ctrl->sensor_i2c_client;
  slave_info = s_ctrl->sensordata->slave_info;
  sensor_name = s_ctrl->sensordata->sensor_name;

  if (!sensor_i2c_client || !slave_info || !sensor_name) {
      pr_err("%s:%d failed: %pK %pK %pK\n",
          __func__, __LINE__, sensor_i2c_client, slave_info,
          sensor_name);
      return -EINVAL;
  }
  rc = sensor_i2c_client->i2c_func_tbl->i2c_read(
      sensor_i2c_client, slave_info->sensor_id_reg_addr,
      &chipid, MSM_CAMERA_I2C_WORD_DATA);
  if (rc < 0) {
      pr_err("LIWANCHAO %s: %s: read id failed\n", __func__, sensor_name);
      return rc;
  }
  pr_err("LIWANCHAO,%s: line = %d,%s,read id: 0x%x expected id 0x%x:\n",
          __func__, __LINE__,sensor_name, chipid, slave_info->sensor_id);
  
  //add by liwanchao satrt
  if(!strcmp(sensor_name, "ov5675_truly") || !strcmp(sensor_name, "ov5675_back"))
  {
      pr_err("LIWANCHAO,%s,%d,%s,\n",__func__,__LINE__,sensor_name);
      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x0100,
              0x01, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x5001,
              0x02, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x3d84,
              0xc0, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x3d88,
              0x70, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x3d89,
              0x10, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otP_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x3d8a,
              0x72, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x3d8b,
              0x0e, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x3d81,
              0x01, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_read(
              sensor_i2c_client, 0x7011,
              &module_id, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0)
      {
          pr_err("%s: %s: read module_id failed\n", __func__, sensor_name);
          return rc;
      }
      
      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x5001,
              0x0a, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x0100,
              0x00, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }
  }

/*pr_err("LIWANCHAO module_id = 0x%x\n", module_id );
  
  if( module_id == 0x4)//gz
  {
      chipid = 0x5675;
      pr_err("this is gz,module_id = 0x%x,\n", module_id );
  }
  else if( module_id == 0x2 )//truly
  {
      chipid += 1;
      pr_err("this is truly,module_id = 0x%x,\n", module_id );
  }*/
  
  
  if(!strcmp(sensor_name, "ov8856_i18") || !strcmp(sensor_name, "ov8856_i18_truly"))
  {
      pr_err("LIWANCHAO,%s,%d,%s,\n",__func__,__LINE__,sensor_name);
      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x0100,
              0x01, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x5001,
              0x02, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x3d84,
              0xc0, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x3d88,
              0x70, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x3d89,
              0x10, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otP_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x3d8a,
              0x72, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x3d8b,
              0x0a, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x3d81,
              0x01, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_read(
              sensor_i2c_client, 0x7011,
              &module_id, MSM_CAMERA_I2C_BYTE_DATA);//在这里通过读取寄存器0x7011的值,把读取到的值放到module_id里面,通过查看otp map,可以知道这个地址是用来存module_id的。
      if (rc < 0)
      {
          pr_err("%s: %s: read module_id failed\n", __func__, sensor_name);
          return rc;
      }
      
      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x5001,
              0x0a, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }

      rc = sensor_i2c_client->i2c_func_tbl->i2c_write(
              sensor_i2c_client, 0x0100,
              0x00, MSM_CAMERA_I2C_BYTE_DATA);
      if (rc < 0) {
          pr_err("%s: %s: otp_read id failed\n", __func__, sensor_name);
          return rc;
      }
  }
  
  pr_err("LIWANCHAO module_id = 0x%x\n", module_id );
  
  if( module_id == 0x4)//gz
  {
      if(chipid == 0x885a)//后摄
      {
          pr_err("this is ov8856 gz,module_id = 0x%x,\n", module_id );
      }
      else if(chipid == 0x5675 )//前摄
      {
          pr_err("this is ov5675 gz,module_id = 0x%x,\n", module_id );
      }
  }
  else if( module_id == 0x2 )//truly
  {
      if(chipid == 0x885a)//后摄
      {
          chipid += 1; 
          pr_err("this is ov8856 truly,module_id = 0x%x,\n", module_id );
      }
      else if(chipid == 0x5675 )//前摄
      {
          chipid += 1;
          pr_err("this is ov5675 truly,module_id = 0x%x,\n", module_id );
      }
  }
  //add by liwanchao end
  
  
  if (msm_sensor_id_by_mask(s_ctrl, chipid) != slave_info->sensor_id) {
      pr_err("%s chip id %x does not match %x\n",
              __func__, chipid, slave_info->sensor_id);
      return -ENODEV;
  }
  
  return rc;
}

总结

利用OTP兼容 第一个要能够根据读出OTP数据。 第二个是要跟模组厂沟通好 有唯一性的数据来进行区分

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值