MTK camera eeprom

以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

否则编译可能会报错

你可能感兴趣的:(android_camera)