设置Hi3536的HDMI2.0自定义显示时序

        Hi3536的SDK定义了一些常见的分辨率,诸如3840X2160@30/1920X1080@60/3840X2160@60等:

typedef enum hiVO_INTF_SYNC_E
{
    VO_OUTPUT_PAL = 0,
    VO_OUTPUT_NTSC,
    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_1080P24,
    VO_OUTPUT_1080P25,
    VO_OUTPUT_1080P30,
    
    VO_OUTPUT_720P50, 
    VO_OUTPUT_720P60,   
    VO_OUTPUT_1080I50,
    VO_OUTPUT_1080I60,    
    VO_OUTPUT_1080P50,
    VO_OUTPUT_1080P60,            

    VO_OUTPUT_576P50,
    VO_OUTPUT_480P60,

    VO_OUTPUT_640x480_60,            /* VESA 640 x 480 at 60 Hz (non-interlaced) CVT */
    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_1680x1050_60,          /* VESA 1680 x 1050 at 60 Hz (non-interlaced) */
    VO_OUTPUT_1920x2160_30,          /* 1920x2160_30 */
    VO_OUTPUT_1600x1200_60,          /* VESA 1600 x 1200 at 60 Hz (non-interlaced) */
    VO_OUTPUT_1920x1200_60,          /* VESA 1920 x 1600 at 60 Hz (non-interlaced) CVT (Reduced Blanking)*/ 
    VO_OUTPUT_2560x1440_30,          /* 2560x1440_30 */
    VO_OUTPUT_2560x1440_60,          /* 2560x1440_60 */
    VO_OUTPUT_2560x1600_60,          /* 2560x1600_60 */
    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_USER,
    VO_OUTPUT_BUTT

} VO_INTF_SYNC_E;

        但是它不一定都满足我们的需求,譬如,给LED屏幕显示,分辨率可能是奇怪的,那么怎么办呢?

        不用担心,海思提供了接口供我们解决这类问题,就是VO_OUTPUT_USER,即自定义输出时序。下面给出一个例子:

static HI_S32 SAMPLE_COMM_VO_StartDev2(VO_DEV VoDev, VO_PUB_ATTR_S *pstPubAttr, HI_S32 u32Fps)
{
    HI_S32 s32Ret = HI_SUCCESS;

    s32Ret = HI_MPI_VO_SetPubAttr(VoDev, pstPubAttr);
    ...
    
    //设置用户时序下的设备输出帧率(文档要求)
    s32Ret = HI_MPI_VO_SetDevFrameRate(VoDev, u32Fps); //该接口只能配置为25、30、50、60
    ...

    s32Ret = HI_MPI_VO_Enable(VoDev);
    ...
    return s32Ret;
}

