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