Camera(4)MTK代码跟读

一、Camera软件架构

主要包含三个部分的介绍:

1)Android Camera 架构:Android系统原生架构简要介绍.

2)Mediatek Android Camera架构: 简要介绍Mediatek平台在Android系统基础上Camera 的架构.

3)Camera data path: 介绍在平台端Camera的数据流.

1.下图为Android Camera 架构

Camera根据Android 架构从上至下可分为

    1)Applications: 最上层的应用,编译后生成Camera  APK;

    2)Application Framework: 主要为Applications提供API;

    3)JNI: 使Application Framework和Libraries可交互;

    4)Libraries: 包括Camera Framework和Camera Service(camera service和camera client);

    5)HAL: 硬件抽象层, 用来链接driver和 Camera Service;

    6)Kernel: image sensor driver的实作.其中2)~4)的部分基本为Android原生的架构和code,Mediatek会有一些拓展,而HAL和Kernel层为Mediatek主要实作的部分,Camera APK是Mediatek基于Android 原生Camera APK修改的应用.

2.下图为MT6589/82/72/92/88平台基于Android架构上,Camera从application到kernel层详细的架构.

1)蓝色部分主要由Java实现(偏向应用层)、黄色为JNI实现(C++,衔接Java层和Native层), 绿色由C++实现(通常称为Native层),而枣红色为C实现(Kernel 层).

2) HAL libraries为Mediatek在HAL层的实现,主要分Camera HAL和Camera Core两大部分.Camera HAL衔接Camera Service并响应它的需求,实现各个feature的scenario; 而Camera Core提供平台一些通用的数据流控制接口.

3.最后这部分为Camera的数据流简要介绍

说明:

1) TG(Timing Generate):从sensor获取数据,并送给ISP处理.

2) Platform Data Processor: 包括平台在后端对图像数据进行resize、rotate、flip、format convert等处理.它可以同时有两个buffer输出.

总结:

Kernel部分:

  • image sensor driver,负责具体型号的sensor的id检测,上电,以及在preview、capture、初始化、3A等等功能设定时的寄存器配置;
  • isp driver,通过DMA将sensor数据流上传;

hal部分:

  • imageio,主要负责数据buffer上传的pipe
  • drv,包含imgsensor和isp的hal层控制;
  • feature io,包含各种3A等性能配置;

二、camera调用过程

        imgsensor起到承上启下的作用,在系统起来时会创建整个camera驱动运行的环境,其中主要的文件和函数如下框图所示,先设备挂载时会调用注册platform设备platform_driver_register,在匹配成功后会调用probe函数进行初始相关的设备:

一、平台驱动注册

文件路径:

kernel-$(KernelVersion)/drivers/misc/mediatek/imgsensor/src/common/v_$(Version)/imgsensor.c

kernel-$(KernelVersion)/drivers/misc/mediatek/imgsensor/src/common/v_$(Version)/imgsensor_proc.c

kernel-$(KernelVersion)/drivers/base/platform.c

kernel-$(KernelVersion)/include/linux/of_device.h

注:v_$(Version)版本信息根据平台确认,上级目录src/Makefile中有定义。

        camera 驱动先是注册 platform 平台驱动,然后注册Camera字符设备,创建class类,再通过 I2c 注册前后摄注册字符设备,封装底层方法 imgsensor_ioctl,上层访问底层驱动时候先是使用 setdriver 获取具体IC的驱动的入口,然后使用 checkisalive 对 sensorlist 中的 IC 进行上电,上电完成就通过 I2C 读取设备 ID ,到此为止,上层应用与底层驱动挂接完成,紧接着就是预览和拍照,具体 IC 驱动的实现了。这里介绍v1_1版本,mt6771平台。

module_init

设备加载 module_init加载模块,注册platform总线驱动

#ifdef CONFIG_OF
static const struct of_device_id gimgsensor_of_device_id[] = {
    {.compatible = "mediatek,imgsensor",},
    {}
};
#endif

