/**
 * @file hv_drv_DpuCommon.c
 * @brief dpu driver source code.
 * @details This file provides the following functions: \n
 *          (1) Initialization and reset functions \n
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2022-08-23
 * @copyright Copyright(c),2022-8, Hiview Software. All rights reserved.
 * @par History:
 * <table>
 * <tr><th>Author                        <th>Date         <th>Change Description
 * <tr><td>HiView SoC Software Team      <td>2022-08-23   <td>init
 * </table>
*/

#include "PanelConfig.h"
#include "hv_comm_Assert.h"
#include "hv_comm_Utilities.h"
#include "hv_comm_DataBase.h"
#include "hv_comm_PqDef.h"
#include "hv_comm_MemParser.h"
#include "hv_chip_Irq.h"

#include "hv_vos_Comm.h"
#include "hv_drv_DpuCommon.h"
#include "hv_drv_PQ.h"
#include "hv_drv_PLL.h"
#include "hv_drv_DpuMainScaler.h"
#include "hv_drv_Dither.h"

#include "hv_cal_MainMute.h"
#include "hv_cal_DpuCprConfig.h"
#include "hv_cal_DpuMainScaler.h"
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
#include "hv_cal_SubMute.h"
#include "hv_cal_DpuSubScaler.h"
#include "hv_drv_DpuSubScaler.h"
#include "hv_drv_DynamicColorWin.h"
#endif

#include "hv_cal_PLL.h"
#include "hv_drv_Gpio.h"
#ifdef  CONFIG_USER_PANEL_TYPE_EDPTX
#include "hv_drv_EdpTx.h"
#endif
#include "hv_drv_Mprt.h"
#include "hv_drv_Od.h"
#include "hv_chip_Debug.h"

extern UINT32 g_uiNeedConfigPtcdPll;

typedef enum _DpuFrameSyncState
{
    DPU_FRAME_SYNC_IDLE = 1,
    DPU_FRAME_SYNC_START,
    DPU_FRAME_SYNC_RESTART,
    DPU_FRAME_SYNC_STABLE,
    DPU_FRAME_SYNC_FREERUN,
    DPU_FRAME_SYNC_WAIT,
}DpuFrameSyncState;

typedef enum _DpuDtcState
{
    DTC_STATE_IDLE = 1,
    DTC_STATE_ENTER_FREERUN0,
    DTC_STATE_FREERUN0,
    DTC_STATE_EXIT_FREERUN0,
    DTC_STATE_ENTER_TCON,
    DTC_STATE_TCON,
    DTC_STATE_EXIT_TCON,
    DTC_STATE_ENTER_FRMSYNC,
    DTC_STATE_FRMSYNC,
    DTC_STATE_EXIT_FRMSYNC,
    DTC_STATE_ENTER_FREERUN1,
    DTC_STATE_FREERUN1,
    DTC_STATE_EXIT_FREERUN1,
}DpuDtcState;

typedef struct _ScalerCursorFunction
{
    VOID (*pfSetEnable)(BOOL bEn);
    VOID (*pfSetPostion)(USHORT16 usHcnt, USHORT16 usVcnt);
    VOID (*pfSetWidth)(UCHAR8 ucHwidth, UCHAR8 ucVwidth);
    VOID (*pfGetColor)(UCHAR8 *pucR, UCHAR8 *pucG, UCHAR8 *pucB);
} ScalerCursorFunction;

typedef struct _ColorCaptureManager
{
    UCHAR8 aucPixelR[SCALER_CURSOR_NUM][COLOR_CAPTURE_FRAME_CNT];
    UCHAR8 aucPixelG[SCALER_CURSOR_NUM][COLOR_CAPTURE_FRAME_CNT];
    UCHAR8 aucPixelB[SCALER_CURSOR_NUM][COLOR_CAPTURE_FRAME_CNT];
    USHORT16 ausXArray[COLOR_CAPTURE_POINT_CNT];
    USHORT16 ausYArray[COLOR_CAPTURE_POINT_CNT];
    BOOL bCaptureDoing;
} ColorCaptureManager;

static ColorCaptureManager stColorCapture;

static const ScalerCursorFunction s_astCursorFunc[SCALER_CURSOR_NUM] =
{
#if 0
    /* HS_RX */
    {
        .pfSetEnable = Hv_Drv_PQ_SetHSRXCursorEnable,
        .pfSetPostion = Hv_Drv_PQ_SetHSRXCursorPos,
        .pfSetWidth = Hv_Drv_PQ_SetHSRXCursorWidth,
        .pfGetColor = Hv_Drv_PQ_GetHSRXCursorColor,
    },
#endif
    /* SRP */
    {
        .pfSetEnable = Hv_Drv_PQ_SetSrpCursorEnable,
        .pfSetPostion = Hv_Drv_PQ_SetSrpCursorPos,
        .pfSetWidth = Hv_Drv_PQ_SetSrpCursorWidth,
        .pfGetColor = Hv_Drv_PQ_GetSrpCursorColor,
    },
    /* LDG */
    {
        .pfSetEnable = Hv_Drv_PQ_SetLdgCursorEnable,
        .pfSetPostion = Hv_Drv_PQ_SetLdgCursorPos,
        .pfSetWidth = Hv_Drv_PQ_SetLdgCursorWidth,
        .pfGetColor = Hv_Drv_PQ_GetLdgCursorColor,
    },
    /* DISPCTRL_PRE */
    {
        .pfSetEnable = Hv_Drv_PQ_SetDispCtrlPreCursorEnable,
        .pfSetPostion = Hv_Drv_PQ_SetDispCtrlPreCursorPos,
        .pfSetWidth = Hv_Drv_PQ_SetDispCtrlPreCursorWidth,
        .pfGetColor = Hv_Drv_PQ_GetDispCtrlPreCursorBdColor,
    },
    /* DITHER */
    {
        .pfSetEnable = Hv_Drv_Dither_SetCursorEnable,
        .pfSetPostion = Hv_Drv_Dither_SetCursorPos,
        .pfSetWidth = Hv_Drv_Dither_SetCursorWidth,
        .pfGetColor = Hv_Drv_Dither_GetCursorBdColor,
    },
    /* DISPCTRL_POST */
    {
        .pfSetEnable = Hv_Drv_PQ_SetTXPostCursorEnable,
        .pfSetPostion = Hv_Drv_PQ_SetTXPostCursorPos,
        .pfSetWidth = Hv_Drv_PQ_SetTXPostCursorWidth,
        .pfGetColor = Hv_Drv_PQ_GetTXPostCursorBdColor,
    },
};

VOID Hv_Drv_DpuScaler_ColorCaptureEn(BOOL bEn)
{
    if (bEn)
    {
        for (UCHAR8 ucCursorId = 0; ucCursorId < SCALER_CURSOR_NUM; ucCursorId++)
        {
            if (NULL != s_astCursorFunc[ucCursorId].pfSetWidth)
            {
                s_astCursorFunc[ucCursorId].pfSetWidth(0, 0);
            }
            if (NULL != s_astCursorFunc[ucCursorId].pfSetEnable)
            {
                s_astCursorFunc[ucCursorId].pfSetEnable(HV_TRUE);
            }
        }
    }
    else
    {
        for (UCHAR8 ucCursorId = 0; ucCursorId < SCALER_CURSOR_NUM; ucCursorId++)
        {
            if (NULL != s_astCursorFunc[ucCursorId].pfSetEnable)
            {
                s_astCursorFunc[ucCursorId].pfSetEnable(HV_FALSE);
            }
            if (NULL != s_astCursorFunc[ucCursorId].pfSetWidth)
            {
                s_astCursorFunc[ucCursorId].pfSetPostion(0, 0);
            }
        }
    }

    stColorCapture.bCaptureDoing = bEn;
}

