多sensor功能实现及代码流程

Version 1.0


1. 硬件说明

1.1. 硬件图说明

图 1-1:硬件实物图

如上图,Pudding 系列板子有两路4 lane MIPI RX:

  • mipi0

    可以作一路4 lane MIPI RX,也可以分为两路 2 lane 的MIPI RX:

    • mipi00

    • mipi01

    • mipi1

注意:当mipi0分成两路2 lane MIPI RX的时候,kernel dts需要更改为infinity6e-ssc012b-s01a-2+2mipi.dts或者infinity6e-ssc013a-s0a1-2+2mipi.dts

1.2. 多sensor 的使用场景

  1. 双sensor接两路4 lane sensor ,其中一路接如上图mipi0,另一路接如图 mipi1;

  2. 双sensor接两路2 lane sensor,其中一路接如图mipi00,另一路接mipi01;

  3. 三sensor 接两路 2 lane sensor + 一路4 lane sensor,其中一路接如图mipi00 ,一路接mipi01,一路接 mipi1。


2. 流程图说明

2.1. SNR PAD与VIF流程图

图 2-1:SNR与VIF流程图

SNR PAD0 对应mipi0(当mipi0作1路4 lane mipi 使用的时候)/mipi00(当mipi0 分成两路2 lane mipi 使用的时候)

SNR PAD1 对应mipi1

SNR PAD2 对应mipi01 (当mipi0 分成两路2 lane mipi 使用的时候)

多sensor连接方式:

  1. 双sensor 接两路4 lane sensor,其中一路接SNR PAD0 另一路接SNR PAD1;分别通过mipi0 和mipi1 连接VIF,因此SNR PAD0->VIF DEV0->VIF Channel 0; SNR PAD1->VIF DEV2->VIF Channel 8。

  2. 双sensor 接两路2 lane sensor,其中一路接SNR PAD0, 另一路接SNR PAD2;分别通过mipi00 和mipi01 连接VIF,因此SNR PAD0->VIF DEV0->VIF Channel 0; SNR PAD2->VIF DEV1->VIF Channel 4。

  3. 三sensor 接两路2 lane sensor,其中一路接pad0 一路接pad2 一路接pad3;分别通过mipi00 、mipi01、mipi1 连接VIF,因此SNR PAD0->VIF DEV0->VIF Channel 0; SNR PAD2->VIF DEV1->VIF Channel 4; SNR PAD1->VIF DEV2->VIF Channel 8

2.2. 多sensor流程图

图 2-2:4lane+4lane双sensor流程图

  1. 接入两路sensor;把两路sensor采集到的raw数据,通过mipi0/1协议传送到VIF device 0/2;

  2. VIF 与VPE Chn之间的bind mode选择frame mode或者unbind 方式,VIF0 连VPE Chn0,VIF2 连VPE Chn1;

  3. ISP 处理完后的数据,会通过WDMA把数据传送到各个VPE input port,经过crop、scale等操作,最终输出到VPE out port,对应的VPE out port 可以接DIVP或者VENC;当然,如果遇到DIVP的scale性能不够等问题,可以考虑DIVP后级连上DIVP。

图 2-3:2lane+2lane双sensor流程图

  1. 接入两路sensor;把两路sensor采集到的raw数据,通过mipi00/01协议传送到vif device 0/1。

  2. VIF与VPE Chn之间的bind mode选择frame mode或者unbind 方式,VIF0 连VPE Chn0,VIF1连VPE Chn1。

  3. ISP 处理完后的数据,会通过WDMA把数据传送到各个VPE input port,过crop、scale等操作,最终输出到VPE out port,对应的VPE out port 可以接DIVP或者VENC;当然,如果遇到DIVP的scale性能不够等问题,可以考虑DIVP后级连上DIVP。

图 2-4:2lane+2lane+4lane 3sensor流程图

  1. 接入三路sensor;把三路sensor采集到的raw数据,通过mipi00/01/1协议传送到vif device 0 / 1 /2

  2. VIF与VPE Chn之间的bind mode选择frame mode或者unbind 方式,VIF0 连VPE Chn0,VIF1连VPE Chn1,VIF2连VPE Chn2;

  3. Isp 处理完后的数据,会通过WDMA把数据传送到各个VPE input port,过crop、scale等操作,最终输出到VPE out port,对应的VPE out port 可以接DIVP或者VENC;当然,如果遇到DIVP的scale性能不够等问题,可以考虑DIVP后级连上DIVP。


3. DEMO CODE

3.1. Demo code 编译及执行

以Pudding接IMX405+IMX274为例,其中IMX405接pad0,IMX274插pad1

/customer/demo.sh脚本(系统启动后会启动)中配置,insmod ko:

insmod /config/modules/4.9.84/imx415_MIPI.ko chmap=1

insmod /config/modules/4.9.84/imx274_MIPI.ko chmap=2