static struct platform_driver gimgsensor_platform_driver = {
    .probe   = imgsensor_probe,
    .remove  = imgsensor_remove,
    .suspend = imgsensor_suspend,
    .resume  = imgsensor_resume,
    .driver  = {
           .name  = "image_sensor",
           .owner = THIS_MODULE,
#ifdef CONFIG_OF
           .of_match_table = gimgsensor_of_device_id,
#endif
        }
};
/*与设备树节点中 compatible = "mediatek,imgsensor" 属进行匹配,匹配成功后调用 imgsensor_probe函数*/

static int imgsensor_probe(struct platform_device *pplatform_device)
{
    struct IMGSENSOR *pimgsensor = &gimgsensor;
    struct IMGSENSOR_HW *phw = &pimgsensor->hw;
    struct device *pdevice;

    /* Register char driver */
    if (alloc_chrdev_region(&pimgsensor->dev_no, 0, 1,
            IMGSENSOR_DEV_NAME)) {
        PK_DBG("[CAMERA SENSOR] Allocate device no failed\n");
        return -EAGAIN;
    }

    /* Allocate driver */
    pimgsensor->pcdev = cdev_alloc();
    if (pimgsensor->pcdev == NULL) {
        unregister_chrdev_region(pimgsensor->dev_no, 1);
        PK_DBG("[CAMERA SENSOR] Allocate mem for kobject failed\n");
        return -ENOMEM;
    }

    /* Attatch file operation. */
    cdev_init(pimgsensor->pcdev, &gimgsensor_file_operations);
    pimgsensor->pcdev->owner = THIS_MODULE;

    /* Add to system */
    if (cdev_add(pimgsensor->pcdev, pimgsensor->dev_no, 1)) {
        PK_DBG("Attatch file operation failed\n");
        unregister_chrdev_region(pimgsensor->dev_no, 1);
        return -EAGAIN;
    }

    pimgsensor->pclass = class_create(THIS_MODULE, "sensordrv");
    if (IS_ERR(pimgsensor->pclass)) {
        int ret = PTR_ERR(pimgsensor->pclass);

        PK_DBG("Unable to create class, err = %d\n", ret);
        return ret;
    }

    pdevice = device_create(pimgsensor->pclass, NULL,
            pimgsensor->dev_no, NULL, IMGSENSOR_DEV_NAME);
    pdevice->of_node =
        of_find_compatible_node(NULL, NULL, "mediatek,imgsensor");
    if (!pdevice->of_node) {
        PK_PR_ERR("Get cust camera node failed!\n");
        return -ENODEV;
    }

    phw->common.pplatform_device = pplatform_device;
    /*以上注册字符设备,注册IO Ctrl操作函数*/
    imgsensor_hw_init(phw);    //获取电压配置,电压初始化
    imgsensor_i2c_create();    //创建i2c设备
    imgsensor_proc_init();
    imgsensor_init_sensor_list();

#ifdef IMGSENSOR_OC_ENABLE
    imgsensor_oc_init();  //用于启用或禁用相机图像传感器的Occlusion(遮挡)功能
#endif

    return 0;
}
imgsensor_hw_init解析

imgsensor_hw_init函数调用,主要进行电压初始化,获取电压配置信息。

enum IMGSENSOR_RETURN imgsensor_hw_init(struct IMGSENSOR_HW *phw)
{
    struct IMGSENSOR_HW_SENSOR_POWER      *psensor_pwr;
    struct IMGSENSOR_HW_CFG               *pcust_pwr_cfg;
    struct IMGSENSOR_HW_CUSTOM_POWER_INFO *ppwr_info;
    unsigned int i, j, len;
    char str_prop_name[LENGTH_FOR_SNPRINTF];
    const char *pin_hw_id_name;
    struct device_node *of_node
        = of_find_compatible_node(NULL, NULL, "mediatek,imgsensor");
        /*根据compatible信息获取设备节点*/
    mutex_init(&phw->common.pinctrl_mutex);