VOID Hv_Drv_DpuScaler_ColorCaptureLoadPositionTable(USHORT16 *pusXArray, USHORT16 *pusYArray)
{
    HV_ASSERT_VALID_PTR_VOID(pusXArray);
    HV_ASSERT_VALID_PTR_VOID(pusYArray);
    HV_MEMCPY(stColorCapture.ausXArray, pusXArray, sizeof(USHORT16) * COLOR_CAPTURE_POINT_CNT);
    HV_MEMCPY(stColorCapture.ausYArray, pusYArray, sizeof(USHORT16) * COLOR_CAPTURE_POINT_CNT);
}

UINT32 Hv_Drv_DpuScaler_CalculateAvgColor(VOID)
{
    UINT32 uiAvgR = 0;
    UINT32 uiAvgG = 0;
    UINT32 uiAvgB = 0;
    UINT32 uiAvgRGB888 = 0;

    for (UCHAR8 ucCursorId = 0; ucCursorId < SCALER_CURSOR_NUM; ucCursorId++)
    {
        for (USHORT16 usFcnt = 0; usFcnt < COLOR_CAPTURE_FRAME_CNT; usFcnt++)
        {
            uiAvgR += stColorCapture.aucPixelR[ucCursorId][usFcnt];
            uiAvgG += stColorCapture.aucPixelG[ucCursorId][usFcnt];
            uiAvgB += stColorCapture.aucPixelB[ucCursorId][usFcnt];
            if (ucCursorId == SCALER_CURSOR_SRP)
            {
                uiAvgR += stColorCapture.aucPixelR[ucCursorId][usFcnt];
                uiAvgG += stColorCapture.aucPixelG[ucCursorId][usFcnt];
                uiAvgB += stColorCapture.aucPixelB[ucCursorId][usFcnt];
            }
        }
    }
    uiAvgR /= COLOR_CAPTURE_FRAME_CNT * (SCALER_CURSOR_NUM + 1);
    uiAvgG /= COLOR_CAPTURE_FRAME_CNT * (SCALER_CURSOR_NUM + 1);
    uiAvgB /= COLOR_CAPTURE_FRAME_CNT * (SCALER_CURSOR_NUM + 1);
    uiAvgRGB888 = (uiAvgR << 16) | (uiAvgG << 8) | (uiAvgB);

    return uiAvgRGB888;
}

BOOL Hv_Drv_DpuScaler_ColorCapturing(VOID)
{
    return stColorCapture.bCaptureDoing;
}

static VOID Hv_Drv_DpuScaler_CursorCaptureColor(VOID)
{
    static USHORT16 usFcnt = 0;

    for (UCHAR8 ucCursorId = 0; ucCursorId < SCALER_CURSOR_NUM; ucCursorId++)
    {
        if (NULL != s_astCursorFunc[ucCursorId].pfGetColor)
        {
            s_astCursorFunc[ucCursorId].pfGetColor(&stColorCapture.aucPixelR[ucCursorId][usFcnt],
                                                   &stColorCapture.aucPixelG[ucCursorId][usFcnt],
                                                   &stColorCapture.aucPixelB[ucCursorId][usFcnt]);
        }
    }

    usFcnt++;
    if (usFcnt >= COLOR_CAPTURE_FRAME_CNT)
    {
        usFcnt = 0;
    }

    for (UCHAR8 ucCursorId = 0; ucCursorId < SCALER_CURSOR_NUM; ucCursorId++)
    {
        if (NULL != s_astCursorFunc[ucCursorId].pfSetPostion)
        {
            s_astCursorFunc[ucCursorId].pfSetPostion(stColorCapture.ausXArray[usFcnt + ucCursorId * COLOR_CAPTURE_FRAME_CNT], stColorCapture.ausYArray[usFcnt + ucCursorId * COLOR_CAPTURE_FRAME_CNT]); 
        }
    }
}

VOID Hv_Drv_DpuScaler_Enable_Vsync_Interrupt(VOID)
{
    Hv_Cal_DpuScaler_ClearHsIpInt(DisplayInterruptType_HsDisplay);
    Hv_Vos_WClrMiscInt(HV_CHIP_IRQ_HS_DISP - HV_CHIP_IRQ_BASE);
    Hv_Cal_DpuScaler_SetIntDispEnHs24(0x1f);/*enable vtotal_0*/
    Hv_Vos_UnmaskIrq(HV_CHIP_IRQ_HS_DISP);
    return;
}

VOID Hv_Drv_DpuScaler_Disable_Vsync_Interrupt(VOID)
{
    Hv_Cal_DpuScaler_SetIntDispEnHs24(0x0);/*disable vtotal_0*/
    Hv_Vos_MaskIrq(HV_CHIP_IRQ_HS_DISP);
    Hv_Cal_DpuScaler_ClearHsIpInt(DisplayInterruptType_HsDisplay);
    Hv_Vos_WClrMiscInt(HV_CHIP_IRQ_HS_DISP - HV_CHIP_IRQ_BASE);
    return;
}

VOID Hv_Drv_DpuScaler_InsertBlackInit( VOID )
{
    /*在收到vsync之后再解插黑*/
    Hv_Cal_DpuScaler_SubLdgTopVsReleaseBlackEnable(1);
    /*使能主副通道的ldg硬件自动插黑功能*/
    Hv_Cal_DpuScaler_SubLdgTopBlackInsertEnable(BIT_0|BIT_1);
    /*选择硬件自动插黑模式*/
#if (HV_CONFIG_OFF == HV_PROJECT_CONFIG_CHANNEL_SEAMLESS_SWITCH)
    Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwMode(0);
#endif
    /*关闭软件插黑功能*/
    Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwEnable(0);
    /*设置LDG插黑颜色为黑色*/
    Hv_Cal_DpuScaler_SubLdgTopBlackInsertColor(0, 0, 0);   
    Hv_Cal_DpuScaler_SetMainMuteCompW2Enable(1); 
    /*使能主副通道mute信号触发遮黑动作*/
    Hv_Cal_DpuScaler_LDGMainInsertBlackEventInit(BIT_5);
    return;
}