其中chmap 的二进制位表示sensor 对应接入的pad ,如上IMX405 接pad0 chmap 为二进制01,值为1,IMX274 接pad1 ,二进制为10,值为2。

将编译生成的demo prog_dualsensor cp 到customer 目录下,执行./prog_dualsensor 1 1 0。Demo code位于:sdk\verify\mi_demo\source\dualsensor

3.2. Demo code 分析

  1. 调用ST_StreamInit 分别创建每个sensor 出流通道

  2. VIF 创建

    ST_VIF_PortInfo_T stVifPortInfoInfo;
        memset(&stVifPortInfoInfo, 0, sizeof(ST_VIF_PortInfo_T));
        stVifPortInfoInfo.u32RectX = stSnrPlane0Info.stCapRect.u16X;
        stVifPortInfoInfo.u32RectY = stSnrPlane0Info.stCapRect.u16Y;
        stVifPortInfoInfo.u32RectWidth = u32CapWidth;
        stVifPortInfoInfo.u32RectHeight = u32CapHeight;
        stVifPortInfoInfo.u32DestWidth = u32CapWidth;
        stVifPortInfoInfo.u32DestHeight = u32CapHeight;
        stVifPortInfoInfo.eFrameRate = eFrameRate;
        stVifPortInfoInfo.ePixFormat = ePixFormat;//E_MI_SYS_PIXEL_FRAME_RGB_BAYER_12BPP_GR;
        STCHECKRESULT(ST_Vif_CreatePort(vifChn, 0, &stVifPortInfoInfo));
        STCHECKRESULT(ST_Vif_StartPort(0, vifChn, 0));
    
  3. VPE 创建红的eRunningMode需要设置为E_MI_VPE_RUN_CAM_MODE,是ISP 内部走frame mode,如果ISP 内部走的real time mode,ISP 硬件将不能分时复用,导致另外一路VIF数据得不到ISP处理。

    /************************************************
        Step3:  init VPE (create one VPE)
        *************************************************/
        ST_VPE_ChannelInfo_T stVpeChannelInfo;
    
        memset(&stVpeChannelInfo, 0, sizeof(ST_VPE_ChannelInfo_T));
        stVpeChannelInfo.u16VpeMaxW = u32CapWidth;
        stVpeChannelInfo.u16VpeMaxH = u32CapHeight;
        stVpeChannelInfo.u32X = 0;
        stVpeChannelInfo.u32Y = 0;
        stVpeChannelInfo.u16VpeCropW = 0;
        stVpeChannelInfo.u16VpeCropH = 0;
        stVpeChannelInfo.eRunningMode = E_MI_VPE_RUN_CAM_MODE;
        stVpeChannelInfo.eFormat = ePixFormat;//E_MI_SYS_PIXEL_FRAME_RGB_BAYER_12BPP_GR;
        stVpeChannelInfo.eHDRtype = eVpeHdrType;
        if(eSnrPad == E_MI_SNR_PAD_ID_0)
            stVpeChannelInfo.eBindSensorId = E_MI_VPE_SENSOR0;
        else if(eSnrPad == E_MI_SNR_PAD_ID_1)
        stVpeChannelInfo.eBindSensorId = E_MI_VPE_SENSOR1;
        else if(eSnrPad == E_MI_SNR_PAD_ID_2)
            stVpeChannelInfo.eBindSensorId = E_MI_VPE_SENSOR2;
    
        STCHECKRESULT(ST_Vpe_CreateChannel(vpechn, &stVpeChannelInfo));
        STCHECKRESULT(ST_Vpe_StartChannel(vpechn));
    
  4. VIF 与VPE之间的stBindInfo.eBindType = E_MI_SYS_BIND_TYPE_FRAME_BASE;

    /************************************************
    Step1:  bind VIF->VPE
    *************************************************/
    ST_Sys_BindInfo_T stBindInfo;
    memset(&stBindInfo, 0x0, sizeof(ST_Sys_BindInfo_T));
    stBindInfo.stSrcChnPort.eModId = E_MI_MODULE_ID_VIF;
    stBindInfo.stSrcChnPort.u32DevId = s32vifDev;
    stBindInfo.stSrcChnPort.u32ChnId = vifChn;
    stBindInfo.stSrcChnPort.u32PortId = 0;
    
    stBindInfo.stDstChnPort.eModId = E_MI_MODULE_ID_VPE;
    stBindInfo.stDstChnPort.u32DevId = 0;
    stBindInfo.stDstChnPort.u32ChnId = vpechn;
    stBindInfo.stDstChnPort.u32PortId = 0;
    
    stBindInfo.u32SrcFrmrate = 30;
    stBindInfo.u32DstFrmrate = 30;
    stBindInfo.eBindType = E_MI_SYS_BIND_TYPE_FRAME_BASE;
    STCHECKRESULT(ST_Sys_Bind(&stBindInfo));