    /* update the imgsensor_custom_cfg by dts 依次调用REGULATOR/GPIO/MCLK的init接口*/
    for (i = 0; i < IMGSENSOR_SENSOR_IDX_MAX_NUM; i++) {
        PK_DBG("IMGSENSOR_SENSOR_IDX: %d\n", i);
        pcust_pwr_cfg = imgsensor_custom_config;//根据imgsensor_custom_config数组,获取所有相机供电方式如:GPIO,PMIC,具体配置于imgsensor_cfg_table.c文件中
        while (pcust_pwr_cfg->sensor_idx != i &&
               pcust_pwr_cfg->sensor_idx != IMGSENSOR_SENSOR_IDX_NONE)
            pcust_pwr_cfg++;

        if (pcust_pwr_cfg->sensor_idx == IMGSENSOR_SENSOR_IDX_NONE)
            continue;        //遍历整个数组

        ppwr_info = pcust_pwr_cfg->pwr_info;
        while (ppwr_info->pin != IMGSENSOR_HW_PIN_NONE) {
            memset(str_prop_name, 0, sizeof(str_prop_name));
            snprintf(str_prop_name,
                sizeof(str_prop_name),
                "cam%d_pin_%s",
                i,
                imgsensor_hw_pin_names[ppwr_info->pin]);//拼接str_prop_name字符串
            if (of_property_read_string(                    //读取节点中str_prop_name属性
                of_node, str_prop_name,
                &pin_hw_id_name) == 0) {
                for (j = 0; j < IMGSENSOR_HW_ID_MAX_NUM; j++) {
                    len = strlen(imgsensor_hw_id_names[j]);
                    if (strncmp(pin_hw_id_name, imgsensor_hw_id_names[j], len)
                        == 0) {
                        PK_DBG(
                            "imgsensor_hw_cfg hw_pin:%s, id name:%s, id:%d\n",
                            str_prop_name, pin_hw_id_name, j);
                        ppwr_info->id = j;
                        break;
                    }
                }
            }
            ppwr_info++;
        }
    }
    /* update the imgsensor_custom_cfg by dts END 以上代码主要获取dts文件中对相机供电设置,并进行配置*/

    for (i = 0; i < IMGSENSOR_HW_ID_MAX_NUM; i++) { //依次调用REGULATOR/GPIO/MCLK的init接口
        if (hw_open[i] != NULL)
            (hw_open[i]) (&phw->pdev[i]); //函数hw_open获取对应结构体

        if (phw->pdev[i]->init != NULL)
            (phw->pdev[i]->init)(
                phw->pdev[i]->pinstance, &phw->common);    //执行 gpio,regulator中init函数
    }

    for (i = 0; i < IMGSENSOR_SENSOR_IDX_MAX_NUM; i++) {
        psensor_pwr = &phw->sensor_pwr[i];

        pcust_pwr_cfg = imgsensor_custom_config;    //根据imgsensor_custom_config数组,获取所有相机供电方式如:GPIO,PMIC,具体配置于imgsensor_cfg_table.c文件中
        while (pcust_pwr_cfg->sensor_idx != i &&
               pcust_pwr_cfg->sensor_idx != IMGSENSOR_SENSOR_IDX_NONE)
            pcust_pwr_cfg++;
                
        if (pcust_pwr_cfg->sensor_idx == IMGSENSOR_SENSOR_IDX_NONE)
            continue;
            //获取该摄像头的引脚配置
        ppwr_info = pcust_pwr_cfg->pwr_info;
        while (ppwr_info->pin != IMGSENSOR_HW_PIN_NONE) {
            for (j = 0;
                j < IMGSENSOR_HW_ID_MAX_NUM &&
                    ppwr_info->id != phw->pdev[j]->id;
                j++) {
            }
                        //保存对应ID的擦操作方法
            psensor_pwr->id[ppwr_info->pin] = j;
            ppwr_info++;
        }
    }
        //从设备树中获取指定摄像头名字,如:cam3_enable_sensor = "gc2375hmain3_mipi_raw";
    for (i = 0; i < IMGSENSOR_SENSOR_IDX_MAX_NUM; i++) {
        memset(str_prop_name, 0, sizeof(str_prop_name));
        snprintf(str_prop_name,
                    sizeof(str_prop_name),
                    "cam%d_%s",
                    i,
                    "enable_sensor");
        if (of_property_read_string(
            of_node, str_prop_name,
            &phw->enable_sensor_by_index[i]) < 0) {
            PK_DBG("Property cust-sensor not defined\n");
            phw->enable_sensor_by_index[i] = NULL;
        }
    }