VOID Hv_Drv_PQ_BrightParam( VOID )
{
    BrightnessOsdSet stBrightnessOsdConfig;
    stBrightnessOsdConfig.BrightOsdStart    = PQ_BRIGHTNESS_OSD_START;
    stBrightnessOsdConfig.BrightOsdMidl     = PQ_BRIGHTNESS_OSD_MIDDLE;
    stBrightnessOsdConfig.BrightOsdEnd      = PQ_BRIGHTNESS_OSD_END;
    stBrightnessOsdConfig.BrightDrvforOsdStart  = PQ_BRIGHTNESS_DRV_FOR_OSD_SET_START;
    stBrightnessOsdConfig.BrightDrvforOsdMidl   = PQ_BRIGHTNESS_DRV_FOR_OSD_SET_MIDDLE;
    stBrightnessOsdConfig.BrightDrvforOsdEnd    = PQ_BRIGHTNESS_DRV_FOR_OSD_SET_END;
    stBrightnessOsdConfig.BrightforHdrMax   = PQ_BRIGHTNESS_DRV_FOR_HDR_MAX;
    stBrightnessOsdConfig.BrightforPart1    = PQ_BRIGHTNESS_FOR_PAT1;
    stBrightnessOsdConfig.BrightforPart2    = PQ_BRIGHTNESS_FOR_PAT2;
    stBrightnessOsdConfig.BrightforPart3    = PQ_BRIGHTNESS_FOR_PAT3;

    Hv_Drv_SetBrightnessConfigValue(&stBrightnessOsdConfig);
    return;
}

VOID Hv_Drv_DpuScaler_Init(const PanelParam stPanelParam)
{
    Hv_Cal_DpuScaler_Init(stPanelParam);
    Hv_Drv_DpuScaler_InsertBlackInit();
    Hv_Drv_PQ_BrightParam();
    Hv_Drv_DpuPQ_ConfigInit();
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    Hv_Cal_DpuScaler_SubInit();
    Hv_Drv_DpuScaler_SubWindowConfig(stPanelParam.usPanelHactive, stPanelParam.usPanelVactive);
    Hv_Cal_DpuScaler_SetSubMuteCompW2Enable(1);
    Hv_Cal_DpuScaler_LDGSubInsertBlackEventInit(BIT_1);
    Hv_Cal_DpuScaler_SubLdgTopSubBlendEn(0);
    Hv_Cal_DpuScaler_DtcSubWindowEn(0);
    Hv_Drv_DpuScaler_LdgSubBorderEn(0);
#endif
    return;
}

static VOID DtcFrameSyncModeVrrConfig(DisplayTimingMode enTimingMode, BOOL bOsdVrrEnable)
{
    if (DIS_TIMING_MODE_FRAMESYNC == enTimingMode)
    {
        if (bOsdVrrEnable)
        {
            Hv_Cal_DpuScaler_DtcFrameSyncVrrModeEn(1);
        }
        else
        {
            Hv_Cal_DpuScaler_DtcFrameSyncVrrModeEn(0);
        }
    }
    else
    {
        Hv_Cal_DpuScaler_DtcFrameSyncVrrModeEn(0);
    }
    return;
}


VOID Hv_Drv_DpuScaler_DtcClockConfig(VOID)
{
    Hv_Cal_DpuScaler_DtcClockConfig();
    return;
}

VOID Hv_Drv_PLL_PtcdReload(VOID)
{
    Hv_Cal_PLL_PtcdReload();
    return;
}
VOID Hv_Drv_PLL_TogglePtcdUpdate(VOID)
{
    Hv_Cal_PLL_TogglePtcdUpdate(); 
    return;
}

VOID Hv_Drv_DpuScaler_Enter_FrameSync(const VideoConfigParams* pstVideoConfigParams)
{
    HV_ASSERT_VALID_PTR_VOID(pstVideoConfigParams);
    if (DIS_TIMING_MODE_FRAMESYNC == pstVideoConfigParams->enTimingMode)
    {
        UINT32 uiDynamicEn = Hv_Cal_DpuScaler_GetDtcDynamicPllEn();
        if(1 != uiDynamicEn)
        {
            Hv_Cal_DpuScaler_DtcTimingSel(3);
            Hv_Cal_DpuScaler_DtcDynamicPllEn(1);
            DtcFrameSyncModeVrrConfig(pstVideoConfigParams->enTimingMode, pstVideoConfigParams->bOsdVrrEnable);
            #if (HV_CONFIG_ON == HV_PROJECT_CONFIG_DPU_BRIGHT_FRAME)
            /*为了减少main和sub帧率不同步问题，main timing走frame sync, video data走ddr*/
            BOOL bEn = HV_COMMON_DATABASE_GET(UserData, bBrightFrameEn);
            BOOL bLowLatency = (bEn && Hv_Cal_DpuScaler_GetBrightFrameLowLatency());
            if (bLowLatency)
            {
                Hv_Cal_DpuScaler_DpcSrpMainFrcFrameSyncSel(0);
            }
            else
            {
                Hv_Cal_DpuScaler_DpcSrpMainFrcFrameSyncSel(1);
            }
            #else
            Hv_Cal_DpuScaler_DpcSrpMainFrcFrameSyncSel(1);
            #endif
        }
    }
    return;
}

VOID Hv_Drv_DpuScaler_Exit_FrameSync(VOID)
{
    Hv_Cal_DpuScaler_DtcFrameSyncVrrModeEn(1);
    Hv_Cal_DpuScaler_DtcDynamicPllEn(0);
    Hv_Cal_DpuScaler_DtcTimingSel(1);
    Hv_Cal_DpuScaler_DpcSrpMainFrcFrameSyncSel(0);
    return;
}

static UINT32 GetColorRealBit(ColorDepthType enClrDepth)
{
    UINT32 uiColorBit = 8;
    switch (enClrDepth)
    {
        case ColorDepthType_6Bit:/*过csc后在使用6bit会导致数据砍掉过多，使用8bit*/
        case ColorDepthType_8Bit:
        {
            uiColorBit = 8;
            break;
        }
        case ColorDepthType_10Bit:
        {
            uiColorBit = 10;
            break;
        }
        case ColorDepthType_12Bit:
        case ColorDepthType_16Bit:/*DPU 仅支持最大12bit 16bit数据当成12bit计算*/
        {
            uiColorBit = 12;
            break;
        }
        default:
        {
            uiColorBit = 8;
            break;
        }
    }
    return uiColorBit;
}

UINT32 Hv_Drv_DpuScaler_GetPxlBits(ColorFormatType enColorFormatType, ColorDepthType enClrDepth)
{
    UINT32 uiPxlBits = 0;
    if(ColorFormatType_YCbCr422 == enColorFormatType)
    {
        uiPxlBits = GetColorRealBit(enClrDepth) * 2;
    }
    else if (ColorFormatType_YCbCr420 == enColorFormatType)
    {
        uiPxlBits = GetColorRealBit(enClrDepth) * 15 / 10;
    }
    else/*YUV444 and RGB444*/
    {
        uiPxlBits = GetColorRealBit(enClrDepth) * 3;
    }
    return uiPxlBits;
}

Status Hv_Drv_DpuScaler_DpuClockConfig(UINT32* puiDClkCfg, UINT32 uiDClockDst,VideoConfigParams* pstVideoConfigParams)
{
    /*退出framesync模式，重新加载时钟，保持稳定*/
    Hv_Drv_PLL_PtcdReload();
    Hv_Drv_DpuScaler_Exit_FrameSync();
    Hv_Drv_PLL_TogglePtcdUpdate();
    HV_ASSERT_SUCCESS(Hv_Drv_PLL_SetDisplayClock(puiDClkCfg, uiDClockDst,pstVideoConfigParams));
    Hv_Drv_DpuScaler_DtcClockConfig();
    return HV_SUCCESS;
}