HI_S32 HiUsrDisplayTimingConfig(USR_DISPLAY_TIMING_S *pstTiming)
{
    HI_S32 s32Ret = -1;
    VO_DEV voDev = SAMPLE_VO_DEV_DHD0;
    VO_LAYER voLayer = SAMPLE_VO_LAYER_VHD0;
    VO_PUB_ATTR_S stVoPubAttr;
    VO_VIDEO_LAYER_ATTR_S stVoLayerAttr;

    memset(&stVoPubAttr,0,sizeof(VO_PUB_ATTR_S));
    memset(&stVoLayerAttr,0,sizeof(VO_VIDEO_LAYER_ATTR_S));

    stVoPubAttr.enIntfSync = VO_OUTPUT_USER;  //接口时序类型
    stVoPubAttr.enIntfType = VO_INTF_HDMI;    //接口类型
    stVoPubAttr.u32BgColor = 0x000000ff;      //设备背景色
    
    stVoPubAttr.stSyncInfo.bSynm = HI_FALSE;  //保留字段
    stVoPubAttr.stSyncInfo.u8Intfb = 8;       //保留字段
    stVoPubAttr.stSyncInfo.bIdv = HI_FALSE;   //保留字段
    
    stVoPubAttr.stSyncInfo.bIop = pstTiming->bIop;        //逐行或隔行扫描
    
    stVoPubAttr.stSyncInfo.u16Vact = pstTiming->u16Vact;  //垂直有效区域
    stVoPubAttr.stSyncInfo.u16Vbb = pstTiming->u16Vbb;    //垂直消隐后肩
    stVoPubAttr.stSyncInfo.u16Vfb = pstTiming->u16Vfb;    //垂直消隐前肩
    stVoPubAttr.stSyncInfo.u16Hact = pstTiming->u16Hact;  //水平有效区域
    stVoPubAttr.stSyncInfo.u16Hbb = pstTiming->u16Hbb;    //水平消隐后肩
    stVoPubAttr.stSyncInfo.u16Hfb = pstTiming->u16Hfb;    //水平消隐前肩
    
    stVoPubAttr.stSyncInfo.u16Hpw = pstTiming->u16Hpw;     //水平同步宽度 
    stVoPubAttr.stSyncInfo.u16Vpw = pstTiming->u16Vpw;     //垂直同步宽度
    stVoPubAttr.stSyncInfo.bIhs = pstTiming->bIhs;         //hs极性
    stVoPubAttr.stSyncInfo.bIvs = pstTiming->bIvs;         //vs极性

    //隔行扫描相关参数
    stVoPubAttr.stSyncInfo.u16Hmid = pstTiming->u16Hmid;
    stVoPubAttr.stSyncInfo.u16Bvact = pstTiming->u16Bvact;
    stVoPubAttr.stSyncInfo.u16Bvbb = pstTiming->u16Bvbb;
    stVoPubAttr.stSyncInfo.u16Bvfb = pstTiming->u16Bvfb;

    s32Ret = SAMPLE_COMM_VO_StartDev2(voDev, &stVoPubAttr, pstTiming->u32Fps);
    
    //根据像素时钟,设置vpll0寄存器的参数
    SetVpll0(pstTiming->u32PixelClock);

    s32Ret = SAMPLE_COMM_VO_HdmiStart(VO_OUTPUT_3840x2160_30); //使用VO_OUTPUT_3840x2160_30做个样子即可
    ...
    
    stVoLayerAttr.bClusterMode = HI_FALSE;
    stVoLayerAttr.bDoubleFrame = HI_FALSE;
    stVoLayerAttr.enPixFormat = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
    stVoLayerAttr.stDispRect.u32Width = pstTiming->u16Hact;
    stVoLayerAttr.stDispRect.u32Height =  pstTiming->u16Vact;
    stVoLayerAttr.u32DispFrmRt = pstTiming->u32Fps;

    stVoLayerAttr.stImageSize.u32Width =  stVoLayerAttr.stDispRect.u32Width ;
    stVoLayerAttr.stImageSize.u32Height = stVoLayerAttr.stDispRect.u32Height ;
    s32Ret = SAMPLE_COMM_VO_StartLayer(voLayer, &stVoLayerAttr);
    ...
    
    s32Ret = SAMPLE_COMM_VO_StartChn(voLayer, VO_MODE_1MUX);
    
    return s32Ret;
}

//使用参考:
USR_DISPLAY_TIMING_S stTiming[] =
{
  [0] = {
    .u32Fps = 60		  , //帧率,只能配置为25、30、50、60
    .u32PixelClock = 101000  , //像素时钟101MHz(REDUCED BLANKING) 
    .bIop = 1			  , //逐行扫描
    .u16Vact = 1050 	  , //垂直有效区域
    .u16Vbb = 23		  , //垂直消隐后肩
    .u16Vfb = 3 		  , //垂直消隐前肩
    .u16Hact = 1400 	  , //水平有效区域
    .u16Hbb = 80		  , //水平消隐后肩
    .u16Hfb = 48		  , //水平消隐前肩
    .u16Hpw = 32		  , //水平同步宽度
    .u16Vpw = 4 		  , //垂直同步宽度
    .bIhs   = 0           , //hs极性 0为高有效,1为低有效
    .bIvs   = 1           , //vs极性 0为高有效,1为低有效
  },
  
  [1] = {
    .u32Fps = 60		  , //帧率,只能配置为25、30、50、60
    .u32PixelClock = 148500  , //像素时钟148.5MHz
    .bIop = 1			  , //逐行扫描
    .u16Vact = 1080 	  , //垂直有效区域
    .u16Vbb = 36		  , //垂直消隐后肩
    .u16Vfb = 4 		  , //垂直消隐前肩
    .u16Hact = 1920 	  , //水平有效区域
    .u16Hbb = 148		  , //水平消隐后肩
    .u16Hfb = 88		  , //水平消隐前肩
    .u16Hpw = 44		  , //水平同步宽度
    .u16Vpw = 5 		  , //垂直同步宽度
    .bIhs   = 0           , //hs极性 0为高有效,1为低有效
    .bIvs   = 0           , //vs极性 0为高有效,1为低有效
  },
  // ...
  //...	
};

  USR_DISPLAY_TIMING_S *pstTiming = &stTiming[1];
  HiUsrDisplayTimingConfig(pstTiming);

        上面的代码完全就是按照海思SDK里01.software/board/document_cn/《HiMPP V3.0 媒体处理软件 FAQ.pdf》文档的”3.6 如何设置VO的用户时序“章节的描述写出来的,包括各参数意义说明、vpll0配置方法以及VO帧率设置,我并没有创新之处!

设置Hi3536的HDMI2.0自定义显示时序_第1张图片

Vpll0的配置参考文章《https://blog.csdn.net/litao31415/article/details/107326413》,

以及SDK提及的:

设置Hi3536的HDMI2.0自定义显示时序_第2张图片

你可能感兴趣的:(海思视频处理器)