    return IMGSENSOR_RETURN_SUCCESS;
}
imgsensor_i2c_create解析

imgsensor_i2c_create用于添加I2C设备

enum IMGSENSOR_RETURN imgsensor_i2c_create(void)
{
    int i;

    for (i = 0; i < IMGSENSOR_I2C_DEV_MAX_NUM; i++)
        i2c_add_driver(&gi2c_driver[i]);

    return IMGSENSOR_RETURN_SUCCESS;
}

描述i2c_driver配置信息。

#define IMGSENSOR_I2C_DRV_NAME_0  "kd_camera_hw"
#define IMGSENSOR_I2C_DRV_NAME_1  "kd_camera_hw_bus2"
#define IMGSENSOR_I2C_DRV_NAME_2  "kd_camera_hw_bus3"
#define IMGSENSOR_I2C_DRV_NAME_3  "kd_camera_hw_bus4"
#define IMGSENSOR_I2C_DRV_NAME_4  "kd_camera_hw_bus5"
#define IMGSENSOR_I2C_DRV_NAME_5  "kd_camera_hw_bus6"
#define IMGSENSOR_I2C_DRV_NAME_6  "kd_camera_hw_bus7"
#define IMGSENSOR_I2C_DRV_NAME_7  "kd_camera_hw_bus8"
#define IMGSENSOR_I2C_DRV_NAME_8  "kd_camera_hw_trigger"

#define IMGSENSOR_I2C_OF_DRV_NAME_0 "mediatek,camera_main"
#define IMGSENSOR_I2C_OF_DRV_NAME_1 "mediatek,camera_sub"
#define IMGSENSOR_I2C_OF_DRV_NAME_2 "mediatek,camera_main_two"
#define IMGSENSOR_I2C_OF_DRV_NAME_3 "mediatek,camera_sub_two"
#define IMGSENSOR_I2C_OF_DRV_NAME_4 "mediatek,camera_main_three"
#define IMGSENSOR_I2C_OF_DRV_NAME_5 "mediatek,camera_sub_three"
#define IMGSENSOR_I2C_OF_DRV_NAME_6 "mediatek,camera_main_four"
#define IMGSENSOR_I2C_OF_DRV_NAME_7 "mediatek,camera_sub_four"

enum IMGSENSOR_I2C_DEV {
    IMGSENSOR_I2C_DEV_0,
    IMGSENSOR_I2C_DEV_1,
    IMGSENSOR_I2C_DEV_2,
    IMGSENSOR_I2C_DEV_3,
    IMGSENSOR_I2C_DEV_4,
    IMGSENSOR_I2C_DEV_5,
    IMGSENSOR_I2C_DEV_6,
    IMGSENSOR_I2C_DEV_7,
    IMGSENSOR_I2C_DEV_MAX_NUM,
};
/**************************************/
static const struct of_device_id gof_device_id_0[] = {
    {.compatible = IMGSENSOR_I2C_OF_DRV_NAME_0,},
    {}
};

static const struct of_device_id gof_device_id_1[] = {
    {.compatible = IMGSENSOR_I2C_OF_DRV_NAME_1,},
    {}
};

