/**
 * @file hv_drv_Dprx.c
 * @brief drv dp rx c file.
 * @details This file provides the following functions: \n
 *          (1) Initialization and reset functions \n
 *          (2) Write and read EDID functions \n
 *          (3) Write and read DPCD functions \n
 *          (4) Cable detect function \n
 *          (5) Irq related functions \n
 *          (6) Link related functions \n
 *          (7) Timing related functions \n
 *          (7) Event analyze 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>dp group      <td>2022-08-23   <td>init
 * </table>
*/
#include <hv_comm_MemoryConfig.h>
#include "hv_comm_Assert.h"
#include "hv_cal_Dprx.h"
#include "hv_drv_DisplayPort.h"
#include "hv_drv_Gpio.h"
#include "hv_vos_Log.h"
#include "hv_chip_Config.h"
#include "hv_comm_Utilities.h"

#define VSC_SDP_INDICATE_FLAG_MASK                         0x40
#define PIXEL_ENCODEING_COLORIMETRY_INDICATOR_FIELD_MASK   0xC0
#define COLOR_DEPTH_INDICATOR_MASK                         0xE0
/* Misc0 bit1~bit4 define */
#define DP_MISC0_LEGACY_RGB_MODE                           0x00
#define DP_MISC0_xvYCC422_BT601                            0x01
#define DP_MISC0_xvYCC444_BT601                            0x02
#define DP_MISC0_RGB_FIXED_POINT                           0x03
#define DP_MISC0_CEA_RGB                                   0x04
#define DP_MISC0_YUV422_BT601                              0x05
#define DP_MISC0_YUV444_BT601                              0x06
#define DP_MISC0_DCI_P3                                    0x07
#define DP_MISC0_xvYCC422_BT709                            0x09
#define DP_MISC0_xvYCC444_BT709                            0x0A
#define DP_MISC0_RGB_FLOATING_POINT                        0x0B
#define DP_MISC0_ADOBE_RGB                                 0x0C
#define DP_MISC0_YUV422_BT709                              0x0D
#define DP_MISC0_YUV444_BT709                              0x0E
#define DP_MISC0_COLOR_PROFILE                             0x0F
/* Misc0 bit1~bit4 define end */

#define DP_SDP_PACKET_LEN                                  36
#define DP_LINK_RATE_N                                     27000    /* KHz, Link Rate = dpcd_link_bw_set * DP_LINK_RATE_N */

#define DP_TIMING_HMIN                                     320
#define DP_TIMING_VMIN                                     240
#define DP_TIMING_HMAX                                     10240
#define DP_PIXEL_CLOCK_MIN                                 10000    /* KHz */

#define SDP_TYPE_INFOFRAME_VSI                             0x81
#define SDP_TYPE_INFOFRAME_SPD                             0x83
#define SDP_TYPE_INFOFRAME_HDR                             0x87
#define SDP_TYPE_ADAPTIVE_SYNC                             0x22

#define DP_ADDR_OFFSET0                                    0x00     /* DP0 register offset*/
#define DP_ADDR_OFFSET1                                    0x2000   /* DP1 register offset*/

static UCHAR8 s_aucHdr[MAX(HV_BOARD_CONFIG_MAX_DP_PORT_NUM, 1)][DP_SDP_PACKET_LEN] = {0};
static UCHAR8 s_aucVrr[MAX(HV_BOARD_CONFIG_MAX_DP_PORT_NUM, 1)][DP_SDP_PACKET_LEN] = {0};

VOID Hv_Drv_DpRx_Init(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_SysInit(ucPortId);
    Hv_Cal_DpRx_CableInit(ucPortId,
        HV_BOARD_CONFIG_DP0_TYPE,
        HV_BOARD_CONFIG_DP1_TYPE);
    Hv_Cal_DpRx_HpdInit(ucPortId,
        HV_BOARD_CONFIG_DP0_TYPE,
        HV_BOARD_CONFIG_DP1_TYPE,
        0x19);
    Hv_Cal_DpRx_StandbyAuxInit(ucPortId, (HV_PROJECT_CONFIG_CTS == HV_CONFIG_ON));
    Hv_Cal_DpRx_AuxInit(ucPortId, (HV_PROJECT_CONFIG_CTS == HV_CONFIG_ON), HV_CHIP_CLK_APB);
    Hv_Cal_DpRx_DpcdInit(ucPortId, (HV_PROJECT_CONFIG_CTS == HV_CONFIG_ON));
    Hv_Cal_DpRx_SetSinkOui(ucPortId,
        HV_PROJECT_CONFIG_MANUFACT_OUI,
        HV_PROJECT_CONFIG_DEV_STRING0,
        HV_PROJECT_CONFIG_DEV_STRING1,
        HV_PROJECT_CONFIG_DEV_STRING2,
        HV_PROJECT_CONFIG_HW_MAJOR_REV,
        HV_PROJECT_CONFIG_HW_MINOR_REV,
        HV_PROJECT_CONFIG_FW_MAJOR_REV,
        HV_PROJECT_CONFIG_FW_MINOR_REV);
    Hv_Cal_DpRx_SetGuid(ucPortId,
        HV_PROJECT_CONFIG_GUID0,
        HV_PROJECT_CONFIG_GUID1,
        HV_PROJECT_CONFIG_GUID2,
        HV_PROJECT_CONFIG_GUID3);
    Hv_Cal_DpRx_MacInit(ucPortId, (HV_PROJECT_CONFIG_CTS == HV_CONFIG_ON), HV_CHIP_CLK_APB);
    if (ucPortId == 0)
    {
        Hv_Cal_DpRx_SetLaneSwap(ucPortId,
            HV_BOARD_CONFIG_DP0_LANE0,
            HV_BOARD_CONFIG_DP0_LANE1,
            HV_BOARD_CONFIG_DP0_LANE2,
            HV_BOARD_CONFIG_DP0_LANE3,
            HV_BORAD_CONFIG_DP0_LANE_POLARITY);
    }
    else
    {
        Hv_Cal_DpRx_SetLaneSwap(ucPortId,
            HV_BOARD_CONFIG_DP1_LANE0,
            HV_BOARD_CONFIG_DP1_LANE1,
            HV_BOARD_CONFIG_DP1_LANE2,
            HV_BOARD_CONFIG_DP1_LANE3,
            HV_BORAD_CONFIG_DP1_LANE_POLARITY);
    }
    Hv_Cal_DpRx_TrainingInit(ucPortId, (HV_PROJECT_CONFIG_CTS == HV_CONFIG_ON));
    Hv_Cal_DpRx_SdpInit(ucPortId);
    Hv_Cal_DpRx_Reset(ucPortId, HV_TRUE);

    if (ucPortId == 0)
    {
#if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
#if (HV_BOARD_CONFIG_DP0_TYPE == DP_PORT_NORM)
        Hv_Drv_Gpio_SetDirection(HV_BOARD_CONFIG_GPIO_DP0_HPD, GPIO_DIR_OUTPUT);
        Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_GPIO_DP0_HPD, GPIO_LEVEL_LOW);
#endif
#endif
    }
    else
    {
        Hv_Cal_DpRx_EvtHpd(ucPortId, DP_HPD_LOW);
    }

    return;
}