Status Hv_Drv_DpuScaler_SetPortMux(ChannelType enChannelType, LinkPortIndex enPortIndex)
{
    UINT32 uiCurrentPortMux = Hv_Cal_DpuScaler_GetPortMux();
    UINT32 uiPortMuxValue = 4;
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        {
            uiPortMuxValue = 2;
            break;
        }
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            uiPortMuxValue = 3;
            break;
        }
        case LINK_PORT_INDEX_DP_RX0:
        {
            uiPortMuxValue = 0;
            break;
        }
        case LINK_PORT_INDEX_DP_RX1:
        {
            uiPortMuxValue = 1;
            break;
        }
        default:
        {
            HV_LOG_DEBUG(VIDEO, "invalid PortIndex=%u for channel dummy status", enPortIndex);
            break;
        }
    }
    if (CHANNEL_TYPE_MAIN == enChannelType)
    {
        uiCurrentPortMux &= ~(BIT_0|BIT_1|BIT_2);
        uiCurrentPortMux |= uiPortMuxValue;
    }
    else
    {
        uiCurrentPortMux &= ~(BIT_4|BIT_5|BIT_6);
        uiCurrentPortMux |= uiPortMuxValue << 4;
    }
    Hv_Cal_DpuScaler_SetPortMux(uiCurrentPortMux);
    return HV_SUCCESS;
}

VOID Hv_Drv_DpuScaler_MainSoftwareModeVideoMute(ChannelType enChannelType, BOOL bMute)
{
    UINT32 uiBlackInsertFwMode = Hv_Cal_DpuScaler_GetSubLdgTopBlackInsertFwMode();
    UINT32 uiBlackInsertFwEnable = Hv_Cal_DpuScaler_GetSubLdgTopBlackInsertFwEnable();
    uiBlackInsertFwMode |= BIT_0;
    uiBlackInsertFwEnable |= bMute;
    Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwMode(uiBlackInsertFwMode);
#if (HV_CONFIG_OFF == HV_PROJECT_CONFIG_CHANNEL_SEAMLESS_SWITCH)
    Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwEnable(uiBlackInsertFwEnable);
#endif
    return;
}

VOID Hv_Drv_DpuScaler_SoftwareVideoMute(ChannelType enChannelType)
{
    UINT32 uiBlackInsertFwMode = Hv_Cal_DpuScaler_GetSubLdgTopBlackInsertFwMode();
    UINT32 uiBlackInsertFwEnable = Hv_Cal_DpuScaler_GetSubLdgTopBlackInsertFwEnable();
    if (CHANNEL_TYPE_MAIN == enChannelType)
    {
        uiBlackInsertFwMode |= BIT_0;
        uiBlackInsertFwEnable |= BIT_0;
        Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwMode(uiBlackInsertFwMode);
#if (HV_CONFIG_OFF == HV_PROJECT_CONFIG_CHANNEL_SEAMLESS_SWITCH)
        Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwEnable(uiBlackInsertFwEnable);
#endif
        
    }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    else
    {
        uiBlackInsertFwMode |= BIT_1;
        uiBlackInsertFwEnable |= BIT_1;
        Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwMode(uiBlackInsertFwMode);
        Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwEnable(uiBlackInsertFwEnable);
    }
#endif    
    return;
}

VOID Hv_Drv_DpuScaler_VideoUnmute(ChannelType enChannelType)
{
    UINT32 uiBlackInsertFwMode = Hv_Cal_DpuScaler_GetSubLdgTopBlackInsertFwMode();
    UINT32 uiBlackInsertFwEnable = Hv_Cal_DpuScaler_GetSubLdgTopBlackInsertFwEnable();
    if (CHANNEL_TYPE_MAIN == enChannelType)
    {
        uiBlackInsertFwMode &= (~BIT_0);
        uiBlackInsertFwEnable &= (~BIT_0);
#if (HV_CONFIG_OFF == HV_PROJECT_CONFIG_CHANNEL_SEAMLESS_SWITCH)
        Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwMode(uiBlackInsertFwMode);
#endif
        Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwEnable(uiBlackInsertFwEnable);
        Hv_Cal_DpuScaler_LDGMainReleaseBlack();
    }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    else
    {
        uiBlackInsertFwMode &= (~BIT_1);
        uiBlackInsertFwEnable &= (~BIT_1);
        Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwMode(uiBlackInsertFwMode);
        Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwEnable(uiBlackInsertFwEnable);
        Hv_Cal_DpuScaler_LDGSubReleaseBlack();
    }
#endif    
    return;
}

Status Hv_Drv_DpuScaler_SoftwareVideoUnmute(ChannelType enChannelType)
{
    UINT32 uiBlackInsertFwMode = Hv_Cal_DpuScaler_GetSubLdgTopBlackInsertFwMode();
    UINT32 uiBlackInsertFwEnable = Hv_Cal_DpuScaler_GetSubLdgTopBlackInsertFwEnable();
    if (CHANNEL_TYPE_MAIN == enChannelType)
    {
        uiBlackInsertFwMode &= (~BIT_0);
        uiBlackInsertFwEnable &= (~BIT_0);
#if (HV_CONFIG_OFF == HV_PROJECT_CONFIG_CHANNEL_SEAMLESS_SWITCH)
        Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwMode(uiBlackInsertFwMode);
#endif
        Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwEnable(uiBlackInsertFwEnable);
    }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    else
    {
        uiBlackInsertFwMode &= (~BIT_1);
        uiBlackInsertFwEnable &= (~BIT_1);
        Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwMode(uiBlackInsertFwMode);
        Hv_Cal_DpuScaler_SubLdgTopBlackInsertFwEnable(uiBlackInsertFwEnable);
    }
#endif
    return HV_SUCCESS;
}

VOID Hv_Drv_DpuScaler_DpuIntProc(DpuInterruptDefine *pstDpuInterrupt, const VideoConfigParams* pstVideoConfigParams, UCHAR8 (*pfPQCallback)(PQCALLBACKMODE , const VOID *))
{
    HV_ASSERT_VALID_PTR_VOID(pstDpuInterrupt);
    Hv_Cal_DpuScaler_GetDpuInt(pstDpuInterrupt);

    Hv_Cal_DpuScaler_ClearDpuInt();

    /*Kspi send data中断处理*/
    if (pstDpuInterrupt->uiKspiIntWbuf)
    {
        Hv_Cal_DpuScaler_SendRemainKspiDataInISR();
        
    }
    if (pstDpuInterrupt->uiKspiTconVsL)
    {
        pfPQCallback(PQCALLBACK_VSYNC_DPU, pstVideoConfigParams);
    }
    return;
}

VOID Hv_Drv_DpuScaler_DtcIntProc(DtcInterruptDefine *pstDpuInterrupt)
{
    HV_ASSERT_VALID_PTR_VOID(pstDpuInterrupt);
    Hv_Cal_DpuScaler_GetDtcInt(pstDpuInterrupt);

    Hv_Cal_DpuScaler_ClearDtcInt();

    return;
}

#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
static BOOL s_bNeedMainFakeBlend = 0;

VOID Hv_Drv_DpuScaler_SetMainFakeBlendFlag(BOOL bBlendEn)
{
    s_bNeedMainFakeBlend = bBlendEn;
}
#endif