static const struct of_device_id gof_device_id_2[] = {
    {.compatible = IMGSENSOR_I2C_OF_DRV_NAME_2,},
    {}
};
/**************************************/
static struct i2c_driver gi2c_driver[IMGSENSOR_I2C_DEV_MAX_NUM] = {
    {
        .probe = imgsensor_i2c_probe_0,
        .remove = imgsensor_i2c_remove,
        .driver = {
        .name = IMGSENSOR_I2C_DRV_NAME_0,
        .owner = THIS_MODULE,
#ifdef CONFIG_OF
        .of_match_table = gof_device_id_0,
#endif
        },
        .id_table = gi2c_dev_id,
    },
    {
        .probe = imgsensor_i2c_probe_1,
        .remove = imgsensor_i2c_remove,
        .driver = {
        .name = IMGSENSOR_I2C_DRV_NAME_1,
        .owner = THIS_MODULE,
#ifdef CONFIG_OF
        .of_match_table = gof_device_id_1,
#endif
        },
        .id_table = gi2c_dev_id,
    },
    {
        .probe = imgsensor_i2c_probe_2,
        .remove = imgsensor_i2c_remove,
        .driver = {
        .name = IMGSENSOR_I2C_DRV_NAME_2,
        .owner = THIS_MODULE,
#ifdef CONFIG_OF
        .of_match_table = gof_device_id_2,
#endif
        },
        .id_table = gi2c_dev_id,
    }

        设备树中的compatible信息于项目dws文件配置,dws经过编译(DrvGen.py脚本)后生成cust_*.h文件,路径:obj\PRELOADER_OBJ\inc;在Preloader和Lk的代码中,很多文件都会包含cust_i2c.h、cust_gpio_boot.h、cust_gpio_usage.h

在Kernel的代码中,每个工程的dts文件都会包含cust.dtsi,路径:obj\KERNEL_OBJ\arch\arm64\boot\dts\******

最终设备树compatible信息生成于out目录下的dts/mediatek中,例如:.tb8797p2_64_k419_wifi.dtb.dts.tmp

&i2c2 {
 #address-cells = <1>;
 #size-cells = <0>;
 clock-frequency = <400000>;
 mediatek,use-open-drain;
 camera_main_mtk:camera_main@1a {
  compatible = "mediatek,camera_main";
  reg = <0x1a>;
  status = "okay";
 };

 camera_main_eeprom_mtk:camera_main_eeprom@50 {
  compatible = "mediatek,camera_main_eeprom";
  reg = <0x50>;
  status = "okay";
 };

 camera_main_af_mtk:camera_main_af@72 {
  compatible = "mediatek,camera_main_af";
  reg = <0x72>;
  status = "okay";
 };

};

compatible信息匹配成功后调用对对应的probe程序

static int imgsensor_i2c_probe_0(struct i2c_client *client,
                const struct i2c_device_id *id)
{
    gi2c.inst[IMGSENSOR_I2C_DEV_0].pi2c_client = client;
    return 0;
}
imgsensor_proc_init解析

imgsensor_proc_init用于在proc/driver/下创建一些文件接口,cat proc/driver/camera_info,该文件可以看到摄像头硬件信息

enum IMGSENSOR_RETURN imgsensor_proc_init(void)
{
    memset(mtk_ccm_name, 0, camera_info_size);

    proc_create("driver/camsensor", 0000, NULL, &fcamera_proc_fops);
    proc_create("driver/camsensor2", 0000, NULL, &fcamera_proc_fops2);
    proc_create("driver/camsensor3", 0000, NULL, &fcamera_proc_fops3);
    proc_create("driver/camsensor4", 0000, NULL, &fcamera_proc_fops4);
    proc_create("driver/camsensor5", 0000, NULL, &fcamera_proc_fops5);
    proc_create("driver/camsensor6", 0000, NULL, &fcamera_proc_fops6);
    proc_create("driver/camsensor7", 0000, NULL, &fcamera_proc_fops7);
    proc_create("driver/camsensor8", 0000, NULL, &fcamera_proc_fops8);
    proc_create("driver/pdaf_type", 0000, NULL,
                &fcamera_proc_fops_set_pdaf_type);
    proc_create("driver/imgsensor_status_info", 0000, NULL,
                &fcamera_proc_fops_status_info);

    /* Camera information */
    proc_create(PROC_CAMERA_INFO, 0000, NULL, &fcamera_proc_fops1);

    return IMGSENSOR_RETURN_SUCCESS;
}