VOID Hv_Drv_DpRx_UpdtEdid(UCHAR8 ucPortId, const UCHAR8 *pucEdid, USHORT16 usLen)
{
    UINT32 uiEdidRegAddr = (ucPortId ? DP_ADDR_OFFSET1 : DP_ADDR_OFFSET0) + RX_EDP_RX_DPCD_EDID_00_00;
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    HV_ASSERT_VALID_PTR_VOID(pucEdid);

    if (usLen == 0)
    {
        usLen = DP_EDID_MAX_LENGTH;
    }

    Hv_Common_WriteRegBytes(pucEdid, uiEdidRegAddr, (UINT32)usLen);

    return;
}

Status Hv_Drv_DpRx_SetDpVer(UCHAR8 ucPortId, UCHAR8 ucDpVer)
{
    HV_ASSERT_TRUE_RET(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM, HV_FAILURE);

    return Hv_Cal_DpRx_SetDpVer(ucPortId, ucDpVer);
}

UCHAR8 Hv_Drv_DpRx_GetDpVer(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_RET(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM, HV_DP_VER14);

    return Hv_Cal_DpRx_GetDpVer(ucPortId);
}

BOOL Hv_Drv_DpRx_DetectCable(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_RET(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM, HV_FALSE);

    return Hv_Cal_DpRx_DetectCable(ucPortId);
}

BOOL Hv_Drv_DpRx_GetAuxState(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_RET(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM, HV_FALSE);

    if (ucPortId == 0)
    {
#if ((HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID) && (HV_BOARD_CONFIG_DP0_TYPE == DP_PORT_NORM))
        return Hv_Cal_DpRx_GetAuxState(3);
#else
        return HV_FALSE;
#endif
    }
    else
    {
#if ((HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID) && (HV_BOARD_CONFIG_DP1_TYPE == DP_PORT_NORM))
        return Hv_Cal_DpRx_GetAuxState(2);
#else
        return HV_FALSE;
#endif
    }
}

VOID Hv_Drv_DpRx_SetCableStatus(UCHAR8 ucPortId, BOOL bPlugIn)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_SetCableStatus(ucPortId, bPlugIn);

    return;
}

VOID Hv_Drv_DpRx_SetHPDStatus(UCHAR8 ucPortId, BOOL bHigh)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_SetHPDStatus(ucPortId, bHigh);

    return;
}

VOID Hv_Drv_DpRx_IrqHpd(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    if (ucPortId == 0)
    {
#if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
#if (HV_BOARD_CONFIG_DP0_TYPE == DP_PORT_NORM)
        Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_GPIO_DP0_HPD, GPIO_LEVEL_LOW);
        Hv_Vos_Delayus(800);
        Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_GPIO_DP0_HPD, GPIO_LEVEL_HIGH);
#endif
#endif
    }
    else
    {
        Hv_Cal_DpRx_IrqHpd(ucPortId);
    }

    return;
}

VOID Hv_Drv_DpRx_EvtHpd(UCHAR8 ucPortId, BOOL bSwitch)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    if (ucPortId == 0)
    {
#if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
#if (HV_BOARD_CONFIG_DP0_TYPE == DP_PORT_NORM)
        if (bSwitch)
        {
            Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_GPIO_DP0_HPD, GPIO_LEVEL_HIGH);
        }
        else
        {
            Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_GPIO_DP0_HPD, GPIO_LEVEL_LOW);
        }
#endif
#endif
    }
    else
    {
        Hv_Cal_DpRx_EvtHpd(ucPortId, bSwitch);
    }

    return;
}

BOOL Hv_Drv_DpRx_DetectLink(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_RET(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM, HV_FALSE);

    return Hv_Cal_DpRx_GetLtState(ucPortId);
}

VOID Hv_Drv_DpRx_DumpFailStatus(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    return Hv_Cal_DpRx_DumpFailStatus(ucPortId);
}

BOOL Hv_Drv_DpRx_DetectVideo(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_RET(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM, HV_FALSE);

    return Hv_Cal_DpRx_GetVideoFlag(ucPortId);
}

BOOL Hv_Drv_DpRx_DetectAudio(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_RET(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM, HV_FALSE);

    return Hv_Cal_DpRx_GetAudioFlag(ucPortId);
}

Status Hv_Drv_DpRx_GetTiming(UCHAR8 ucPortId, VideoTimingParam *pstTiming, AudioTimingParam *pstAudioTiming)
{
    HV_ASSERT_TRUE_RET(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM, HV_FAILURE);
    DpMsaParam stMsa = {0};
    UINT32 uiLaneClk = 0;

    Hv_Cal_DpRx_GetMsa(ucPortId, &stMsa);
    if ((stMsa.usHTotal == 0) || (stMsa.usVTotal == 0) || (stMsa.uiNvid == 0))
    {
        HV_LOG_DEBUG(DP, "DP%d zeros in timing info", ucPortId);

        return HV_FAILURE;
    }

    HV_ASSERT_VALID_PTR(pstTiming);
    HV_ASSERT_VALID_PTR(pstAudioTiming);
    pstTiming->usHActive = stMsa.usHActive;
    pstTiming->usHTotal  = stMsa.usHTotal;
    pstTiming->usHFProch = stMsa.usHTotal - stMsa.usHActive - stMsa.usHStart;
    pstTiming->usHSyncW  = stMsa.usHSW;
    pstTiming->usHBProch = stMsa.usHStart - stMsa.usHSW;
    pstTiming->usHPol    = stMsa.ucHSP;
    pstTiming->usVActive = stMsa.usVActive;
    pstTiming->usVTotal  = stMsa.usVTotal;
    pstTiming->usVFProch = stMsa.usVTotal - stMsa.usVActive - stMsa.usVStart;
    pstTiming->usVSyncW  = stMsa.usVSW;
    pstTiming->usVBProch = stMsa.usVStart - stMsa.usVSW;
    pstTiming->usVPol    = stMsa.ucVSP;
    pstAudioTiming->uiMaud = stMsa.uiMaud;
    pstAudioTiming->uiNaud = stMsa.uiNaud;
    
    /* Check Timing Is Valid */
    if ((pstTiming->usHActive < DP_TIMING_HMIN)
     || (pstTiming->usHActive > DP_TIMING_HMAX)
     || (pstTiming->usVActive < DP_TIMING_VMIN)
     || (pstTiming->usHTotal <= pstTiming->usHActive)
     || (pstTiming->usVTotal <= pstTiming->usVActive))
    {
        HV_LOG_DEBUG(DP, "Timing is invalid");

        return HV_FAILURE;
    }

    uiLaneClk = Hv_Cal_DpRx_GetLaneClk(ucPortId);

    pstTiming->uiFreqKHz = (UINT32)(uiLaneClk * 20 * 1.0f / stMsa.uiNvid * stMsa.uiMvid);
    pstTiming->usFrameRate = (USHORT16)(pstTiming->uiFreqKHz * 1000.0f / (stMsa.usHTotal * stMsa.usVTotal) + 0.5f);
    pstTiming->bInterlacedMode = Hv_Cal_DpRx_GetInterlaceFlag(ucPortId);
    pstTiming->uiHFreqHz = (UINT32)(pstTiming->uiFreqKHz * 1000.0f / pstTiming->usHTotal);
    pstTiming->fFrameRate = (FLOAT32)((DOUBLE64)(pstTiming->uiFreqKHz) * 1000.0f / stMsa.usHTotal / stMsa.usVTotal);

    if (pstTiming->uiFreqKHz > DP_PIXEL_CLOCK_MIN)
    {
        Hv_Cal_DpRx_SetTriggerPos(ucPortId, pstTiming->uiFreqKHz);

        return HV_SUCCESS;
    }
    else
    {
        HV_LOG_DEBUG(DP, "Pixel clock %d is invalid", pstTiming->uiFreqKHz);

        return HV_FAILURE;
    }
}

