MTK camera驅動結構 一、概述 二、sensor driver介紹

和你一起終身學習,這裏是程序員 Android

經典好文推薦,通過閱讀本文,您將收穫以下知識點:

一、概述

MTK camera主要的內容在hal層,現在有hal1/hal3,當下主流的使用的是hal3,驅動主要負責sensor電源的控制以及sensor相關寄存器的操作,MTK採用設備和驅動分離的思想,抽象出imgsensor.c來控制sensor的上下電以及sensor具體的操作,結構圖如下:

二、sensor driver介紹

Sensor driver對上響應需求,對下控制sensor硬件行爲,處理器通過I2C接口來控制sensor的大部分行爲,sensor輸出的數據傳輸到TG、ISP等模塊處理後,ISP將數據保存到內存中之後,纔可以dumpsensor的數據,才能看到sensor的第一幀畫面。這節主要介紹sensor driver的代碼。

1、sensor driver函數結構體:

(1) 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;
}

sensorlinelength是固定的,每個模式的pclk也是不可調的,所以要調整幀率framerate,只能調整frame_lengthset_dummy使得當前幀率立刻變化爲設置的幀率,如果pclk或者linelength與對應sensor setting的實際值不一致,設置的幀率和響應的幀率會有一個偏差,畫面可能出現水波紋:

(2) 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*/
};

(3)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*/
};

2、驅動入口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這個結構體包含了所有sensor driver的操作接口:

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
};

3、open 函數介紹及其所完成的任務

(1)此函每次打開camera都會調用;

(2)讀取sensor id,確保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;
}

4、feature_control接口

(1)獲取linelengthpclk

    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;

獲取各個modesensor pclk(pixel/s)PCLKpixel採樣的時鐘,

linelength, 結合pclk來計算linetime, 用來換算ae plinetableexposure 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中相應indexexp轉換爲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

5、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;
}

至此,本篇已結束。轉載網絡的文章,小編覺得很優秀,歡迎點擊閱讀原文,支持原創作者,如有侵權,懇請聯繫小編刪除,歡迎您的建議與指正。同時期待您的關注,感謝您的閱讀,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章