#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_DPU_BRIGHT_FRAME)
static BOOL s_bBrightFramSync = 0;
static DpuCapCutParam s_stDpuCapCutParam = {0};
VOID Hv_Drv_DpuScaler_SetBrightFramSyncFlag(BOOL bSync, DpuCapCutParam* pstDpuCapCutParam)
{
    s_stDpuCapCutParam = *pstDpuCapCutParam;
    s_bBrightFramSync = bSync;
}
#endif

extern VOID Hv_Cal_DpuScaler_DcwCapVgsfOutMaskOn(UINT32 uiValue);
VOID Hv_Drv_DpuScaler_VsyncHandler(HsIpInterruptDefine *pstDpuInterruptDefine, DisplayInterruptType enType,const VideoConfigParams* pstVideoConfigParams, UCHAR8 (*pfPQCallback)(PQCALLBACKMODE , const VOID *))
{
#ifdef CONFIG_USER_DISPCTRL_OD_ON
    static UCHAR8 s_u8VsyncCnt = 0;
#endif
    HV_ASSERT_VALID_PTR_VOID(pstDpuInterruptDefine);
    
    Hv_Cal_DpuScaler_GetHsIpInt(enType, pstDpuInterruptDefine);
    static UCHAR8 usVsyncCnt = 0;
    static UCHAR8 usBfVsyncCnt = 0;
    
    Hv_Cal_DpuScaler_ClearHsIpInt(enType);
    if(DisplayInterruptType_HsDisplay == enType)
    {
        if(pstDpuInterruptDefine->uiHsIntSource0 > 0)
        {
            if(1 == g_uiNeedConfigPtcdPll)
            {
                Hv_Drv_DpuScaler_Disable_Vsync_Interrupt();
                Hv_Cal_PLL_SetPtcdpllPreDiv(pstVideoConfigParams->uiPtcdPreDiv);
                Hv_Cal_PLL_SetPtcdpllPostdivD(pstVideoConfigParams->uiPtcdPostDiv);
                Hv_Cal_PLL_SetPtcdPllFbdiv(pstVideoConfigParams->uiPtcdFBDivInt);
                Hv_Cal_PLL_SetPtcdpllSscgPllnFrac(pstVideoConfigParams->uiPtcdFBDivFrac);
                Hv_Cal_PLL_TogglePtcdUpdate();
                //清除Pll lock标志位
                Hv_Cal_PLL_FN_ClearPllLockFlag();
#ifdef  CONFIG_USER_PANEL_TYPE_EDPTX
                Hv_Drv_EdpTx_SetEdpTxMvidTuSize(pstVideoConfigParams->uiEdpTuDataSize,pstVideoConfigParams->uiMvid);
#endif
                g_uiNeedConfigPtcdPll = 0;
            }
            else
            {
                //if(Hv_Drv_PQ_GetDynamicBLEn())
                //{
                //    USHORT16 usBrightness  = Hv_Drv_PQ_LdcCalcPWM();
                //    Hv_Drv_MPRT_SetOutHighFreqPwmDuty(HV_PROJECT_CONFIG_MPRT_HIGHT_PORT, (HV_PROJECT_CONFIG_MPRT_HIGHT_FREQ_PWM_TOTAL - usBrightness), usBrightness);
                //}

                //if((pstVideoConfigParams->stHdrParam.xType == 2)||(pstVideoConfigParams->stHdrParam.xType == 3))
                //{
                //    if(HV_R32(SW_DUMMY_PQTOOL_HDR_PATDETECT) == HV_TRUE)
                //    {
                //        Hv_Drv_DpuPQ_PatternDetProc();
                //    }
                //}

#ifdef CONFIG_USER_DISPCTRL_OD_ON
                if(HV_TRUE == Hv_Drv_OD_GetOdOpenDelayFlag())
                {
                    s_u8VsyncCnt++;
                    if(s_u8VsyncCnt == 2)
                    {
                        Hv_Drv_OD_Enable(HV_TRUE);
                        Hv_Drv_OD_DynamicCrcEnable(HV_TRUE);
                        Hv_Drv_OD_ClearOdOpenDelayFlag();
                        s_u8VsyncCnt = 0;
                    }
                }
#endif
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
                if (HV_TRUE == s_bNeedMainFakeBlend)
                {
                    usVsyncCnt++;
                    if ((usVsyncCnt > 6) && (HV_FALSE != HV_COMMON_DATABASE_GET(UserData, ucPxPMode)))
                    {
                        usVsyncCnt = 0;
                        Hv_Drv_DpuScaler_SubLdgTopSubBlendEn(HV_TRUE);
                        s_bNeedMainFakeBlend = HV_FALSE;
                        Hv_Cal_DpuScaler_SetLdgLatch(0);
                        Hv_Cal_DpuScaler_SetSubSrpLatch(0);
                        Hv_Drv_DpuScaler_SetSubSeamlessApplyInEn(0);
                    }
                }
#endif
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_DPU_BRIGHT_FRAME)
                if (HV_TRUE == s_bBrightFramSync)
                {
                    usBfVsyncCnt++;
                    if (usBfVsyncCnt == 1)
                    {
                        Hv_Cal_DpuScaler_SetCapVgsfSubCutParam(&s_stDpuCapCutParam);
                        Hv_Cal_DpuScaler_DcwCapVgsfOutMaskOn(1);
                        Hv_Drv_DpuScaler_SubVdmWriteAddrSwap();
                    }
                    if (usBfVsyncCnt == 2)
                    {
                        Hv_Cal_DpuScaler_DpuDtcSubReadFreeze(0);
                    }
                    if ((usBfVsyncCnt == 3) && (HV_FALSE != HV_COMMON_DATABASE_GET(UserData, ucPxPMode)))
                    {
                        Hv_Drv_DpuScaler_SubVdmReadAddrSwap();
                        Hv_Drv_DpuScaler_DcwWindowConfig();
                        //Hv_Drv_DpuScaler_SubWindowConfig(pstVideoConfigParams->usVideoPanelHactive, pstVideoConfigParams->usVideoPanelVactive);
                        usBfVsyncCnt = 0;
                        s_bBrightFramSync = HV_FALSE;
                    }
                    if (usBfVsyncCnt > 3)
                    {
                        usBfVsyncCnt = 0;
                        s_bBrightFramSync = HV_FALSE;
                    }
                }
#endif
                pfPQCallback(PQCALLBACK_VSYNC, pstVideoConfigParams);
            }

            if (Hv_Drv_DpuScaler_ColorCapturing())
            {
                /* catch color */
                Hv_Drv_DpuScaler_CursorCaptureColor();
            }
        }
        else if(pstDpuInterruptDefine->uiHsIntSource1 > 0)
        {
             pfPQCallback(PQCALLBACK_HSYNC1, pstVideoConfigParams);
        }
        else if(pstDpuInterruptDefine->uiHsIntSource2 > 0)
        {
             pfPQCallback(PQCALLBACK_HSYNC2, pstVideoConfigParams);
        }
        else if(pstDpuInterruptDefine->uiHsIntSource3 > 0)
        {
             pfPQCallback(PQCALLBACK_HSYNC3, pstVideoConfigParams);
        }
        else if(pstDpuInterruptDefine->uiHsIntSource4 > 0)
        {
             pfPQCallback(PQCALLBACK_HSYNC4, pstVideoConfigParams);
        }
        else if(pstDpuInterruptDefine->uiHsIntSource5 > 0)
        {
             pfPQCallback(PQCALLBACK_HSYNC5, pstVideoConfigParams);
        }
        else if(pstDpuInterruptDefine->uiHsIntSource6 > 0)
        {
             pfPQCallback(PQCALLBACK_HSYNC6, pstVideoConfigParams);
        }
        else
        {
            //do nothing
        }
        //if (pstDpuInterruptDefine->uiHsIntSource1 > 0)
        //{
        //    HV_LOG_INFO(VIDEO, "windex=%u, rindex=%u,buf stauts=%u", Hv_Cal_DpuScaler_GetFrcWindex(),Hv_Cal_DpuScaler_GetFrcRindex(), Hv_Cal_DpuScaler_GetFrcBufStatus());
        //}
    }
    return;
}