static VOID Hv_Drv_DpRx_GetMiscColor(UCHAR8 ucPortId, UCHAR8 *pucVSC, VideoColorParam *pstColor)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    UCHAR8 ucDepIdx = 0;
    DpMsaParam stMsa = {0};
    HV_ASSERT_VALID_PTR_VOID(pucVSC);
    HV_ASSERT_VALID_PTR_VOID(pstColor);

    Hv_Cal_DpRx_GetMsa(ucPortId, &stMsa);

    if ((stMsa.ucMisc1 & VSC_SDP_INDICATE_FLAG_MASK) == 0x40)
    {
        *pucVSC = 1;

        return;
    }

    if ((stMsa.ucMisc1 & PIXEL_ENCODEING_COLORIMETRY_INDICATOR_FIELD_MASK) == 0x00)
    {
        ucDepIdx = (stMsa.ucMisc0 & COLOR_DEPTH_INDICATOR_MASK) >> 5;

        switch (ucDepIdx)
        {
            case 0:
            {
                pstColor->eClrDepth = ColorDepthType_6Bit;
                break;
            }
            case 1:
            {
                pstColor->eClrDepth = ColorDepthType_8Bit;
                break;
            }
            case 2:
            {
                pstColor->eClrDepth = ColorDepthType_10Bit;
                break;
            }
            case 3:
            {
                pstColor->eClrDepth = ColorDepthType_12Bit;
                break;
            }
            case 4:
            {
                HV_LOG_DEBUG(DP, "Not support 16Bit, cut to 12Bit later");
                pstColor->eClrDepth = ColorDepthType_16Bit;
                break;
            }
            default:
            {
                pstColor->eClrDepth = ColorDepthType_8Bit;
                break;
            }
        }

        switch ((stMsa.ucMisc0 & 0x1E) >> 1)
        {
            case DP_MISC0_LEGACY_RGB_MODE:
            case DP_MISC0_RGB_FIXED_POINT:
            case DP_MISC0_RGB_FLOATING_POINT:
            {
                pstColor->eClrFormat = ColorFormatType_RGB;
                pstColor->eClrSpace  = ColorSpaceType_SRGB;
                pstColor->eClrRange  = ColorRangeType_Full_Range;
                break;
            }
            case DP_MISC0_DCI_P3:
            {
                pstColor->eClrFormat = ColorFormatType_RGB;
                pstColor->eClrSpace  = ColorSpaceType_ST2113_P3DCI;
                pstColor->eClrRange  = ColorRangeType_Limited_Range;
                break;
            }
            case DP_MISC0_ADOBE_RGB:
            {
                pstColor->eClrFormat = ColorFormatType_RGB;
                pstColor->eClrSpace  = ColorSpaceType_OP_RGB;
                /* Special for ATI graphic card */
                pstColor->eClrRange  = ColorRangeType_Full_Range;
                break;
            }
            case DP_MISC0_COLOR_PROFILE:
            {
                pstColor->eClrFormat = ColorFormatType_RGB;
                pstColor->eClrSpace  = ColorSpaceType_SRGB;
                pstColor->eClrRange  = ColorRangeType_Limited_Range;
                break;
            }
            case DP_MISC0_CEA_RGB:
            {
                pstColor->eClrFormat = ColorFormatType_RGB;
                pstColor->eClrSpace  = ColorSpaceType_SRGB;
                pstColor->eClrRange  = ColorRangeType_Limited_Range;
                break;
            }
            case DP_MISC0_xvYCC422_BT601:
            {
                pstColor->eClrFormat = ColorFormatType_YCbCr422;
                pstColor->eClrSpace  = ColorSpaceType_XV_YCC_601;
                pstColor->eClrRange  = ColorRangeType_Full_Range;
                break;
            }
            case DP_MISC0_YUV422_BT601:
            {
                pstColor->eClrFormat = ColorFormatType_YCbCr422;
                pstColor->eClrSpace  = ColorSpaceType_BT601;
                pstColor->eClrRange  = ColorRangeType_Limited_Range;
                break;
            }
            case DP_MISC0_xvYCC444_BT601:
            {
                pstColor->eClrFormat = ColorFormatType_YCbCr444;
                pstColor->eClrSpace  = ColorSpaceType_XV_YCC_601;
                pstColor->eClrRange  = ColorRangeType_Full_Range;
                break;
            }
            case DP_MISC0_YUV444_BT601:
            {
                pstColor->eClrFormat = ColorFormatType_YCbCr444;
                pstColor->eClrSpace  = ColorSpaceType_BT601;
                pstColor->eClrRange  = ColorRangeType_Limited_Range;
                break;
            }
            case DP_MISC0_xvYCC422_BT709:
            {
                pstColor->eClrFormat = ColorFormatType_YCbCr422;
                pstColor->eClrSpace  = ColorSpaceType_XV_YCC_709;
                pstColor->eClrRange  = ColorRangeType_Full_Range;
                break;
            }
            case DP_MISC0_YUV422_BT709:
            {
                pstColor->eClrFormat = ColorFormatType_YCbCr422;
                pstColor->eClrSpace  = ColorSpaceType_BT709;
                pstColor->eClrRange  = ColorRangeType_Limited_Range;
                break;
            }
            case DP_MISC0_xvYCC444_BT709:
            {
                pstColor->eClrFormat = ColorFormatType_YCbCr444;
                pstColor->eClrSpace  = ColorSpaceType_XV_YCC_709;
                pstColor->eClrRange  = ColorRangeType_Full_Range;
                break;
            }
            case DP_MISC0_YUV444_BT709:
            {
                pstColor->eClrFormat = ColorFormatType_YCbCr444;
                pstColor->eClrSpace  = ColorSpaceType_BT709;
                pstColor->eClrRange  = ColorRangeType_Limited_Range;
                break;
            }
            default:
            {
                pstColor->eClrFormat = ColorFormatType_RGB;
                pstColor->eClrSpace  = ColorSpaceType_SRGB;
                pstColor->eClrRange  = ColorRangeType_Full_Range;
                break;
            }
        }
    }

    return;
}

