以AF为例:
在vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/isp_xx/af_mgr/af_mgr.cpp
进行config的时候会调用GetCamCalCalData函数,
该原函数在文件:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/xxx/core/featureio/drv/cam_cal/cam_cal_drv.cpp
然后调用到:m32CamCalDataValidation= GetCameraCalData(i4CurrSensorId, (MUINT32*)pCamcalData);
该原函数在custom下:vendor/mediatek/proprietary/custom/xxx/hal/camera_3a/camera_custom_msdk.cpp
继续调用到:CAM_CALGetCalData(pGetSensorCalData);这里就正式跳转到处理eeprom数据的地方了
MTK平台对eeprom数据的读取调用解析在文件
vendor/mediatek/proprietary/custom/xxx/hal/imgsensor_src/camera_calibration_cam_cal.cpp
入口函数在CAM_CALGetCalData
对应这个函数的被调用是配置在vendor/mediatek/proprietary/custom/xxx/hal/imgsensor_src/sensorlist.cpp中的
例如:RAW_INFO(OV8856_SENSOR_ID, SENSOR_DRVNAME_OV8856_MIPI_RAW, CAM_CALGetCalData),
添加对应sensor的链接,说明该sensor支持otp
{//CALIBRATION_LAYOUT_SENSOR_OTP
0x00000001, 0x010b00ff, CAM_CAL_SINGLE_OTP_DATA,
{
{0x00000001, 0x00000000, 0x00000000, DoCamCalModuleVersion}, //CAMERA_CAM_CAL_DATA_MODULE_VERSION
{0x00000001, 0x00000005, 0x00000002, DoCamCalPartNumber}, //CAMERA_CAM_CAL_DATA_PART_NUMBER
{0x00000001, 0x00000017, 0x0000074C, DoCamCalSingleLsc}, //CAMERA_CAM_CAL_DATA_SHADING_TABLE
{0x00000001, 0x00000007, 0x0000000E, DoCamCal2AGain}, //CAMERA_CAM_CAL_DATA_3A_GAIN
{0x00000001, 0x00000763, 0x00000800, DoCamCalPDAF},
{0x00000001, 0x00000FAE, 0x00000550, DoCamCalStereoData} //CAMERA_CAM_CAL_DATA_STEREO_DATA
}
},
这个对应结构体:
typedef struct
{
UINT32 HeaderAddr; //Header Address
UINT32 HeaderId; //Header ID
UINT32 DataVer; ////new for 658x CAM_CAL_SINGLE_EEPROM_DATA, CAM_CAL_SINGLE_OTP_DATA,CAM_CAL_N3D_DATA
CALIBRATION_ITEM_STRUCT CalItemTbl[CAMERA_CAM_CAL_DATA_LIST];
} CALIBRATION_LAYOUT_STRUCT;
CAM_CALGetCalData会调用DoCamCalLayoutCheck(pGetSensorCalData)判断当前结构体是否是对应sensor的eeprom,若是则继续读取,若不是则跳过,继续下一组
这里DoCamCalLayoutCheck的具体操作就是,通过ioctl读取HeaderAddr地址的值,并于Header ID进行匹配,若相等则说明是我们需要的。
所以这里需要自己进行配置对应sensor的eeprom
typedef struct
{
UINT16 Include; //calibration layout include this item?
UINT32 StartAddr; // item Start Address
UINT32 BlockSize; //BlockSize
UINT32 (*GetCalDataProcess)(INT32 CamcamFID, UINT32 start_addr, UINT32 BlockSize,
UINT32* pGetSensorCalData);
//(INT32 CamcamFID, UINT32 start_addr, UINT32 BlockSize, UINT32* pGetSensorCalData);
} CALIBRATION_ITEM_STRUCT;
匹配成功后开始正式的eeprom数据读取工作:
result = CalLayoutTbl[LayoutType].CalItemTbl[lsCommand].GetCalDataProcess(
CamcamFID,
CalLayoutTbl[LayoutType].CalItemTbl[lsCommand].StartAddr,
CalLayoutTbl[LayoutType].CalItemTbl[lsCommand].BlockSize,
pGetSensorCalData);
这里就是通过pGetSensorCalData分别调用DoCamCalModuleVersion,DoCamCalSingleLsc,DoCamCal2AGain等等函数
具体调用哪个函数是通过lsCommand确定的,一般情况下MTK的架构是只读取2a和lsc
具体的读取规则以DoCamCal2AGain为例:
读取操作中的核心操作:
cam_calCfg.u4Offset = start_addr;
cam_calCfg.u4Length = BlockSize;
cam_calCfg.pu1Params = (u8 *)&pbuf;//0x0f
cam_calCfg.sensorID = pCamCalData->sensorID;
cam_calCfg.deviceID = pCamCalData->deviceID;
ioctlerr= ioctl(CamcamFID, CAM_CALIOC_G_READ, &cam_calCfg);
其中参数对应上面CALIBRATION_ITEM_STRUCT结构体,通过Include参数判断eeprom参数是否支持该模块
start_addr表示起始地址,BlockSize表示读取长度,pbuf表示读取到的数据存放地址
最终通过ioctl函数调到kernel实现读取操作。CAM_CALIOC_G_READ为读取操作,同时CAM_CALIOC_G_WRITE也可以进行写入操作。
在获取到eeprom对应数据后,在进行处理,这里也可以自己根据sensor数据进行修改,毕竟有些sensor 的eeprom数据格式并不符合MTK平台要求
ioctl由此进入kernel
kernel-4.9/drivers/misc/mediatek/cam_cal/src/common/v1/eeprom_driver.c
EEPROM_drv_ioctl函数接收CAM_CALIOC_G_READ指令并做出对应操作
其中最重点的操作就是:
一、pcmdInf = EEPROM_get_cmd_info_ex(ptempbuf->sensorID,
ptempbuf->deviceID);
EEPROM_get_cmd_info_ex通过EEPROM_get_cmd_info函数获取kernel对对应sensor eeprom的支持情况,
具体配置在/home/ts/jingci/kernel-4.9/drivers/misc/mediatek/cam_cal/src/xxx/cam_cal_list.c
{OV8856_SENSOR_ID, 0xA0, Common_read_region},
Common_read_region为默认调用函数,也可以根据需求自己客制化函数
二、 i4RetValue = pcmdInf->readCMDFunc(pcmdInf->client,
ptempbuf->u4Offset,
pu1Params,
ptempbuf->u4Length);
这里的readCMDFunc就是上面配置的Common_read_region函数,
Common_read_region原函数在kernel-4.9/drivers/misc/mediatek/cam_cal/src/common/v1/eeprom_i2c_common_driver.c
通过iReadData_CAM_CAL(addr, size, data)函数来读取数值
又调用到Read_I2C_CAM_CAL函数(这里基本就是单纯的数据处理于函数调用)
最终通过i2c获取到实际数据 i4RetValue = i2c_master_recv(g_pstI2CclientG,
(char *)a_puBuff, ui4_length);
这里获取到的数据就会存储到a_puBuff指针中,这里的指针也同时就是对应vender中传下来的cam_calCfg.pu1Params = (u8 *)&pbuf;
这样vendor就能获取到kernel读取的eeprom值了
另外还需要配置
kernel/arch/arm64/config/XXX_debug_config
kernel/arch/arm64/config/XXX_config
否则编译可能会报错