SSD_Sensor使用参考


1. MIPI SENSOR配置参考


1.1. MIPI pin脚配置

Mipi Sensor需要配置的pin主要是 mipi data & clk, mclk, powerdown, reset, i2c 如下图所示:

1.1.1. Mipi data & clk pin配置

首先查看hwchecklist 表格看目前用的是哪组mipi pin,如下是公版搭配两个GC1054 1lane sensor选用的pin:

所以在kernel\arch\arm\boot\dts\pioneer3.dtsi中配置sensor0和sensor1的mode为1:

1.  vif: vif {  
2.      compatible = "sstar,vif";  
3.      status = "ok";  
4.      reg = <0x1F263200 0x600>, <0x0 0x0>, <0x0 0x0>, <0x0 0x0>, <0x0 0x0>, <0x0 0x0>, <0x1F203C00 0x200>, <0x1F227200 0x200>, <0x1F207000 0x200>, <0x1F000000 0x400000>, <0x1F207C00 0x200>;  
5.      //clocks = <&CLK_sr_mclk>;  
6.      interrupts = <GIC_SPI INT_IRQ_VIF IRQ_TYPE_LEVEL_HIGH>;  
7.      // Config sensor 0 pad mux  
8.    
9.      vif_sr0_par_mode = <3>;  
10.     vif_sr0_parallel_rst_mode = <1>;  
11.     vif_sr0_parallel_pdn_mode = <1>;  
12.     vif_sr0_mclk_mode = <1>;  
13.     vif_sr0_mipi_mode = <1>;  
14.     vif_sr0_mipi_ctrl_mode = <1>;  
15.     vif_sr0_bt656_mode = <4>;  
16.     // Config sensor 1 pad mux  
17.     vif_sr1_par_mode = <0>;  
18.     vif_sr1_mipi_mode = <1>;  
19.     vif_sr1_mipi_ctrl_mode = <1>;  
20.     vif_sr1_bt656_mode = <2>;  
21. };

配置完成后可以通过读如下寄存器看配置是否成功:

Sensor0: /customer/riu_r 0x103c 0x74 //查看bit0对应的值是否为vif_sr0_mipi_mode配置的值

Sensor1: /customer/riu_r 0x103c 0x74 //查看bit4~5对应的值是否为vif_sr1_mipi_mode配置的值

注意:开机不会自动配置这个寄存器,是在初始化vif的时候才会配置,所以必须要初始化vif后才能读到正确的值。

如果sensor端mipi的clk和data跟芯片出来的不一致,可以通过dts的csi来配置:

csi {
/* mipi0 2lane setting */
/* Config max lane number */
csi_sr0_lane_num = <1>; // 1: for GC1054 1 lane; 2: for imx307 2 lane
/* Config lane selection */
csi_sr0_lane_select = <1 0 2 3 4>; //<clk d0 d1 d2 d3>; <1 0 2 3 4> for GC1054, <0 1 2 3 4> for imx307
//csi_sr1_lane_select = <1 0 2 3 4>;
/* Config lane P/N swap */
csi_sr0_lane_pn_swap = <1 1 1 1 1>;
//csi_sr1_lane_pn_swap = <1 1 1 1 1>;
};

其中csi_sr0_lane_select是对应驱动中的一个数组,数组里面的元素为PADA_OUT_CH对应的坐标,csi_sr0_lane_select里面5个位置分别对应MIPI CSI的\< CLK Lane0 Lane1 Lane2 Lane3>

以接1lane的gc1054为例,只要配置clk和lane0就可以了,对应的clk和lane0 index分别为1,0,所以csi_sr0_lane_select的值为\< 1 0 x x x> ;

但是csi_sr0_lane_pn_swap 里面5个位置分别对应 PADA_OUT_\< CH0 CH1 CH2 CH3 CH4>是否需要P/N交叉,而不是对应 \< CLK Lane0 Lane1 Lane2 Lane3> 这5组lane的顺序,注意swap的5个index固定对应PADA_OUT_CH,不随select的lane顺序变化改变。

如上图原本芯片PAD_SR_IO07要接的是mipi P信号,但是实际接是sensor的N信号,所以csi_sr0_lane_pn_swap的值也要填1来做swap。

如果dts里面没有配置csi信息,驱动默认吃的2lane如下配置:

csi {
    /* mipi0 2lane setting */
    /* Config max lane number */
    csi_sr0_lane_num = <2>; // 1: for GC1054 1 lane; 2: for imx307 2 lane
    /* Config lane selection */
    csi_sr0_lane_select = <1 0 2 3 4>; 
    csi_sr1_lane_select = <1 0 2 3 4>;
    /* Config lane P/N swap */
    csi_sr0_lane_pn_swap = <1 1 1 1 1>;
    csi_sr1_lane_pn_swap = <1 1 1 1 1>;
};