static VOID Hv_Drv_DpRx_GetVscColor(UCHAR8 ucPortId, VideoColorParam *pstColor)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    DpRxVscClolor stVscColor = {0};
    HV_ASSERT_VALID_PTR_VOID(pstColor);

    Hv_Cal_DpRx_GetVscValue(ucPortId, &stVscColor);

    switch (stVscColor.ucColorFormat)
    {
        case 0:
        {
            pstColor->eClrFormat = ColorFormatType_RGB;
            break;
        }
        case 1:
        {
            pstColor->eClrFormat = ColorFormatType_YCbCr444;
            break;
        }
        case 2:
        {
            pstColor->eClrFormat = ColorFormatType_YCbCr422;
            break;
        }
        case 3:
        {
            pstColor->eClrFormat = ColorFormatType_YCbCr420;
            break;
        }
        default:
        {
            HV_LOG_DEBUG(DP, "Not support Y-Only or RAW");
            pstColor->eClrFormat = ColorFormatType_RGB;
            break;
        }
    }

    switch (stVscColor.ucBitDepth)
    {
        case 0:
        {
            pstColor->eClrDepth = ColorDepthType_6Bit;
            break;
        }
        case 1:
        {
            pstColor->eClrDepth = ColorDepthType_8Bit;
            break;
        }
        case 2:
        {
            pstColor->eClrDepth = ColorDepthType_10Bit;
            break;
        }
        case 3:
        {
            pstColor->eClrDepth = ColorDepthType_12Bit;
            break;
        }
        case 4:
        {
            HV_LOG_DEBUG(DP, "Not Support 16Bit, cut to 12Bit later");
            pstColor->eClrDepth = ColorDepthType_16Bit;
            break;
        }
        default:
        {
            pstColor->eClrDepth = ColorDepthType_8Bit;
            break;
        }
    }

    if (stVscColor.ucColorRange == 0)
    {
        pstColor->eClrRange = ColorRangeType_Full_Range;
    }
    else
    {
        pstColor->eClrRange = ColorRangeType_Limited_Range;
    }

    if (pstColor->eClrFormat == ColorFormatType_RGB)
    {
        switch (stVscColor.ucColorSpace)
        {
            case 3:
            {
                pstColor->eClrSpace = ColorSpaceType_OP_RGB;
                break;
            }
            case 4:
            {
                pstColor->eClrSpace = ColorSpaceType_ST2113_P3DCI;
                break;
            }
            case 6:
            {
                pstColor->eClrSpace = ColorSpaceType_BT2020_RGB;
                break;
            }
            default:
            {
                pstColor->eClrSpace = ColorSpaceType_SRGB;
                break;
            }
        }
    }
    else
    {
        switch (stVscColor.ucColorSpace)
        {
            case 0:
            {
                pstColor->eClrSpace = ColorSpaceType_BT601;
                break;
            }
            case 1:
            {
                pstColor->eClrSpace = ColorSpaceType_XV_YCC_601;
                break;
            }
            case 2:
            {
                pstColor->eClrSpace = ColorSpaceType_S_YCC_601;
                break;
            }
            case 3:
            {
                pstColor->eClrSpace = ColorSpaceType_OP_YCC_601;
                break;
            }
            case 4:
            {
                pstColor->eClrSpace = ColorSpaceType_BT709;
                break;
            }
            case 5:
            {
                pstColor->eClrSpace = ColorSpaceType_XV_YCC_709;
                break;
            }
            case 6:
            {
                pstColor->eClrSpace = ColorSpaceType_BT2020_cYCC;
                break;
            }
            case 7:
            {
                pstColor->eClrSpace = ColorSpaceType_BT2020_YCC;
                break;
            }
            default:
            {
                pstColor->eClrSpace = ColorSpaceType_BT709;
                break;
            }
        }
    }

    return;
}


