基于MTK平台的camera 移植总结

 1. 移植任务:实现 MTK 平台主副camera 移植

 2.  移植前的准备工作:

1)  MTK 平台手机一台,这里我们称作 P1

2)  获知MTK 的主副camera新片型号, 这里 P1 的前camera 为bf3703,后camera的型号为bf3920 //呵呵,比亚迪的便宜货

3)   厂商提供的 camera 驱动代码, 对于 每一款camera 都有两个同名的文件夹,为如 bf3703 对应的两个文件夹为bf3703_yuv分别存放的为 hal 层和 kernel 层的驱动代码; bf3920 的对应的两个同名文件夹为 bf3920_yuv这两个文件下的文件列表如下:

hal 层驱动代码目录: 
bf3920_yuv:

camera_info_bf3920_yuv.cpp
camera_info_bf3920_yuv.h
camera_sensor_para_bf3920_yuv.h
camera_tuning_para_bf3920_yuv.cpp
cfg_ftbl_bf3920_yuv.h
config.ftbl.bf3920_yuv.h
bf3703_yuv: 
camera_info_bf3703_yuv.cpp
camera_info_bf3703_yuv.h
camera_sensor_para_bf3703_yuv.h
camera_tuning_para_bf3703_yuv.cpp
config.ftbl.bf3703_yuv.
kernel 层驱动代码: 
bf3920_yuv: 
feature_bf3920_yuv.cpp
bf3920yuv_CameraCustomized.h
bf3920yuv_Camera_Sensor_para.h
bf3920_yuv_Sensor.c
bf3920yuv_Sensor.h
bf3703_yuv: 
bf3703_yuv_CameraCustomized.h
bf3703_yuv_Camera_Sensor_para.h
bf3703_yuv_Sensor.c
bf3703_yuv_Sensor.h

注意:

(1)不要想当然认为camera 代码目录就是 camera name+_yuv ,有些支持 mipi 或者其他接口的camera 驱动目录就不是这样,如camera ov5645 的驱动目录ov5645_mipi_yuv 

(2)如果代码需要保证低耦合性,最好将驱动代码拷贝至mediatek/custom/ v2_e324_2ggsm4_wvga_t62d/hal/imgsensor和 mediatek/custom/common/kernel/imgsensor/

4) MTK 提供的系统开发平台代码,我这里提供的是mtk6572 的一套代码,这里简称V2

3.      移植步骤:

1)  裁剪模块:

/* v2_e324_2ggsm4_wvga_t62d 为项目新建的工程目录 */

①  进入文件 mediatek/config/v2_e324_2ggsm4_wvga_t62d/ProjectConfig.mk  查看:

 /* 添加摄像头模块,定义hal 层,以下四个选项 bf3920_yuv sp0718_yuv 

为我们手机的camera 驱动模块,其余两个为其他手机项目的需要添加的

驱动代码模块*/

 CUSTOM_HAL_IMGSENSOR=bf3920_yuv sp0718_yuvsp0a19_yuv bf3703_yuv

/*在hal 层添加主摄像头(后置摄像头)*/

CUSTOM_HAL_MAIN_IMGSENSOR = bf3920_yuv sp0718_yuv

/*在hal 层添加副摄像头(前置摄像头)*/

CUSTOM_HAL_SUB_IMGSENSOR = sp0a19_yuv bf3703_yuv

/* 添加摄像头模块,定义kernel 层,以下四个选项bf3920_yuv sp0718_yuv 

为我们手机的camera 驱动模块,其余两个为其他手机项目的需要添加的

驱动代码模块*/

CUSTOM_KERNEL_IMGSENSOR =bf3920_yuv sp0718_yuv sp0a19_yuv bf3703_yuv

/*在kernel层添加主摄像头(后置摄像头)*/

CUSTOM_KERNEL_MAIN_IMGSENSOR = bf3920_yuv sp0718_yuv

/*在kernel层添加副摄像头(前置摄像头)*/

CUSTOM_KERNEL_SUB_IMGSENSOR = sp0a19_yuv bf3703_yuv

注意: 上述操作中 模块的名称千万不要随意填写,一定要和厂商提供的驱动代码目录一致; 主副摄像头也不能填写错误,要区分开来,不能填错位,主副 camera 的区分可以根据像素来判断,一般高像素的作为主camera ,低像素的作为副camera ,当然也有例外,最好的区分方式就是看你的硬件。

 /* hal层的副摄像头自动对焦设置*/

 CUSTOM_HAL_LENS= dummy_lens  dummy_lens dummy_lens

  /* hal层的主摄像头自动对焦设置*/   