1.1.2. Mipi mclk & powerdown & reset pin配置

首先跟硬件确认用的哪组pin然后在hwchecklist找到使用的mode,如下是公版接两个gc1054 sensor使用的pin:

所以在kernel\arch\arm\boot\dts\pioneer3.dtsi中配置sensor0和sensor1的mode为1:

22. vif: vif {  
23.     compatible = "sstar,vif";  
24.     status = "ok";  
25.     reg = <0x1F263200 0x600>, <0x0 0x0>, <0x0 0x0>, <0x0 0x0>, <0x0 0x0>, <0x0 0x0>, <0x1F203C00 0x200>, <0x1F227200 0x200>, <0x1F207000 0x200>, <0x1F000000 0x400000>, <0x1F207C00 0x200>;  
26.     //clocks = <&CLK_sr_mclk>;  
27.     interrupts = <GIC_SPI INT_IRQ_VIF IRQ_TYPE_LEVEL_HIGH>;  
28.     // Config sensor 0 pad mux  
29.   
30.     vif_sr0_par_mode = <3>;  
31.     vif_sr0_parallel_rst_mode = <1>;  
32.     vif_sr0_parallel_pdn_mode = <1>;  
33.     vif_sr0_mclk_mode = <1>;  
34.     vif_sr0_mipi_mode = <1>;  
35.     vif_sr0_mipi_ctrl_mode = <1>;  
36.     vif_sr0_bt656_mode = <4>;  
37.     // Config sensor 1 pad mux  
38.     vif_sr1_par_mode = <0>;  
39.     vif_sr1_mipi_mode = <1>;  
40.     vif_sr1_mipi_ctrl_mode = <1>;  
41.     vif_sr1_bt656_mode = <2>;  
42. };

配置完成后可以通过读如下寄存器看配置是否成功:

Sensor0: /customer/riu_r 0x103c 0x74 //查看bit8~9对应的值是否为vif_sr0_mipi_ctrl_mode配置的值

Sensor1: /customer/riu_r 0x103c 0x74 //查看bit12~13对应的值是否为vif_sr1_mipi_ctrl_mode配置的值

注意:开机不会自动配置这个寄存器,是在初始化vif的时候才会配置,所以必须要初始化vif后才能读到正确的值。


1.1.3. Mipi i2c的配置

首先跟硬件确认sensor用的是哪组i2c,然后在对应的dts里面配置sensor的i2c bus,如下是公板接两个gc1054 sensor共用一路i2c0的配置:

1.  sensorif: sensorif {  
2.      compatible = "sigma,sensorif";  
3.      sensorif_grp0_i2c = <0>;  
4.      sensorif_grp1_i2c = <0>;  
5.  };

I2c具体pin的配置是在kernel\arch\arm\boot\dts\下面对应padmux的dtsi中配置:

1.  //i2c0_mode_11  
2.  <PAD_SR_IO14               PINMUX_FOR_I2C0_MODE_7       MDRV_PUSE_I2C0_SCL>,  
3.  <PAD_SR_IO15               PINMUX_FOR_I2C0_MODE_7       MDRV_PUSE_I2C0_SDA>,

配置完成后,可以开机通过读如下寄存器确认是否匹配成功:

I2c0: /customer/riu_r 0x103c 6f //bit0~3是否为对应mode的值

I2c1: /customer/riu_r 0x103c 6f //bit4~7是否为对应mode的值

1.2. Sensor 驱动导入

Sensor驱动里面主要包含sensor的slave地址和lanenum以及初始化参数。拿到sensor驱动后放到sdk\driver\SensorDriver\drv\src目录,make clean;make即可得到对应sensor的ko。

遇到多sensor的场景,是通过insmod ko所带参数chmap来决定sensor驱动对应哪颗sensor,对应关系如下:

Sensor N \rightarrow chmap:2^N

Chmap的参数在project\configs\defconfigs下面对应的config文件中配置:

1.3. Sensor iq文件导入

目前sensor图像的效果主要是靠iqfile和iq api两个文件来调节,分别放在如下目录:

其中iqfile是common部分一般不会改动,iq 工程师主要是调节iq api文件来调节图像的效果。这两个文件在project\configs\defconfigs对应的config文件中配置:

1.4. Demo使用参考

Sensor相关的SDK模块主要是sensor & vif & vpe,需要注意的地方如下。

1.4.1. Sensor

Sensor模块主要是从sensor驱动里面拿到sensor信息供其他模块使用以及配置sensor的分辨率。