Status Hv_Drv_DpRx_GetColor(UCHAR8 ucPortId, VideoColorParam *pstColor)
{
    HV_ASSERT_TRUE(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    UCHAR8 ucVsc = 0;
    Status enRetVal = HV_SUCCESS;
    HV_ASSERT_VALID_PTR(pstColor);

    Hv_Drv_DpRx_GetMiscColor(ucPortId, &ucVsc, pstColor);

    if (ucVsc == 1)
    {
        HV_LOG_DEBUG(DP, "Use VSC color");
        Hv_Drv_DpRx_GetVscColor(ucPortId, pstColor);
    }

    if (HV_FALSE == Hv_Cal_DpRx_GetSdpStatus(ucPortId))
    {
        HV_LOG_INFO(DP, "DP SDP ERR");
        enRetVal = HV_FAILURE;
    }

    if ((pstColor->eClrFormat == ColorFormatType_YCbCr420)
        && (pstColor->eClrDepth == ColorDepthType_8Bit))
    {
        Hv_Drv_DpRx_SetAudVldThro(ucPortId, 0);
    }
    else
    {
        Hv_Drv_DpRx_SetAudVldThro(ucPortId, 1);
    }

    return enRetVal;
}

BOOL Hv_Drv_DpRx_GetSdpStatus(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_RET(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM, HV_FALSE);

    return Hv_Cal_DpRx_GetSdpStatus(ucPortId);
}

BOOL Hv_Drv_DpRx_GetAudioSta(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_RET(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM, HV_FALSE);

    return Hv_Cal_DpRx_GetAudioSta(ucPortId);
}

Status Hv_Drv_DpRx_ParserVrr(UCHAR8 *pucSdpBuf, VRRInfoParam *pstVrrParam)
{
    HV_ASSERT_VALID_PTR(pucSdpBuf);
    HV_ASSERT_VALID_PTR(pstVrrParam);

    if (pucSdpBuf[1] != SDP_TYPE_INFOFRAME_SPD)
    {
        HV_LOG_DEBUG(DP, "SPD header is invalid");

        return HV_FAILURE;
    }

    if ((pucSdpBuf[5] == 0x1A)
     && (pucSdpBuf[6] == 0x00)
     && (pucSdpBuf[7] == 0x00))
    {
        pstVrrParam->eVendor = VendorType_AMD;
        pstVrrParam->uvsi.stAmdSpdInfPara.ucVersion = (pucSdpBuf[3] >> 2);
        pstVrrParam->uvsi.stAmdSpdInfPara.ucFreeSyncMinReFresh = pucSdpBuf[11];
        pstVrrParam->uvsi.stAmdSpdInfPara.ucFreeSyncMaxReFresh = pucSdpBuf[12];
        pstVrrParam->uvsi.stAmdSpdInfPara.bFreeSyncSupported = pucSdpBuf[10] & BIT_0;
        pstVrrParam->uvsi.stAmdSpdInfPara.bFreeSyncEnabled = (pucSdpBuf[10] & BIT_1) >> 1;
        pstVrrParam->uvsi.stAmdSpdInfPara.bFreeSyncActive = (pucSdpBuf[10] & BIT_2) >> 2;
        pstVrrParam->bVRREnable = pstVrrParam->uvsi.stAmdSpdInfPara.bFreeSyncEnabled;
        if (pstVrrParam->uvsi.stAmdSpdInfPara.ucVersion == 2)
        {
            pstVrrParam->uvsi.stAmdSpdInfPara.bNativeColorSpaceActive = (pucSdpBuf[10] & BIT_3) >> 3;
            pstVrrParam->uvsi.stAmdSpdInfPara.bLocalDimmingDisabled = (pucSdpBuf[10] & BIT_5) >> 5;
            pstVrrParam->uvsi.stAmdSpdInfPara.ucBrightneesControl = pucSdpBuf[14];
            pstVrrParam->uvsi.stAmdSpdInfPara.bSRGBEOTFActive = pucSdpBuf[13] & BIT_0;
            pstVrrParam->uvsi.stAmdSpdInfPara.bBT709EOTFActive = (pucSdpBuf[13] & BIT_1) >> 1;
            pstVrrParam->uvsi.stAmdSpdInfPara.bGamma22EOTFActive = (pucSdpBuf[13] & BIT_2) >> 2;
            pstVrrParam->uvsi.stAmdSpdInfPara.bGamma26EOTFActive = (pucSdpBuf[13] & BIT_3) >> 3;
        }
    }
    else if ((pucSdpBuf[5] == 'N')
          && (pucSdpBuf[6] == 'V')
          && (pucSdpBuf[7] == 'I')
          && (pucSdpBuf[8] == 'D')
          && (pucSdpBuf[9] == 'I')
          && (pucSdpBuf[10] == 'A')
          && (pucSdpBuf[11] == 0x00)
          && (pucSdpBuf[12] == 0x00))
    {
        pstVrrParam->eVendor = VendorType_NVIDIA;
        HV_MEMCPY(pstVrrParam->uvsi.stNvidiaVSIPara.ucModeName, &pucSdpBuf[13], HV_VENDOR_DESCRIP_LEN);
        pstVrrParam->uvsi.stNvidiaVSIPara.eSourceInfoCode = pucSdpBuf[29];
    }
    else
    {
    }

    return HV_SUCCESS;
}

Status Hv_Drv_DpRx_GetVrr(UCHAR8 ucPortId, VRRInfoParam *pstVrrParam)
{
    HV_ASSERT_TRUE(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    UCHAR8 ucTruePort = 0;

    if(HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_INVALID)
    {
        ucTruePort = 0;
    }
    else
    {
        ucTruePort = ucPortId;
    }

    return Hv_Drv_DpRx_ParserVrr(s_aucVrr[ucTruePort], pstVrrParam);
}

VOID Hv_Drv_DpRx_SetTimingIgnore(UCHAR8 ucPortId, BOOL bIgnore)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_SetTimIgnore(ucPortId, bIgnore);

    return;
}

Status Hv_Drv_DpRx_SetMaxLaneCount(UCHAR8 ucPortId, UCHAR8 ucDpLaneCount)
{
    HV_ASSERT_TRUE(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    return Hv_Cal_DpRx_SetMaxLaneCount(ucPortId, ucDpLaneCount);
}

Status Hv_Drv_DpRx_CheckOui(UCHAR8 ucPortId, VRRInfoParam *pstVrrParam)
{
    HV_ASSERT_TRUE(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    BOOL bTimingIgnore = HV_FALSE;
    UINT32 uiOui = 0;
    UCHAR8 aucIdentification[6] = {0};
    HV_ASSERT_VALID_PTR(pstVrrParam);

    bTimingIgnore = Hv_Cal_DpRx_GetTimIgnore(ucPortId);
    Hv_Cal_DpRx_GetSrcOui(ucPortId, &uiOui, aucIdentification);
    Hv_Cal_DpRx_MaskMSAInt(ucPortId, bTimingIgnore);

    if (bTimingIgnore)
    {
        HV_LOG_DEBUG(DP, "DP%d Timing Ignore is Enabled", ucPortId);
        pstVrrParam->bVRREnable = HV_TRUE;
    }
    else
    {
        HV_LOG_DEBUG(DP, "DP%d Timing Ignore is Disabled", ucPortId);
        pstVrrParam->bVRREnable = HV_FALSE;
    }

    if (uiOui == 0x4B0400)
    {
        pstVrrParam->eVendor = VendorType_NVIDIA;
    }
    else if (uiOui == 0x1AA00)
    {
        pstVrrParam->eVendor = VendorType_AMD_AdaptSync;
    }
    else if (uiOui == 0x1A0050)
    {
        pstVrrParam->eVendor = VendorType_AMD;
    }
    else
    {
        pstVrrParam->eVendor = VendorType_UnKnown;
    }

    return HV_SUCCESS;
}

UCHAR8 Hv_Drv_DpRx_GetPowerState(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_RET(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM, 0);

    return Hv_Cal_DpRx_GetPowerState(ucPortId);
}

VOID Hv_Drv_DpRx_AudioReshape(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_AudioReshape(ucPortId);

    return;
}

Status Hv_Drv_DpRx_ParserHdr(UCHAR8 *pucSdpBuf, HDRParam *pstHdr)
{
    UINT32 uiIndex = 0;
    HV_ASSERT_VALID_PTR(pucSdpBuf);
    HV_ASSERT_VALID_PTR(pstHdr);

    if (pucSdpBuf[1] != SDP_TYPE_INFOFRAME_HDR)
    {
        HV_LOG_DEBUG(DP, "HDR header is invalid");

        return HV_FAILURE;
    }

    if ((pucSdpBuf[3] >> 2) >= HV_DP_VER12)
    {
        uiIndex = 6;
    }
    else
    {
        HV_LOG_DEBUG(DP, "HDR SDP version is unsupported");

        return HV_FAILURE;
    }

    pstHdr->xType = pucSdpBuf[uiIndex++];
    pstHdr->ucMetaID = pucSdpBuf[uiIndex++];
    if (pstHdr->ucMetaID == 0)
    {
        pstHdr->usPrimX0     = pucSdpBuf[uiIndex++];
        pstHdr->usPrimX0    += (pucSdpBuf[uiIndex++] << 8);
        pstHdr->usPrimY0     = pucSdpBuf[uiIndex++];
        pstHdr->usPrimY0    += (pucSdpBuf[uiIndex++] << 8);
        pstHdr->usPrimX1     = pucSdpBuf[uiIndex++];
        pstHdr->usPrimX1    += (pucSdpBuf[uiIndex++] << 8);
        pstHdr->usPrimY1     = pucSdpBuf[uiIndex++];
        pstHdr->usPrimY1    += (pucSdpBuf[uiIndex++] << 8);
        pstHdr->usPrimX2     = pucSdpBuf[uiIndex++];
        pstHdr->usPrimX2    += (pucSdpBuf[uiIndex++] << 8);
        pstHdr->usPrimY2     = pucSdpBuf[uiIndex++];
        pstHdr->usPrimY2    += (pucSdpBuf[uiIndex++] << 8);
        pstHdr->usWhtX       = pucSdpBuf[uiIndex++];
        pstHdr->usWhtX      += (pucSdpBuf[uiIndex++] << 8);
        pstHdr->usWhtY       = pucSdpBuf[uiIndex++];
        pstHdr->usWhtY      += (pucSdpBuf[uiIndex++] << 8);
        pstHdr->usMaxLum     = pucSdpBuf[uiIndex++];
        pstHdr->usMaxLum    += (pucSdpBuf[uiIndex++] << 8);
        pstHdr->usMinLum     = pucSdpBuf[uiIndex++];
        pstHdr->usMinLum    += (pucSdpBuf[uiIndex++] << 8);
        pstHdr->usMaxCntn    = pucSdpBuf[uiIndex++];
        pstHdr->usMaxCntn   += (pucSdpBuf[uiIndex++] << 8);
        pstHdr->usMaxFrmAvg  = pucSdpBuf[uiIndex++];
        pstHdr->usMaxFrmAvg += (pucSdpBuf[uiIndex++] << 8);
    }
    else
    {
        pstHdr->xType = 0;
    }

    return HV_SUCCESS;
}

Status Hv_Drv_DpRx_GetHdr(UCHAR8 ucPortId, HDRParam *pstHdr)
{
    HV_ASSERT_TRUE(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    UCHAR8 ucTruePort = 0;

    if(HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_INVALID)
    {
        ucTruePort = 0;
    }
    else
    {
        ucTruePort = ucPortId;
    }

    return Hv_Drv_DpRx_ParserHdr(s_aucHdr[ucTruePort], pstHdr);
}

VOID Hv_Drv_DpRx_SaveHdr(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    UINT32 uiSdpAddr = (ucPortId ? DP_ADDR_OFFSET1 : DP_ADDR_OFFSET0) + RX_EDP_RX_MAC_SDP_REG_00_70;
    UCHAR8 ucTruePort = 0;

    if(HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_INVALID)
    {
        ucTruePort = 0;
    }
    else
    {
        ucTruePort = ucPortId;
    }

    Hv_Common_ReadRegBytes(s_aucHdr[ucTruePort], uiSdpAddr, DP_SDP_PACKET_LEN);

    return;
}

Status Hv_Drv_DpRx_ClrHdr(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    UCHAR8 ucTruePort = 0;

    if(HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_INVALID)
    {
        ucTruePort = 0;
    }
    else
    {
        ucTruePort = ucPortId;
    }

    HV_MEMSET(s_aucHdr[ucTruePort], 0, DP_SDP_PACKET_LEN);

    return HV_SUCCESS;
}

VOID Hv_Drv_DpRx_SaveVrr(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    UINT32 uiSdpAddr = (ucPortId ? DP_ADDR_OFFSET1 : DP_ADDR_OFFSET0) + RX_EDP_RX_MAC_SDP_REG_00_70;
    UCHAR8 ucTruePort = 0;

    if(HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_INVALID)
    {
        ucTruePort = 0;
    }
    else
    {
        ucTruePort = ucPortId;
    }

    Hv_Common_ReadRegBytes(s_aucVrr[ucTruePort], uiSdpAddr, DP_SDP_PACKET_LEN);

    return;
}

Status Hv_Drv_DpRx_ClrVrr(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    UCHAR8 ucTruePort = 0;

    if(HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_INVALID)
    {
        ucTruePort = 0;
    }
    else
    {
        ucTruePort = ucPortId;
    }

    HV_MEMSET(s_aucVrr[ucTruePort], 0, DP_SDP_PACKET_LEN);

    return HV_SUCCESS;
}

VOID Hv_Drv_DpRx_UpdateSdp(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    UCHAR8 ucSdpDepth = 0;
    UCHAR8 ucIndex = 0;
    
    ucSdpDepth = Hv_Cal_DpRx_GetFifoDepth(ucPortId);
    for (ucIndex = 0; ucIndex < ucSdpDepth; ucIndex++)
    {
        Hv_Cal_DpRx_ReadFifo(ucPortId);
        if (SDP_TYPE_INFOFRAME_HDR == Hv_Cal_DpRx_GetSdpType(ucPortId))
        {
            Hv_Drv_DpRx_SaveHdr(ucPortId);
        }
        else if (SDP_TYPE_INFOFRAME_SPD == Hv_Cal_DpRx_GetSdpType(ucPortId))
        {
            Hv_Drv_DpRx_SaveVrr(ucPortId);
        }
        else
        {
        }
    }

    Hv_Cal_DpRx_ClrSdpFifo(ucPortId);

    return;
}

VOID Hv_Drv_DpRx_GetMccsCmd(UCHAR8 ucPortId, UCHAR8 *pucMccsCmd, UCHAR8 ucLength)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    HV_ASSERT_VALID_PTR_VOID(pucMccsCmd);

    UINT32 uiSdpAddr = (ucPortId ? DP_ADDR_OFFSET1 : DP_ADDR_OFFSET0) + RX_EDP_RX_DPCD_MCCS_0_00_00;

    if (ucLength > DP_MCCS_CMD_LENGTH)
    {
        ucLength = DP_MCCS_CMD_LENGTH;
    }

    Hv_Common_ReadRegBytes(pucMccsCmd, uiSdpAddr, ucLength);

    return;
}

UCHAR8 Hv_Drv_DpRx_GetIrqId(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_RET(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM, 0xFF);

    return Hv_Cal_DpRx_GetIrqId(ucPortId);
}

UCHAR8 Hv_Drv_DpRx_GetCableIrqId(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_RET(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM, 0xFF);

    return Hv_Cal_DpRx_GetCableIrqId(ucPortId);
}

VOID Hv_Drv_DpRx_MaskSdpInt(UCHAR8 ucPortId, BOOL bSwitch)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_MaskSdpInt(ucPortId, bSwitch);

    return;
}

VOID Hv_Drv_DpRx_MaskColorInt(UCHAR8 ucPortId, BOOL bSwitch)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_MaskColorInt(ucPortId, bSwitch);

    return;
}

VOID Hv_Drv_DpRx_MaskTimingInt(UCHAR8 ucPortId, BOOL bSwitch)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_MaskTimingInt(ucPortId, bSwitch);

    return;
}