        可获取camera名称、ID信息。每个摄像头的配置信息包括预览、捕获、视频、HSV和子采样的分辨率、延迟帧数、传感器类型、输出格式、驱动电流、mclk频率、mipi通道数以及PDAF支持和HDR支持等信息。

imgsensor_init_sensor_list解析

        用于获取gimgsensor_sensor_list列表。获取都dts中cust-sensor属性,如果没有找到该属性,函数将直接将所有传感器添加到pimgsensor->psensor_list中。

static void imgsensor_init_sensor_list(void)
{
    unsigned int i = 0;
    int ret = 0;
    struct IMGSENSOR             *pimgsensor   = &gimgsensor;
    struct IMGSENSOR_SENSOR_LIST *psensor_list =  gimgsensor_sensor_list;
    const char *penable_sensor;
    struct device_node *of_node
        = of_find_compatible_node(NULL, NULL, "mediatek,imgsensor");
        //获取dts中cust-sensor属性,
    ret = of_property_read_string(of_node, "cust-sensor", &penable_sensor);
    if (ret < 0) {
        PK_DBG("Property cust-sensor not defined\n");
        while (psensor_list->id && i < MAX_NUM_OF_SUPPORT_SENSOR) {
            pimgsensor->psensor_list[i] = psensor_list;
            i++;
            psensor_list++;
        }
    } else {
        PK_DBG("Customizedsensors: %s\n", penable_sensor);
        while (psensor_list->id && i < MAX_NUM_OF_SUPPORT_SENSOR) {
            if (strstr(penable_sensor, psensor_list->name)) {
                pimgsensor->psensor_list[i] = psensor_list;
                i++;
            }
            psensor_list++;
        }
    }
}

二、Android hal操作