1.  DBG_INFO("i[%d]\n", i);  
2.  //Choose sensor ID  
3.  eSNRPad = (MI_SNR_PAD_ID_e)i;  
4.  //set HDR mode  
5.  if(pstConfig->s32HDRtype > 0)  
6.  {  
7.      STCHECKRESULT(MI_SNR_SetPlaneMode(eSNRPad, TRUE));  
8.  }  
9.  else  
10. {  
11.     STCHECKRESULT(MI_SNR_SetPlaneMode(eSNRPad, FALSE));  
12. }  
13. //Query all resolutions supported by sensor driver  
14. STCHECKRESULT(MI_SNR_QueryResCount(eSNRPad, &u32ResCount));  
15. for(u8ResIndex = 0; u8ResIndex < u32ResCount; u8ResIndex++)  
16. {  
17.     MI_SNR_GetRes(eSNRPad, u8ResIndex, &stRes);  
18.     DBG_INFO("eSNRPad[%d], index[%d], Crop(%d,%d,%d,%d), outputsize(%d,%d), maxfps[%d], minfps[%d], ResDesc[%s] \n",  
19.     eSNRPad,  
20.     u8ResIndex,  
21.     stRes.stCropRect.u16X, stRes.stCropRect.u16Y, stRes.stCropRect.u16Width,stRes.stCropRect.u16Height,  
22.     stRes.stOutputSize.u16Width, stRes.stOutputSize.u16Height,  
23.     stRes.u32MaxFps,stRes.u32MinFps,  
24.     stRes.strResDesc);  
25. }  
26.   
27. DBG_INFO("eSNRPad[%d], cnt[%d]resolutions, choice[%d] \n", eSNRPad, u32ResCount, pstConfig->u8SNRChocieRes);  
28. #if 0  
29. do  
30. {  
31.     scanf("%d", &u32ChocieRes);  
32.     ST_Flush();  
33.     MI_SNR_QueryResCount(E_MI_SNR_PAD_ID_0, &u32ResCount);  
34.     if(u32ChocieRes >= u32ResCount)  
35.     {  
36.         DBG_INFO("choice err res %d > =cnt %d\n", u32ChocieRes, u32ResCount);  
37.     }  
38. }while(u32ChocieRes >= u32ResCount);  
39. DBG_INFO("You select %d res\n", u32ChocieRes);  
40. #else  
41.   
42. u32ChocieRes = pstConfig->u8SNRChocieRes;  
43. #endif  
44. //gc1054 default set mirror/flip = 1  
45. if(ST_Sensor_Type_GC1054 == pstConfig->enSensorType)  
46. {  
47.     STCHECKRESULT(MI_SNR_SetOrien(eSNRPad, 1, 1));  
48. }  
49. //Select the resolution you want to output  
50. STCHECKRESULT(MI_SNR_SetRes(eSNRPad,u32ChocieRes));  
51. //enable sensor  
52. STCHECKRESULT(MI_SNR_Enable(eSNRPad));  
53. //Get the resolution, frame rate and pixformat information output by the sensor  
54. STCHECKRESULT(MI_SNR_GetPadInfo(eSNRPad, &stPadInfo));  
55. STCHECKRESULT(MI_SNR_GetPlaneInfo(eSNRPad, 0, &stSnrPlaneInfo));  
56.   
57. g_u32CapWidth = stSnrPlaneInfo.stCapRect.u16Width;  
58. g_u32CapHeight = stSnrPlaneInfo.stCapRect.u16Height;  
59. u32CapWidth = stSnrPlaneInfo.stCapRect.u16Width;  
60. u32CapHeight = stSnrPlaneInfo.stCapRect.u16Height;  
61. eFrameRate = E_MI_VIF_FRAMERATE_FULL;  
62. ePixFormat = (MI_SYS_PixelFormat_e)RGB_BAYER_PIXEL(stSnrPlaneInfo.ePixPrecision, stSnrPlaneInfo.eBayerId);

1.4.2. Vif

Vif模块主要是配置sensor进来图像的分辨率,PixFormat,帧率,需要注意的地方是vif的channel num跟vif dev的对应关系是:

Dev N \rightarrow Channel 4*N

