MTK Camera驱动 结构介绍

MTK camera主要的内容在hal层,现在有hal1/hal3,当下主流的使用的是hal3,驱动主要负责sensor、电源的控制以及sensor相关寄存器的操作,MTK采用设备和驱动分离的思想,抽象出imgsensor.c来控制。

sensor的上下电以及sensor具体的操作,结构图如下:
MTK camera驱动结构介绍

Camera sensor driver介绍

Sensordriver的对上响应需求,对下控制sensor硬件行为,处理器通过I2C 接口来控制sensor的大部分行为,sensor输出的数据传输到TG、ISP等模块处理后,ISP将数据保存到内存中之后,才可以dump出sensor的数据,才能看到sensor的第一帧画面。这节主要介绍sensordriver的代码。

sensorDriver函数结构体

imgsensor_mode_struct不同模式特征的结构体

这个结构体描叙了各个模式下的pclk/linelength/framelength 等

struct imgsensor_mode_struct {
    kal_uint32 pclk;
    kal_uint32 linelength;
    kal_uint32 framelength;

    kal_uint8 startx;
    kal_uint8 starty;

    kal_uint16 grabwindow_width;
    kal_uint16 grabwindow_height;

    /* MIPIDataLowPwr2HighSpeedSettleDelayCount by different scenario */
    kal_uint8 mipi_data_lp2hs_settle_dc;

    /*   following for GetDefaultFramerateByScenario()  */
    kal_uint16 max_framerate;
    kal_uint32 mipi_pixel_rate;
};

对应的描叙信息如下:pclk ≈ linelength * frame_length * framerate:

static kal_uint32 set_max_framerate_by_scenario(enum MSDK_SCENARIO_ID_ENUM scenario_id, MUINT32 framerate)
{
    kal_uint32 frame_length;

    switch (scenario_id) {
    case MSDK_SCENARIO_ID_CAMERA_PREVIEW:
        frame_length = imgsensor_info.pre.pclk / framerate * 10 / imgsensor_info.pre.linelength;//计算frame_length
        spin_lock(&imgsensor_drv_lock);
        imgsensor.dummy_line = (frame_length > imgsensor_info.pre.framelength) ?
            (frame_length - imgsensor_info.pre.framelength) : 0;
        imgsensor.frame_length = imgsensor_info.pre.framelength + imgsensor.dummy_line;
        imgsensor.min_frame_length = imgsensor.frame_length;
        spin_unlock(&imgsensor_drv_lock);
        set_dummy(); //更新新的frame_length
        break;
}

sensor的linelength是固定的,每个模式的pclk也是不可调的,所以要调整帧率framerate,只能调整frame_length。

set_dummy使得当前帧率立刻变化为设置的帧率,如果pclk或者linelength与对应sensor setting的实际值不一致,设置的帧率和响应的帧率会有一个偏差,画面可能出现水波纹:

sensorDriver函数结构体

struct imgsensor_info_struct描叙sensor info常量的结构体

struct imgsensor_info_struct {
    kal_uint32 sensor_id;                      /*record sensor id defined in Kd_imgsensor.h*/
    kal_uint32 checksum_value;                 /*checksum value for Camera Auto Test*/
//不同mode 的信息
    struct imgsensor_mode_struct pre;          /*preview scenario relative information*/
    struct imgsensor_mode_struct cap;          /*capture scenario relative information*/
    struct imgsensor_mode_struct cap1;
    struct imgsensor_mode_struct cap2;
    struct imgsensor_mode_struct normal_video; /*normal video  scenario relative information*/
    struct imgsensor_mode_struct hs_video;     /*high speed video scenario relative information*/
    struct imgsensor_mode_struct slim_video;   /*slim video for VT scenario relative information*/
//支持的功能
    kal_uint8  ae_shut_delay_frame;            /*shutter delay frame for AE cycle*/
    kal_uint8  ae_sensor_gain_delay_frame;     /*sensor gain delay frame for AE cycle*/
    kal_uint8  ae_ispGain_delay_frame;         /*isp gain delay frame for AE cycle*/
    kal_uint8  ihdr_support;                   /*1, support; 0,not support*/
    kal_uint8  ihdr_le_firstline;              /*1,le first ; 0, se first*/
    kal_uint8  sensor_mode_num;                /*support sensor mode num*/
//丢帧处理(丢掉不稳定帧的数据)
    kal_uint8  cap_delay_frame;                /*enter capture delay frame num*/
    kal_uint8  pre_delay_frame;                /*enter preview delay frame num*/
    kal_uint8  video_delay_frame;              /*enter video delay frame num*/
    kal_uint8  hs_video_delay_frame;           /*enter high speed video  delay frame num*/
    kal_uint8  slim_video_delay_frame;         /*enter slim video delay frame num*/
    kal_uint8  margin;                         /*sensor framelength & shutter margin*/
    kal_uint32 min_shutter;                    /*min shutter*/
    kal_uint32 max_frame_length;               /*max framelength by sensor register's limitation*/
//isp驱动电流,电流过大可能会射频干扰
    kal_uint8  isp_driving_current;            /*mclk driving current*/
    kal_uint8  sensor_interface_type;          /*sensor_interface_type*/
    kal_uint8  mipi_sensor_type;
    /*0,MIPI_OPHY_NCSI2; 1,MIPI_OPHY_CSI2, default is NCSI2, don't modify this para*/
    /*don't modify this para*/
    kal_uint8  mipi_settle_delay_mode;
    /*0, high speed signal auto detect; 1, use settle delay,unit is ns, */
    kal_uint8  sensor_output_dataformat;       /*sensor output first pixel color*/
    kal_uint8  mclk;                           /*mclk value, suggest 24 or 26 for 24Mhz or 26Mhz*/
    kal_uint8  mipi_lane_num;                  /*mipi lane num*/
    kal_uint8  i2c_addr_table[5];
    /*record sensor support all write id addr, only supprt 4must end with 0xff*/
};

struct imgsensor_struct记录sensor info变量的结构体,用于动态的保存sensor的关键信息:

struct imgsensor_struct {
//记录当前是normal, or H mirror, or V flip,or both H& V
    kal_uint8  mirror;                        /*mirrorflip information*/
//记录当前处于哪种mode(init/preview/capture/video)
    kal_uint8  sensor_mode;                   /*record IMGSENSOR_MODE enum value*/
//记录当前的shutter值
    kal_uint32 shutter;                       /*current shutter*/
//记录当前的sensor gain值
    kal_uint16 gain;                          /*current gain*/
    kal_uint32 pclk;                          /*current pclk*/
    kal_uint32 frame_length;                  /*current framelength*/
    kal_uint32 line_length;                   /*current linelength*/
    kal_uint32 min_frame_length;              /*current min  framelength to max framerate*/
//记录当前的dummy pixel, dummy line的值
    kal_uint16 dummy_pixel;                   /*current dummypixel*/
    kal_uint16 dummy_line;                    /*current dummline*/
    kal_uint16 current_fps;                   /*current max fps*/
    kal_bool   autoflicker_en;                /*record autoflicker enable or disable*/
    kal_bool   test_pattern;                  /*record test pattern mode or not*/
//记录当前处于哪个scenario( preview/capture/video)
    enum MSDK_SCENARIO_ID_ENUM current_scenario_id;/*current scenario id*/
    kal_bool   ihdr_en;                       /*ihdr enable or disable*/
//记录当前i2c使用的address
    kal_uint8  i2c_write_id;                  /*record current sensor's i2c write id*/
};

驱动入口xxxx_MIPI_RAW_SensorInit

可以看到SensorInit以函数指针的形式传入到kdSensorList结构体中:

//kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_sensor_list.c
struct IMGSENSOR_INIT_FUNC_LIST kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR] = {
    #if defined(XXXXX_MIPI_RAW)
            {XXXXX_SENSOR_ID,
            SENSOR_DRVNAME_XXXXX_MIPI_RAW,
            XXXXX_MIPI_RAW_SensorInit},
    #endif
    ......
}

UINT32 XXXXX_MIPI_RAW_SensorInit(struct SENSOR_FUNCTION_STRUCT **pfFunc)
{
    /* Check Sensor status here */
    if (pfFunc != NULL)
        *pfFunc = &sensor_func;
    return ERROR_NONE;
}

SENSOR_FUNCTION_STRUCT这个结构体包含了所有sensorDriver的操作接口:

struct SENSOR_FUNCTION_STRUCT {
    MUINT32 (*SensorOpen)(void);
    MUINT32 (*SensorGetInfo)(enum MSDK_SCENARIO_ID_ENUM ScenarioId,
        MSDK_SENSOR_INFO_STRUCT *pSensorInfo,
        MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData);

    MUINT32 (*SensorGetResolution)(
        MSDK_SENSOR_RESOLUTION_INFO_STRUCT * pSensorResolution);

    MUINT32 (*SensorFeatureControl)(MSDK_SENSOR_FEATURE_ENUM FeatureId,
        MUINT8 *pFeaturePara,
        MUINT32 *pFeatureParaLen);

    MUINT32 (*SensorControl)(enum MSDK_SCENARIO_ID_ENUM ScenarioId,
        MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *pImageWindow,
        MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData);

    MUINT32 (*SensorClose)(void);

    MUINT8  arch;
    void   *psensor_inst; /* IMGSENSOR_SENSOR_INST */
};

对应驱动中填充的信息如下:

static struct SENSOR_FUNCTION_STRUCT sensor_func = {
    open,//打开camera时调用
    get_info,// 获取sensor的动态信息
    get_resolution,//获取sensor特定模式下的尺寸
    feature_control,
    control,
    close
};

open 函数介绍及其所完成的任务

(1)此函每次打开camera都会调用;

  (2)读取sensorid,确保I2C通讯正常;

(3)调用sensor_init初始化sensor芯片;

(4)初始化imgsensor结构体中的变量;

(5)读取otp中信息;

static kal_uint32 open(void)
{
    //获取sensor的ID确认i2c是否正常
  sensor_id = return_sensor_id();
    //设置I2C 的速率
    kdSetI2CSpeed(400);
    //sensor初始化参数设置
    sensor_init();
    //初始化imgsensor结构体
    imgsensor.autoflicker_en = KAL_FALSE;
    imgsensor.sensor_mode = IMGSENSOR_MODE_INIT;
    imgsensor.pclk = imgsensor_info.pre.pclk;
    imgsensor.frame_length = imgsensor_info.pre.framelength;
    imgsensor.line_length = imgsensor_info.pre.linelength;
    imgsensor.min_frame_length = imgsensor_info.pre.framelength;
    imgsensor.dummy_pixel = 0;
    imgsensor.dummy_line = 0;
    imgsensor.ihdr_en = 0;
    imgsensor.test_pattern = KAL_FALSE;
    imgsensor.current_fps = imgsensor_info.pre.max_framerate;
}

feature_control接口

(1)获取linelength和pclk:

    case SENSOR_FEATURE_GET_PERIOD:
        *feature_return_para_16++ = imgsensor.line_length;
        *feature_return_para_16 = imgsensor.frame_length;
        *feature_para_len = 4;
        break;
    case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ:
        *feature_return_para_32 = imgsensor.pclk;
        *feature_para_len = 4;
        break;

获取各个mode的sensor pclk(pixel/s),PCLK指pixel采样的时钟,

linelength, 结合pclk来计算linetime, 用来换算ae plinetable的exposure time对应的shutter (unit: line,条数)。

(2)set_shutter设置曝光行:

    case SENSOR_FEATURE_SET_ESHUTTER:
        set_shutter(*feature_data);
        break;

设置曝光行,曝光行物理上小于frame_length,所以曝光行大于当前frame_length时,frame_length会自动撑长,

帧率降低所以亮度较低时,帧率会下降,因为这时候shutter比较大。每个AE周期会根据AE算法找到的对应pline

table中相应index的exp转换为shutter下给driver。

(3)streaming_control控制sensor输出数据:

    case SENSOR_FEATURE_SET_STREAMING_SUSPEND:
        pr_info("SENSOR_FEATURE_SET_STREAMING_SUSPEND\n");
        streaming_control(KAL_FALSE);
        break;
    case SENSOR_FEATURE_SET_STREAMING_RESUME:
        pr_info("SENSOR_FEATURE_SET_STREAMING_RESUME, shutter:%llu\n",
                *feature_data);
        if (*feature_data != 0)
            set_shutter(*feature_data);
        streaming_control(KAL_TRUE);
        break;

在打开sensor输出数据前,需要先设置shutter。

control 模式切换函数

static kal_uint32 control(enum MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window,
    MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data)
{
    spin_lock(&imgsensor_drv_lock);
    imgsensor.current_scenario_id = scenario_id;
    spin_unlock(&imgsensor_drv_lock);
    switch (scenario_id) {
    case MSDK_SCENARIO_ID_CAMERA_PREVIEW:
        preview(image_window, sensor_config_data);
        break;
    case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG:
        capture(image_window, sensor_config_data);
        break;
    case MSDK_SCENARIO_ID_VIDEO_PREVIEW:
        normal_video(image_window, sensor_config_data);
        break;
    case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO:
        hs_video(image_window, sensor_config_data);
        break;
    case MSDK_SCENARIO_ID_SLIM_VIDEO:
        slim_video(image_window, sensor_config_data);
        break;
    }
    return ERROR_NONE;
}

以preview为例说明流程:

static kal_uint32 preview(MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window,
    MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data)
{
//更新imgsensor结构体信息
    spin_lock(&imgsensor_drv_lock);
    imgsensor.sensor_mode = IMGSENSOR_MODE_PREVIEW;
    imgsensor.pclk = imgsensor_info.pre.pclk;
    /* imgsensor.video_mode = KAL_FALSE; */
    imgsensor.line_length = imgsensor_info.pre.linelength;
    imgsensor.frame_length = imgsensor_info.pre.framelength;
    imgsensor.min_frame_length = imgsensor_info.pre.framelength;
    imgsensor.autoflicker_en = KAL_TRUE;
    spin_unlock(&imgsensor_drv_lock);
//更新寄存器
    preview_setting();
    return ERROR_NONE;
}

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程