CUSTOM_HAL_MAIN_LENS=dummy_lens

/* kernel层的副摄像头自动对焦设置*/

 CUSTOM_KERNEL_LENS=dummy_lens dummy_lens dummy_lens

/* kernel层的副摄像头自动对焦设置*/

CUSTOM_KERNEL_MAIN_LENS=dummy_lens

注意:如果移植的摄像头没有自动对焦(AF)功能就必须将默认的AF功能屏蔽掉(否则在DMA操作数据的时候很多的算法受影响,将在切换的时候很卡)!

 

2)  将厂商提供的 camera 驱动代码,分别到…hal/imgesensor 和…kernel/imgesensor 目录下,拷贝后如下,

在路径mediatek/custom/common/hal/imgsensor/下:


在路径mediatek/custom/common/kernel/imgsensor/下:

基于MTK平台的camera 移植总结_第1张图片


3)  注册需要添加的摄像头信息

①  打开文件 custom/common/hal/imgsensor/src/sensorlist.cpp

//MSDK_SENSOR_INIT_FUNCTION_STRUCT SensorList[MAX_NUM_OF_SUPPORT_SENSOR] =
MSDK_SENSOR_INIT_FUNCTION_STRUCTSensorList[] =
{
…
#if defined(BF3920_YUV)  // main sensor 定义在前面
    YUV_INFO(BF3920_SENSOR_ID, SENSOR_DRVNAME_BF3920_YUV,NULL),
#endif
 
#if defined(BF3703_YUV)
    YUV_INFO(BF3703_SENSOR_ID, SENSOR_DRVNAME_BF3703_YUV,NULL),
#endif
…
};

②  打开文件 custom/common/kernel/imgsensor/inc/kd_imgsensor.h

添加定义如下:

#defineBF3703_SENSOR_ID                      0x3703 
#define BF3A03_SENSOR_ID                     0x3a03
#defineBF3920_SENSOR_ID                      0x3920
#defineSENSOR_DRVNAME_BF3920_YUV  "bf3920yuv"
#define SENSOR_DRVNAME_BF3A03_YUV   "bf3a03yuv"
#defineSENSOR_DRVNAME_BF3703_YUV   "bf3703yuv"

注意:上述定义的ID 值实在厂商提供的datasheet 中得到的  

上述定义,将会在以下驱动文件中调用:

文件mediatek/custom/common/kernel/imgsensor/bf3703_yuv/bf3703_yuv_Sensor.c

基于MTK平台的camera 移植总结_第2张图片

在文件mediatek/custom/common/hal/imgsensor/bf3703_yuv/config.ftbl.bf3703_yuv.h中

③  为系统提供调用的API

UINT32BF3920_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc);
UINT32BF3A03_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc);
UINT32BF3703_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc);
//! Add Sensor Init function here
//! Note:
//! 1. Add by the resolution from""large to small"", due to large sensor
//!   will be possible to be main sensor.
//!   This can avoid I2C error during searching sensor.
//!2.This file should be the same as mediatek\custom\common\hal\imgsensor\src\sensorlist.cpp
ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1]={
   ….
#if defined(BF3920_YUV)
{BF3920_SENSOR_ID,SENSOR_DRVNAME_BF3920_YUV,BF3920_YUV_SensorInit},
#endif
#if defined(BF3703_YUV)
{BF3703_SENSOR_ID,SENSOR_DRVNAME_BF3703_YUV,BF3703_YUV_SensorInit},
#endif
….
/*  ADD sensor driver beforethis line */
{0,{0},NULL},//end of list
  };

注意:上述kdSensorList 的元素定义顺序必须和① 中的SensorList 的元素定义保持一致,并且主camera 要放在前面,副 camera 放在后面如下图:

基于MTK平台的camera 移植总结_第3张图片


④camera 上电和掉电 

   以下是 上电代码,路径为:  mediatek/custom/v2_e324_2ggsm4_wvga_t62d/kernel/camera/camera/kd_camera_hw.c,其实上电代码移植很简单,我们只需要将 其它类似的camera 上电拷贝过来即可,你可以考虑像素接近的camera 上电代码 比如:如果你需要移植前摄,

