SSU_SENSOR使用参考


1. 硬件接口确认

如下图demo 板上支持MIPI0 (4lane) 或者 MIPI00 + MIPI01 (2+2 lane)

图1-1 028A_demo板_硬件图

图1-2 028A_MIPI方案接口_硬件图

图1-3 028A_demo板_pinmux图

图1-4 028A_demo板_pinmux图

图1-5 028A_demo板_pinmux图

通过上面的接口可以确认

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>

图2-1 imx307_4lane

如下图:clk 在CH2位置, D0 在CH1位置, D1 在CH0 所以csi_sr0_lane_select = <2 1 0>

图2-2 imx307_2lane

如下图sc132gs_4lane, clk 在CH2位置, D0 在CH3位置, D1 在CH2, D2在CH4, D4在CH0,所以csi_sr0_lane_select = <2 3 1 4 0>

图2-3 sc132gs_4lane

如下图sc132gs_2lane, clk 在CH2位置, D0 在CH0位置, D1 在CH1 所以csi_sr0_lane_select = <2 0 1>

图2-4 sc132gc_2lane

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

帧结构图

mclk支持配置时钟类型

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信息

    请参考MI VIF API 章节5.PROCFS介绍