1.   //Select the Vif device, channel and port to be initialized        
2.   u32VifDevId = i;  
3.   u32VifChnId = i * 4;  
4.   u32VifPortId = 0;  
5.   eVifHdrType = (MI_VIF_HDRType_e)pstConfig->s32HDRtype;  
6.  //Select frame or realtime mode. Realtime mode only supports the scene of one sensor  
7.   eVifWorkMode = u8SensorNum > 1 ? E_MI_VIF_WORK_MODE_RGB_FRAMEMODE : E_MI_VIF_WORK_MODE_RGB_REALTIME;  
8.   DBG_INFO("VIF:DevId[%d] ChnId[%d] PortId[%d], eVifWorkMode[%d]\n", u32VifDevId, u32VifChnId, u32VifPortId, eVifWorkMode);  
9.  //enable vif  
10.  STCHECKRESULT(ST_Vif_EnableDev(u32VifDevId, eVifWorkMode, eVifHdrType, &stPadInfo));  
11.   
12.  memset(&stVifPortInfoInfo, 0, sizeof(ST_VIF_PortInfo_T));  
13.  stVifPortInfoInfo.u32RectX = stSnrPlaneInfo.stCapRect.u16X;  
14.  stVifPortInfoInfo.u32RectY = stSnrPlaneInfo.stCapRect.u16Y;  
15.  stVifPortInfoInfo.u32RectWidth = u32CapWidth;  
16.  stVifPortInfoInfo.u32RectHeight = u32CapHeight;  
17.  stVifPortInfoInfo.u32DestWidth = u32CapWidth;  
18.  stVifPortInfoInfo.u32DestHeight = u32CapHeight;  
19.  stVifPortInfoInfo.eFrameRate = eFrameRate;  
20.  stVifPortInfoInfo.ePixFormat = ePixFormat;  
21.  //Set the position, resolution, frame rate and pixformat of the output image of port corresponding to Vif  
22.  STCHECKRESULT(ST_Vif_CreatePort(u32VifChnId, u32VifPortId, &stVifPortInfoInfo));  
23.  //Start the corresponding port  
24.  STCHECKRESULT(ST_Vif_StartPort(u32VifDevId, u32VifChnId, u32VifPortId));

1.4.3. Vpe

Vpe模块主要是设置输出图像的分辨率,PixFormat。

1.   //Select the dev, CHN, port to initialize         
2.   u32VpeDevId = 0;  
3.   u32VpeChnId = i;  
4.   u32VpePortId = 0;  
5.   memset(&stVpeChannelInfo, 0, sizeof(ST_VPE_ChannelInfo_T));  
6.   eVpeHdrType = (MI_VPE_HDRType_e)pstConfig->s32HDRtype;  
7.   stVpeChannelInfo.u16VpeMaxW = u32CapWidth;  
8.   stVpeChannelInfo.u16VpeMaxH = u32CapHeight;  
9.   stVpeChannelInfo.u32X = 0;  
10.  stVpeChannelInfo.u32Y = 0;  
11.  stVpeChannelInfo.u16VpeCropW = 0;  
12.  stVpeChannelInfo.u16VpeCropH = 0;  
13.  stVpeChannelInfo.eRunningMode = u8SensorNum > 1 ? E_MI_VPE_RUN_CAM_MODE : E_MI_VPE_RUN_REALTIME_MODE;  
14.  stVpeChannelInfo.eFormat = ePixFormat;  
15.  stVpeChannelInfo.e3DNRLevel = pstConfig->en3dNrLevel;  
16.  stVpeChannelInfo.eHDRtype = eVpeHdrType;  
17.  stVpeChannelInfo.bRotation = FALSE;  
18.  if(stVpeChannelInfo.eRunningMode == E_MI_VPE_RUN_DVR_MODE)  
19.  {  
20.      stVpeChannelInfo.eBindSensorId = E_MI_VPE_SENSOR_INVALID;  
21.  }  
22.  else  
23.  {  
24.      stVpeChannelInfo.eBindSensorId = (MI_VPE_SensorChannel_e)(eSNRPad+1);  
25.  }  
26.  DBG_INFO("VPE:DevId[%d] ChnId[%d] PortId[%d],eRunningMode[%d]\n", u32VpeDevId, u32VpeChnId, u32VpePortId, stVpeChannelInfo.eRunningMode);  
27. //Set the position, resolution, crop and pixformat information of the corresponding channel output image  
28.  STCHECKRESULT(ST_Vpe_CreateChannel(u32VpeChnId, &stVpeChannelInfo));  
29.  STCHECKRESULT(ST_Vpe_StartChannel(u32VpeChnId));

如果需要通过iq tool调节图像效果,还需要call MI_IQSERVER_Open打开对应的vpe channel。具体使用参考Demo源码。

1.  //Select the VPE channel to be adjusted       
2.  u32VpeDevId = 0;  
3.  u32VpeChnId = i;  
4.  u32VpePortId = 0;  
5.  //open ip server  
6.  memset(&stVifPortInfo, 0, sizeof(MI_VIF_ChnPortAttr_t));  
7.  STCHECKRESULT(MI_VIF_GetChnPortAttr(u32VpeChnId, u32VpePortId, &stVifPortInfo));  
8.  STCHECKRESULT(MI_IQSERVER_Open(stVifPortInfo.stDestSize.u16Width, stVifPortInfo.stDestSize.u16Height, u32VpeChnId));

2. Demo源码参考

Sensor DemoCode参考