你可以移植 sp0a18,gc0312,sp0a19等 //上电移植过程不可能保证百分百成功,如果失败就得参考datasheet   

else if (currSensorName && (0 == strcmp(SENSOR_DRVNAME_SP2518_YUV,currSensorName))) //这一行为内核 遍历 camera 过程,只需将sensor 驱动名字改为要移植的camera 名字即可 

  { 

            K_DBG("[CAMERA SENSOR] kdCISModulePowerOn get in---SENSOR_DRVNAME_SP2518_YUV sensorIdx:%d; pinSetIdx=%d\n",SensorIdx, pinSetIdx);


            if(TRUE != hwPowerOn(CAMERA_POWER_VCAM_A, VOL_2800,mode_name))
            {
                PK_DBG("[CAMERA SENSOR] Fail to enable analog power\n");
                //return -EIO;
                goto _kdCISModulePowerOn_exit_;
            }
	   
            if(TRUE != hwPowerOn(CAMERA_POWER_VCAM_D2, VOL_1800/*VOL_2800*/,mode_name))
            {
                PK_DBG("[CAMERA SENSOR] Fail to enable digital power\n");
                //return -EIO;
                goto _kdCISModulePowerOn_exit_;
            }
            else
                PK_DBG("[poweron] enable CAMERA_POWER_VCAM_D2\n");	 
	
            if(TRUE != hwPowerOn(CAMERA_POWER_VCAM_D, VOL_1800,mode_name))
            {
                PK_DBG("[CAMERA SENSOR] Fail to enable digital power\n");
                //return -EIO;
                goto _kdCISModulePowerOn_exit_;
            }
            
            //PDN/STBY pin
            if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN])  
            {
                if(mt_set_gpio_mode(pinSet[pinSetIdx][IDX_PS_CMPDN],pinSet[pinSetIdx][IDX_PS_CMPDN+IDX_PS_MODE])){PK_DBG("[CAMERA LENS] set gpio mode failed!! \n");}
                if(mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMPDN],GPIO_DIR_OUT)){PK_DBG("[CAMERA LENS] set gpio dir failed!! \n");}
                if(mt_set_gpio_out(pinSet[pinSetIdx][IDX_PS_CMPDN],pinSet[pinSetIdx][IDX_PS_CMPDN+IDX_PS_OFF])){PK_DBG("[CAMERA LENS] set gpio failed!! \n");}
                msleep(10);
                if(mt_set_gpio_out(pinSet[pinSetIdx][IDX_PS_CMPDN],pinSet[pinSetIdx][IDX_PS_CMPDN+IDX_PS_ON])){PK_DBG("[CAMERA LENS] set gpio failed!! \n");}
                msleep(5);
                if(mt_set_gpio_out(pinSet[pinSetIdx][IDX_PS_CMPDN],pinSet[pinSetIdx][IDX_PS_CMPDN+IDX_PS_OFF])){PK_DBG("[CAMERA LENS] set gpio failed!! \n");}
                msleep(5);
                
                //RST pin
                if(mt_set_gpio_mode(pinSet[pinSetIdx][IDX_PS_CMRST],pinSet[pinSetIdx][IDX_PS_CMRST+IDX_PS_MODE])){PK_DBG("[CAMERA SENSOR] set gpio mode failed!! \n");}
                if(mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMRST],GPIO_DIR_OUT)){PK_DBG("[CAMERA SENSOR] set gpio dir failed!! \n");}
                if(mt_set_gpio_out(pinSet[pinSetIdx][IDX_PS_CMRST],pinSet[pinSetIdx][IDX_PS_CMRST+IDX_PS_OFF])){PK_DBG("[CAMERA SENSOR] set gpio failed!! \n");}
                mdelay(10);
                if(mt_set_gpio_out(pinSet[pinSetIdx][IDX_PS_CMRST],pinSet[pinSetIdx][IDX_PS_CMRST+IDX_PS_ON])){PK_DBG("[CAMERA SENSOR] set gpio failed!! \n");}
                mdelay(5);
            }
       
            //disable inactive sensor
            if(pinSetIdx == 0) {//disable sub
                pinSetIdxTmp = 1;
            }
            else{
                pinSetIdxTmp = 0;
            }

            if (GPIO_CAMERA_INVALID != pinSet[pinSetIdxTmp][IDX_PS_CMRST]) {
                if(mt_set_gpio_mode(pinSet[pinSetIdxTmp][IDX_PS_CMRST],pinSet[pinSetIdxTmp][IDX_PS_CMRST+IDX_PS_MODE])){PK_DBG("[CAMERA SENSOR] set gpio mode failed!! \n");}
                if(mt_set_gpio_mode(pinSet[pinSetIdxTmp][IDX_PS_CMPDN],pinSet[pinSetIdxTmp][IDX_PS_CMPDN+IDX_PS_MODE])){PK_DBG("[CAMERA LENS] set gpio mode failed!! \n");}
                if(mt_set_gpio_dir(pinSet[pinSetIdxTmp][IDX_PS_CMRST],GPIO_DIR_OUT)){PK_DBG("[CAMERA SENSOR] set gpio dir failed!! \n");}
                if(mt_set_gpio_dir(pinSet[pinSetIdxTmp][IDX_PS_CMPDN],GPIO_DIR_OUT)){PK_DBG("[CAMERA LENS] set gpio dir failed!! \n");}
                if(mt_set_gpio_out(pinSet[pinSetIdxTmp][IDX_PS_CMRST],pinSet[pinSetIdxTmp][IDX_PS_CMRST+IDX_PS_OFF])){PK_DBG("[CAMERA SENSOR] set gpio failed!! \n");} //low == reset sensor
                if(mt_set_gpio_out(pinSet[pinSetIdxTmp][IDX_PS_CMPDN],pinSet[pinSetIdxTmp][IDX_PS_CMPDN+IDX_PS_OFF])){PK_DBG("[CAMERA LENS] set gpio failed!! \n");} //high == power down lens module
            }          
       }

 以下为 掉电带,代码:

 if(currSensorName && (0 == strcmp(SENSOR_DRVNAME_SP2518_YUV,currSensorName)))
        {
            msleep(5);


            if(mt_set_gpio_out(pinSet[pinSetIdx][IDX_PS_CMPDN],pinSet[pinSetIdx][IDX_PS_CMPDN+IDX_PS_OFF])){PK_DBG("[CAMERA LENS] set gpio failed!! \n");}
            if(mt_set_gpio_out(pinSet[pinSetIdx][IDX_PS_CMRST],pinSet[pinSetIdx][IDX_PS_CMRST+IDX_PS_OFF])){PK_DBG("[CAMERA SENSOR] set gpio failed!! \n");}
            if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST]) 
            {
                //PDN pin
                if(mt_set_gpio_mode(pinSet[pinSetIdx][IDX_PS_CMPDN],pinSet[pinSetIdx][IDX_PS_CMPDN+IDX_PS_MODE])){PK_DBG("[CAMERA LENS] set gpio mode failed!! \n");}
                if(mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMPDN],GPIO_DIR_OUT)){PK_DBG("[CAMERA LENS] set gpio dir failed!! \n");}
                if(mt_set_gpio_out(pinSet[pinSetIdx][IDX_PS_CMPDN],pinSet[pinSetIdx][IDX_PS_CMPDN+IDX_PS_ON])){PK_DBG("[CAMERA LENS] set gpio failed!! \n");}  //sym modify
                msleep(3);


                //RST pin
                if(mt_set_gpio_mode(pinSet[pinSetIdx][IDX_PS_CMRST],pinSet[pinSetIdx][IDX_PS_CMRST+IDX_PS_MODE])){PK_DBG("[CAMERA SENSOR] set gpio mode failed!! \n");}
                if(mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMRST],GPIO_DIR_OUT)){PK_DBG("[CAMERA SENSOR] set gpio dir failed!! \n");}
                if(mt_set_gpio_out(pinSet[pinSetIdx][IDX_PS_CMRST],pinSet[pinSetIdx][IDX_PS_CMRST+IDX_PS_OFF])){PK_DBG("[CAMERA SENSOR] set gpio failed!! \n");}
                msleep(3);
            }   
       
            MainCameraDigtalPowerCtrl(0);
     
            if(TRUE != hwPowerDown(CAMERA_POWER_VCAM_A,mode_name)) {
                PK_DBG("[CAMERA SENSOR] Fail to OFF analog power\n");
                //return -EIO;
                goto _kdCISModulePowerOn_exit_;
            }
  
            if(TRUE != hwPowerDown(CAMERA_POWER_VCAM_D2,mode_name))
            {
                PK_DBG("[CAMERA SENSOR] Fail to enable analog power\n");
                //return -EIO;
                goto _kdCISModulePowerOn_exit_;
            }
            if(TRUE != hwPowerDown(CAMERA_POWER_VCAM_D, mode_name)) {
                PK_DBG("[CAMERA SENSOR] Fail to OFF digital power\n");
                //return -EIO;
                goto _kdCISModulePowerOn_exit_;
            }  
        }
        else
        {
            mt_set_gpio_mode(GPIO_CAMERA_CMPDN1_PIN, GPIO_CAMERA_CMPDN1_PIN_M_GPIO);
            mt_set_gpio_dir(GPIO_CAMERA_CMPDN1_PIN, GPIO_DIR_OUT);
            mt_set_gpio_out(GPIO_CAMERA_CMPDN1_PIN, GPIO_OUT_ONE);


            mt_set_gpio_mode(GPIO_CAMERA_CMPDN_PIN, GPIO_CAMERA_CMPDN_PIN_M_GPIO);
            mt_set_gpio_dir(GPIO_CAMERA_CMPDN_PIN, GPIO_DIR_OUT);
            mt_set_gpio_out(GPIO_CAMERA_CMPDN_PIN, GPIO_OUT_ONE);


            //RST pin
            mt_set_gpio_mode(GPIO_CAMERA_CMRST1_PIN, GPIO_CAMERA_CMRST1_PIN_M_GPIO);
            mt_set_gpio_dir(GPIO_CAMERA_CMRST1_PIN, GPIO_DIR_OUT);
            mt_set_gpio_out(GPIO_CAMERA_CMRST1_PIN, GPIO_OUT_ONE);
            msleep(5);
            mt_set_gpio_out(GPIO_CAMERA_CMRST1_PIN, GPIO_OUT_ZERO);
            
            //if (currSensorName && (0 == strcmp(SENSOR_DRVNAME_S5K4ECGX_MIPI_YUV,currSensorName)))
            {
                MainCameraDigtalPowerCtrl(0);
            }


            if(TRUE != hwPowerDown(CAMERA_POWER_VCAM_D, mode_name)) {
                PK_DBG("[CAMERA SENSOR] Fail to OFF digital power\n");
                //return -EIO;
                goto _kdCISModulePowerOn_exit_;
            }


            if(TRUE != hwPowerDown(CAMERA_POWER_VCAM_A,mode_name)) {
                PK_DBG("[CAMERA SENSOR] Fail to OFF analog power\n");
                //return -EIO;
                goto _kdCISModulePowerOn_exit_;
            }


            if(TRUE != hwPowerDown(CAMERA_POWER_VCAM_D2,mode_name))
            {
                PK_DBG("[CAMERA SENSOR] Fail to enable analog power\n");
                //return -EIO;
                goto _kdCISModulePowerOn_exit_;
            }


            if(TRUE != hwPowerDown(CAMERA_POWER_VCAM_A2,mode_name))
            {
                PK_DBG("[CAMERA SENSOR] Fail to enable analog power\n");
                //return -EIO;
                goto _kdCISModulePowerOn_exit_;
            }
        }
    }

以下为一款camera 的上电和掉电图,仅作参考: 

基于MTK平台的camera 移植总结_第4张图片

上电时序


基于MTK平台的camera 移植总结_第5张图片

掉电时序

⑤ 到此为止,配置已经完毕,如果还有问题,很可能是由于驱动代码的问题,因为

厂商提供的驱动不是百分百马上移植就可以用的,出现错误,就要结合自己的硬件平台和camera 的datasheet 对驱动代码做出更改,如果还是解决不了就得找 FAE 了。

编译,烧写,调试

因为整个移植过程我们主要更改了 hal、kernel 目录下的代码,因此我们可以使用快速编译: ./mk v2_e324_2ggsm4_wvga_t62d r lk k bootimage ;接着最后一步,打开falshtools à Scatter-loadingà Mt6572_Android_scatter.txt 加载生成的镜像文件à 手机断电冷启动à 等待烧入(大概1min),之后,拔掉 USB开机,打开camera APK , 可以

拍照,测试 前后camera 


 

 

你可能感兴趣的:(02_Android,手机开发)