海思HDMI设置自定义输出时序

海思3559SDK(版本Hi3559AV100_SDK_V2.0.3.0)只定义了以下HDMI输出格式:

typedef enum hiVO_INTF_SYNC_E

{

    VO_OUTPUT_PAL = 0,               /* PAL standard*/

    VO_OUTPUT_NTSC,                  /* NTSC standard */



    VO_OUTPUT_1080P24,               /* 1920 x 1080 at 24 Hz. */

    VO_OUTPUT_1080P25,               /* 1920 x 1080 at 25 Hz. */

    VO_OUTPUT_1080P30,               /* 1920 x 1080 at 30 Hz. */



    VO_OUTPUT_720P50,                /* 1280 x  720 at 50 Hz. */

    VO_OUTPUT_720P60,                /* 1280 x  720 at 60 Hz. */

    VO_OUTPUT_1080I50,               /* 1920 x 1080 at 50 Hz, interlace. */

    VO_OUTPUT_1080I60,               /* 1920 x 1080 at 60 Hz, interlace. */

    VO_OUTPUT_1080P50,               /* 1920 x 1080 at 50 Hz. */

    VO_OUTPUT_1080P60,               /* 1920 x 1080 at 60 Hz. */



    VO_OUTPUT_576P50,                /* 720  x  576 at 50 Hz. */

    VO_OUTPUT_480P60,                /* 720  x  480 at 60 Hz. */



    VO_OUTPUT_800x600_60,            /* VESA 800 x 600 at 60 Hz (non-interlaced) */

    VO_OUTPUT_1024x768_60,           /* VESA 1024 x 768 at 60 Hz (non-interlaced) */

    VO_OUTPUT_1280x1024_60,          /* VESA 1280 x 1024 at 60 Hz (non-interlaced) */

    VO_OUTPUT_1366x768_60,           /* VESA 1366 x 768 at 60 Hz (non-interlaced) */

    VO_OUTPUT_1440x900_60,           /* VESA 1440 x 900 at 60 Hz (non-interlaced) CVT Compliant */

    VO_OUTPUT_1280x800_60,           /* 1280*800@60Hz VGA@60Hz*/

    VO_OUTPUT_1600x1200_60,          /* VESA 1600 x 1200 at 60 Hz (non-interlaced) */

    VO_OUTPUT_1680x1050_60,          /* VESA 1680 x 1050 at 60 Hz (non-interlaced) */

    VO_OUTPUT_1920x1200_60,          /* VESA 1920 x 1600 at 60 Hz (non-interlaced) CVT (Reduced Blanking)*/

    VO_OUTPUT_640x480_60,            /* VESA 640 x 480 at 60 Hz (non-interlaced) CVT */

    VO_OUTPUT_960H_PAL,              /* ITU-R BT.1302 960 x 576 at 50 Hz (interlaced)*/

    VO_OUTPUT_960H_NTSC,             /* ITU-R BT.1302 960 x 480 at 60 Hz (interlaced)*/

    VO_OUTPUT_1920x2160_30,          /* 1920x2160_30 */

    VO_OUTPUT_2560x1440_30,          /* 2560x1440_30 */

    VO_OUTPUT_2560x1600_60,          /* 2560x1600_60 */

    VO_OUTPUT_3840x2160_24,          /* 3840x2160_24 */

    VO_OUTPUT_3840x2160_25,          /* 3840x2160_25 */

    VO_OUTPUT_3840x2160_30,          /* 3840x2160_30 */

    VO_OUTPUT_3840x2160_50,          /* 3840x2160_50 */

    VO_OUTPUT_3840x2160_60,          /* 3840x2160_60 */

    VO_OUTPUT_320x240_60,            /* For ota5182 at 60 Hz (8bit)  */

    VO_OUTPUT_320x240_50,            /* For ili9342 at 50 Hz (6bit)  */

    VO_OUTPUT_240x320_50,            /* For ili9341 at 50 Hz (6bit)  */

    VO_OUTPUT_240x320_60,            /* For ili9341 at 60 Hz (16bit) */

    VO_OUTPUT_800x600_50,            /* For LCD     at 50 Hz (24bit) */

    VO_OUTPUT_720x1280_60,           /* For MIPI DSI Tx 720 x1280 at 60 Hz */

    VO_OUTPUT_1080x1920_60,          /* For MIPI DSI Tx 1080x1920 at 60 Hz */

    VO_OUTPUT_7680x4320_30,          /* For HDMI2.0 at 30 Hz         */

    VO_OUTPUT_USER,                  /* User timing. */

    VO_OUTPUT_BUTT

} VO_INTF_SYNC_E;