VOID Hv_Drv_DpRx_MaskRxHtotalInt(UCHAR8 ucPortId, BOOL bSwitch)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_MaskRxHtotalInt(ucPortId, bSwitch);

    return;
}

VOID Hv_Drv_DpRx_MaskAudioDepthInt(UCHAR8 ucPortId, BOOL bSwitch)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_MaskAudioDepthInt(ucPortId, bSwitch);

    return;
}
VOID Hv_Drv_DpRx_SetIntEnable(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_SetIntEnable(ucPortId);
#if (HV_PROJECT_CONFIG_CTS == HV_CONFIG_ON)
    Hv_Cal_DpRx_ErrIntEnable(ucPortId);
#endif

    return;
}

VOID Hv_Drv_DpRx_GetIntFlag(UCHAR8 ucPortId, UINT32 *puiDpIntFlag, UINT32 *puiHdcpIntFlag)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    if (ucPortId == 0)
    {
        Hv_Cal_DpRx_GetIntFlag(ucPortId,
            (HV_PROJECT_CONFIG_CTS == HV_CONFIG_ON),
            puiDpIntFlag,
            puiHdcpIntFlag,
            HV_BOARD_CONFIG_DP0_LANE0,
            HV_BOARD_CONFIG_DP0_LANE1,
            HV_BOARD_CONFIG_DP0_LANE2,
            HV_BOARD_CONFIG_DP0_LANE3);
    }
    else
    {
        Hv_Cal_DpRx_GetIntFlag(ucPortId,
            (HV_PROJECT_CONFIG_CTS == HV_CONFIG_ON),
            puiDpIntFlag,
            puiHdcpIntFlag,
            HV_BOARD_CONFIG_DP1_LANE0,
            HV_BOARD_CONFIG_DP1_LANE1,
            HV_BOARD_CONFIG_DP1_LANE2,
            HV_BOARD_CONFIG_DP1_LANE3);
    }

    return;
}