VOID Hv_Drv_DpuScaler_SetHflipSwitch(UINT32 uiValue)
{
    Hv_Cal_DpuScaler_SrpTopMainScHflip(uiValue);
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    Hv_Cal_DpuScaler_SrpTopSubScHflip(uiValue);
#endif
    return;
}

UINT32 Hv_Drv_DpuScaler_GetFrmsyncState(VOID)
{
    return Hv_Cal_DpuScaler_GetFrmsyncState();
}

UINT32 Hv_Drv_DpuScaler_GetDtcState(VOID)
{
    return Hv_Cal_DpuScaler_GetDtcState();
}

Status Hv_Drv_DpuScaler_CheckDtcStable(const VideoConfigParams* pstVideoConfigParams)
{
    UINT32 uiFrameSyncStatus = Hv_Drv_DpuScaler_GetFrmsyncState();
    UINT32 uiDtcStatus = Hv_Drv_DpuScaler_GetDtcState();
    HV_LOG_DEBUG(VIDEO, "framsync %u,Dtc %u",uiFrameSyncStatus,uiDtcStatus);
    if(DATA_PATH_MODE_FRAMESYNC == pstVideoConfigParams->enDataPathMode)
    {
        if (pstVideoConfigParams->bOsdVrrEnable)
        {
            return ((DPU_FRAME_SYNC_RESTART == uiFrameSyncStatus) && (DTC_STATE_FRMSYNC == uiDtcStatus));
        }
        else
        {
            return ((DPU_FRAME_SYNC_STABLE == uiFrameSyncStatus) && (DTC_STATE_FRMSYNC == uiDtcStatus));
        }

    }
    else
    {
        return ((DPU_FRAME_SYNC_IDLE == uiFrameSyncStatus) && (DTC_STATE_FREERUN0 == uiDtcStatus));
    }
}

Status Hv_Drv_DpuScaler_BurnInConfig(VOID)
{
    Hv_Cal_DpuScaler_DpcSrpMainEnc1ClkEn(1);
    Hv_Cal_DpuScaler_DpcSrpMainDecClkEn(1);
    Hv_Cal_DpuScaler_DpcSrpMainEncClkEn(1);
    Hv_Cal_DpuScaler_SrpTopMainSrPassthrough(0);
    Hv_Cal_DpuScaler_DpuRvdm00RdEnable(0);
    Hv_Cal_DpuScaler_DpuWvdm00WrEnable(0);
    Hv_Drv_DpuPQ_DmaTableEnable(0);
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    Hv_Cal_DpuScaler_DpuWvdm01WrEnable(0);
    Hv_Cal_DpuScaler_DpuRvdm01LineRdEnable(0);
    Hv_Cal_DpuScaler_SubLdgTopSubBlendEn(0);
    Hv_Drv_DpuScaler_LdgSubBorderEn(0);
    Hv_Cal_DpuScaler_DtcSubWindowEn(0);
#endif
    return HV_SUCCESS;
}

VOID Hv_Drv_DpuScaler_MainChannelEncDecDisenable(VOID)
{
    Hv_Cal_DpuScaler_DpuEncVdmWriteEnable(0);
#if (HV_CONFIG_OFF == HV_PROJECT_CONFIG_CHANNEL_SEAMLESS_SWITCH)
    Hv_Cal_DpuScaler_DpuDecVdmReadEnable(0);
#endif
    return;
}

VOID Hv_Drv_DpuScaler_CalcDcwCapCutParam(const VideoConfigParams* pstVideoConfigParams, DpuCapCutParam* pstDpuCapCutParam)
{
    HV_ASSERT_TRUE_VOID(pstVideoConfigParams->usVideoPanelHactive > 0);
    HV_ASSERT_TRUE_VOID(pstVideoConfigParams->usVideoPanelVactive > 0);
    USHORT16 usDcwInputPosH = 300;
    USHORT16 usDcwInputPosV = 300;
    USHORT16 usDcwInputVideoWidth = pstVideoConfigParams->uiInputVideoWidth;
    USHORT16 usDcwInputVideoHight = pstVideoConfigParams->uiInputVideoHight;
    if (pstVideoConfigParams->uiInputVideoWidth < pstVideoConfigParams->usVideoPanelHactive)
    {
        usDcwInputPosH = pstVideoConfigParams->usMainFakePosH * usDcwInputVideoWidth / pstVideoConfigParams->usVideoPanelHactive;
    }
    else
    {
        usDcwInputPosH = pstVideoConfigParams->usMainFakePosH;
        usDcwInputVideoWidth = pstVideoConfigParams->usVideoPanelHactive;
    }
    if (pstVideoConfigParams->uiInputVideoHight < pstVideoConfigParams->usVideoPanelVactive)
    {
        usDcwInputPosV = pstVideoConfigParams->usMainFakePosV * usDcwInputVideoHight / pstVideoConfigParams->usVideoPanelVactive;
    }
    else
    {
        usDcwInputPosV = pstVideoConfigParams->usMainFakePosV;
        usDcwInputVideoHight = pstVideoConfigParams->usVideoPanelVactive;
    }
    USHORT16 usDcwInputHalfSizeH = pstVideoConfigParams->uiDdrOrWtrVideoWidth >> 1;
    USHORT16 usDcwInputHalfSizeV = pstVideoConfigParams->uiDdrOrWtrVideoHight >> 1;
    if (usDcwInputPosH < usDcwInputHalfSizeH)
    {
        pstDpuCapCutParam->usCutHstart = 1;
        pstDpuCapCutParam->usCutHend = pstVideoConfigParams->uiDdrOrWtrVideoWidth;
    }
    else if ((usDcwInputVideoWidth - usDcwInputPosH) < usDcwInputHalfSizeH)
    {
        pstDpuCapCutParam->usCutHstart = usDcwInputVideoWidth - pstVideoConfigParams->uiDdrOrWtrVideoWidth + 1;
        pstDpuCapCutParam->usCutHend = usDcwInputVideoWidth;
    }
    else
    {
        pstDpuCapCutParam->usCutHstart = usDcwInputPosH - usDcwInputHalfSizeH + 1;
        pstDpuCapCutParam->usCutHend = usDcwInputPosH + usDcwInputHalfSizeH;
    }

    if (usDcwInputPosV < usDcwInputHalfSizeV)
    {
        pstDpuCapCutParam->usCutVstart = 1;
        pstDpuCapCutParam->usCutVend = pstVideoConfigParams->uiDdrOrWtrVideoHight;
    }
    else if ((usDcwInputVideoHight - usDcwInputPosV) < usDcwInputHalfSizeV)
    {
        pstDpuCapCutParam->usCutVstart = usDcwInputVideoHight - pstVideoConfigParams->uiDdrOrWtrVideoHight + 1;  
        pstDpuCapCutParam->usCutVend = usDcwInputVideoHight;
    }
    else
    {
        pstDpuCapCutParam->usCutVstart = usDcwInputPosV - usDcwInputHalfSizeV + 1;
        pstDpuCapCutParam->usCutVend = usDcwInputPosV + usDcwInputHalfSizeV;
    }
    return;
}

