MTK camera主要的内容在hal层,现在有hal1/hal3,当下主流的使用的是hal3,驱动主要负责sensor、电源的控制以及sensor相关寄存器的操作,MTK采用设备和驱动分离的思想,抽象出imgsensor.c来控制。
sensor的上下电以及sensor具体的操作,结构图如下:
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的实际值不一致,设置的帧率和响应的帧率会有一个偏差,画面可能出现水波纹:
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;
}