做项目的时候,经常会遇到新物料导入,我们一般叫二供,换了一家供应商,换不换供应商,我们这些做技术的小喽啰说了不算。当然大家都知道,这个和公司的采购强相关,当然和采购的老大更是密不可分.........................听说某大厂的采购老大,在深圳已经买了好几套房子了。当然,我们做好这颗料的兼容就行了,下面介绍一下高通8909平台(可以当古董拍卖的平台)如何兼容一颗新的camera。
\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;
}
贴了一大段代码,解释一下,这个兼容方案是同一颗sensor,不同模组厂。也就是说芯片是一样的,模组厂不一样,那怎么区分一供和二供呢,就是通过模组厂烧录的mocule_id不同过来区分,为什么可以通过module_id来区分呢?思考一下,因为我们的sensor是一样的,但是sensor里面的很多寄存器的值都烧录的不一样,所以我们可以读取烧录的不一样的寄存器,一般我们都是来读取module_id不同的这个寄存器来区分的,上面那些添加的东西,都是dtsi文件里面读取otp,sensor厂规范好的。
eeprom_spyro1: qcom,eeprom@1 {
cell-index = <1>;
reg = <0x1>;
qcom,eeprom-name = "sunny_8865";
compatible = "qcom,eeprom";
qcom,slave-addr = <0x6c>;
qcom,cci-master = <0>;
qcom,num-blocks = <8>;
qcom,page0 = <1 0x0100 2 0x01 1 1>;
qcom,poll0 = <0 0x0 2 0x0 1 0>;
qcom,mem0 = <0 0x0 2 0x0 1 0>;
qcom,page1 = <1 0x5002 2 0x00 1 0>;
qcom,poll1 = <0 0x0 2 0x0 1 0>;
qcom,mem1 = <0 0x0 2 0x0 1 0>;
qcom,page2 = <1 0x3d84 2 0xc0 1 0>;
qcom,poll2 = <0 0x0 2 0x0 1 0>;
qcom,mem2 = <0 0x0 2 0x0 1 0>;
qcom,page3 = <1 0x3d88 2 0x70 1 0>;
qcom,poll3 = <0 0x0 2 0x0 1 0>;
qcom,mem3 = <0 0x0 2 0x0 1 0>;
qcom,page4 = <1 0x3d89 2 0x10 1 0>;
qcom,poll4 = <0 0x0 2 0x0 1 0>;
qcom,mem4 = <0 0x0 2 0x0 1 0>;
qcom,page5 = <1 0x3d8a 2 0x70 1 0>;
qcom,poll5 = <0 0x0 2 0x0 1 0>;
qcom,mem5 = <0 0x0 2 0x0 1 0>;
qcom,page6 = <1 0x3d8b 2 0xf4 1 0>;
qcom,poll6 = <0 0x0 2 0x0 1 0>;
qcom,mem6 = <0 0x0 2 0x0 1 0>;
qcom,page7 = <1 0x3d81 2 0x01 1 10>;
qcom,poll7 = <0 0x0 2 0x0 1 1>;
qcom,mem7 = <1536 0x7010 2 0 1 0>;
cam_vdig-supply = <&pm660_l3>;
cam_vana-supply = <&pm660_l7>;
cam_vio-supply = <&pm660_l6>;
cam_vaf-supply = <&pm660_l17>;
qcom,cam-vreg-name = "cam_vdig", "cam_vio",
"cam_vana", "cam_vaf";
qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
qcom,cam-vreg-max-voltage = <1200000 0 2800000 3200000>;
qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk2_default
&cam_sensor_front1_default>;
pinctrl-1 = <&cam_sensor_mclk2_sleep
&cam_sensor_front1_sleep>;
gpios = <&tlmm 28 0>,
<&tlmm 40 0>,
<&tlmm 39 0>;
qcom,gpio-reset = <1>;
qcom,gpio-standby = <2>;
qcom,gpio-req-tbl-num = <0 1 2>;
qcom,gpio-req-tbl-flags = <1 0 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
"CAM_RESET2",
"CAM_STANDBY2";
qcom,cam-power-seq-type = "sensor_vreg", "sensor_vreg",
"sensor_vreg",
"sensor_gpio", "sensor_gpio" , "sensor_clk";
qcom,cam-power-seq-val = "cam_vdig", "cam_vana", "cam_vio",
"sensor_gpio_reset", "sensor_gpio_standby",
"sensor_cam_mclk";
qcom,cam-power-seq-cfg-val = <1 1 1 1 1 24000000>;
qcom,cam-power-seq-delay = <1 1 1 30 30 5>;
status = "ok";
clocks = <&clock_gcc clk_mclk2_clk_src>,
<&clock_gcc clk_gcc_camss_mclk2_clk>;
clock-names = "cam_src_clk", "cam_clk";
qcom,clock-rates = <19200000 0>;
};
这样子就区分开来了。