VOID Hv_Drv_DpuScaler_CalcCapCutParam(const VideoConfigParams* pstVideoConfigParams, DpuCapCutParam* pstDpuCapCutParam)
{
    HV_ASSERT_TRUE_VOID(pstVideoConfigParams->usVideoPanelHactive > 0);
    HV_ASSERT_TRUE_VOID(pstVideoConfigParams->usVideoPanelVactive > 0);
    USHORT16 usMgSamplingInputLocH = pstVideoConfigParams->usMainFakePosH;
    USHORT16 usMgSamplingInputLocV = pstVideoConfigParams->usMainFakePosV;
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_MAGNIFY)
#if (HV_CONFIG_OFF == HV_PROJECT_CONFIG_MAGNIFY_SAMPLING_FLOW_POS)
    usMgSamplingInputLocH = HV_COMMON_DATABASE_GET(UserData, usMagnifyGlassSamplingLocH);
    usMgSamplingInputLocV = HV_COMMON_DATABASE_GET(UserData, usMagnifyGlassSamplingLocV);
#endif
#endif
    USHORT16 usMgInputPosH = usMgSamplingInputLocH * pstVideoConfigParams->uiInputVideoWidth / pstVideoConfigParams->usVideoPanelHactive;
    USHORT16 usMgInputPosV = usMgSamplingInputLocV * pstVideoConfigParams->uiInputVideoHight / pstVideoConfigParams->usVideoPanelVactive;
    USHORT16 usMgInputHalfSizeH = pstVideoConfigParams->uiDdrOrWtrVideoWidth >> 1;
    USHORT16 usMgInputHalfSizeV = pstVideoConfigParams->uiDdrOrWtrVideoHight >> 1;
    if (usMgInputPosH < usMgInputHalfSizeH)
    {
        pstDpuCapCutParam->usCutHstart = 1;
        pstDpuCapCutParam->usCutHend = pstVideoConfigParams->uiDdrOrWtrVideoWidth;
    }
    else if ((pstVideoConfigParams->uiInputVideoWidth - usMgInputPosH) < usMgInputHalfSizeH)
    {
        pstDpuCapCutParam->usCutHstart = pstVideoConfigParams->uiInputVideoWidth - pstVideoConfigParams->uiDdrOrWtrVideoWidth + 1;
        pstDpuCapCutParam->usCutHend = pstVideoConfigParams->uiInputVideoWidth;
    }
    else
    {
        pstDpuCapCutParam->usCutHstart = usMgInputPosH - usMgInputHalfSizeH + 1;
        pstDpuCapCutParam->usCutHend = usMgInputPosH + usMgInputHalfSizeH;
    }

    if (usMgInputPosV < usMgInputHalfSizeV)
    {
        pstDpuCapCutParam->usCutVstart = 1;
        pstDpuCapCutParam->usCutVend = pstVideoConfigParams->uiDdrOrWtrVideoHight;
    }
    else if ((pstVideoConfigParams->uiInputVideoHight - usMgInputPosV) < usMgInputHalfSizeV)
    {
        pstDpuCapCutParam->usCutVstart = pstVideoConfigParams->uiInputVideoHight - pstVideoConfigParams->uiDdrOrWtrVideoHight + 1;  
        pstDpuCapCutParam->usCutVend = pstVideoConfigParams->uiInputVideoHight;
    }
    else
    {
        pstDpuCapCutParam->usCutVstart = usMgInputPosV - usMgInputHalfSizeV + 1;
        pstDpuCapCutParam->usCutVend = usMgInputPosV + usMgInputHalfSizeV;
    }
    return;
}

VOID Hv_Drv_DpuScaler_SetMainChannelState(USHORT16 usState)
{
    Hv_Cal_DpuScaler_SetMainChannelState(usState);
    return;
}

VOID Hv_Drv_DpuScaler_SetSubChannelState(USHORT16 usState)
{
    Hv_Cal_DpuScaler_SetSubChannelState(usState);
    return;
}

#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON

static VOID DtcBufReadFast(const VideoConfigParams* pstVideoConfigParams, USHORT16* pusFrcRdDoneTh, USHORT16* pusFrcWrDoneTh)
{

    HV_ASSERT_TRUE_VOID(pstVideoConfigParams->uiOutputFrameRate > 0);
    HV_ASSERT_TRUE_VOID(pstVideoConfigParams->uiOutputVideoHight > 0);
    USHORT16 usTxVactValid = pstVideoConfigParams->uiDdrOrWtrVideoHight;                                //valid指不带擦黑部分的有效图像部分
    USHORT16 usTxTopBlackInertLine = (pstVideoConfigParams->uiOutputVideoHight - usTxVactValid) >> 1;   //屏幕上部插黑行数
    FLOAT32 fRateRatio = (FLOAT32)pstVideoConfigParams->uiInputFrameRate / pstVideoConfigParams->uiOutputFrameRate;
    if (fRateRatio > 0.5f)
    {
        fRateRatio = 0.5f;
    }

    *pusFrcRdDoneTh = (USHORT16)(fRateRatio * usTxVactValid + usTxTopBlackInertLine);
    *pusFrcWrDoneTh = (USHORT16)((1 - (fRateRatio * (1 - (usTxTopBlackInertLine / pstVideoConfigParams->uiOutputVideoHight)))) * pstVideoConfigParams->uiInputVideoHight);
    return;
}


VOID Hv_Drv_DpuScaler_FrameBufferConfig01(const VideoConfigParams* pstVideoConfigParams)
{
    HV_ASSERT_VALID_PTR_VOID(pstVideoConfigParams);
    UCHAR8 ucBufferNum = pstVideoConfigParams->bInterlacedMode ? 3 : 2;
    
    Hv_Cal_DpuScaler_DtcFrcBufNum01(ucBufferNum);

    USHORT16 usFrcRdDoneTh = 0;
    USHORT16 usFrcWrDoneTh = 0;

    if (pstVideoConfigParams->uiOutputFrameRate >=  pstVideoConfigParams->uiInputFrameRate)
    {
        DtcBufReadFast(pstVideoConfigParams, &usFrcRdDoneTh, &usFrcWrDoneTh);
    }
    else
    {
        usFrcWrDoneTh = pstVideoConfigParams->uiInputVideoHight / 3;
        usFrcRdDoneTh = (pstVideoConfigParams->uiOutputVideoHight << 1) / 3;
    }
    if (HV_TRUE == pstVideoConfigParams->bMainFakeSwitch)   /*sub虚拟功能开*/
    {
        USHORT16 usInVsize = Hv_Cal_DpuScaler_GetSubCuVsize();
        if (pstVideoConfigParams->uiInputFrameRate == pstVideoConfigParams->uiOutputFrameRate)
        {
            usFrcWrDoneTh = usInVsize >> 1;
            usFrcRdDoneTh = pstVideoConfigParams->usMainFakeVsize >> 1;
        }
        else if (pstVideoConfigParams->uiInputFrameRate > pstVideoConfigParams->uiOutputFrameRate)
        {
            usFrcWrDoneTh = usInVsize / 3;
            usFrcRdDoneTh = (pstVideoConfigParams->usMainFakeVsize << 1) / 3;
        }
        else
        {
            usFrcWrDoneTh = (usInVsize << 1) / 3;
            usFrcRdDoneTh = pstVideoConfigParams->usMainFakeVsize / 3;
        }
    }
    Hv_Cal_DpuScaler_DtcFrcRdDoneTh01(usFrcRdDoneTh);
    Hv_Cal_DpuScaler_DtcFrcWrDoneTh01(usFrcWrDoneTh);
    return;
}