下面以HDMI需要输出分辨率:1280x1024,帧率:30的视频格式为例讲解HDMI自定义输出格式设置流程。

用sample_vio.c中函数HI_S32 SAMPLE_VIO_8K30_PARALLEL(VO_INTF_TYPE_E enVoIntfType)为参考,将其修改成1280x1024@30格式输出。

该函数需要修改一下两个地方。

1、SAMPLE_COMM_VO_GetDefConfig函数功能是初始化输出参数,该函数修改成如下所示:

HI_S32 SAMPLE_COMM_VO_GetDefConfig(SAMPLE_VO_CONFIG_S *pstVoConfig)

{

    RECT_S  stDefDispRect  = {0, 0, 1280, 1024}; //改为1280x1024

    SIZE_S  stDefImageSize = {1280, 1024};

    if(NULL == pstVoConfig)

    {

        SAMPLE_PRT("Error:argument can not be NULL\n");

        return HI_FAILURE;

    }



    pstVoConfig->VoDev             = SAMPLE_VO_DEV_UHD;

    pstVoConfig->enVoIntfType      = VO_INTF_HDMI;

    pstVoConfig->enIntfSync        = VO_OUTPUT_USER; //改为自定义格式

    pstVoConfig->u32BgColor        = COLOR_RGB_BLUE;

    pstVoConfig->enPixFormat       = PIXEL_FORMAT_YVU_SEMIPLANAR_420;

    pstVoConfig->stDispRect        = stDefDispRect;

    pstVoConfig->stImageSize       = stDefImageSize;

    pstVoConfig->enVoPartMode      = VO_PART_MODE_SINGLE;

    pstVoConfig->u32DisBufLen      = 3;

    pstVoConfig->enDstDynamicRange = DYNAMIC_RANGE_SDR8;

    pstVoConfig->enVoMode          = VO_MODE_1MUX;



    return HI_SUCCESS;

}

2、将视频输出设置函数SAMPLE_COMM_VO_StartVO修改成如下所示:

HI_S32 SAMPLE_COMM_VO_StartVO(SAMPLE_VO_CONFIG_S *pstVoConfig)