VOID Hv_Drv_DpRx_ClrIntFlag(UCHAR8 ucPortId, UINT32 *puiDpIntFlag, UINT32 *puiHdcpIntFlag)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_ClrIntFlag(ucPortId, puiDpIntFlag, puiHdcpIntFlag);

    return;
}

VOID Hv_Drv_DpRx_LinkBwChanged(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_LinkBwChanged(ucPortId);

    return;
}

VOID Hv_Drv_DpRx_LinkCountChanged(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    if (ucPortId == 0)
    {
        Hv_Cal_DpRx_LinkCountChanged(ucPortId,
            HV_BOARD_CONFIG_DP0_LANE0,
            HV_BOARD_CONFIG_DP0_LANE1,
            HV_BOARD_CONFIG_DP0_LANE2,
            HV_BOARD_CONFIG_DP0_LANE3,
            HV_BOARD_CONFIG_DP0_AUX_POLARITY);
    }
    else
    {
        Hv_Cal_DpRx_LinkCountChanged(ucPortId,
            HV_BOARD_CONFIG_DP1_LANE0,
            HV_BOARD_CONFIG_DP1_LANE1,
            HV_BOARD_CONFIG_DP1_LANE2,
            HV_BOARD_CONFIG_DP1_LANE3,
            HV_BOARD_CONFIG_DP1_AUX_POLARITY);
    }

    return;
}

VOID  Hv_Drv_DpRx_EqPermit(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_EqPermit(ucPortId, (HV_PROJECT_CONFIG_CTS == HV_CONFIG_ON));

    return;
}

VOID Hv_Drv_DpRx_TrainingDone(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_TrainingDone(ucPortId);

    return;
}

VOID Hv_Drv_DpRx_TrainingFail(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_TrainingFail(ucPortId, (HV_PROJECT_CONFIG_CTS == HV_CONFIG_ON));

    return;
}

VOID Hv_Drv_DpRx_SetTrainMode(UCHAR8 ucPortId, UCHAR8 ucTrainMode)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_SetTrainMode(ucPortId, ucTrainMode);

    return;
}

Status Hv_Drv_DpRx_AudioFifoOnOff(UCHAR8 ucPortId, BOOL bEn)
{
    HV_ASSERT_TRUE_RET_NO_LOG(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM, HV_FAILURE);

    return Hv_Cal_DpRx_AudioFifoOnOff(ucPortId, bEn);
}


VOID Hv_Drv_DpRx_ToggleDeskew(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_ToggleDeskew(ucPortId);

    return;
}

VOID Hv_Drv_DpRx_SwIrq(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_SwIrq(ucPortId);

    return;
}

VOID Hv_Drv_DpRx_ClrCableIntFlag(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_ClrCableIntFlag(ucPortId);

    return;
}

Status Hv_Drv_DpRx_AlysIntEvent(UCHAR8 ucPortId,UINT32 *puiNoHdcpIntFlag, DpRxIntEventList *pstDpRxEventList)
{
    HV_ASSERT_TRUE(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    HV_ASSERT_VALID_PTR(puiNoHdcpIntFlag);
    HV_ASSERT_VALID_PTR(pstDpRxEventList);
    HV_ASSERT_VALID_PTR(pstDpRxEventList->usEventList);

    pstDpRxEventList->ucSize = 0;

    if ((puiNoHdcpIntFlag[0] == 0) && (puiNoHdcpIntFlag[1] == 0) && (puiNoHdcpIntFlag[2] == 0))
    {
        HV_LOG_DEBUG(DP, "Invalid Interrupt");

        return HV_FAILURE;
    }

    if (puiNoHdcpIntFlag[0] & (1 << O_DPRX_FT_IRQ_0))
    {
        pstDpRxEventList->usEventList[pstDpRxEventList->ucSize++] = InputPortEventId_DP_TrainingDone;
    }
    if (puiNoHdcpIntFlag[0] & (1 << O_DPRX_FT_IRQ_1))
    {
        pstDpRxEventList->usEventList[pstDpRxEventList->ucSize++] = InputPortEventId_DP_TrainingFail;
    }
    if ((puiNoHdcpIntFlag[0] & (1 << VB_ID_IRQ_2)))
    {
        pstDpRxEventList->usEventList[pstDpRxEventList->ucSize++] = InputPortEventId_DP_VideoStream;
    }
    if ((puiNoHdcpIntFlag[0] & (1 << VB_ID_IRQ_3)))
    {
        pstDpRxEventList->usEventList[pstDpRxEventList->ucSize++] = InputPortEventId_DP_AudioMuteChg;
    }
    if ((puiNoHdcpIntFlag[0] & (1 << DPRX_RESOLUTION_CHANGE))
     || (puiNoHdcpIntFlag[0] & (1 << DPRX_MNVID_CHANGE))
     || (puiNoHdcpIntFlag[2] & (1 << DPRX_RWTOTAL_CHG))
     || (puiNoHdcpIntFlag[2] & (1 << DPRX_MSATOTAL_CHG)))
    {
        pstDpRxEventList->usEventList[pstDpRxEventList->ucSize++] = InputPortEventId_DP_TimingChange;
    }
    if ((puiNoHdcpIntFlag[0] & (1 << DPRX_COLOR_CHANGE)))
    {
        pstDpRxEventList->usEventList[pstDpRxEventList->ucSize++] = InputPortEventId_DP_ColorChange;
    }
    if ((puiNoHdcpIntFlag[0] & (1 << VB_ID_IRQ_0)))
    {
        pstDpRxEventList->usEventList[pstDpRxEventList->ucSize++] = InputPortEventId_DP_VsyncEvent;
    }
    if ((puiNoHdcpIntFlag[1] & (1 << DP_RX_MCCS)))
    {
        pstDpRxEventList->usEventList[pstDpRxEventList->ucSize++] = InputPortEventId_DP_Mccs;
    }
    if (puiNoHdcpIntFlag[1] & (1 << DPRX_AUX_RD_DPCD_EN_13))
    {
        pstDpRxEventList->usEventList[pstDpRxEventList->ucSize++] = InputPortEventId_DP_WakeUp;
    }
    if ((puiNoHdcpIntFlag[1] & (1 << DPRX_AUX_RD_DPCD_EN_16)))
    {
        pstDpRxEventList->usEventList[pstDpRxEventList->ucSize++] = InputPortEventId_DP_WriteTimingIgnore;
    }
    if ((puiNoHdcpIntFlag[1] & (1 << SDP_IRQ_2)))
    {
        pstDpRxEventList->usEventList[pstDpRxEventList->ucSize++] = InputPortEventId_DP_HdrChange;
    }
    if ((puiNoHdcpIntFlag[2] & (1 << DPRX_VRR_UPDATE_IRQ)))
    {
        pstDpRxEventList->usEventList[pstDpRxEventList->ucSize++] = InputPortEventId_DP_VrrChange;
    }
    if ((puiNoHdcpIntFlag[2] & (1 << DPRX_ADPT_START_IRQ)))
    {
        pstDpRxEventList->usEventList[pstDpRxEventList->ucSize++] = InputPortEventId_DP_AdaptiveSyncStart;
    }
    if ((puiNoHdcpIntFlag[2] & (1 << DPRX_ADPT_END_IRQ)))
    {
        pstDpRxEventList->usEventList[pstDpRxEventList->ucSize++] = InputPortEventId_DP_AdaptiveSyncEnd;
    }
    if (puiNoHdcpIntFlag[2] & (1 << DPRX_AUDO_DEPTH_HIGH))
    {
        pstDpRxEventList->usEventList[pstDpRxEventList->ucSize++] = InputPortEventId_DP_AudioStart;
    }

    return HV_SUCCESS;
}

VOID Hv_Drv_DpRx_MccsReply(UCHAR8 ucPortId, UCHAR8 *pucData, UCHAR8 ucLen)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    HV_ASSERT_TRUE_VOID(ucLen <= (DP_MCCS_CMD_LENGTH * 3));
    HV_ASSERT_VALID_PTR_VOID(pucData);
    UINT32 uiAddrOffset = ucPortId ? DP_ADDR_OFFSET1 : DP_ADDR_OFFSET0;
    UINT32 uiMccsAddr = HV_EDP_RX_DPCD_MCCS_0_00_BASE_ADDRESS + uiAddrOffset + 0x21;

    Hv_Common_WriteRegBytes(pucData, uiMccsAddr, ucLen);
    Hv_Cal_DpRx_MccsReady(ucPortId, ucLen);

    return;
}