Status Hv_Drv_DpuScaler_DpuVdm01Settings(const VideoConfigParams* pstVideoConfigParams)
{
    HV_ASSERT_VALID_PTR(pstVideoConfigParams);
    DpuVdmConfigSettings stDpuVdmConfigSettings = {0};
    UINT32 uiWidthScf = pstVideoConfigParams->uiDdrOrWtrVideoWidth;
    UINT32 uiHeightScf = pstVideoConfigParams->uiDdrOrWtrVideoHight;
    UINT32 uiheight = uiHeightScf;
    UINT32 uiPxlBits = 0;
    UINT32 uiBusBits = 128;/*固定值*/

    /*配置VDM首先需要关闭开关，硬件要求规范*/
    Hv_Cal_DpuScaler_DpuRvdm01LineRdEnable(0);
    Hv_Cal_DpuScaler_DpuWvdm01WrEnable(0);

    uiPxlBits = Hv_Drv_DpuScaler_GetPxlBits(pstVideoConfigParams->stFrameBufferCfg.enFBColorFormat, pstVideoConfigParams->stFrameBufferCfg.enFBColorDepth);
    UINT32 uiColDatNum = ROUND_DIV(uiWidthScf * uiPxlBits, uiBusBits);
    /*reg_dm_rd_col_step = reg_dm_rd_col_dat_num * iBusBits / 8*/
    UINT32 uiColStep = uiColDatNum * uiBusBits >> 3;

    HV_LOG_DEBUG(VIDEO,"Dpu Vdm01 setting %u,%u,%u,%u,%u",uiWidthScf,uiHeightScf,uiPxlBits,uiColDatNum,uiColStep);

    /*配置辅通道固定从FRC start处开始分配，在计算带宽处已经预估了PIP/PBP场景的最大内存。主通道从最大内存之后才开始分配*/
    UINT32 uiSubChannelFrcStartAddress = Hv_Board_Memory_FRCStart();

    UINT32 uiWdmaStartAdr  = 0 * (uiColStep * uiheight) + uiSubChannelFrcStartAddress;
    UINT32 uiWdmaStartAdr1 = 1 * (uiColStep * uiheight) + uiSubChannelFrcStartAddress;
    UINT32 uiWdmaStartAdr2 = 2 * (uiColStep * uiheight) + uiSubChannelFrcStartAddress;
    UINT32 uiWdmaStartAdr3 = 3 * (uiColStep * uiheight) + uiSubChannelFrcStartAddress;
    UINT32 uiRdmaStartAdr = uiWdmaStartAdr;
    UINT32 uiRdmaStartAdr1 = uiWdmaStartAdr1;
    UINT32 uiRdmaStartAdr2 = uiWdmaStartAdr2;
    if (pstVideoConfigParams->bVflipEnable)
    {
        /*硬件第一行是0，0-vactive - 1行，反着读需要读的是vactive - 1的地址，vactive是第二帧的起始地址了需要注意*/
        uiRdmaStartAdr = uiWdmaStartAdr1 - uiColStep;
        uiRdmaStartAdr1 = uiWdmaStartAdr2 - uiColStep;
        uiRdmaStartAdr2 = uiWdmaStartAdr3 - uiColStep;
        stDpuVdmConfigSettings.ucDmRdColStepDir = 1;
        stDpuVdmConfigSettings.ucDmRdLineStepDir = 1;
    }
    else
    {
        stDpuVdmConfigSettings.ucDmRdColStepDir = 0;
        stDpuVdmConfigSettings.ucDmRdLineStepDir = 0;
    }

    /*RDMA Line Mode Setting*/
    stDpuVdmConfigSettings.uiDmColStep = uiColStep;
    stDpuVdmConfigSettings.usDmRdColDatNum = uiColDatNum;
    stDpuVdmConfigSettings.usDmTotalColNum = uiheight;
    /*burstLen - 1(建议值31，15，7)*/
    UINT32 uiBurstLen = 31;
    stDpuVdmConfigSettings.ucDmBurstLen = uiBurstLen;

    /*=int(reg_dm_rd_col_dat_num/(reg_dm_rd_burst_len+1)*/
    UINT32 uiBurstNum = uiColDatNum / (uiBurstLen + 1);
    stDpuVdmConfigSettings.uiDmBurstNum = uiBurstNum;

    /*=reg_dm_rd_col_dat_num-reg_dm_rd_burst_num*(reg_dm_rd_burst_len+1)*/
    UINT32 uiBurstRmd = uiColDatNum - uiBurstNum * (uiBurstLen + 1);
    stDpuVdmConfigSettings.ucDmBurstRmd = uiBurstRmd;

    UINT32 uiLineStep = uiColStep;
    stDpuVdmConfigSettings.uiDmLineStep = uiLineStep;
    stDpuVdmConfigSettings.usDmTotalLineNum = 1;
    stDpuVdmConfigSettings.ucDmOutstanding = 2;
    stDpuVdmConfigSettings.uiDmRdStartAdr = uiRdmaStartAdr;
    stDpuVdmConfigSettings.uiDmRdStartAdr0 = uiRdmaStartAdr;
    stDpuVdmConfigSettings.uiDmRdStartAdr1 = uiRdmaStartAdr1;
    stDpuVdmConfigSettings.uiDmRdStartAdr2 = uiRdmaStartAdr2;

    /*WDMA Line Mode Setting*/
    /*WVDM向DDR写帧数*/
    stDpuVdmConfigSettings.uiDmWrStartAdr = uiWdmaStartAdr;
    stDpuVdmConfigSettings.uiDmWrStartAdr0 = uiWdmaStartAdr;
    stDpuVdmConfigSettings.uiDmWrStartAdr1 = uiWdmaStartAdr1;
    stDpuVdmConfigSettings.uiDmWrStartAdr2 = uiWdmaStartAdr2;
    Hv_Cal_DpuScaler_DpuVdmSubConfig(&stDpuVdmConfigSettings);
    /*配置VDM完成打开开关，硬件要求规范*/
    Hv_Cal_DpuScaler_DpuRvdm01LineRdEnable(1);
    Hv_Cal_DpuScaler_DpuWvdm01WrEnable(1);

    return HV_SUCCESS;
}
#endif