SSU_SENSOR使用参考
1. 硬件接口确认¶
如下图demo 板上支持MIPI0 (4lane) 或者 MIPI00 + MIPI01 (2+2 lane)
通过上面的接口可以确认
pinmux mode type | FPC(4lane) | FPC(2+2) |
---|---|---|
mipi_mode | snr0 mode1 | snr0 & snr2 mode6 |
mipiclt_mode | snr0 mode1 | snr0 & snr2 mode1 |
I2C_mode | I2C0 mode1 | I2C0 & I2C1 mode1 |
PS: BGA16 只有MIPI0 4lane snr0或者 拆成 MIPI00 2lane + MIPI01 2lane snr0 + snr2, 所以目前设置 2+2 驱动上要注意 配置是snr0 和snr2
snr0 对应 snr00、srn2对应snr01、snr1对应snr10、snr3对应snr11。 Opera 最高规格支持MIPI0(4lane) + MIPI1(2lane)。MIPI0 可以拆分为MIPI00和MIPI01 --snr00和snr01。MIPI1 拆分为MIPI10和MIPI11 --snr10和snr11。
2. 驱动配置¶
2.1. dts 配置¶
4lane:
<vif> vif_sr0_mipi_mode = <1>; vif_sr0_mipi_rst_mode = <1>; vif_sr0_mipi_pdn_mode = <1>; vif_sr0_mipi_mclk_mode = <1>; <csi> //csi 操作 可以sensor 0通过riu_r 0x1538 0x6 0xA 0xE 0x22 0x25 来确定线序 bit[12:15] csi_sr0_lane_num = <4>; csi_sr1_lane_num = <4>; csi_sr2_lane_num = <2>; csi_sr3_lane_num = <2>; csi_sr0_lane_select = <2 1 3 0 4>; csi_sr1_lane_select = <2 1 3 0 4>; csi_sr2_lane_select = <2 1 0>; csi_sr3_lane_select = <2 1 0>; csi_sr0_lane_pn_swap = <0 0 0 0 0>; csi_sr1_lane_pn_swap = <0 0 0 0 0>; csi_sr2_lane_pn_swap = <0 0 0>; csi_sr3_lane_pn_swap = <0 0 0>; <sensorif> //配置sensor 绑定的i2c sensorif_mipi_grp0_i2c = <0>; sensorif_mipi_grp1_i2c = <1>; sensorif_mipi_grp2_i2c = <1>;
2+2lane:
<vif> vif_sr0_mipi_mode = <6>; vif_sr0_mipi_rst_mode = <1>; vif_sr0_mipi_pdn_mode = <1>; vif_sr0_mipi_mclk_mode = <1>; vif_sr2_mipi_mode = <6>; vif_sr2_mipi_rst_mode = <1>; vif_sr2_mipi_pdn_mode = <1>; vif_sr2_mipi_mclk_mode = <1>; <csi> //csi 操作 可以sensor 0通过riu_r 0x1538 0x6 0xA 0xE 0x22 0x25 来确定线序 bit[12:15] csi_sr0_lane_num = <2>; csi_sr1_lane_num = <4>; csi_sr2_lane_num = <2>; csi_sr3_lane_num = <2>; csi_sr0_lane_select = <2 1 0>; csi_sr1_lane_select = <2 1 3 0 4>; csi_sr2_lane_select = <2 1 0>; csi_sr3_lane_select = <2 1 0>; csi_sr0_lane_pn_swap = <0 0 0>; csi_sr1_lane_pn_swap = <0 0 0 0 0>; csi_sr2_lane_pn_swap = <0 0 0>; csi_sr3_lane_pn_swap = <0 0 0>; <sensorif> //配置sensor 绑定的i2c sensorif_mipi_grp0_i2c = <0>; sensorif_mipi_grp1_i2c = <1>; sensorif_mipi_grp2_i2c = <1>;
2.2. IIC 配置¶
如上节所示: 4lane 情况下snr0 绑定 i2c0 mode1 2+2情况下snr00 和 snr01 绑定i2c0 mode1 和 i2c1 mode1
Sensorif_mipi_grp0_i2c = <0>
grp0
代表MIPI sensor 0
<0>
代表使用I2C bus 0
I2C padmux 在对应kernel\arch\arm\boot\dts\下面对应padmux的dtsi中配置:
//I2C1 Mode1,sensorif_mipi_grp1_i2c <PAD_I2C1_SCL PINMUX_FOR_I2C1_MODE_1 MDRV_PUSE_I2C1_SCL>, <PAD_I2C1_SDA PINMUX_FOR_I2C1_MODE_1 MDRV_PUSE_I2C1_SDA>, //I2C0 Mode1,sensorif_mipi_grp0_i2c <PAD_I2C0_SDA PINMUX_FOR_I2C0_MODE_1 MDRV_PUSE_I2C0_SDA>, <PAD_I2C0_SCL PINMUX_FOR_I2C0_MODE_1 MDRV_PUSE_I2C0_SCL>,
I2c0: /customer/riu_r 0x103c 6f //bit[0:2]是否为对应mode的值
I2c1: /customer/riu_r 0x103c 53 //bit[0:2]是否为对应mode的值
2.3. MIPI 接口线序匹配¶
csi_sr0_lane_select里面5个位置分别对应MIPI CSI的\< CLK Lane0 Lane1 Lane2 Lane3>
如下图:clk 在CH2位置, D0 在CH1位置, D1 在CH3, D2在CH0, D4在CH4,所以csi_sr0_lane_select = <2 1 3 0 4>
如下图:clk 在CH2位置, D0 在CH1位置, D1 在CH0 所以csi_sr0_lane_select = <2 1 0>
如下图sc132gs_4lane, clk 在CH2位置, D0 在CH3位置, D1 在CH2, D2在CH4, D4在CH0,所以csi_sr0_lane_select = <2 3 1 4 0>
如下图sc132gs_2lane, clk 在CH2位置, D0 在CH0位置, D1 在CH1 所以csi_sr0_lane_select = <2 0 1>
lane 顺序修改 ./riu_r 0x1538 0x6 0xA 0xE 0x22 0x25 的bit[12:15] 来看顺序是否有生效 0x1538 为sensor0 MIPI mode Sensor0: /customer/riu_r 0x103c 0x69 //查看bit[0:2]对应的值是否为vif_sr0_mipi_mode配置的值 Sensor1: /customer/riu_r 0x103c 0x69 //查看bit[4:6]对应的值是否为vif_sr1_mipi_mode配置的值 /customer/riu_r 0x103c 0x51 //查看bit[0]对应的值是否为vif_sr0_mipi_pdn_mode的值 /customer/riu_r 0x103c 0x6a //查看bit[0]对应的值是否为vif_sr0_mipi_mclk_mode的值 /customer/riu_r 0x103c 0x54 //查看bit[0]对应的值是否为vif_sr0_mipi_rst_mode的值 Sensor1: /customer/riu_r 0x103c 0x51 //查看bit[2]对应的值是否为vif_sr0_mipi_pdn_mode的值 /customer/riu_r 0x103c 0x6a //查看bit[3]对应的值是否为vif_sr0_mipi_mclk_mode的值 /customer/riu_r 0x103c 0x54 //查看bit[2]对应的值是否为vif_sr0_mipi_rst_mode的值
以上所述csi N\P 和 sensor 板的MIPI 接口 N\P 一致, 则配置csi_sr0_lane_pn_swap = <0 0 0 0 0>, 如果N 和 P 相接即配置csi_sr0_lane_pn_swap = <1 1 1 1 1>
PS:由于修改sensor 线序需要替换kernel,较为麻烦, 可以先用以下方式快速确认线序
通过加载 insmod /config/modules/5.10/mi_sensor.ko gp_sntExternalConfig=/customer/sensorpad0_2lane.json
加载json来配置
例如:
imx307 2lane线序 2 1 0:
{ "SensorIF": [ { "sensorPad": 0, "hwClass": "mipi", "content": { "lane_number": 2, "hdr_lane_number": 2, "lane_select": "2,1,0", "lane_swap": "0,0,0" } }, { "sensorPad": 2, "hwClass": "mipi", "content": { "lane_number": 2, "hdr_lane_number": 2, "lane_select": "2,1,0", "lane_swap": "0,0,0" } } ] }
sc132gs 2lane线序 2 0 1:
{ "SensorIF": [ { "sensorPad": 0, "hwClass": "mipi", "content": { "lane_number": 2, "hdr_lane_number": 2, "lane_select": "2,0,1", "lane_swap": "0,0,0" } }, { "sensorPad": 2, "hwClass": "mipi", "content": { "lane_number": 2, "hdr_lane_number": 2, "lane_select": "2,0,1", "lane_swap": "0,0,0" } } ] }
2.4. sensor 驱动加载¶
insmod /config/modules/5.10/imx307_MIPI.ko chmap=1 sensor 0 ----> chmap=1 sensor 1 ----> chmap=2 sensor 2 ----> chmap=4 sensor 3 ----> chmap=8
Chmap的参数在project\configs\defconfigs下面对应的config文件中配置
SENSOR_LIST = imx323.ko imx415_MIPI.ko imx307_MIPI.ko SENSOR0 = imx307_MIPI.ko //sensor 0 选择sensor driver SENSOR0_OPT = chmap=1 lane_num=4 mclk=36M //sensor 0 设置driver参数 SENSOR1 = SENSOR1_OPT =
sensor IQ 文件导入 sensor图像的效果主要是靠iqfile和iq api两个文件来调节。
两个文件在project\configs\defconfigs对应的config文件中配置
2.5. sensor driver 部分函数介绍¶
函数名 | 功能 |
---|---|
cus_camsensor_init_handle | c设置sensor基础参数、注册功能回调 |
chandle->pCus_sensor_init\handle->pCus_sensor_release | c初始化sensor(通过iic配置参数) |
chandle->pCus_sensor_poweron/handle->pCus_sensor_poweroff | c上电\掉电函数(poweron会在sensor_init之前调用) |
chandle->sif_bus | c接口类型(MIPI、DVP等) |
chandle->data_prec | c数据类型(raw8\10\12 YUV等) |
chandle->bayer_id\handle->RGBIR_id | cBAYE或者RGB排列顺序 |
chandle->interface_attr.attr_mipi | cMIPI 配置 |
chandle->video_res_supported | c支持多少种配置 |
chandle->i2c_cfg | iic配置 |
chandle->pwdn_POLARITY\handle->reset_POLARITY\handle->VSYNC_POLARITY\handle->HSYNC_POLARITY\handle->PCLK_POLARITY | c控制引脚的极性配置 |
chandle->mclk | cMCLK clk |
csensor_if->SetCSI_Clk\sensor_if->SetCSI_Lane\sensor_if->SetCSI_LongPacketType | cCSI 配置(clk、 lane 数、支持收包类型(1c代表支持收Raw8、10、12)) |
cPreview_line_period | c行长(包含h blank) |
cparams->expo.vts | c帧长(包含V blank& h blank) |
PS: Preview_line_period = 1*10^9/(fps*(data_h+v_blank))
3. TEST DEMO¶
snr vif 初始化函数
MI_S32 ST_VifInit(ST_Stream_Attr_T *pStreamAttr) { MI_SNR_PADInfo_t stSnrPadInfo; MI_SNR_PlaneInfo_t stSnrPlaneInfo; MI_SNR_PADID snrPadId = pStreamAttr->u32SnrId; MI_U32 u32ResCount = 0; memset(&stSnrPadInfo, 0x0, sizeof(MI_SNR_PADInfo_t)); memset(&stSnrPlaneInfo, 0x0, sizeof(MI_SNR_PlaneInfo_t)); ExecFunc(MI_SNR_SetPlaneMode(snrPadId, FALSE), DRM_SUCCESS); ExecFunc(MI_SNR_QueryResCount(snrPadId, &u32ResCount), DRM_SUCCESS); if(pStreamAttr->u32SnrChoiceRes > u32ResCount-1){ printf("MI_SNR_QueryResCount :%d\n", u32ResCount); return -1; } ExecFunc(MI_SNR_SetRes(snrPadId, pStreamAttr->u32SnrChoiceRes), DRM_SUCCESS); ExecFunc(MI_SNR_Enable(snrPadId), DRM_SUCCESS); /************************************************ Step1: Init Vif *************************************************/ MI_VIF_GROUP VifGroupId = 0; MI_VIF_DEV VifDevId = 0; MI_VIF_DEV VifChnId = pStreamAttr->VifChnId; MI_VIF_PORT VifPortId = pStreamAttr->VifPortId; MI_VIF_GroupAttr_t stVifGroupAttr; MI_VIF_DevAttr_t stVifDevAttr; MI_VIF_OutputPortAttr_t stVifPortAttr; get_vif_from_snrpad(snrPadId, &VifGroupId, &VifDevId); memset(&stVifGroupAttr, 0x0, sizeof(MI_VIF_GroupAttr_t)); memset(&stVifDevAttr, 0x0, sizeof(MI_VIF_DevAttr_t)); memset(&stVifPortAttr, 0x0, sizeof(MI_VIF_OutputPortAttr_t)); ExecFunc(MI_SNR_GetPadInfo(snrPadId, &stSnrPadInfo), DRM_SUCCESS); ExecFunc(MI_SNR_GetPlaneInfo(snrPadId, 0, &stSnrPlaneInfo), DRM_SUCCESS); printf( "MI_SNR_GetPlaneInfo %d, outputsize(%d, %d, %d, %d)\n", snrPadId,stSnrPlaneInfo.stCapRect.u16X,stSnrPlaneInfo.stCapRect.u16Y, stSnrPlaneInfo.stCapRect.u16Width,stSnrPlaneInfo.stCapRect.u16Height); stVifGroupAttr.eIntfMode = E_MI_VIF_MODE_MIPI; stVifGroupAttr.eWorkMode = E_MI_VIF_WORK_MODE_1MULTIPLEX; stVifGroupAttr.eHDRType = E_MI_VIF_HDR_TYPE_OFF; if (stVifGroupAttr.eIntfMode == E_MI_VIF_MODE_BT656) { stVifGroupAttr.eClkEdge = (MI_VIF_ClkEdge_e)stSnrPadInfo.unIntfAttr.stBt656Attr.eClkEdge; } else { stVifGroupAttr.eClkEdge = E_MI_VIF_CLK_EDGE_DOUBLE; } ExecFunc(MI_VIF_CreateDevGroup(VifGroupId, &stVifGroupAttr), DRM_SUCCESS); stVifDevAttr.stInputRect.u16X = stSnrPlaneInfo.stCapRect.u16X; stVifDevAttr.stInputRect.u16Y = stSnrPlaneInfo.stCapRect.u16Y; stVifDevAttr.stInputRect.u16Width = stSnrPlaneInfo.stCapRect.u16Width; stVifDevAttr.stInputRect.u16Height = stSnrPlaneInfo.stCapRect.u16Height; if (stSnrPlaneInfo.eBayerId >= E_MI_SYS_PIXEL_BAYERID_MAX) { stVifDevAttr.eInputPixel = stSnrPlaneInfo.ePixel; } else { stVifDevAttr.eInputPixel = (MI_SYS_PixelFormat_e)RGB_BAYER_PIXEL( stSnrPlaneInfo.ePixPrecision, stSnrPlaneInfo.eBayerId); } ExecFunc(MI_VIF_SetDevAttr(VifDevId, &stVifDevAttr), DRM_SUCCESS); ExecFunc(MI_VIF_EnableDev(VifDevId), DRM_SUCCESS); stVifPortAttr.stCapRect.u16X = stSnrPlaneInfo.stCapRect.u16X; stVifPortAttr.stCapRect.u16Y = stSnrPlaneInfo.stCapRect.u16Y; stVifPortAttr.stCapRect.u16Width = stSnrPlaneInfo.stCapRect.u16Width; stVifPortAttr.stCapRect.u16Height = stSnrPlaneInfo.stCapRect.u16Height; stVifPortAttr.stDestSize.u16Width = stSnrPlaneInfo.stCapRect.u16Width; stVifPortAttr.stDestSize.u16Height = stSnrPlaneInfo.stCapRect.u16Height; stVifPortAttr.eFrameRate = E_MI_VIF_FRAMERATE_FULL; if (stSnrPlaneInfo.eBayerId >= E_MI_SYS_PIXEL_BAYERID_MAX) { stVifPortAttr.ePixFormat = stSnrPlaneInfo.ePixel; } else { stVifPortAttr.ePixFormat = (MI_SYS_PixelFormat_e)RGB_BAYER_PIXEL( stSnrPlaneInfo.ePixPrecision, stSnrPlaneInfo.eBayerId); } ExecFunc(MI_VIF_SetOutputPortAttr(VifDevId, VifPortId, &stVifPortAttr), DRM_SUCCESS); return 0; }
4. DEBUG¶
-
抓图debug
echo dumptaskfile 0 2 /mnt/pcm > /proc/mi_modules/mi_isp/mi_isp0 echo dumptaskfile 0 2 /mnt/pcm > /proc/mi_modules/mi_scl/mi_scl0 /mnt/pcm :存图路径 2:抓2张图 0: chnNum
-
读取VIF debug信息