        CameraService是在开机时启动的,启动后进行searchSensor的操作,会search系统有多少camera,开机时的search操作,只进行camera支持数量的遍历,以及sensor ID的读取操作。

文件路径:vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1_1/HalSensorList.cpp

MUINT
 HalSensorList::
searchSensors()
{
    Mutex::Autolock _l(mEnumSensorMutex);

    MY_LOGD("searchSensors");
    return  enumerateSensor_Locked();
}

文件路径:vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1_1/HalSensorList.enumList.cpp

MUINT
 HalSensorList::
enumerateSensor_Locked()
{
    int ret = 0;
    NSFeature::SensorInfoBase* pSensorInfo ;

    SensorDrv *const pSensorDrv = SensorDrv::get();
    SeninfDrv *const pSeninfDrv = SeninfDrv::createInstance(); //获取SensorDrv和SeninfDrv实例
    if(!pSeninfDrv) {
        MY_LOGE("pSeninfDrv == NULL");
        return 0;
    }
    //初始化SeninfDrv,配置ISP相关内容
    if((ret = pSeninfDrv->init()) < 0) {
        MY_LOGE("pSeninfDrv->init() fail");
        return 0;
    }

    /*search sensor using 8mA driving current*/
    pSeninfDrv->setAllMclkOnOff(ISP_DRIVING_8MA, TRUE);    //设置所有时钟为8mA驱动电流

    pSensorDrv->init(); //初始化SensorDrv

    MUINT max_index_of_camera = IMGSENSOR_SENSOR_IDX_SUB;
#ifdef MTK_CAM_MAX_NUMBER_OF_CAMERA
    max_index_of_camera = MTK_CAM_MAX_NUMBER_OF_CAMERA - 1;
#endif

    MY_LOGD("impSearchSensor search to %d\n", max_index_of_camera); //遍历所有传感器所有
    for (MUINT i = IMGSENSOR_SENSOR_IDX_MIN_NUM; i <= max_index_of_camera; i++) {

#ifdef MCLK_DRIVE_CURRENT_BY_PINCTRL
        /*search sensor using 8mA driving current*/
        MUINT32 current = ISP_DRIVING_8MA;
        pSensorDrv->sendCommand((IMGSENSOR_SENSOR_IDX)i, CMD_SENSOR_SET_DRIVE_CURRENT, (MUINTPTR)&current);
#endif    //如果使用引脚控制设置驱动电流为8mA
        //搜索所有传感器
        if((ret = pSensorDrv->searchSensor((IMGSENSOR_SENSOR_IDX)i)) == SENSOR_NO_ERROR) {
            //query sensorinfo    查询传感器信息
            querySensorDrvInfo((IMGSENSOR_SENSOR_IDX)i);
            //fill in metadata     填充元素数据                                                                                                                          
            buildSensorMetadata((IMGSENSOR_SENSOR_IDX)i);
            //获取传感器信息            
            pSensorInfo = pSensorDrv->getSensorInfo((IMGSENSOR_SENSOR_IDX)i);
            if (pSensorInfo == nullptr) {
                MY_LOGE("Error! null pSensorInfo\n");
                return 0;
            }
            if (pSensorInfo->getDrvMacroName() == nullptr) {    //检查传感器信息是否为空
                MY_LOGE("Error! null pSensorInfo->getDrvMacroName\n");
                return 0;
            }
            else {
            addAndInitSensorEnumInfo_Locked(
                (IMGSENSOR_SENSOR_IDX)i,
                mapToSensorType(pSensorInfo->GetType()),
                pSensorInfo->getDrvMacroName());    //传感器信息不为空,添加并初始化传感器枚举信息
           }
        }
    }
    //关闭所有时钟
    pSeninfDrv->setAllMclkOnOff(0, FALSE);
    //反向初始化seninfdrc、sensordrv
    ret = pSeninfDrv->uninit();
    if(ret < 0) {
        MY_LOGE("pSeninfDrv->uninit() fail");
        return 0;
    }
    pSeninfDrv->destroyInstance();
    pSensorDrv->uninit();
    //返回枚举传感器数量
    return  mEnumSensorList.size();
}

文件路径:vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1_1/imgsensor_drv.cpp

searchSensor()函数的主要功能是搜索并设置图像传感器驱动。它尝试设置一个指定的驱动程序,如果成功,则记录相应的信息;如果设置失败或者该驱动程序已经存在,则根据情况返回不同的错误代码。

MINT32
 ImgSensorDrv::searchSensor()
{
    MINT32 ret = 0; 
    //检查m_list.id值,为0表示已经处理过
    if (m_list.id != 0) { 
        LOG_MSG("[searchSensor] Already processed");
        return SENSOR_ALREADY_SEARCH;
    }    

    LOG_MSG("searchSensor idx = %d", m_sensorIdx);
    // 调用 featureControl函数获取 m_list
    ret = featureControl(SENSOR_FEATURE_SET_DRIVER, (MUINT8 *)&m_list, sizeof(IMGSENSOR_SENSOR_LIST));
    if (ret != 0)
        LOG_MSG("Error! SENSOR_FEATURE_SET_DRIVER ret = %d", ret);

    if(m_list.id == 0) { 
        LOG_WRN("Search fail");
        m_list.id = 0xFFFFFFFF;
        return SENSOR_INVALID_DRIVER;
    } else {
        LOG_MSG("found <%x/%s>", m_list.id, m_list.name);
        getInfo();
        return SENSOR_NO_ERROR;
    }
}

featureControl函数

MINT32
ImgSensorDrv::featureControl(
    ACDK_SENSOR_FEATURE_ENUM FeatureId,
    MUINT8 *pFeaturePara,
    MUINT32 featureParaLen
)
{
    ACDK_SENSOR_FEATURECONTROL_STRUCT featureCtrl;
    int ret = SENSOR_NO_ERROR;

    if (FeatureId == SENSOR_FEATURE_BEGIN) {
        LOG_MSG("[featureControl] Skip due to no FeatureId");
        return SENSOR_NO_ERROR;
    }

    if (m_fd == -1) {
        LOG_ERR("[sendCommand]m_fd fail, sendCommand must be called after init()!");
        return SENSOR_UNKNOWN_ERROR;
    }

    if (pFeaturePara == NULL)
        return SENSOR_INVALID_PARA;

    featureCtrl.InvokeCamera    = m_sensorIdx;    //根据枚举,前摄还是后摄ID
    featureCtrl.FeatureId       = FeatureId;    //打开还是关闭的ID
    featureCtrl.pFeaturePara    = pFeaturePara;    //传递的参数
    featureCtrl.pFeatureParaLen = &featureParaLen;    //参数的长度
    ret = ioctl(m_fd, KDIMGSENSORIOC_X_FEATURECONCTROL, &featureCtrl);//利用IOCTL调用到kernel中的imgsensor_ioctl函数
    if (ret != 0) {
        LOG_ERR("[featureControl] Err-ctrlCode (%s) ret = %d", strerror(errno), ret);
    }
    return ret;
}

三、imgsensor_ioctl

imgsensor_ioctl操作整体框架如下:

文件路径:kernel-$(KernelVersion)/drivers/misc/mediatek/imgsensor/src/common/v_$(Version)/imgsensor.c

static long imgsensor_ioctl(
        struct file *a_pstFile,
        unsigned int a_u4Command, unsigned long a_u4Param)
{
    int i4RetValue = 0;
    void *pBuff = NULL;
    //判断传递的命令参数是否为空
    if (_IOC_DIR(a_u4Command) != _IOC_NONE) {
        pBuff = kmalloc(_IOC_SIZE(a_u4Command), GFP_KERNEL);    //申请命令参数储存空间
        if (pBuff == NULL) {
            PK_DBG("[CAMERA SENSOR] ioctl allocate mem failed\n");
            i4RetValue = -ENOMEM;
            goto CAMERA_HW_Ioctl_EXIT;
        }

        memset(pBuff, 0x0, _IOC_SIZE(a_u4Command));    //将命令储存至空间

        if (_IOC_WRITE & _IOC_DIR(a_u4Command)) {    //判断命令是否可写
            if (copy_from_user(pBuff, (void *)a_u4Param,
            _IOC_SIZE(a_u4Command))) {    //将命令从用户空间复制到内核
                PK_DBG(
            "[CAMERA SENSOR] ioctl copy from user failed\n");
                i4RetValue = -EFAULT;
                goto CAMERA_HW_Ioctl_EXIT;
            }
        }
    } else {
        i4RetValue = -EFAULT;
        goto CAMERA_HW_Ioctl_EXIT;
    }

    switch (a_u4Command) {
    case KDIMGSENSORIOC_X_GETINFO2:        //获取信息
        i4RetValue = adopt_CAMERA_HW_GetInfo2(pBuff);
        break;

    case KDIMGSENSORIOC_X_FEATURECONCTROL:    //功能控制,包含时钟设置,相机打开关闭
        i4RetValue = adopt_CAMERA_HW_FeatureControl(pBuff);
        break;

    case KDIMGSENSORIOC_X_CONTROL:    //控制
        i4RetValue = adopt_CAMERA_HW_Control(pBuff);
        break;

    default:
        PK_DBG("No such command %d\n", a_u4Command);
        i4RetValue = -EPERM;
        goto CAMERA_HW_Ioctl_EXIT;
        break;
    }

    if ((_IOC_READ & _IOC_DIR(a_u4Command)) &&
        copy_to_user((void __user *)a_u4Param, pBuff,
            _IOC_SIZE(a_u4Command))) {    //将数据复制到用户空间
        PK_DBG("[CAMERA SENSOR] ioctl copy to user failed\n");
        i4RetValue = -EFAULT;
        goto CAMERA_HW_Ioctl_EXIT;
    }

CAMERA_HW_Ioctl_EXIT:
    if (pBuff != NULL) {
        kfree(pBuff);
        pBuff = NULL;
    }

    return i4RetValue;
}

adopt_CAMERA_HW_FeatureControl函数根据命令调用imgsensor_sensor_open函数,imgsensor_sensor_open函数调用imgsensor_hw_power函数进行上下电操作,imgsensor_hw_power调用imgsensor_hw_power_sequence函数进行具体的上下电操作,imgsensor_check_is_alive函数进行sensor ID读取。

  • 9
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值