VOID Hv_Drv_DpRx_ResetDpcd(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_ResetDpcd(ucPortId);

    return;
}

VOID Hv_Drv_DpRx_SetAudVldThro(UCHAR8 ucPortId, UINT32 uiAudVld)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_SetAudVldThro(ucPortId, uiAudVld);

    return;
}

UCHAR8 Hv_Drv_DpRx_GetPortMux(VOID)
{
    return Hv_Cal_DpRx_GetPortMux();
}

UINT32 Hv_Drv_DpRx_GetFrameRate(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_RET(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM, 0);
    BOOL bTimIgnore = HV_FALSE;
    DpMsaParam stMsa = {0};
    UINT32 uiLaneClk = 0;
    USHORT16 usHTotal = 0;
    USHORT16 usVTotal = 0;
    UINT32 uiFrameRate = 0;
    UINT32 uiFrameCnt = 0;

    bTimIgnore = Hv_Cal_DpRx_GetTimIgnore(ucPortId);

    Hv_Cal_DpRx_GetMsa(ucPortId, &stMsa);
    if ((stMsa.usHTotal == 0) || (stMsa.usVTotal == 0) || (stMsa.uiNvid == 0))
    {
        HV_LOG_DEBUG(DP, "DP%d zeros in timing info", ucPortId);

        return 0;
    }

    if (bTimIgnore)
    {
        uiFrameCnt = Hv_Cal_DpRx_GetFrameCnt(ucPortId);

        if (uiFrameCnt == 0)
        {
            HV_LOG_DEBUG(DP, "Frame count is invalid");
            return 0;
        }
        else
        {
            return (UINT32)(DP_LINK_RATE_N * 1000000.0f / uiFrameCnt);
        }
    }
    else
    {
        HV_LOG_DEBUG(DP, "Use MSA timing");
        usHTotal = stMsa.usHTotal;
        usVTotal = stMsa.usVTotal;
    }

    uiLaneClk = Hv_Cal_DpRx_GetLaneClk(ucPortId);

    uiFrameRate = (UINT32)((UINT64)uiLaneClk * 20 * 1000000.0f / (UINT64)stMsa.uiNvid
                  * (UINT64)stMsa.uiMvid / ((UINT64)usHTotal * (UINT64)usVTotal));

    return uiFrameRate;
}

VOID Hv_Drv_DpRx_SetTypecOrientation(UCHAR8 ucPortId, UCHAR8 ucOrientation, UCHAR8 ucPinAssignment)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    if (ucPortId == 0)
    {
        Hv_Cal_DpRx_SetTypecOrientation(ucPortId, ucOrientation, ucPinAssignment, 
            HV_BOARD_CONFIG_DP0_LANE0,
            HV_BOARD_CONFIG_DP0_LANE1,
            HV_BOARD_CONFIG_DP0_LANE2,
            HV_BOARD_CONFIG_DP0_LANE3,
            HV_BOARD_CONFIG_DP0_AUX_POLARITY,
            HV_BORAD_CONFIG_DP0_LANE_POLARITY);
    }
    else
    {
        Hv_Cal_DpRx_SetTypecOrientation(ucPortId, ucOrientation, ucPinAssignment,
            HV_BOARD_CONFIG_DP1_LANE0,
            HV_BOARD_CONFIG_DP1_LANE1,
            HV_BOARD_CONFIG_DP1_LANE2,
            HV_BOARD_CONFIG_DP1_LANE3,
            HV_BOARD_CONFIG_DP1_AUX_POLARITY,
            HV_BORAD_CONFIG_DP1_LANE_POLARITY);
    }

    return;
}

VOID Hv_Drv_DpRx_AudioStop(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_AudioFifoOnOff(ucPortId, HV_FALSE);
    Hv_Cal_DpRx_AudioStop(ucPortId);

    return;
}

VOID Hv_Drv_DpRx_AudioStart(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_AudioStart(ucPortId);

    return;
}

VOID Hv_Drv_DpRx_AudioCheck(UCHAR8 ucPortId)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);
    UINT32 uiStreamTmp = 0;
    UINT32 uiVtotalTmp = 0;
    UCHAR8 ucAudioCh = 0;

    Hv_Cal_DpRx_GetAudioInfo(ucPortId, &uiVtotalTmp, &uiStreamTmp, &ucAudioCh);
    Hv_Cal_DpRx_SetAudioCh(ucPortId, ucAudioCh);
    Hv_Cal_DpRx_AudioCheck(ucPortId);

    return;
}

VOID Hv_Drv_DpRx_Reset(UCHAR8 ucPortId, BOOL bEn)
{
    HV_ASSERT_TRUE_VOID(ucPortId <= HV_BOARD_CONFIG_MAX_DP_PORT_NUM);

    Hv_Cal_DpRx_Reset(ucPortId, bEn);

    return;
}

VOID Hv_Drv_DpRx_EnableApbWr(BOOL bEn)
{
    Hv_Cal_DpRx_EnableApbWr(bEn);

    return;
}