{

    RECT_S                 stDefDispRect  = {0, 0, 1920, 1080};

    SIZE_S                 stDefImageSize = {1920, 1080};



    /*******************************************

    * VO device VoDev# information declaration.

    ********************************************/

    VO_DEV                 VoDev          = 0;

    VO_LAYER               VoLayer        = 0;

    SAMPLE_VO_MODE_E       enVoMode       = 0;

    VO_INTF_TYPE_E         enVoIntfType   = VO_INTF_HDMI;

    VO_INTF_SYNC_E         enIntfSync     = VO_OUTPUT_1080P30;

    DYNAMIC_RANGE_E        enDstDyRg      = DYNAMIC_RANGE_SDR8;

    VO_PART_MODE_E         enVoPartMode   = VO_PART_MODE_SINGLE;

    VO_PUB_ATTR_S          stVoPubAttr    = {0};

    VO_VIDEO_LAYER_ATTR_S  stLayerAttr    = {0};

    VO_CSC_S               stVideoCSC     = {0};

    HI_S32                 s32Ret         = HI_SUCCESS;



    if (NULL == pstVoConfig)

    {

        SAMPLE_PRT("Error:argument can not be NULL\n");

        return HI_FAILURE;

    }

    VoDev          = pstVoConfig->VoDev;

    VoLayer        = pstVoConfig->VoDev;

    enVoMode       = pstVoConfig->enVoMode;

    enVoIntfType   = pstVoConfig->enVoIntfType;

    enIntfSync     = pstVoConfig->enIntfSync;

    enDstDyRg      = pstVoConfig->enDstDynamicRange;

    enVoPartMode   = pstVoConfig->enVoPartMode;



    /********************************

    * Set and start VO device VoDev#.

    *********************************/

    stVoPubAttr.enIntfType  = enVoIntfType;

    stVoPubAttr.enIntfSync  = enIntfSync;



    stVoPubAttr.u32BgColor  = pstVoConfig->u32BgColor;





    /*

     s32Ret = SAMPLE_COMM_VO_StartDev(VoDev, &stVoPubAttr);

    if (HI_SUCCESS != s32Ret)

    {

        SAMPLE_PRT("SAMPLE_COMM_VO_StartDev failed!\n");

        return s32Ret;

    }*/

         /*将上面注释部分替换成下面部分*/

         /*设置视频输出设备公共属性参数,下面参数一般显示器厂家提供*/

         //同步模式

         stVoPubAttr.stSyncInfo.bSynm=1;

         //0 为隔行,1 为逐行

         stVoPubAttr.stSyncInfo.bIop=1;

         //无效参数,可以忽略。

         stVoPubAttr.stSyncInfo.u8Intfb =0;

         //垂直效区,隔行输出时表示顶场垂直效区。单位:行。

         stVoPubAttr.stSyncInfo.u16Vact =1024;

         //垂直同步信号的宽度。单位:行

         stVoPubAttr.stSyncInfo.u16Vpw=3;

         //垂直消隐后肩,隔行输出时表示顶场垂直消隐后肩。单位:行。

         stVoPubAttr.stSyncInfo.u16Vbb=38;

         //垂直消隐前肩,隔行输出时表示顶场垂直消隐前肩。单位:行

         stVoPubAttr.stSyncInfo.u16Vfb=1;

         //水平效区。单位:像素

         stVoPubAttr.stSyncInfo.u16Hact =1280;

         //水平同步信号的宽度。单位:像素。

         stVoPubAttr.stSyncInfo.u16Hpw=112;

         //水平消隐后肩。单位:像素

         stVoPubAttr.stSyncInfo.u16Hbb=248;

         //水平消隐前肩。单位:像素

         stVoPubAttr.stSyncInfo.u16Hfb=48;

         //底场垂直效区,隔行时有效。单位:行

         stVoPubAttr.stSyncInfo.u16Bvact=512;

         //底场垂直同步效像素值

         stVoPubAttr.stSyncInfo.u16Hmid =3;

         //底场垂直消隐后肩,隔行时有效。单位:行

         stVoPubAttr.stSyncInfo.u16Bvbb =38;

         //底场垂直消隐前肩,隔行时有效。单位:行

         stVoPubAttr.stSyncInfo.u16Bvfb =1;

         //数据效信号的极性。配置 0 为高效,配置 1 为低效 。

         stVoPubAttr.stSyncInfo.bIdv=0;

         //水平效信号的极性,配置 0 为高效,配置 1 为低效。

         stVoPubAttr.stSyncInfo.bIhs=0;

         //垂直效信号的极性,配置 0 为高效,配置 1 为低效。

         stVoPubAttr.stSyncInfo.bIvs=0;



         s32Ret = HI_MPI_VO_SetPubAttr(VoDev, &stVoPubAttr);

         if (s32Ret != HI_SUCCESS)

         {

                   SAMPLE_PRT("failed with %#x!\n", s32Ret);

                   return HI_FAILURE;

         }



         /* Fill user sync info */

         VO_USER_INTFSYNC_INFO_S stUserInfo = {0};

         stUserInfo.stUserIntfSyncAttr.enClkSource = VO_CLK_SOURCE_PLL;

         /*

         u32Fbdiv、u32Frac、u32Refdiv 需满足:PLL 引脚 FOUTVCO 范围在[800, 3200],

         FOUTVCO=FREF x (u32Fbdiv + u32Frac / 2^24) / u32Refdiv (FREF 值固定为 24)。

         u32Postdiv1、u32Postdiv2 需满足 u32Postdiv1 >= u32Postdiv2。

         所以:VO=FOUTVCO/(u32Postdiv1 u32Postdiv2)=FREF x (u32Fbdiv + u32Frac / 2^24) / 
             ( u32Refdiv * u32Postdiv1 * u32Postdiv2)



         像素时钟计算方法:

         Htatal=hpw+hdisp+hfp+hbp

         Vtatal=vpw+vdisp+vfp+vbp

         pixel_clk = Htatal*Vtatal*fps (单位HZ,程序中采用KHZ)

         VO=pixel_clk = 54M= FOUTVCO/(u32Postdiv1 u32Postdiv2)=FREF x (u32Fbdiv +         
                   u32Frac / 2^24) /( u32Refdiv * u32Postdiv1 * u32Postdiv2)

         54 = 24 x (u32Fbdiv + u32Frac / 2^24) /( u32Refdiv * u32Postdiv1 *u32Postdiv2)

         可以设置PLL相关参数如下:

         */

        

         stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Fbdiv = 45; 

         stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Frac = 0;

         stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Postdiv1 = 5;

         stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Postdiv2 = 4;

         stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Refdiv = 1;

         stUserInfo.u32PreDiv = 0;// 设备前置分频

         stUserInfo.u32DevDiv = 2;// 设备的时钟分频比

        //时钟相位是否反向。 1:时钟反向; 0:时钟不反向。
        stUserInfo.bClkReverse = 0; 


        

         /* Set user interface sync info */

         s32Ret = HI_MPI_VO_SetUserIntfSyncInfo(VoDev, &stUserInfo);

         if (s32Ret != HI_SUCCESS)

         {
                 SAMPLE_PRT("Set user interface sync info failed with %x.\n",s32Ret);
                 return HI_FAILURE;
         }

         s32Ret = HI_MPI_VO_SetDevFrameRate(VoDev, 30);//taolang debug 帧率这里暂时设置为30

         if (s32Ret != HI_SUCCESS)

         {

                   SAMPLE_PRT("failed with %#x!\n", s32Ret);

                   return HI_FAILURE;

         }



         s32Ret = HI_MPI_VO_Enable(VoDev);

         if (s32Ret != HI_SUCCESS)

         {

                   SAMPLE_PRT("failed with %#x!\n", s32Ret);

                   return HI_FAILURE;

         }



    /******************************

    * Set and start layer VoDev#.

    ********************************/



    /*s32Ret = SAMPLE_COMM_VO_GetWH(stVoPubAttr.enIntfSync,
               &stLayerAttr.stDispRect.u32Width,&stLayerAttr.stDispRect.u32Height,             
               &stLayerAttr.u32DispFrmRt);

    if (HI_SUCCESS != s32Ret)

    {

        SAMPLE_PRT("SAMPLE_COMM_VO_GetWH failed!\n");

        SAMPLE_COMM_VO_StopDev(VoDev);

        return s32Ret;

    }*/

    /*将上面注释部分修改成,此处也可以直接修改SAMPLE_COMM_VO_GetWH */

    stLayerAttr.stDispRect.u32Width = 1280;

    stLayerAttr.stDispRect.u32Height = 1024;

    stLayerAttr.u32DispFrmRt = 30;



    stLayerAttr.bClusterMode     = HI_FALSE;

    stLayerAttr.bDoubleFrame    = HI_FALSE;

    stLayerAttr.enPixFormat       = pstVoConfig->enPixFormat;



    stLayerAttr.stDispRect.s32X = 0;

    stLayerAttr.stDispRect.s32Y = 0;



    /******************************

    // Set display rectangle if changed.

    ********************************/

    if (0 != memcmp(&pstVoConfig->stDispRect, &stDefDispRect, sizeof(RECT_S)))

    {

        stLayerAttr.stDispRect = pstVoConfig->stDispRect;

    }

    stLayerAttr.stImageSize.u32Width  = stLayerAttr.stDispRect.u32Width;

    stLayerAttr.stImageSize.u32Height = stLayerAttr.stDispRect.u32Height;



    stLayerAttr.stImageSize.u32Width  = stLayerAttr.stDispRect.u32Width;

    stLayerAttr.stImageSize.u32Height = stLayerAttr.stDispRect.u32Height;



    /******************************

    //Set image size if changed.

    ********************************/

    if (0 != memcmp(&pstVoConfig->stImageSize, &stDefImageSize, sizeof(SIZE_S)))

    {

        stLayerAttr.stImageSize = pstVoConfig->stImageSize;

    }

    stLayerAttr.enDstDynamicRange     = pstVoConfig->enDstDynamicRange;





    if (VO_PART_MODE_MULTI == enVoPartMode)

    {

        s32Ret = HI_MPI_VO_SetVideoLayerPartitionMode(VoLayer, enVoPartMode);

        if (HI_SUCCESS != s32Ret)

        {

            SAMPLE_PRT("HI_MPI_VO_SetVideoLayerPartitionMode failed!\n");

            SAMPLE_COMM_VO_StopDev(VoDev);

            return s32Ret;

        }

    }



    if (pstVoConfig->u32DisBufLen)

    {

        s32Ret = HI_MPI_VO_SetDisplayBufLen(VoLayer, pstVoConfig->u32DisBufLen);

        if (HI_SUCCESS != s32Ret)

        {

            SAMPLE_PRT("HI_MPI_VO_SetDisplayBufLen failed with %#x!\n",s32Ret);

            SAMPLE_COMM_VO_StopDev(VoDev);

            return s32Ret;

        }

    }



    s32Ret = SAMPLE_COMM_VO_StartLayer(VoLayer, &stLayerAttr);

    if (HI_SUCCESS != s32Ret)

    {

        SAMPLE_PRT("SAMPLE_COMM_VO_Start video layer failed!\n");

        SAMPLE_COMM_VO_StopDev(VoDev);

        return s32Ret;

    }



    if(VO_INTF_MIPI == enVoIntfType)

    {

        s32Ret = HI_MPI_VO_GetVideoLayerCSC(VoLayer, &stVideoCSC);

        if (HI_SUCCESS != s32Ret)

        {

            SAMPLE_PRT("HI_MPI_VO_GetVideoLayerCSC failed!\n");

            SAMPLE_COMM_VO_StopDev(VoDev);

            return s32Ret;

        }

        stVideoCSC.enCscMatrix =VO_CSC_MATRIX_BT709_TO_RGB_PC;

        s32Ret = HI_MPI_VO_SetVideoLayerCSC(VoLayer, &stVideoCSC);

        if (HI_SUCCESS != s32Ret)

        {

            SAMPLE_PRT("HI_MPI_VO_SetVideoLayerCSC failed!\n");

            SAMPLE_COMM_VO_StopDev(VoDev);

            return s32Ret;

        }

    }



    /******************************

    * start vo channels.

    ********************************/

    s32Ret = SAMPLE_COMM_VO_StartChn(VoLayer, enVoMode);

    if (HI_SUCCESS != s32Ret)

    {

        SAMPLE_PRT("SAMPLE_COMM_VO_StartChn failed!\n");

        SAMPLE_COMM_VO_StopLayer(VoLayer);

        SAMPLE_COMM_VO_StopDev(VoDev);

        return s32Ret;

    }



    /******************************

    * Start hdmi device.

    * Note : do this after vo device started.

    ********************************/

    if(VO_INTF_HDMI & enVoIntfType)

    {

        SAMPLE_COMM_VO_HdmiStartByDyRg(enIntfSync, enDstDyRg);

    }



    /******************************

    * Start mipi_tx device.

    * Note : do this after vo device started.

    ********************************/

    if(VO_INTF_MIPI & enVoIntfType)

    {

        SAMPLE_COMM_VO_StartMipiTx(enIntfSync);

    }



    return HI_SUCCESS;

}

3、修改SAMPLE_COMM_VO_HdmiStartByDyRg->SAMPLE_COMM_VO_HdmiConvertSync

在SAMPLE_COMM_VO_HdmiConvertSync中针对VO_OUTPUT_USER类型返回HI_HDMI_VIDEO_FMT_VESA_CUSTOMER_DEFINE

海思SDK参考资料说明:

1、《HiMPP V4.0 媒体处理软件开发参考》

通过查阅SDK资料《HiMPP V4.0 媒体处理软件开发参考》中视频输出部分得知

HI_S32 HI_MPI_VO_SetDevFrameRate(VO_DEV VoDev, HI_U32 u32FrameRate);API可以设置输出帧率。该API调用说明如下:

2、《Hi3559AV100ES ultra-HD Mobile Camera SoC 用户指南》

PLL相关寄存器说明:

参考博客资料:

https://blog.csdn.net/weixin_46866980/article/details/111600265

https://blog.csdn.net/litao31415/article/details/107331501

https://blog.csdn.net/litao31415/article/details/107326413

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

缥缈孤鸿_jason

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值