/**
 * @file hv_mw_InputPortManager.c
 * @brief middlware inputport manager cpp file.
 * @details This file provides the following functions: \n
 *          (1) Initialization and de-initialization functions \n
 *          (2) Start and stop functions \n
 *          (3) Feed 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 <math.h>

#include "hv_mw_InputPortManager.h"
#include "hv_mw_StateMachine.h"
#include "hv_mw_Hdmi.h"
#include "hv_mw_DisplayPort.h"
#include "hv_mw_Hdcp.h"

#include "hv_drv_PLL.h"
#include "hv_drv_DpuMainMute.h"
#include "hv_drv_DpuMainScaler.h"

#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
#include "hv_drv_DpuSubMute.h"
#include "hv_drv_DpuSubScaler.h"
#endif

static InputPortManager s_stInputPortManager;
static const InputPortStateMachine s_astInputPortStateMachine[] = 
{
    /*HDMI*/

    /*idle state*/
    {INPUT_PORT_STATE_IDLE,           InputPortEventId_HDMI_OnFirstEnterState,   Hv_Mw_HdmiRx_Sm_EnterIdleHandle,           INPUT_PORT_STATE_IDLE,           INPUT_PORT_STATE_IDLE},
    {INPUT_PORT_STATE_IDLE,           InputPortEventId_HDMI_IdleStart,           Hv_Mw_HdmiRx_Sm_IdleStartHandle,           INPUT_PORT_STATE_IDLE,           INPUT_PORT_STATE_IDLE},
    {INPUT_PORT_STATE_IDLE,           InputPortEventId_HDMI_5VPlugIn,            Hv_Mw_HdmiRx_Sm_PlugInCableHandle,         INPUT_PORT_STATE_WAIT_FAST_LOCK, INPUT_PORT_STATE_IDLE},

    /* SoftWare PHY Training */
    {INPUT_PORT_STATE_WAIT_FAST_LOCK, InputPortEventId_HDMI_OnFirstEnterState,   Hv_Mw_HdmiRx_Sm_EnterWaitLockHandle,       INPUT_PORT_STATE_WAIT_FAST_LOCK, INPUT_PORT_STATE_WAIT_FAST_LOCK},
    {INPUT_PORT_STATE_WAIT_FAST_LOCK, InputPortEventId_HDMI_FastLocked,          Hv_Mw_HdmiRx_Sm_LaneFastLockedHandle,      INPUT_PORT_STATE_WAIT_SYNC,      INPUT_PORT_STATE_WAIT_EQ_DONE},
    {INPUT_PORT_STATE_WAIT_FAST_LOCK, SYS_EVENT_TIMER_HDMI0_FASTLCK,             Hv_Mw_HdmiRx_Sm_WaitFastLockTimeoutHandle, INPUT_PORT_STATE_WAIT_FAST_LOCK, INPUT_PORT_STATE_WAIT_SYNC},
    {INPUT_PORT_STATE_WAIT_FAST_LOCK, SYS_EVENT_TIMER_HDMI1_FASTLCK,             Hv_Mw_HdmiRx_Sm_WaitFastLockTimeoutHandle, INPUT_PORT_STATE_WAIT_FAST_LOCK, INPUT_PORT_STATE_WAIT_SYNC},

    {INPUT_PORT_STATE_WAIT_EQ_DONE,   InputPortEventId_HDMI_OnFirstEnterState,   Hv_Mw_HdmiRx_Sm_EnterWaitEqDoneHandle,     INPUT_PORT_STATE_WAIT_EQ_DONE,   INPUT_PORT_STATE_WAIT_EQ_DONE},
    {INPUT_PORT_STATE_WAIT_EQ_DONE,   InputPortEventId_HDMI_TrainDone,           Hv_Mw_HdmiRx_Sm_CheckEqCedHandle,          INPUT_PORT_STATE_WAIT_EQ_DONE,   INPUT_PORT_STATE_WAIT_FAST_LOCK},
    {INPUT_PORT_STATE_WAIT_EQ_DONE,   SYS_EVENT_TIMER_HDMI0_WAIT_EQ_DONE,        Hv_Mw_HdmiRx_Sm_WaitEqDoneTimeOutHandle,   INPUT_PORT_STATE_WAIT_FAST_LOCK, INPUT_PORT_STATE_WAIT_FAST_LOCK},
    {INPUT_PORT_STATE_WAIT_EQ_DONE,   SYS_EVENT_TIMER_HDMI1_WAIT_EQ_DONE,        Hv_Mw_HdmiRx_Sm_WaitEqDoneTimeOutHandle,   INPUT_PORT_STATE_WAIT_FAST_LOCK, INPUT_PORT_STATE_WAIT_FAST_LOCK},
    {INPUT_PORT_STATE_WAIT_EQ_DONE,   InputPortEventId_HDMI_FastLocked,          Hv_Mw_HdmiRx_Sm_FastLockedHandle,          INPUT_PORT_STATE_WAIT_EQ_DONE,   INPUT_PORT_STATE_WAIT_FAST_LOCK},

    /*wait sync state*/
    {INPUT_PORT_STATE_WAIT_SYNC,      InputPortEventId_HDMI_OnFirstEnterState,   Hv_Mw_HdmiRx_Sm_EnterWaitSyncHandle,       INPUT_PORT_STATE_WAIT_SYNC,      INPUT_PORT_STATE_WAIT_SYNC},
    {INPUT_PORT_STATE_WAIT_SYNC,      InputPortEventId_HDMI_TrainDone,           Hv_Mw_HdmiRx_Sm_TrainingDoneHandle,        INPUT_PORT_STATE_SYNC_OK,        INPUT_PORT_STATE_WAIT_SYNC},
    {INPUT_PORT_STATE_WAIT_SYNC,      InputPortEventId_HDMI_FastLocked,          Hv_Mw_HdmiRx_Sm_FastLockedHandle,          INPUT_PORT_STATE_WAIT_SYNC,      INPUT_PORT_STATE_WAIT_FAST_LOCK},
    {INPUT_PORT_STATE_WAIT_SYNC,      SYS_EVENT_TIMER_HDMI0_WAITSYNC,            Hv_Mw_HdmiRx_Sm_WaitSyncTimeOutHandle,     INPUT_PORT_STATE_WAIT_SYNC,      INPUT_PORT_STATE_WAIT_FAST_LOCK},
    {INPUT_PORT_STATE_WAIT_SYNC,      SYS_EVENT_TIMER_HDMI1_WAITSYNC,            Hv_Mw_HdmiRx_Sm_WaitSyncTimeOutHandle,     INPUT_PORT_STATE_WAIT_SYNC,      INPUT_PORT_STATE_WAIT_FAST_LOCK},

    /*sync ok state*/
    {INPUT_PORT_STATE_SYNC_OK,        InputPortEventId_HDMI_OnFirstEnterState,   Hv_Mw_HdmiRx_Sm_EnterSyncOkHandle,         INPUT_PORT_STATE_SYNC_OK,        INPUT_PORT_STATE_SYNC_OK},
    {INPUT_PORT_STATE_SYNC_OK,        InputPortEventId_HDMI_TimingStable,        Hv_Mw_HdmiRx_Sm_TimingStableHandle,        INPUT_PORT_STATE_DISPLAY_RDY,    INPUT_PORT_STATE_WAIT_SYNC},
    {INPUT_PORT_STATE_SYNC_OK,        SYS_EVENT_TIMER_HDMI0_SYNCOK,              Hv_Mw_HdmiRx_Sm_SyncOkTimeoutHandle,       INPUT_PORT_STATE_SYNC_OK,        INPUT_PORT_STATE_WAIT_SYNC},
    {INPUT_PORT_STATE_SYNC_OK,        SYS_EVENT_TIMER_HDMI1_SYNCOK,              Hv_Mw_HdmiRx_Sm_SyncOkTimeoutHandle,       INPUT_PORT_STATE_SYNC_OK,        INPUT_PORT_STATE_WAIT_SYNC},
    {INPUT_PORT_STATE_SYNC_OK,        InputPortEventId_HDMI_PllChange,           Hv_Mw_HdmiRx_Sm_SignalLossHandle,          INPUT_PORT_STATE_WAIT_FAST_LOCK, INPUT_PORT_STATE_WAIT_FAST_LOCK},
    {INPUT_PORT_STATE_SYNC_OK,        InputPortEventId_HDMI_FastLocked,          Hv_Mw_HdmiRx_Sm_FastLockedHandle,          INPUT_PORT_STATE_SYNC_OK,        INPUT_PORT_STATE_WAIT_FAST_LOCK},

    /*disply ready state*/
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_HDMI_OnFirstEnterState,    Hv_Mw_HdmiRx_Sm_EnterDisplayReadyHandle,   INPUT_PORT_STATE_DISPLAY_RDY,    INPUT_PORT_STATE_WAIT_SYNC},
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_HDMI_AVIPacketChange,      Hv_Mw_HdmiRx_Sm_AVIPacketChangeHandle,     INPUT_PORT_STATE_WAIT_FAST_LOCK, INPUT_PORT_STATE_DISPLAY_RDY},    
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_HDMI_TimingChange,         Hv_Mw_HdmiRx_Sm_TimingChangeHandle,        INPUT_PORT_STATE_WAIT_FAST_LOCK, INPUT_PORT_STATE_DISPLAY_RDY},
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_HDMI_PllChange,            Hv_Mw_HdmiRx_Sm_SignalLossHandle,          INPUT_PORT_STATE_WAIT_FAST_LOCK, INPUT_PORT_STATE_WAIT_SYNC},
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_HDMI_AudioResetFifo,       Hv_Mw_HdmiRx_Sm_ResetAudioFifoHandle,      INPUT_PORT_STATE_DISPLAY_RDY,    INPUT_PORT_STATE_DISPLAY_RDY},
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_HDMI_DRMPacketChange,      Hv_Mw_HdmiRx_Sm_RcvHDRPacketHandle,        INPUT_PORT_STATE_DISPLAY_RDY,    INPUT_PORT_STATE_DISPLAY_RDY},    
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_HDMI_DecodeError,          Hv_Mw_HdmiRx_Sm_SignalLossHandle,          INPUT_PORT_STATE_WAIT_SYNC,      INPUT_PORT_STATE_WAIT_SYNC},    
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_HDMI_GcpCDChg,             Hv_Mw_HdmiRx_Sm_AVIPacketChangeHandle,     INPUT_PORT_STATE_WAIT_FAST_LOCK, INPUT_PORT_STATE_DISPLAY_RDY},
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_HDMI_AudioCTSOrNChang,     Hv_Mw_HdmiRx_Sm_AudioStartHandle,          INPUT_PORT_STATE_ANY_STATE,      INPUT_PORT_STATE_ANY_STATE},
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_HDMI_AudioPacketChange,    Hv_Mw_HdmiRx_Sm_AIFChangeHandle,           INPUT_PORT_STATE_DISPLAY_RDY,    INPUT_PORT_STATE_DISPLAY_RDY},

    /*any state*/
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_HDMI_5VPlugOut,            Hv_Mw_HdmiRx_Sm_PlugOutCableHandle,        INPUT_PORT_STATE_IDLE,           INPUT_PORT_STATE_IDLE},
#if (HV_PROJECT_CONFIG_FRL == HV_CONFIG_ON)
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_HDMI_FRLRateChange,        Hv_Mw_HdmiRx_Sm_FRLRateChangeHandle,       INPUT_PORT_STATE_WAIT_FAST_LOCK, INPUT_PORT_STATE_WAIT_FAST_LOCK},
#endif
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_HDMI_RatioChange,          Hv_Mw_HdmiRx_Sm_RatioChangeHandle,         INPUT_PORT_STATE_WAIT_FAST_LOCK, INPUT_PORT_STATE_WAIT_FAST_LOCK},
    {INPUT_PORT_STATE_ANY_STATE,     SYS_EVENT_TIMER_HDMI0_HPD_SET_HIGH,         Hv_Mw_HdmiRx_Sm_SetHpdHighTimeoutHandle,   INPUT_PORT_STATE_WAIT_FAST_LOCK, INPUT_PORT_STATE_ANY_STATE}, 
    {INPUT_PORT_STATE_ANY_STATE,     SYS_EVENT_TIMER_HDMI1_HPD_SET_HIGH,         Hv_Mw_HdmiRx_Sm_SetHpdHighTimeoutHandle,   INPUT_PORT_STATE_WAIT_FAST_LOCK, INPUT_PORT_STATE_ANY_STATE}, 
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_HDMI_VersionChange,        Hv_Mw_HdmiRx_Sm_ChangeHdmiVersionHandle,   INPUT_PORT_STATE_ANY_STATE,      INPUT_PORT_STATE_ANY_STATE},  
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_HDMI_SPDChsChanged,        Hv_Mw_HdmiRx_Sm_SPDPacketChangeHandle,     INPUT_PORT_STATE_ANY_STATE,      INPUT_PORT_STATE_ANY_STATE},    
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_HDMI_VSIPacketChange,      Hv_Mw_HdmiRx_Sm_RcvVSIPacketHandle,        INPUT_PORT_STATE_ANY_STATE,      INPUT_PORT_STATE_ANY_STATE},    
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_HDMI_EMPPacketRcv,         Hv_Mw_HdmiRx_Sm_RcvEMPPacketHandle,        INPUT_PORT_STATE_ANY_STATE,      INPUT_PORT_STATE_ANY_STATE},    
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_HDMI_PktErrForHdcp,        Hv_Mw_HdmiRx_Sm_PacketErrorHandle,         INPUT_PORT_STATE_ANY_STATE,      INPUT_PORT_STATE_WAIT_FAST_LOCK},    
    {INPUT_PORT_STATE_ANY_STATE,     SYS_EVENT_TIMER_HDMI0_HDCPSYNC,             Hv_Mw_HdmiRx_Sm_HdcpSyncTimerOutHandle,    INPUT_PORT_STATE_ANY_STATE,      INPUT_PORT_STATE_WAIT_FAST_LOCK},    
    {INPUT_PORT_STATE_ANY_STATE,     SYS_EVENT_TIMER_HDMI1_HDCPSYNC,             Hv_Mw_HdmiRx_Sm_HdcpSyncTimerOutHandle,    INPUT_PORT_STATE_ANY_STATE,      INPUT_PORT_STATE_WAIT_FAST_LOCK},    
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_HDMI_AudioFifoStart,       Hv_Mw_HdmiRx_Sm_AudioFifoStartHandle,      INPUT_PORT_STATE_ANY_STATE,      INPUT_PORT_STATE_ANY_STATE},

    /* DP State Event */
    {INPUT_PORT_STATE_IDLE,          InputPortEventId_DP_OnFirstEnterState,  Hv_Mw_DpRx_Sm_FirstEnter,           INPUT_PORT_STATE_WAIT_SYNC,   INPUT_PORT_STATE_IDLE},
    {INPUT_PORT_STATE_IDLE,          InputPortEventId_DP_IdleStart,          Hv_Mw_DpRx_Sm_IdleStart,            INPUT_PORT_STATE_WAIT_SYNC,   INPUT_PORT_STATE_IDLE},
    {INPUT_PORT_STATE_IDLE,          InputPortEventId_DP_CableConnect,       Hv_Mw_DpRx_Sm_CableDet,             INPUT_PORT_STATE_WAIT_SYNC,   INPUT_PORT_STATE_IDLE},
    /* WaitSync state */
    {INPUT_PORT_STATE_WAIT_SYNC,     InputPortEventId_DP_OnFirstEnterState,  Hv_Mw_DpRx_Sm_FirstEnter,           INPUT_PORT_STATE_SYNC_OK,     INPUT_PORT_STATE_WAIT_SYNC},
    {INPUT_PORT_STATE_WAIT_SYNC,     InputPortEventId_DP_CableDisconnect,    Hv_Mw_DpRx_Sm_CableDet,             INPUT_PORT_STATE_IDLE,        INPUT_PORT_STATE_WAIT_SYNC},
    {INPUT_PORT_STATE_WAIT_SYNC,     InputPortEventId_DP_TrainingDone,       Hv_Mw_DpRx_Sm_TrainingDone,         INPUT_PORT_STATE_SYNC_OK,     INPUT_PORT_STATE_WAIT_SYNC},
    {INPUT_PORT_STATE_WAIT_SYNC,     SYS_EVENT_TIMER_DP0_TRAINING_NG,        Hv_Mw_DpRx_Sm_TrainingNG,           INPUT_PORT_STATE_WAIT_SYNC,   INPUT_PORT_STATE_WAIT_SYNC},
    {INPUT_PORT_STATE_WAIT_SYNC,     SYS_EVENT_TIMER_DP1_TRAINING_NG,        Hv_Mw_DpRx_Sm_TrainingNG,           INPUT_PORT_STATE_WAIT_SYNC,   INPUT_PORT_STATE_WAIT_SYNC},
    {INPUT_PORT_STATE_WAIT_SYNC,     InputPortEventId_DP_CableConnect,       Hv_Mw_DpRx_Sm_CableDet,             INPUT_PORT_STATE_WAIT_SYNC,   INPUT_PORT_STATE_WAIT_SYNC},
    /* SyncOk state */
    {INPUT_PORT_STATE_SYNC_OK,       InputPortEventId_DP_OnFirstEnterState,  Hv_Mw_DpRx_Sm_FirstEnter,           INPUT_PORT_STATE_SYNC_OK,     INPUT_PORT_STATE_SYNC_OK},
    {INPUT_PORT_STATE_SYNC_OK,       InputPortEventId_DP_CableDisconnect,    Hv_Mw_DpRx_Sm_CableDet,             INPUT_PORT_STATE_IDLE,        INPUT_PORT_STATE_SYNC_OK},
    {INPUT_PORT_STATE_WAIT_SYNC,     InputPortEventId_DP_TrainingFail,       Hv_Mw_DpRx_Sm_TrainingFail,         INPUT_PORT_STATE_WAIT_SYNC,   INPUT_PORT_STATE_WAIT_SYNC},
    {INPUT_PORT_STATE_SYNC_OK,       InputPortEventId_DP_TrainingFail,       Hv_Mw_DpRx_Sm_TrainingFail,         INPUT_PORT_STATE_WAIT_SYNC,   INPUT_PORT_STATE_SYNC_OK},
    {INPUT_PORT_STATE_SYNC_OK,       SYS_EVENT_TIMER_DP0_TIMING_CHECK,       Hv_Mw_DpRx_Sm_CheckTiming,          INPUT_PORT_STATE_DISPLAY_RDY, INPUT_PORT_STATE_SYNC_OK},
    {INPUT_PORT_STATE_SYNC_OK,       SYS_EVENT_TIMER_DP1_TIMING_CHECK,       Hv_Mw_DpRx_Sm_CheckTiming,          INPUT_PORT_STATE_DISPLAY_RDY, INPUT_PORT_STATE_SYNC_OK},
    /* DisplyReady state */
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_DP_OnFirstEnterState,  Hv_Mw_DpRx_Sm_FirstEnter,           INPUT_PORT_STATE_DISPLAY_RDY, INPUT_PORT_STATE_DISPLAY_RDY},
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_DP_CableDisconnect,    Hv_Mw_DpRx_Sm_CableDet,             INPUT_PORT_STATE_IDLE,        INPUT_PORT_STATE_DISPLAY_RDY},
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_DP_TrainingFail,       Hv_Mw_DpRx_Sm_TrainingFail,         INPUT_PORT_STATE_WAIT_SYNC,   INPUT_PORT_STATE_DISPLAY_RDY},
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_DP_TimingChange,       Hv_Mw_DpRx_Sm_TimingChange,         INPUT_PORT_STATE_WAIT_SYNC,   INPUT_PORT_STATE_DISPLAY_RDY},
#ifdef CONFIG_USER_DP_AUDIO_RESHAPE_ON
    {INPUT_PORT_STATE_DISPLAY_RDY,   SYS_EVENT_TIMER_DP0_AUDIO_CHECK,        Hv_Mw_DpRx_Sm_AudioReshape,         INPUT_PORT_STATE_DISPLAY_RDY, INPUT_PORT_STATE_DISPLAY_RDY},
    {INPUT_PORT_STATE_DISPLAY_RDY,   SYS_EVENT_TIMER_DP1_AUDIO_CHECK,        Hv_Mw_DpRx_Sm_AudioReshape,         INPUT_PORT_STATE_DISPLAY_RDY, INPUT_PORT_STATE_DISPLAY_RDY},
#endif
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_DP_AudioMuteChg,       Hv_Mw_DpRx_Sm_AudioMuteChgHandler,  INPUT_PORT_STATE_DISPLAY_RDY,   INPUT_PORT_STATE_DISPLAY_RDY},
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_DP_AudioStart,         Hv_Mw_DpRx_Sm_AudioMuteChgHandler,  INPUT_PORT_STATE_DISPLAY_RDY,   INPUT_PORT_STATE_DISPLAY_RDY},
    /* DP Common Event */
    {INPUT_PORT_STATE_DISPLAY_RDY,   InputPortEventId_DP_ColorChange,        Hv_Mw_DpRx_Sm_ColorChange,          INPUT_PORT_STATE_WAIT_SYNC,   INPUT_PORT_STATE_DISPLAY_RDY},
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_DP_HdrChange,          Hv_Mw_DpRx_Sm_HdrChange,            INPUT_PORT_STATE_ANY_STATE,   INPUT_PORT_STATE_ANY_STATE},
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_DP_VrrChange,          Hv_Mw_DpRx_Sm_VrrChange,            INPUT_PORT_STATE_ANY_STATE,   INPUT_PORT_STATE_ANY_STATE},
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_DP_WriteTimingIgnore,  Hv_Mw_DpRx_Sm_TimingIgnoreChange,   INPUT_PORT_STATE_ANY_STATE,   INPUT_PORT_STATE_ANY_STATE},
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_DP_AdaptiveSyncStart,  Hv_Mw_DpRx_Sm_AdaptSyncStart,       INPUT_PORT_STATE_ANY_STATE,   INPUT_PORT_STATE_ANY_STATE},
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_DP_AdaptiveSyncEnd,    Hv_Mw_DpRx_Sm_AdaptSyncEnd,         INPUT_PORT_STATE_ANY_STATE,   INPUT_PORT_STATE_ANY_STATE},
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_DP_Mccs,               Hv_Mw_DpRx_Sm_MccsProc,             INPUT_PORT_STATE_ANY_STATE,   INPUT_PORT_STATE_ANY_STATE},
    {INPUT_PORT_STATE_ANY_STATE,     SYS_EVENT_TIMER_DP0_HPD_TIMEOUT,        Hv_Mw_DpRx_Sm_HpdTimeOut,           INPUT_PORT_STATE_ANY_STATE,   INPUT_PORT_STATE_ANY_STATE},
    {INPUT_PORT_STATE_ANY_STATE,     SYS_EVENT_TIMER_DP1_HPD_TIMEOUT,        Hv_Mw_DpRx_Sm_HpdTimeOut,           INPUT_PORT_STATE_ANY_STATE,   INPUT_PORT_STATE_ANY_STATE},
    {INPUT_PORT_STATE_ANY_STATE,     InputPortEventId_DP_WakeUp,             Hv_Mw_DpRx_Sm_WakeUp,               INPUT_PORT_STATE_ANY_STATE,   INPUT_PORT_STATE_ANY_STATE},
};

/* FIFO是否为空 */
static BOOL QueueIsEmpty(const InputPortInnerMsgQueue *pstQueue)
{
    return (pstQueue->usWriteAddr == pstQueue->usReadAddr);
}

/* FIFO是否为满 */
static BOOL QueueIsFull(const InputPortInnerMsgQueue *pstQueue)
{
    return ((pstQueue->usWriteAddr + 1) % MAX_INPUT_QUEUE_SIZE == pstQueue->usReadAddr);
}

/* FIFO内数据的个数 */
static USHORT16 QueueCount(const InputPortInnerMsgQueue *pstQueue)
{
    if (pstQueue->usReadAddr <= pstQueue->usWriteAddr)
    {
        return (pstQueue->usWriteAddr - pstQueue->usReadAddr);
    }
    return (MAX_INPUT_QUEUE_SIZE + pstQueue->usWriteAddr - pstQueue->usReadAddr);
}

/* FIFO复位 */
static VOID QueueReset(InputPortInnerMsgQueue *pstQueue)
{
    pstQueue->usWriteAddr = 0;
    pstQueue->usReadAddr = 0;
    for(USHORT16 usIndex = 0; usIndex < MAX_INPUT_QUEUE_SIZE; usIndex++)
    {
        memset(&pstQueue->astFifo[usIndex], 0 , sizeof(pstQueue->astFifo[usIndex]));
    }
    return;
}

/* FIFO写入数据 */
static QueueStatus QueueWrite(InputPortInnerMsgQueue *pstQueue, const InputPortEvent *pstData)
{
    if (QueueIsFull(pstQueue))
    {
        HV_LOG_ERROR(DEFAULT,"Write failed, queue is full:%d, %d.", pstQueue->usReadAddr, pstQueue->usWriteAddr);
        return QUEUE_FULL;
    }
    HV_MEMCPY(&pstQueue->astFifo[pstQueue->usWriteAddr], pstData, sizeof(InputPortEvent));
    pstQueue->usWriteAddr = (pstQueue->usWriteAddr + 1) % MAX_INPUT_QUEUE_SIZE;
    return QUEUE_OK;
}

/* FIFO读出数据 */
static QueueStatus QueueRead(InputPortInnerMsgQueue *pstQueue, InputPortEvent *pstdata)
{
    if (QueueIsEmpty(pstQueue))
    {
        return QUEUE_EMPTY;
    }
    HV_MEMCPY(pstdata, &pstQueue->astFifo[pstQueue->usReadAddr], sizeof(InputPortEvent));
    pstQueue->usReadAddr = (pstQueue->usReadAddr + 1) % MAX_INPUT_QUEUE_SIZE;
    return QUEUE_OK;
}

Status Hv_Mw_InputPort_SendInnerMsg(const InputPortEvent* pstInputPortEvent)
{
    HV_ASSERT_TRUE(QUEUE_OK == QueueWrite(&s_stInputPortManager.stIPInnerMsgQueue, pstInputPortEvent));
    return HV_SUCCESS;
}

static BOOL PullOneMsgFromInpurtPortInnerMsgPool(InputPortInnerMsgQueue* pstIPInnerMsgQueue, InputPortEvent* pstEvent)
{
    if (QUEUE_OK == QueueRead(pstIPInnerMsgQueue, pstEvent))
    {
        return HV_TRUE;
    }
    return HV_FALSE;
}

#ifdef HV_SCALER_DEBUG_VERSION
static const CHAR8* EventTypeConvert(SystemRevEventType enEventType)
{
    const CHAR8* paEventType[] =
    {
        "power",
        "osd",
        "channel",
        "inputport",
        "panel",
        "timer",
        "ddc/ci",
    };
    if(enEventType >= sizeof(paEventType)/sizeof(paEventType[0]))
    {
        return "NULL";
    }
    else
    {
        return paEventType[enEventType];
    }
}
static const CHAR8* InputportEventIDConvert(USHORT16 enEventType)
{
    const CHAR8* paEventIDType[] =
    {
        "hdmi idle",                   //0
        "hdmi on first",
        "hdmi version change",
        "hdmi interupt",
        "hdmi enter display",
        "hdmi exit display",
        "hdmi hpd set low",
        "hdmi pll change", 
        "hdmi clock stable",
        "hdmi clock unstable",
        "hdmi 5v plug in",
        "hdmi 5v plug out",
        "hdmi hpd set high",
        "hdmi timing change",
        "hdmi timing stable",
        "hdmi cd/cf/vic change",
        "hdmi ratio change",
        "hdmi rr change",
        "hdmi cec rev data",
        "hdmi frl rate change",
        "hdmi gcp av mute",
        "hdmi audio change",
        "hdmi avi change",
        "hdmi vsi rcv",
        "hdmi vsi change",
        "hdmi drm change",
        "hdmi drm rcv",
        "hdmi audio reset fifo",
        "hdmi audio cts or nchang",
        "hdmi audio stable",
        "hdmi decode error",
        "hdmi spd chs change",
        "hdmi spd rcv",
        "hdmi vrr switch",
        "hdmi edid update done",
        "hdmi pd new entry",
        "hdmi pd under overflow",
        "hdmi phy conf",
        "hdmi standby ddc",
        "hdmi emp rcv",
        "hdmi pkt err for hdcp",
        "hdmi gcp cd change",
        "hdmi fast lock",
        "hdmi training done",           //43
        "hdmi Audio Start"              //44
        "dp idle",                      //45
        "dp on first",
        "dp interupt",
        "dp cable disconnct",
        "dp cable connect",
        "dp training done",
        "dp training fail",
        "dp video stream",
        "dp timing change",
        "dp color change",
        "dp hdr change",
        "dp sdp rcv",
        "dp vsync event",
        "dp vbid audio mute flag",      //58
        "dp timer out",
        "dp update edid",
        "dp version change",
        "dp vrr switch",
        "dp mccs",
        "dp cable interrupt",
        "dp adaptive sync start",
        "dp adaptive sync end",
        "dp sdp depth thro",
        "dp write timing ignore",      //68
        "dp wake up",
        "hdcp interupt",
    };

    if(enEventType < InputPortEventId_HDMI_Max)
    {
        enEventType = enEventType;
    }
    else if((enEventType >= InputPortEventId_DP_IdleStart) && (enEventType < InputPortEventId_DP_MAX))
    {
        enEventType = enEventType - InputPortEventId_DP_IdleStart + InputPortEventId_HDMI_Max;
    }
    else if(200 == enEventType)
    {
        return "hdcp interupt";
    }
    else
    {
        return "NULL";
    }

    if(enEventType >= sizeof(paEventIDType)/sizeof(paEventIDType[0]))
    {
        return "NULL";
    }
    else
    {
        return paEventIDType[enEventType];
    }

}
#endif


CHAR8* GetInputPortState(InputPortState enCurrentPortState)
{
    if (enCurrentPortState == INPUT_PORT_STATE_ANY_STATE)
    {
        return "AnyState";
    }
    else if (enCurrentPortState & INPUT_PORT_STATE_IDLE)
    {
        return "Idle";
    }
    else if (enCurrentPortState & INPUT_PORT_STATE_WAIT_SYNC)
    {
        return "WaitSync";
    }
    else if (enCurrentPortState & INPUT_PORT_STATE_SYNC_OK)
    {
        return "SyncOk";
    }
    else if (enCurrentPortState & INPUT_PORT_STATE_DISPLAY_RDY)
    {
        return "DisplayReady";
    }
    else if (enCurrentPortState & INPUT_PORT_STATE_WAIT_FAST_LOCK)
    {
        return "WaitFastLock";
    }
    else if (enCurrentPortState & INPUT_PORT_STATE_WAIT_EQ_DONE)
    {
        return "WaitEqDone";
    }
    return "unknown";
}

static Status RunInpurtPortStateMachine(InputPortEvent* pstInputPortEvent, InputPortState *pEnCurrentInputPortState, void* pvInputPortData, BOOL* pbNeedChangeState)
{
    Status uiRet = HV_FAILURE;
    HV_ASSERT_VALID_PTR(pEnCurrentInputPortState);
    HV_ASSERT_VALID_PTR(pvInputPortData);
    InputPortState enNextState = INPUT_PORT_STATE_ANY_STATE;
    *pbNeedChangeState = HV_FALSE;/*很关键必须置位false，否则convert消息如果在for循环中无法找到则pbNeedChangeState无法赋值为false，导致while死循环*/
    for (USHORT16 usIndex = 0; usIndex < ARRAY_SIZE(s_astInputPortStateMachine); ++usIndex)
    {
        if ((pstInputPortEvent->usEventId == s_astInputPortStateMachine[usIndex].usEventId)
           && (*pEnCurrentInputPortState & s_astInputPortStateMachine[usIndex].usAcceptStates))
        {
            uiRet = s_astInputPortStateMachine[usIndex].pfActionHandle(pstInputPortEvent, pvInputPortData);
            if (HV_SUCCESS == uiRet)
            {
                enNextState = s_astInputPortStateMachine[usIndex].enNextSuccessState;
            }
            else if (HV_FAILURE == uiRet)
            {
                enNextState = s_astInputPortStateMachine[usIndex].enNextFailState;
            }
            else
            {
                /*continue 以及其他返回值场景*/
            }

            if( pstInputPortEvent->usEventId != SYS_EVENT_TIMER_DP0_AUDIO_CHECK
                && pstInputPortEvent->usEventId != SYS_EVENT_TIMER_DP1_AUDIO_CHECK
                && pstInputPortEvent->usEventId != InputPortEventId_DP_Mccs)
            {
                HV_LOG_INFO(INPUTPORT, "Port %u, %s, %u, %s", pstInputPortEvent->enPortIndex,GetInputPortState(*pEnCurrentInputPortState), pstInputPortEvent->usEventId, GetInputPortState(enNextState));
            }

            if ((enNextState != *pEnCurrentInputPortState) && (enNextState != INPUT_PORT_STATE_ANY_STATE))
            {
                *pEnCurrentInputPortState = enNextState;
                *pbNeedChangeState = HV_TRUE;
            }
            else
            {
                *pbNeedChangeState = HV_FALSE;
            }
            /*CurrentInputPortState 已修改，不能继续匹配。保证每次只执一次！所以需要break退出*/
            break;
        }
    }
    return uiRet;
}

static USHORT16 GetInputPortConvertEventId(LinkPortIndex enPortIndex)
{
    if ((LINK_PORT_INDEX_HDMI_RX0 == enPortIndex) || (LINK_PORT_INDEX_HDMI_RX1 == enPortIndex))
    {
        return InputPortEventId_HDMI_OnFirstEnterState;
    }


    if ((LINK_PORT_INDEX_DP_RX0 == enPortIndex) || (LINK_PORT_INDEX_DP_RX1 == enPortIndex))
    {
        return InputPortEventId_DP_OnFirstEnterState;
    }

    return INVALID_PARAM_USHORT16; 
}

Status Hv_Mw_InputPort_ProcInnerMsgs(VOID)
{
    InputPortEvent stInputPortEvent = {0};
    BOOL bHasMsg = HV_FALSE;
    do
    {
        bHasMsg = PullOneMsgFromInpurtPortInnerMsgPool(&s_stInputPortManager.stIPInnerMsgQueue, &stInputPortEvent);
        if ((HV_TRUE == bHasMsg))
        {
            HV_LOG_DEBUG(INPUTPORT, "Pull One Msg From InpurtPort InnerMsgPool enPortIndex=%u usEventId=%u", stInputPortEvent.enPortIndex, stInputPortEvent.usEventId);
            InputPortState *pEnCurrentInputPortState = NULL;
            VOID* pvInputPortData = NULL;
            switch (stInputPortEvent.enPortIndex)
            {
                case LINK_PORT_INDEX_HDMI_RX0:
                {
                    pvInputPortData = (VOID*)&s_stInputPortManager.stHDMIManager.astHdmiData[0];
                    pEnCurrentInputPortState = &s_stInputPortManager.stHDMIManager.astHdmiData[0].enCurrentPortState;
                    break;
                }
                case LINK_PORT_INDEX_HDMI_RX1:
                {
                    if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID)
                    {
                        pvInputPortData = (VOID*)&s_stInputPortManager.stHDMIManager.astHdmiData[1];
                        pEnCurrentInputPortState = &s_stInputPortManager.stHDMIManager.astHdmiData[1].enCurrentPortState;
                    }
                    else
                    {
                        pvInputPortData = (VOID*)&s_stInputPortManager.stHDMIManager.astHdmiData[0];
                        pEnCurrentInputPortState = &s_stInputPortManager.stHDMIManager.astHdmiData[0].enCurrentPortState;
                    }
                    break;
                }
                case LINK_PORT_INDEX_DP_RX0:
                {
                    pvInputPortData = (VOID*)&s_stInputPortManager.stDisplayPortManager.astDpCtrl[0];
                    pEnCurrentInputPortState = &s_stInputPortManager.stDisplayPortManager.astDpCtrl[0].enCurrentPortState;
                    break;
                }
                case LINK_PORT_INDEX_DP_RX1:
                {
                    if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
                    {
                        pvInputPortData = (VOID*)&s_stInputPortManager.stDisplayPortManager.astDpCtrl[1];
                        pEnCurrentInputPortState = &s_stInputPortManager.stDisplayPortManager.astDpCtrl[1].enCurrentPortState;
                    }
                    else
                    {
                        pvInputPortData = (VOID*)&s_stInputPortManager.stDisplayPortManager.astDpCtrl[0];
                        pEnCurrentInputPortState = &s_stInputPortManager.stDisplayPortManager.astDpCtrl[0].enCurrentPortState;
                    }
                    break;
                }
                default:
                {
                    HV_LOG_ERROR(INPUTPORT, "unknown InputPortEvent! enPortIndex=%u", stInputPortEvent.enPortIndex);
                    break;
                }
            }
            if ((NULL != pEnCurrentInputPortState) && (NULL != pvInputPortData))
            {
                BOOL bNeedChangeState = HV_FALSE;
                HV_LOG_DEBUG(INPUTPORT, "pEnCurrentInputPortState%s", GetInputPortState(*pEnCurrentInputPortState));
                (VOID)RunInpurtPortStateMachine(&stInputPortEvent, pEnCurrentInputPortState, pvInputPortData, &bNeedChangeState);
                while(bNeedChangeState)
                {
                    InputPortEvent stConvertEvent = {0};
                    stConvertEvent.usEventId = GetInputPortConvertEventId(stInputPortEvent.enPortIndex);
                    stConvertEvent.enPortIndex = stInputPortEvent.enPortIndex;
                    (VOID)RunInpurtPortStateMachine(&stConvertEvent, pEnCurrentInputPortState, pvInputPortData, &bNeedChangeState);
                }
            }
        }
    } while ( bHasMsg );
    return HV_SUCCESS;
}

VOID SystemEventConvertToIpEvent(InputPortEvent* pstInputPortEvent, const SystemEvent* pstSystemEvent)
{
    pstInputPortEvent->usEventId = pstSystemEvent->usEventId;
    pstInputPortEvent->enPortIndex = pstSystemEvent->ucPortIndex;
    pstInputPortEvent->buffer = pstSystemEvent->buffer;

    if (SYS_EVENT_TIMER_HDMI0_BEGIN <= pstSystemEvent->usEventId
        && SYS_EVENT_TIMER_HDMI0_END >= pstSystemEvent->usEventId)
    {
        pstInputPortEvent->enPortIndex = LINK_PORT_INDEX_HDMI_RX0;
    }
    if (SYS_EVENT_TIMER_HDMI1_BEGIN <= pstSystemEvent->usEventId
        && SYS_EVENT_TIMER_HDMI1_END >= pstSystemEvent->usEventId)
    {
        pstInputPortEvent->enPortIndex = LINK_PORT_INDEX_HDMI_RX1;
    }
    if (SYS_EVENT_TIMER_DP0_BEGIN <= pstSystemEvent->usEventId
        && SYS_EVENT_TIMER_DP0_END >= pstSystemEvent->usEventId)
    {
        pstInputPortEvent->enPortIndex = LINK_PORT_INDEX_DP_RX0;
    }
    if (SYS_EVENT_TIMER_DP1_BEGIN <= pstSystemEvent->usEventId
        && SYS_EVENT_TIMER_DP1_END >= pstSystemEvent->usEventId)
    {
        pstInputPortEvent->enPortIndex = LINK_PORT_INDEX_DP_RX1;
    }
    return;
}


Status Hv_Mw_InputPort_ProcSystemQueueMsg(const SystemEvent* pstSystemEvent)
{
    InputPortEvent stInputPortEvent = {0};
    SystemEventConvertToIpEvent(&stInputPortEvent, pstSystemEvent);
#ifdef HV_INPUT_DEBUG_OPEN
    if(SYSTEM_REV_EVENT_TYPE_TIMER == pstSystemEvent->enEventType 
        && pstSystemEvent->usEventId != SYS_EVENT_TIMER_HDMI0_WAIT_EQ_DONE
        && pstSystemEvent->usEventId != SYS_EVENT_TIMER_HDMI1_WAIT_EQ_DONE
        && pstSystemEvent->usEventId != SYS_EVENT_TIMER_DP0_AUDIO_CHECK
        && pstSystemEvent->usEventId != SYS_EVENT_TIMER_DP1_AUDIO_CHECK)
    {
        HV_INPUT_LOG_INFO(INPUTPORT, "InputPort %s,%s", EventTypeConvert(pstSystemEvent->enEventType),TimerEventIDConvert((TIMER_EVENT_E)pstSystemEvent->usEventId));
    }
    if(SYSTEM_REV_EVENT_TYPE_INPUTPORT == pstSystemEvent->enEventType
        && pstSystemEvent->usEventId != InputPortEventId_DP_Interrupt)
    {
        HV_INPUT_LOG_INFO(INPUTPORT, "%s, %s, 0x%x", EventTypeConvert(pstSystemEvent->enEventType),InputportEventIDConvert(pstSystemEvent->usEventId), pstSystemEvent->ucPortIndex);
    }
#endif
    /*中断事件分发*/
    if(stInputPortEvent.usEventId == InputPortEventId_HDMI_IntGen)
    {
        HdmiCtrlData* pstHdmiData = HV_Mw_HdmiRx_GetHdmiLinkData(stInputPortEvent.enPortIndex);
        HV_ASSERT_VALID_PTR(pstHdmiData);
        HV_ASSERT_VALID_PTR(stInputPortEvent.buffer);

        HdmiRxIntStatus     stHdmiRxStatus;
        HDMIRxIntEventList  stHdmiRxEventList;
        InputPortEvent      stHdmiEvent;
        UCHAR8              ucEventIdx = 0;

        stHdmiEvent.enPortIndex = stInputPortEvent.enPortIndex;
        stHdmiEvent.buffer      = NULL;

        HV_MEMCPY(&stHdmiRxStatus, stInputPortEvent.buffer, sizeof(HdmiRxIntStatus));
        stHdmiRxEventList.ucPortIndex = pstHdmiData->ucDataPortIndex;

        Hv_Cal_HdmiRx_GetInputPortEvent(&stHdmiRxStatus, &stHdmiRxEventList);

        for(ucEventIdx = 0; ucEventIdx < stHdmiRxEventList.ucSize &&
                            ucEventIdx < HV_HDMIRX_INT_EVENT_MAX_SIZE; ucEventIdx++)
        {
            stHdmiEvent.usEventId = stHdmiRxEventList.usEventList[ucEventIdx];
            Hv_Mw_InputPort_SendInnerMsg(&stHdmiEvent);
        }
    }
    else if (stInputPortEvent.usEventId == InputPortEventId_DP_Interrupt)
    {
        HV_ASSERT_VALID_PTR(stInputPortEvent.buffer);
        Hv_Mw_DpRx_ProcSystemMsg(&stInputPortEvent);
    }
    else if (stInputPortEvent.usEventId == InputPortEventId_DP_CableInt)
    {
        Hv_Mw_DpRx_ProcCableMsg(&stInputPortEvent);
    }
    else
    {
        Hv_Mw_InputPort_SendInnerMsg(&stInputPortEvent);
    }

    return HV_SUCCESS;
}

Status Hv_Mw_InputPort_GetVideoPara(LinkPortIndex enPortIndex, ChannelData* pstChannelData)
{
    Status uiRet = HV_FAILURE;
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            HV_ASSERT_VALID_PTR(s_stInputPortManager.stHDMIManager.pfGetVideoPara);
            uiRet = s_stInputPortManager.stHDMIManager.pfGetVideoPara(enPortIndex,pstChannelData);
            break;
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            HV_ASSERT_VALID_PTR(s_stInputPortManager.stDisplayPortManager.pfGetVideoPara);
            uiRet = s_stInputPortManager.stDisplayPortManager.pfGetVideoPara(enPortIndex,pstChannelData);
            break;
        }
        default:
        {
            HV_LOG_ERROR(INPUTPORT, "GetVideoPara unSupport enPortIndex=%u", enPortIndex);
            break;
        }  
    }
    return uiRet;
}

Status Hv_Mw_InputPort_GetSourceVendorPara(LinkPortIndex enPortIndex, VRRInfoParam *ptVendor)
{
    Status uiRet = HV_FAILURE;
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            HV_ASSERT_VALID_PTR(s_stInputPortManager.stHDMIManager.pfGetSourceVendorInfo);
            uiRet = s_stInputPortManager.stHDMIManager.pfGetSourceVendorInfo(enPortIndex, ptVendor);
            break;
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            HV_ASSERT_VALID_PTR(s_stInputPortManager.stDisplayPortManager.pfGetVrrPara);
            uiRet = s_stInputPortManager.stDisplayPortManager.pfGetVrrPara(enPortIndex, ptVendor);
            break;
        }
        default:
        {
            HV_LOG_ERROR(INPUTPORT, "GetSourceVendorPara unSupport enPortIndex=%u", enPortIndex);
            break;
        }
    }

    return uiRet;
}

BOOL Hv_Mw_InputPort_GetAudioStatus(LinkPortIndex enPortIndex)
{
    BOOL bRet = HV_FALSE;
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            HV_ASSERT_VALID_PTR(s_stInputPortManager.stHDMIManager.pfGetAudioStatus);
            bRet = s_stInputPortManager.stHDMIManager.pfGetAudioStatus(enPortIndex);
            break;
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            HV_ASSERT_VALID_PTR(s_stInputPortManager.stDisplayPortManager.pfGetAudioStatus);
            bRet = s_stInputPortManager.stDisplayPortManager.pfGetAudioStatus(enPortIndex);
            break;
        }
        default:
        {
            HV_LOG_ERROR(INPUTPORT, "GetSourceVendorPara unSupport enPortIndex=%u", enPortIndex);
            break;
        }
    }
    return bRet;
}

Status Hv_Mw_InputPort_StartAudio(LinkPortIndex enPortIndex)
{
    Status eRet = HV_FAILURE;
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            HV_ASSERT_VALID_PTR(s_stInputPortManager.stHDMIManager.pfStartAudio);
            eRet = s_stInputPortManager.stHDMIManager.pfStartAudio(enPortIndex);
            break;
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            HV_ASSERT_VALID_PTR(s_stInputPortManager.stDisplayPortManager.pfStartAudio);
            eRet = s_stInputPortManager.stDisplayPortManager.pfStartAudio(enPortIndex);
            break;
        }
        default:
        {
            HV_LOG_ERROR(INPUTPORT, "pfStartAudio unSupport enPortIndex=%u", enPortIndex);
            break;
        }
    }
    return eRet;
}

Status Hv_Mw_InputPort_StopAudio(LinkPortIndex enPortIndex)
{
    Status eRet = HV_FAILURE;
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            HV_ASSERT_VALID_PTR(s_stInputPortManager.stHDMIManager.pfStopAudio);
            eRet = s_stInputPortManager.stHDMIManager.pfStopAudio(enPortIndex);
            break;
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            HV_ASSERT_VALID_PTR(s_stInputPortManager.stDisplayPortManager.pfStopAudio);
            eRet = s_stInputPortManager.stDisplayPortManager.pfStopAudio(enPortIndex);
            break;
        }
        default:
        {
            HV_LOG_ERROR(INPUTPORT, "pfStopAudio unSupport enPortIndex=%u", enPortIndex);
            break;
        }
    }
    return eRet;
}

Status Hv_Mw_InputPort_CheckAudio(LinkPortIndex enPortIndex)
{
    Status eRet = HV_FAILURE;
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            // eRet = Hv_Mw_HdmiRx_AudioCheck(enPortIndex);
            break;
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            eRet = Hv_Mw_DpRx_AudioCheck(enPortIndex);
            break;
        }
        default:
        {
            HV_LOG_ERROR(INPUTPORT, "CheckAudio unSupport enPortIndex=%u", enPortIndex);
            break;
        }
    }
    return eRet;
}

Status Hv_Mw_InputPort_PreProcess(LinkPortIndex enPortIndex)
{
    Status eRet = HV_FAILURE;
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            break;
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            Hv_Mw_DpRx_MaskRxHtotalInt(enPortIndex, HV_TRUE);
            eRet = HV_SUCCESS;
            break;
        }
        default:
        {
            HV_LOG_ERROR(INPUTPORT, "PreProcess unSupport enPortIndex=%u", enPortIndex);
            break;
        }
    }
    return eRet;
}

Status Hv_Mw_InputPort_PostProcess(LinkPortIndex enPortIndex)
{
    Status eRet = HV_FAILURE;
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            break;
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            Hv_Mw_DpRx_MaskRxHtotalInt(enPortIndex, HV_FALSE);
            eRet = HV_SUCCESS;
            break;
        }
        default:
        {
            HV_LOG_ERROR(INPUTPORT, "PostProcess unSupport enPortIndex=%u", enPortIndex);
            break;
        }
    }
    return eRet;
}

BOOL Hv_Mw_InputPort_GetPortLastUnSyncStatus(LinkPortIndex enPortIndex, LastPortUnSyncReason* penLastPortUnSyncReason)
{
    BOOL bRet = HV_TRUE;
    HV_ASSERT_VALID_PTR_RET(penLastPortUnSyncReason, HV_FALSE);
    *penLastPortUnSyncReason = LastPortUnSyncReason_None;
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        {
            *penLastPortUnSyncReason = s_stInputPortManager.stHDMIManager.astHdmiData[0].enLastPortUnSyncReason;
            break;
        }
#if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID)
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID)
            {
                *penLastPortUnSyncReason = s_stInputPortManager.stHDMIManager.astHdmiData[1].enLastPortUnSyncReason;
            }
            else
            {
                *penLastPortUnSyncReason = s_stInputPortManager.stHDMIManager.astHdmiData[0].enLastPortUnSyncReason;
            }
            break;
        }
#endif
        case LINK_PORT_INDEX_DP_RX0:
        {
            *penLastPortUnSyncReason = s_stInputPortManager.stDisplayPortManager.astDpCtrl[0].enLastPortUnSyncReason;
            break;
        }
#if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID)
        case LINK_PORT_INDEX_DP_RX1:
        {
            if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
            {
                *penLastPortUnSyncReason = s_stInputPortManager.stDisplayPortManager.astDpCtrl[1].enLastPortUnSyncReason;
            }
            else
            {
                *penLastPortUnSyncReason = s_stInputPortManager.stDisplayPortManager.astDpCtrl[0].enLastPortUnSyncReason;
            }
            break;
        }
#endif
        default:
        {
            bRet = HV_FALSE;
            break;
        }
    }
    return bRet;
}

VOID Hv_Mw_InputPort_ClearPortLastUnSyncStatus(LinkPortIndex enPortIndex)
{
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        {
            s_stInputPortManager.stHDMIManager.astHdmiData[0].enLastPortUnSyncReason = LastPortUnSyncReason_None;
            break;
        }
#if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID)
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID)
            {
                s_stInputPortManager.stHDMIManager.astHdmiData[1].enLastPortUnSyncReason = LastPortUnSyncReason_None;
            }
            else
            {
                s_stInputPortManager.stHDMIManager.astHdmiData[0].enLastPortUnSyncReason = LastPortUnSyncReason_None;
            }
            break;
        }
#endif
        case LINK_PORT_INDEX_DP_RX0:
        {
            s_stInputPortManager.stDisplayPortManager.astDpCtrl[0].enLastPortUnSyncReason = LastPortUnSyncReason_None;
            break;
        }
#if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID)
        case LINK_PORT_INDEX_DP_RX1:
        {
            if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
            {
                s_stInputPortManager.stDisplayPortManager.astDpCtrl[1].enLastPortUnSyncReason = LastPortUnSyncReason_None;
            }
            else
            {
                s_stInputPortManager.stDisplayPortManager.astDpCtrl[0].enLastPortUnSyncReason = LastPortUnSyncReason_None;
            }
            break;
        }
#endif
        default:
        {
            HV_LOG_ERROR(INPUTPORT, "GetSourceVendorPara unSupport enPortIndex=%u", enPortIndex);
            break;
        }
    }
    return;
}

UINT32 Hv_Mw_InputPort_GetMuteStatus(ChannelType mutePath)
{
    if(CHANNEL_TYPE_MAIN == mutePath)
    {
        return Hv_Drv_DpuScaler_GetMainMuteState();
    }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    else
    {
        return Hv_Drv_DpuScaler_GetSubMuteState();
    }
#endif
    return 0;
}

Status Hv_Mw_InputPort_UpdataEdid(LinkPortIndex enPortIndex, EDIDType eEdidConfigure)
{
    HV_ASSERT_VALID_PTR(s_stInputPortManager.stHDMIManager.pfUpdateEdid);
    HV_ASSERT_VALID_PTR(s_stInputPortManager.stDisplayPortManager.pfUpdateEdid);
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            HV_LOG_DEBUG(INPUTPORT, "HDMI pfUpdateEdid enPortIndex=%u", enPortIndex);
            return (s_stInputPortManager.stHDMIManager.pfUpdateEdid(enPortIndex, eEdidConfigure));
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            HV_LOG_DEBUG(INPUTPORT, "DP pfUpdateEdid enPortIndex=%u", enPortIndex);
            return (s_stInputPortManager.stDisplayPortManager.pfUpdateEdid(enPortIndex, eEdidConfigure));
        }
        default:
        {
            HV_LOG_DEBUG(INPUTPORT, "GetSourceVendorPara unSupport enPortIndex=%u", enPortIndex);
            return HV_FAILURE;
        }
    }
    return HV_SUCCESS;
}

Status Hv_Mw_InputPort_ToggleHpd(LinkPortIndex enPortIndex)
{
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            HV_LOG_DEBUG(INPUTPORT, "HDMI Toggle HPD enPortIndex=%u", enPortIndex);
            s_stInputPortManager.stHDMIManager.pfHPDToggle(enPortIndex);
            break;
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            HV_LOG_DEBUG(INPUTPORT, "DP Toggle HPD enPortIndex=%u", enPortIndex);
            s_stInputPortManager.stDisplayPortManager.pfHpdToggle(enPortIndex);
            break;
        }
        default:
        {
            HV_LOG_DEBUG(INPUTPORT, "unSupport enPortIndex=%u", enPortIndex);
            return HV_FAILURE;
        }
    }
    return HV_SUCCESS;
}

Status Hv_Mw_InputPort_Reset(LinkPortIndex enPortIndex)
{
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            HV_LOG_DEBUG(INPUTPORT, "HDMI Reset enPortIndex=%u", enPortIndex);
            s_stInputPortManager.stHDMIManager.pfReset(enPortIndex);
            break;
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            HV_LOG_DEBUG(INPUTPORT, "DP Reset enPortIndex=%u", enPortIndex);
            s_stInputPortManager.stDisplayPortManager.pfReset(enPortIndex);
            s_stInputPortManager.stDisplayPortManager.pfHpdToggle(enPortIndex);
            break;
        }
        default:
        {
            HV_LOG_DEBUG(INPUTPORT, "Reset unSupport enPortIndex=%u", enPortIndex);
            return HV_FAILURE;
        }
    }
    return HV_SUCCESS;
}

Status Hv_Mw_InputPort_GetPortErrorCode(LinkPortIndex enPortIndex)
{
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            HV_LOG_DEBUG(INPUTPORT, "HDMI GetPortErrorCode enPortIndex=%u", enPortIndex);
            return s_stInputPortManager.stHDMIManager.pfGetPortErrorCode(enPortIndex);
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            HV_LOG_DEBUG(INPUTPORT, "DP GetPortErrorCode enPortIndex=%u", enPortIndex);
            return s_stInputPortManager.stDisplayPortManager.pfGetPortErrorCode(enPortIndex);
        }
        default:
        {
            HV_LOG_DEBUG(INPUTPORT, "GetPortErrorCode unSupport enPortIndex=%u", enPortIndex);
            return HV_FAILURE;
        }
    }
    return HV_SUCCESS;
}

UINT32 Hv_Mw_InputPort_GetCurrentFrameRate(LinkPortIndex enPortIndex)
{
    UINT32 uiRet = 0;
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            HV_ASSERT_VALID_PTR_RET(s_stInputPortManager.stHDMIManager.pfGetCurrentFrameRate, 0);
            uiRet = s_stInputPortManager.stHDMIManager.pfGetCurrentFrameRate(enPortIndex);
            break;
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            HV_ASSERT_VALID_PTR_RET(s_stInputPortManager.stDisplayPortManager.pfGetCurrentFrameRate, 0);
            uiRet = s_stInputPortManager.stDisplayPortManager.pfGetCurrentFrameRate(enPortIndex);
            break;
        }
        default:
        {
            HV_LOG_ERROR(INPUTPORT, "pfGetCurrentFrameRate unSupport enPortIndex=%u", enPortIndex);
            break;
        }
    }

    return uiRet;
}

Status Hv_Mw_InputPort_BindChannelPortIndex(ChannelType enChannelType, LinkPortIndex enPortIndex)
{
    LinkPortIndex ePortIndexToRealse = LINK_PORT_INDEX_INVALID;

    if(enChannelType == CHANNEL_TYPE_MAIN)
    {
        Hv_Mw_Hdcp_Retry(enPortIndex);
        /* 同时绑定两个的时候，不能释放，只有全部不绑定才能释放RX PLL */
        if(s_stInputPortManager.enMainPortIndex != s_stInputPortManager.enSubPortIndex)
        {
            ePortIndexToRealse = s_stInputPortManager.enMainPortIndex;
        }
        else
        {
            Hv_Drv_PLL_ConfigRxDpllSel(1, ePortIndexToRealse, s_stInputPortManager.enSubPortIndex);
        }

        Hv_Drv_PLL_ConfigRxDpllSel(0, ePortIndexToRealse, enPortIndex);

        s_stInputPortManager.enMainPortIndex = enPortIndex;
        Hv_Drv_PLL_ConfigRxDpllMuteSel(s_stInputPortManager.enMainPortIndex == s_stInputPortManager.enSubPortIndex);

        Hv_Drv_DpuScaler_LDGMainInsertBlackCableDetect();
    }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    if(enChannelType == CHANNEL_TYPE_SUB)
    {
        Hv_Mw_Hdcp_Retry(enPortIndex);
        /* 同时绑定两个的时候，不能释放，只有全部不绑定才能释放RX PLL */
        if(s_stInputPortManager.enMainPortIndex != s_stInputPortManager.enSubPortIndex)
        {
            ePortIndexToRealse = s_stInputPortManager.enSubPortIndex;
        }
        else
        {
            Hv_Drv_PLL_ConfigRxDpllSel(0, ePortIndexToRealse, s_stInputPortManager.enMainPortIndex);
        }

        if(enPortIndex != s_stInputPortManager.enMainPortIndex)
        {
            Hv_Drv_PLL_ConfigRxDpllSel(1, ePortIndexToRealse, enPortIndex);
        }

        s_stInputPortManager.enSubPortIndex = enPortIndex;
        Hv_Drv_PLL_ConfigRxDpllMuteSel(s_stInputPortManager.enMainPortIndex == s_stInputPortManager.enSubPortIndex);

        Hv_Drv_DpuScaler_LDGSubInsertBlackCableDetect();
    }
#endif
    HV_LOG_DEBUG(INPUTPORT, "Bind Port %d to Chanel:%d release:%d", enPortIndex, enChannelType, ePortIndexToRealse);

    return HV_SUCCESS;
}

LinkPortIndex Hv_Mw_InputPort_GetChannelBindPortIndex(ChannelType enChannelType)
{
    if(enChannelType == CHANNEL_TYPE_MAIN)
    {
        return s_stInputPortManager.enMainPortIndex;
    }
#ifdef CONFIG_USER_DOUBLE_CHANNEL_ON
    if(enChannelType == CHANNEL_TYPE_SUB)
    {
        return s_stInputPortManager.enSubPortIndex;
    }
#endif
    return LINK_PORT_INDEX_INVALID;
}

Status Hv_Mw_InputPort_EnterStandby(VOID)
{
#if (PORT_VALID == HV_BOARD_CONFIG_HDMI_0)
    Hv_Drv_HdmiRx_EnterStandby(0, HV_TRUE);
#endif

#if (PORT_VALID == HV_BOARD_CONFIG_HDMI_1)
    Hv_Drv_HdmiRx_EnterStandby(1, HV_TRUE);
#endif

    return HV_SUCCESS;
}

Status Hv_Mw_InputPort_EnterPowerOff(VOID)
{
    HV_ASSERT_VALID_PTR(s_stInputPortManager.stHDMIManager.pfHPDAction);

#if (PORT_VALID == HV_BOARD_CONFIG_HDMI_0)
    s_stInputPortManager.stHDMIManager.pfHPDAction(LINK_PORT_INDEX_HDMI_RX0, HV_FALSE);
#endif

#if (PORT_VALID == HV_BOARD_CONFIG_HDMI_1)
    s_stInputPortManager.stHDMIManager.pfHPDAction(LINK_PORT_INDEX_HDMI_RX1, HV_FALSE);
#endif

    return HV_SUCCESS;
}

Status Hv_Mw_InputPort_EnterResume(VOID)
{
#if (PORT_VALID == HV_BOARD_CONFIG_HDMI_0)
    Hv_Drv_HdmiRx_EnterStandby(0, HV_FALSE);
#endif

#if (PORT_VALID == HV_BOARD_CONFIG_HDMI_1)
    Hv_Drv_HdmiRx_EnterStandby(1, HV_FALSE);
#endif

    return HV_SUCCESS;
}


Status Hv_Mw_InputPortManager_Init(VOID)
{
    QueueReset(&s_stInputPortManager.stIPInnerMsgQueue);

    HV_ASSERT_SUCCESS(Hv_Mw_HDMI_Init(&s_stInputPortManager.stHDMIManager));
    HV_ASSERT_SUCCESS(Hv_Mw_DpRx_Init(&s_stInputPortManager.stDisplayPortManager));
    HV_ASSERT_SUCCESS(Hv_Mw_Hdcp_Init(&s_stInputPortManager.stHDCPManager));
    
    s_stInputPortManager.enMainPortIndex        = LINK_PORT_INDEX_INVALID;
    s_stInputPortManager.enSubPortIndex         = LINK_PORT_INDEX_INVALID;
    s_stInputPortManager.pfGetVideoPara         = Hv_Mw_InputPort_GetVideoPara;
    s_stInputPortManager.pfGetSourceVendorInfo  = Hv_Mw_InputPort_GetSourceVendorPara;
    s_stInputPortManager.pfGetAudioStatus       = Hv_Mw_InputPort_GetAudioStatus;
    s_stInputPortManager.pfStartAudio           = Hv_Mw_InputPort_StartAudio;
    s_stInputPortManager.pfStopAudio            = Hv_Mw_InputPort_StopAudio;
    s_stInputPortManager.pfCheckAudio           = Hv_Mw_InputPort_CheckAudio;
    s_stInputPortManager.pfPreProcess           = Hv_Mw_InputPort_PreProcess;
    s_stInputPortManager.pfPostProcess          = Hv_Mw_InputPort_PostProcess;
    s_stInputPortManager.pfGetMuteStatus        = Hv_Mw_InputPort_GetMuteStatus;
    s_stInputPortManager.pfUpdateEdid           = Hv_Mw_InputPort_UpdataEdid;
    s_stInputPortManager.pfGetCurrentFrameRate  = Hv_Mw_InputPort_GetCurrentFrameRate;
    s_stInputPortManager.pfBindChannelPortIndex = Hv_Mw_InputPort_BindChannelPortIndex;
    s_stInputPortManager.pfGetPortLastUnSyncStatus   = Hv_Mw_InputPort_GetPortLastUnSyncStatus;
    s_stInputPortManager.pfClearPortLastUnSyncStatus = Hv_Mw_InputPort_ClearPortLastUnSyncStatus;
    s_stInputPortManager.pfEnterStandby              = Hv_Mw_InputPort_EnterStandby;
    s_stInputPortManager.pfEnterPowerOff             = Hv_Mw_InputPort_EnterPowerOff;
    s_stInputPortManager.pfEnterResume               = Hv_Mw_InputPort_EnterResume;
    s_stInputPortManager.pfReset                     = Hv_Mw_InputPort_Reset;
    s_stInputPortManager.pfGetPortErrorCode          = Hv_Mw_InputPort_GetPortErrorCode;
#if (PORT_VALID == HV_BOARD_CONFIG_DISPLAYPORT_0)
    {
        Hv_Mw_DpRx_InterruptInit(LINK_PORT_INDEX_DP_RX0);
    }
#endif
#if (PORT_VALID == HV_BOARD_CONFIG_DISPLAYPORT_1)
    {
        Hv_Mw_DpRx_InterruptInit(LINK_PORT_INDEX_DP_RX1);
    }
#endif
#if (PORT_VALID == HV_BOARD_CONFIG_HDMI_0)
    {
        Hv_Mw_HdmiRx_InterruptInit(LINK_PORT_INDEX_HDMI_RX0);
    }
#endif
#if (PORT_VALID == HV_BOARD_CONFIG_HDMI_1)
    {
        Hv_Mw_HdmiRx_InterruptInit(LINK_PORT_INDEX_HDMI_RX1);
    }
#endif

    Hv_Mw_Hdcp_InterruptInit();

    return HV_SUCCESS;
}

BOOL Hv_Mw_InputPort_HasInnerMsgs( VOID )
{
    BOOL bHasMsgToProc = QueueIsEmpty(&s_stInputPortManager.stIPInnerMsgQueue);
    return !bHasMsgToProc;
}

HV_ATTR_ISR_SECTION InputPortManager* Hv_Mw_InputPort_GetManagerPtr(VOID)
{
    return &s_stInputPortManager;
}

BOOL Hv_Mw_InputPort_GetCableStatus(LinkPortIndex enPortIndex)
{
    BOOL bPortCableStatus = HV_FALSE;
    switch (enPortIndex)
    {
#if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID)
        case LINK_PORT_INDEX_HDMI_RX0:
        {
            bPortCableStatus = s_stInputPortManager.stHDMIManager.astHdmiData[0].bIsCableConnected;
            break;
        }
#endif
#if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID)
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            if(HV_BOARD_CONFIG_HDMI_0 == PORT_VALID)
            {
                bPortCableStatus = s_stInputPortManager.stHDMIManager.astHdmiData[1].bIsCableConnected;
            }
            else
            {
                bPortCableStatus = s_stInputPortManager.stHDMIManager.astHdmiData[0].bIsCableConnected;
            }
            break;
        }
#endif
#if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
        case LINK_PORT_INDEX_DP_RX0:
        {
            bPortCableStatus = s_stInputPortManager.stDisplayPortManager.astDpCtrl[0].bCableConnected;
            break;
        }
#endif
#if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID)
        case LINK_PORT_INDEX_DP_RX1:
        {
            if(HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
            {
                bPortCableStatus = s_stInputPortManager.stDisplayPortManager.astDpCtrl[1].bCableConnected;
            }
            else
            {
                bPortCableStatus = s_stInputPortManager.stDisplayPortManager.astDpCtrl[0].bCableConnected;
            }
            break;
        }
#endif
        default:
        {
            break;
        }
    }

    return bPortCableStatus;
}

/*
 * 计算Check Sum, 计算 8 字节 check sum.
 * 这里进行8字节check sum计算。
 */
UCHAR8 Hv_Mw_InputPort_CaculateCheckSum(UCHAR8* pucData, UCHAR8 ucLength)
{
    UINT32 uiIndex = 0;
    UCHAR8 ucValueSum = 0;

    for(uiIndex = 0; uiIndex < ucLength; uiIndex++ )
    {
        ucValueSum += (*pucData);
        pucData++;
    }

    return ((UCHAR8)0x00 - ucValueSum);
}

/* 
 * 使用说明：
 * unsigned char g_aucHdmiSerialNumber[4] = {0x12, 0x34, 0x56, 0x78};
 * unsigned char ucWeek = 23;
 * unsigned char ucYear = (2024 - 1990);
 * unsigned char g_aucSerialDescriptor[18] = {0x00,0x00,0x00,0xFF,0x00,'V','T','T','2','2','1','8','8','0','1','6',0x0A,0x20};
 * 
 * Serial Number : 0x0C - 0x0F
 * Hv_Mw_InputPort_InsertEdidBlockData( 0x0C, 0x0F, g_aucHdmiEdid, g_aucHdmiSerialNumber);
 * 
 * Week : 0x10
 * Hv_Mw_InputPort_InsertEdidBlockData( 0x10, 0x10, g_aucHdmiEdid, &ucWeek);
 * 
 * Year : 0x11
 * Hv_Mw_InputPort_InsertEdidBlockData( 0x11, 0x11, g_aucHdmiEdid, &ucYear);
 * 
 * Descriptor Serial Number :
 * Descriptor0 : 0x36 - 0x47
 * Descriptor1 : 0x48 - 0x59
 * Descriptor2 : 0x5A - 0x6B
 * Descriptor3 : 0x6C - 0x7D
 * Hv_Mw_InputPort_InsertEdidBlockData( 0x48, 0x59, g_aucHdmiEdid, g_aucSerialDescriptor);
 * 
 */
Status Hv_Mw_InputPort_InsertEdidBlockData(UCHAR8 ucAddrStart, UCHAR8 ucAddrEnd, UCHAR8* pucEdidData, const UCHAR8 *pucValueInsert)
{
    HV_ASSERT_TRUE(ucAddrStart < HV_EDID_BLOCK_DATA_SIZE);
    HV_ASSERT_TRUE(ucAddrEnd < HV_EDID_BLOCK_DATA_SIZE);

    for(;ucAddrStart <= ucAddrEnd; ucAddrStart++)
    {
        pucEdidData[ucAddrStart] = (*pucValueInsert);
        pucValueInsert++;
    }

    pucEdidData[HV_EDID_BLOCK_DATA_SIZE - 1] = Hv_Mw_InputPort_CaculateCheckSum(pucEdidData, HV_EDID_BLOCK_DATA_SIZE - 1);

    return HV_SUCCESS;
}

#ifdef HV_PROJECT_CONFIG_COLOR_CHARACTOR
/*
 * 0x19 = Red/Green Low Bits (Rx1 Rx0 Ry1 Ry0 Gx1 Gx0 Gy1Gy0)
 * 0x1A = Blue/White Low Bits (Bx1 Bx0 By1 By0 Wx1 Wx0 Wy1 Wy0)
 * 0x1B = Red-x   (Red-x Bits 9 - 2)
 * 0x1C = Red-y   (Red-y Bits 9 - 2)
 * 0x1D = Green-x (Green-x Bits 9 - 2)
 * 0x1E = Green-y (Green-y Bits 9 - 2)
 * 0x1F = Blue-x  (Blue-x Bits 9 - 2)
 * 0x20 = Blue-y  (Blue-y Bits 9 - 2)
 * 0x21 = White-x (White-x Bits 9 - 2)
 * 0x22 = White-y (White-y Bits 9 - 2)
 * 
 */

#define EDID_Rx 0.6846
#define EDID_Ry 0.3105
#define EDID_Gx 0.2783
#define EDID_Gy 0.6699
#define EDID_Bx 0.1563
#define EDID_By 0.1563
#define EDID_Wx 0.3125
#define EDID_Wy 0.3291

Status Hv_Mw_InputPort_InsertColorCharact(UCHAR8* pucEdidData)
{
    UCHAR8   ucLowValueToBeConfigure = 0;
    USHORT16 usColorCharactValue     = 0;
    FLOAT32  fColorValue = 0.0;

    fColorValue = EDID_Rx;
    usColorCharactValue = (USHORT16)((fColorValue * 1024) + 0.5);
    
    ucLowValueToBeConfigure = usColorCharactValue & 0x3;
    ucLowValueToBeConfigure <<= 2;
    pucEdidData[0x1B] = (usColorCharactValue >> 2) & 0xFF;

    fColorValue = EDID_Ry;
    usColorCharactValue = (USHORT16)((fColorValue * 1024) + 0.5);
    ucLowValueToBeConfigure |= usColorCharactValue & 0x3;
    ucLowValueToBeConfigure <<= 2;
    pucEdidData[0x1C] = (usColorCharactValue >> 2) & 0xFF;

    fColorValue = EDID_Gx;
    usColorCharactValue = (USHORT16)((fColorValue * 1024) + 0.5);
    ucLowValueToBeConfigure |= usColorCharactValue & 0x3;
    ucLowValueToBeConfigure <<= 2;
    pucEdidData[0x1D] = (usColorCharactValue >> 2) & 0xFF;

    fColorValue = EDID_Gy;
    usColorCharactValue = (USHORT16)((fColorValue * 1024) + 0.5);
    ucLowValueToBeConfigure |= usColorCharactValue & 0x3;
    pucEdidData[0x1E] = (usColorCharactValue >> 2) & 0xFF;
    pucEdidData[0x19] = ucLowValueToBeConfigure;

    ucLowValueToBeConfigure = 0;

    fColorValue = EDID_Bx;
    usColorCharactValue = (USHORT16)((fColorValue * 1024) + 0.5);
    ucLowValueToBeConfigure |= usColorCharactValue & 0x3;
    ucLowValueToBeConfigure <<= 2;
    pucEdidData[0x1F] = (usColorCharactValue >> 2) & 0xFF;

    fColorValue = EDID_By;
    usColorCharactValue = (USHORT16)((fColorValue * 1024) + 0.5);
    ucLowValueToBeConfigure |= usColorCharactValue & 0x3;
    ucLowValueToBeConfigure <<= 2;
    pucEdidData[0x20] = (usColorCharactValue >> 2) & 0xFF;

    fColorValue = EDID_Wx;
    usColorCharactValue = (USHORT16)((fColorValue * 1024) + 0.5);
    ucLowValueToBeConfigure |= usColorCharactValue & 0x3;
    ucLowValueToBeConfigure <<= 2;
    pucEdidData[0x21] = (usColorCharactValue >> 2) & 0xFF;

    fColorValue = EDID_Wy;
    usColorCharactValue = (USHORT16)((fColorValue * 1024) + 0.5);
    ucLowValueToBeConfigure |= usColorCharactValue & 0x3;
    pucEdidData[0x22] = (usColorCharactValue >> 2) & 0xFF;
    pucEdidData[0x1A] = ucLowValueToBeConfigure;

    pucEdidData[HV_EDID_BLOCK_DATA_SIZE - 1] = Hv_Mw_InputPort_CaculateCheckSum(pucEdidData, HV_EDID_BLOCK_DATA_SIZE - 1);

    return HV_SUCCESS;
}
#endif

#define HV_EDID_DESC_NUM         4
#define HV_EDID_DESC_LEN         18
#define HV_EDID_DESC_HEADER_LEN  5

BOOL Hv_Mw_InputPort_CheckAndInsertDescSnHeader(UCHAR8 *pucDescSn, const CHAR8 *pcDescSnInsert)
{

    UCHAR8 ucDescSnIndex = 0;

    if(pucDescSn[0] == 0x0 && pucDescSn[1] == 0x0 && pucDescSn[2] == 0x0 && pucDescSn[3] == 0xFF && pucDescSn[4] == 0x0)
    {
        for(ucDescSnIndex = 0; ucDescSnIndex < EDID_DESC_SN_LENTH; ucDescSnIndex++)
        {
            pucDescSn[HV_EDID_DESC_HEADER_LEN + ucDescSnIndex] = pcDescSnInsert[ucDescSnIndex];
        }

        return HV_TRUE;
    }

    return HV_FALSE;
}


Status Hv_Mw_InputPort_InsertEdidDescSn(UCHAR8* pucEdidData, const CHAR8 *pcDescSnInsert)
{
    UCHAR8 ucDescIndex = 0;
    UCHAR8 *pucDescriptor = NULL;

    HV_ASSERT_VALID_PTR(pcDescSnInsert);

    if('\0' == pcDescSnInsert[0])
    {
        HV_LOG_DEBUG(HDMI, "The EDID SN is not Include.");

        return HV_SUCCESS;
    }

    for(pucDescriptor = pucEdidData + HV_EDID_DESCRIPTOR4_OFFSET; ucDescIndex < HV_EDID_DESC_NUM; ucDescIndex++)
    {
        if(Hv_Mw_InputPort_CheckAndInsertDescSnHeader(pucDescriptor, pcDescSnInsert))
        {
            pucEdidData[HV_EDID_BLOCK_DATA_SIZE - 1] = Hv_Mw_InputPort_CaculateCheckSum(pucEdidData, HV_EDID_BLOCK_DATA_SIZE - 1);

            HV_LOG_DEBUG(HDMI, "Edid is update with DescSn:%x:%s",pucDescriptor - pucEdidData, pcDescSnInsert);

            return HV_SUCCESS;
        }

        pucDescriptor -= HV_EDID_DESC_LEN;
    }

    return HV_FAILURE;
}

Status Hv_Mw_InputPort_GetFactoryEdidInfo(LinkPortIndex enPortIndex, HvFactoryEdidInfo *pstFactEdidDetail)
{
    UINT32 uiEdidLength      = 0;
    UCHAR8 aucEdidValue[512] = {0};
    USHORT16 usManFactId     = 0;
    UCHAR8 *pucDescriptor    = NULL;
    UCHAR8 ucDescIndex       = 0;
    UCHAR8 ucDescSnIndex     = 0;
    UCHAR8 ucDescNameIndex   = 0;
    USHORT16 usActive        = 0;
    UCHAR8 ucTempCheckSum[4] = {0, 0, 0, 0};

    HV_ASSERT_VALID_PTR(pstFactEdidDetail);

    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            HV_ASSERT_VALID_PTR(s_stInputPortManager.stHDMIManager.pfGetEdidData);
            uiEdidLength = s_stInputPortManager.stHDMIManager.pfGetEdidData(enPortIndex, aucEdidValue);
#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_EDID_EXTER_EEPROM)
            pstFactEdidDetail->ucStorageType = 1;
#else
            pstFactEdidDetail->ucStorageType = 2;
#endif
            break;
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            HV_ASSERT_VALID_PTR(s_stInputPortManager.stDisplayPortManager.pfGetEdidData);
            uiEdidLength = s_stInputPortManager.stDisplayPortManager.pfGetEdidData(enPortIndex, aucEdidValue);
            pstFactEdidDetail->ucStorageType = 2;
            break;
        }
        default:
        {
            HV_LOG_ERROR(INPUTPORT, "GetFactoryEdidInfo unSupport enPortIndex=%u", enPortIndex);
        }
    }

    if(0 == uiEdidLength)
    {
        pstFactEdidDetail->usHActive = 0;
        pstFactEdidDetail->usVActive = 0;
        return HV_FAILURE;
    }

    usManFactId = aucEdidValue[8];
    usManFactId <<= 8;
    usManFactId += aucEdidValue[9];

    pstFactEdidDetail->acFactName[2] = (usManFactId & 0x1F) + 0x40;
    usManFactId >>= 5;
    pstFactEdidDetail->acFactName[1] = (usManFactId & 0x1F) + 0x40;
    usManFactId >>= 5;
    pstFactEdidDetail->acFactName[0] = (usManFactId & 0x1F) + 0x40;
    pstFactEdidDetail->ucFactNameLen = 3;

    pstFactEdidDetail->usProductCode = (aucEdidValue[11] << 8) | aucEdidValue[10];
    pstFactEdidDetail->uiSerialNum = (aucEdidValue[15] << 24) | (aucEdidValue[14] << 16) | (aucEdidValue[13] << 8) | aucEdidValue[12];

    pstFactEdidDetail->ucWeek = aucEdidValue[HV_EDID_BASE_WEEK_OFFSET];
    pstFactEdidDetail->usYear = aucEdidValue[HV_EDID_BASE_YEAR_OFFSET] + 1990;

    pstFactEdidDetail->ucVersion = aucEdidValue[18];
    pstFactEdidDetail->ucRevision = aucEdidValue[19];

    pstFactEdidDetail->ucExtFlag = aucEdidValue[126];

    pstFactEdidDetail->ucDescSnCount = 0;

    for(pucDescriptor = &(aucEdidValue[HV_EDID_DESCRIPTOR4_OFFSET]), ucDescIndex = 0;
        ucDescIndex < HV_EDID_DESC_NUM; ucDescIndex++)
    {
        if(pucDescriptor[0] == 0x0 && pucDescriptor[1] == 0x0 && pucDescriptor[2] == 0x0 && pucDescriptor[3] == 0xFF && pucDescriptor[4] == 0x0)
        {
            for(ucDescSnIndex = 0; ucDescSnIndex < EDID_DESC_SN_LENTH; ucDescSnIndex++)
            {
                pstFactEdidDetail->acDescSn[ucDescSnIndex] = pucDescriptor[HV_EDID_DESC_HEADER_LEN + ucDescSnIndex];
                if(0x0A == pstFactEdidDetail->acDescSn[ucDescSnIndex] || '\0' == pstFactEdidDetail->acDescSn[ucDescSnIndex])
                {
                    pstFactEdidDetail->acDescSn[ucDescSnIndex] = '\0';
                    break;
                }
            }
            pstFactEdidDetail->ucDescSnCount = ucDescSnIndex;
            break;
        }

        if(pucDescriptor[0] == 0x0 && pucDescriptor[1] == 0x0 && pucDescriptor[2] == 0x0 && pucDescriptor[3] == 0xFC && pucDescriptor[4] == 0x0)
        {
            for(ucDescNameIndex = 0; ucDescNameIndex < 13; ucDescNameIndex++)
            {
                pstFactEdidDetail->acMonitorName[ucDescNameIndex] = pucDescriptor[HV_EDID_DESC_HEADER_LEN + ucDescNameIndex];
            }
        }

        pucDescriptor -= HV_EDID_DESC_LEN;
    }

    usActive = (aucEdidValue[0x3A] & 0xF0);
    usActive <<= 4;
    usActive += aucEdidValue[0x38];
    pstFactEdidDetail->usHActive = usActive;

    usActive = (aucEdidValue[0x3D] & 0xF0);
    usActive <<= 4;
    usActive += aucEdidValue[0x3B];
    pstFactEdidDetail->usVActive = usActive;

    pstFactEdidDetail->ucCheckSumCount = pstFactEdidDetail->ucExtFlag + 1;
    for(ucDescIndex = 0, usActive = 0; usActive < uiEdidLength  && ucDescIndex < pstFactEdidDetail->ucCheckSumCount; ucDescIndex++)
    {
        ucTempCheckSum[ucDescIndex] = Hv_Mw_InputPort_CaculateCheckSum(&aucEdidValue[usActive], 127);
        pstFactEdidDetail->aucCheckSumValue[ucDescIndex] = aucEdidValue[usActive + 127];
        usActive += 128;
    }

    pstFactEdidDetail->bCheckSumStatus = HV_TRUE;
    for (ucDescIndex = 0; ucDescIndex < pstFactEdidDetail->ucCheckSumCount; ucDescIndex++)
    {
        if (pstFactEdidDetail->aucCheckSumValue[ucDescIndex] != ucTempCheckSum[ucDescIndex])
        {
            pstFactEdidDetail->bCheckSumStatus = HV_FALSE;
        }
    }

    uiEdidLength = (aucEdidValue[0x15] * aucEdidValue[0x15]);
    uiEdidLength += (aucEdidValue[0x16] * aucEdidValue[0x16]);

    pstFactEdidDetail->fSreenSize = Hv_Common_Sqrt((FLOAT32)uiEdidLength) / 2.54;

    return HV_SUCCESS;
}

Status Hv_Mw_InputPort_GetFactoryEdidInfoToOsd(LinkPortIndex enPortIndex, HvEdidInfoToOsd *pstEdidInfo)
{
    HvFactoryEdidInfo stFactEdidDetail = {0};
    Status uiRet = HV_SUCCESS;
    HV_ASSERT_VALID_PTR(pstEdidInfo);

    HV_MEMSET(pstEdidInfo, 0x00, sizeof(HvEdidInfoToOsd));
    uiRet = Hv_Mw_InputPort_GetFactoryEdidInfo(enPortIndex, &stFactEdidDetail);
    pstEdidInfo->usProductCode = stFactEdidDetail.usProductCode;
    pstEdidInfo->uiSerialNum = stFactEdidDetail.uiSerialNum;
    pstEdidInfo->usYear = stFactEdidDetail.usYear;
    pstEdidInfo->ucWeek = stFactEdidDetail.ucWeek;
    HV_MEMCPY(pstEdidInfo->acFactName, stFactEdidDetail.acFactName, 3);
    HV_MEMCPY(pstEdidInfo->acDescSn, stFactEdidDetail.acDescSn, 13);
    HV_MEMCPY(pstEdidInfo->acMonitorName, stFactEdidDetail.acMonitorName, 13);
    pstEdidInfo->ucVersion = stFactEdidDetail.ucVersion;
    pstEdidInfo->ucRevision = stFactEdidDetail.ucRevision;
    pstEdidInfo->ucExtFlag = stFactEdidDetail.ucExtFlag;
    pstEdidInfo->ucCheckSumCount = stFactEdidDetail.ucCheckSumCount;
    HV_MEMCPY(pstEdidInfo->aucCheckSumValue, stFactEdidDetail.aucCheckSumValue, 4);
    pstEdidInfo->bCheckSumStatus = stFactEdidDetail.bCheckSumStatus;

    return uiRet;
}

static VOID CalculateEdidBlockChecksum(UCHAR8 *pucEdidData, UINT32 uiStartAddr)
{
    UINT32 uiSum;
    UINT32 uiIndex, uiIndexEnd;
    UCHAR8 *pucData = pucEdidData;

    uiSum = 0;
    uiIndexEnd = uiStartAddr + 127;
    for (uiIndex = uiStartAddr; uiIndex < uiIndexEnd; uiIndex++)
    {
        uiSum += pucData[uiIndex];
    }
    pucData[uiIndexEnd] = 256 - uiSum % 256;
    return;
}

VOID Hv_Mw_InputPort_RmvEdidHdr(UCHAR8* pucEdidUpdate, UINT32 uiEdidLength)
{
    UINT32 uiBlockTagAddr    = HV_EDID_BLOCK_DATA_SIZE;
    UINT32 uiDataBlockOffset = 0;
    UCHAR8 ucDataBlockHead   = 0;
    UCHAR8 ucDataBlockLength = 0;
    UCHAR8 ucCTAExtendedTag  = 0;
    USHORT16 usCheckSum      = 0;

    HV_ASSERT_VALID_PTR_VOID(pucEdidUpdate);
    for(uiBlockTagAddr = HV_EDID_BLOCK_DATA_SIZE; uiBlockTagAddr < uiEdidLength; uiBlockTagAddr += HV_EDID_BLOCK_DATA_SIZE)
    {
        /* 找到 CTA Block */
        if(pucEdidUpdate[uiBlockTagAddr] == HV_EDID_CTA_BLOCK_TAG)
        {
            for(uiDataBlockOffset = 4; uiDataBlockOffset < pucEdidUpdate[uiBlockTagAddr + 2] + 4; uiDataBlockOffset += (ucDataBlockLength + 1))
            {
                ucDataBlockHead = pucEdidUpdate[uiBlockTagAddr + uiDataBlockOffset];
                ucDataBlockLength = ucDataBlockHead & 0x1F;
                ucDataBlockHead >>= 5;

                ucCTAExtendedTag  = pucEdidUpdate[uiBlockTagAddr + uiDataBlockOffset + 1];

                /* 查找到HDR DataBlock */
                if((ucDataBlockHead == 0x7) && (ucCTAExtendedTag == 0x6))
                {
                    HV_LOG_DEBUG(INPUTPORT, "Found Hdr Info at 0x%x.", uiDataBlockOffset);

                    UINT32 uiLabel = uiBlockTagAddr + uiDataBlockOffset;

                    /* 删除HDR内容 */
                    for(; uiLabel < uiBlockTagAddr + (HV_EDID_BLOCK_DATA_SIZE - 2 - ucDataBlockLength); uiLabel++)
                    {
                        pucEdidUpdate[uiLabel] = pucEdidUpdate[uiLabel + ucDataBlockLength + 1];
                    }

                    for(;uiLabel < HV_EDID_BLOCK_DATA_SIZE - 1; uiLabel++)
                    {
                        pucEdidUpdate[uiLabel] = 0x0;
                    }

                    pucEdidUpdate[uiBlockTagAddr + 2] -= (ucDataBlockLength + 1);

                    pucEdidUpdate[uiBlockTagAddr + HV_EDID_BLOCK_DATA_SIZE - 1] = Hv_Mw_InputPort_CaculateCheckSum(pucEdidUpdate + uiBlockTagAddr, HV_EDID_BLOCK_DATA_SIZE - 1);

                    return;
                }
            }
        }
    }

    return;

}

#ifdef HDR_PARAM_DYNAMIC_UP
Status Hv_Mw_InputPort_UpdateEdidHdrParam(UCHAR8 *pucEdidData, UINT32 uiEdidLength)
{
    UINT32 uiBlockTagAddr;
    UINT32 uiDataBlockOffset;
    UCHAR8 *pucData = pucEdidData;
    UCHAR8 ucDataBlockHead, ucDataBlockHeadAfter;
    UCHAR8 ucDataBlockLength, ucDataBlockLengthAfter;
    UINT32 uiMoveSize;
    BOOL bHaveHdr;
    USHORT16 ausColorCharacs[COLOR_ID_BUTT];
    FLOAT32 fTempVal;
    
    HV_ASSERT_VALID_PTR(pucData);

    /* ---- 更新 COLOR CHARACS ---- */
    uiBlockTagAddr = HV_EDID_COLOR_CHARACS_OFFSET;
    ausColorCharacs[COLOR_ID_RED_X] = (USHORT16)(HDR_RED_X * 1024 + 0.5);
    ausColorCharacs[COLOR_ID_RED_Y] = (USHORT16)(HDR_RED_Y * 1024 + 0.5);
    ausColorCharacs[COLOR_ID_GREEN_X] = (USHORT16)(HDR_GREEN_X * 1024 + 0.5);
    ausColorCharacs[COLOR_ID_GREEN_Y] = (USHORT16)(HDR_GREEN_Y * 1024 + 0.5);
    ausColorCharacs[COLOR_ID_BLUE_X] = (USHORT16)(HDR_BLUE_X * 1024 + 0.5);
    ausColorCharacs[COLOR_ID_BLUE_Y] = (USHORT16)(HDR_BLUE_Y * 1024 + 0.5);
    ausColorCharacs[COLOR_ID_WHITE_X] = (USHORT16)(HDR_WHITE_X * 1024 + 0.5);
    ausColorCharacs[COLOR_ID_WHITE_Y] = (USHORT16)(HDR_WHITE_Y * 1024 + 0.5);

    // 不用指针简化处理，防止处理器大小端不兼容
    pucData[uiBlockTagAddr] = 0;
    pucData[uiBlockTagAddr] = pucData[uiBlockTagAddr] | (ausColorCharacs[COLOR_ID_RED_X]   & 0x03)  << 6;
    pucData[uiBlockTagAddr] = pucData[uiBlockTagAddr] | (ausColorCharacs[COLOR_ID_RED_Y]   & 0x03)  << 4;
    pucData[uiBlockTagAddr] = pucData[uiBlockTagAddr] | (ausColorCharacs[COLOR_ID_GREEN_X] & 0x03)  << 2;
    pucData[uiBlockTagAddr] = pucData[uiBlockTagAddr] | (ausColorCharacs[COLOR_ID_GREEN_Y] & 0x03)  << 0;

    uiBlockTagAddr++;
    pucData[uiBlockTagAddr] = 0;
    pucData[uiBlockTagAddr] = pucData[uiBlockTagAddr] | (ausColorCharacs[COLOR_ID_BLUE_X]  & 0x03)  << 6;
    pucData[uiBlockTagAddr] = pucData[uiBlockTagAddr] | (ausColorCharacs[COLOR_ID_BLUE_Y]  & 0x03)  << 4;
    pucData[uiBlockTagAddr] = pucData[uiBlockTagAddr] | (ausColorCharacs[COLOR_ID_WHITE_X] & 0x03)  << 2;
    pucData[uiBlockTagAddr] = pucData[uiBlockTagAddr] | (ausColorCharacs[COLOR_ID_WHITE_Y] & 0x03)  << 0;

    pucData[++uiBlockTagAddr] = ausColorCharacs[COLOR_ID_RED_X]   >> 2;
    pucData[++uiBlockTagAddr] = ausColorCharacs[COLOR_ID_RED_Y]   >> 2;
    pucData[++uiBlockTagAddr] = ausColorCharacs[COLOR_ID_GREEN_X] >> 2;
    pucData[++uiBlockTagAddr] = ausColorCharacs[COLOR_ID_GREEN_Y] >> 2;
    pucData[++uiBlockTagAddr] = ausColorCharacs[COLOR_ID_BLUE_X]  >> 2;
    pucData[++uiBlockTagAddr] = ausColorCharacs[COLOR_ID_BLUE_Y]  >> 2;
    pucData[++uiBlockTagAddr] = ausColorCharacs[COLOR_ID_WHITE_X] >> 2;
    pucData[++uiBlockTagAddr] = ausColorCharacs[COLOR_ID_WHITE_Y] >> 2;

    // 更新 checksum
    CalculateEdidBlockChecksum(pucData, 0);
    HV_INPUT_LOG_INFO(INPUTPORT, "COLOR CHARACS update success.");
    /* ----  ---- */

    /* ---- 更新 HDR Static Metadata ---- */
    bHaveHdr = 0;
    for (uiBlockTagAddr = HV_EDID_BLOCK_DATA_SIZE; uiBlockTagAddr < uiEdidLength; uiBlockTagAddr += HV_EDID_BLOCK_DATA_SIZE)
    {
        /* 查找到 CTA Block */
        if (pucData[uiBlockTagAddr] != HV_EDID_CTA_BLOCK_TAG)
        {
            continue;
        }

        /* 查找到 HDR Static Metadata */
        for (uiDataBlockOffset = 4; uiDataBlockOffset < pucData[uiBlockTagAddr + 2]; uiDataBlockOffset += (ucDataBlockLength + 1))
        {
            ucDataBlockHead = pucData[uiBlockTagAddr + uiDataBlockOffset];
            ucDataBlockLength = ucDataBlockHead & 0x1F;
            if (ucDataBlockHead & 0xE0 && pucData[uiBlockTagAddr + uiDataBlockOffset + 1] == 0x06)
            {
                bHaveHdr = 1;
                goto up_hdr_meta;
            }
        }
    }
    HV_INPUT_LOG_INFO(INPUTPORT, "no hdr, no need update.");
    return HV_SUCCESS;
    
up_hdr_meta:
    /*
    HV_LOG_INFO(INPUTPORT, "uiBlockTagAddr: %u, uiDataBlockOffset: %u, ucDataBlockHead: 0x%x, ucDataBlockLength: %u",
        uiBlockTagAddr, uiDataBlockOffset, ucDataBlockHead, ucDataBlockLength);
    */
    // 检查亮度开关及亮度值是否符合规范
    if (HDR_LUMINANCE_MIN_EN && !HDR_LUMINANCE_AVG_EN)
    {
        HV_LOG_ERROR(INPUTPORT, "if HDR_LUMINANCE_MIN_EN is 1, HDR_LUMINANCE_AVG_EN must be 1!");
        goto up_hdr_fail;
    }
    if (HDR_LUMINANCE_AVG_EN && !HDR_LUMINANCE_MAX_EN)
    {
        HV_LOG_ERROR(INPUTPORT, "if HDR_LUMINANCE_AVG_EN is 1, HDR_LUMINANCE_MAX_EN must be 1!");
        goto up_hdr_fail;
    }
    if (HDR_LUMINANCE_MAX > 12525.722 || HDR_LUMINANCE_MAX < 50)
    {
        HV_LOG_ERROR(INPUTPORT, "LUMINANCE MAX is error, must be 50 ~ 12525.722");
        goto up_hdr_fail;
    }
    if (HDR_LUMINANCE_AVG > 12525.722 || HDR_LUMINANCE_AVG < 50)
    {
        HV_LOG_ERROR(INPUTPORT, "LUMINANCE AVG is error, must be 50 ~ 12525.722");
        goto up_hdr_fail;
    }
    if (HDR_LUMINANCE_MIN > 125.257 || HDR_LUMINANCE_MIN < 0)
    {
        HV_LOG_ERROR(INPUTPORT, "LUMINANCE MIN is error, must be 0 ~ 125.257");
        goto up_hdr_fail;
    }

    // 更新 LUMINANCE
    ucDataBlockLengthAfter = 3 + !!HDR_LUMINANCE_MAX_EN + !!HDR_LUMINANCE_AVG_EN + !!HDR_LUMINANCE_MIN_EN;
    if (ucDataBlockLengthAfter < ucDataBlockLength)
    {
        // 原始数据前移
        uiMoveSize = 128 - (uiDataBlockOffset + 1 + ucDataBlockLength);
        memmove(&pucData[uiBlockTagAddr + uiDataBlockOffset + 1 + ucDataBlockLengthAfter], 
            &pucData[uiBlockTagAddr + uiDataBlockOffset + 1 + ucDataBlockLength], 
            uiMoveSize);
        /*
        HV_LOG_INFO(INPUTPORT, "move %u to %u, size is %u", 
            uiBlockTagAddr + uiDataBlockOffset + 1 + ucDataBlockLength,
            uiBlockTagAddr + uiDataBlockOffset + 1 + ucDataBlockLengthAfter,
            uiMoveSize);
        */
        // 尾部数据清零，包括checksum
        memset(&pucData[uiBlockTagAddr + 127 - (ucDataBlockLength - ucDataBlockLengthAfter)], 0, ucDataBlockLength - ucDataBlockLengthAfter);
        /*
        HV_LOG_INFO(INPUTPORT, "set to zero, addr start %u, size %u", 
            uiBlockTagAddr + 127 - (ucDataBlockLength - ucDataBlockLengthAfter),
            ucDataBlockLength - ucDataBlockLengthAfter);
        */
    }
    else
    {
        // 原始数据后移或不移
        uiMoveSize = 128 - (uiDataBlockOffset + 1 + ucDataBlockLengthAfter);
        memmove(&pucData[uiBlockTagAddr + uiDataBlockOffset + 1 + ucDataBlockLengthAfter], 
            &pucData[uiBlockTagAddr + uiDataBlockOffset + 1 + ucDataBlockLength], 
            uiMoveSize);
        /*
        HV_LOG_INFO(INPUTPORT, "move %u to %u, size is %u", 
            uiBlockTagAddr + uiDataBlockOffset + 1 + ucDataBlockLength,
            uiBlockTagAddr + uiDataBlockOffset + 1 + ucDataBlockLengthAfter,
            uiMoveSize);
        */
    }
    if (HDR_LUMINANCE_MAX_EN)
    {
        fTempVal = HDR_LUMINANCE_MAX / 50;
        fTempVal = log(fTempVal) / log(2);
        pucData[uiBlockTagAddr + uiDataBlockOffset + 4] = (UCHAR8)(fTempVal * 32 + 0.5);
    }
    if (HDR_LUMINANCE_AVG_EN)
    {
        fTempVal = HDR_LUMINANCE_AVG / 50;
        fTempVal = log(fTempVal) / log(2);
        pucData[uiBlockTagAddr + uiDataBlockOffset + 5] = (UCHAR8)(fTempVal * 32 + 0.5);
    }
    if (HDR_LUMINANCE_MIN_EN)
    {
        fTempVal = HDR_LUMINANCE_MIN / HDR_LUMINANCE_MAX * 100;
        fTempVal = sqrt(fTempVal);
        pucData[uiBlockTagAddr + uiDataBlockOffset + 6] = (UCHAR8)(fTempVal * 255 + 0.5);
    }

    // 更新 HDR Length
    pucData[uiBlockTagAddr + uiDataBlockOffset] &= 0xE0;
    pucData[uiBlockTagAddr + uiDataBlockOffset] |= ucDataBlockLengthAfter;

    // 更新 CTA Block Length
    pucData[uiBlockTagAddr + 2] -= ucDataBlockLength;
    pucData[uiBlockTagAddr + 2] += ucDataBlockLengthAfter;

    // 更新 checksum
    CalculateEdidBlockChecksum(pucData, uiBlockTagAddr);
    HV_INPUT_LOG_INFO(INPUTPORT, "LUMINANCE update success.");
    return HV_SUCCESS;
    
up_hdr_fail:
    HV_LOG_ERROR(INPUTPORT, "LUMINANCE update fail.");
    return HV_FAILURE;
    /* ----  ---- */
}
#endif

EDIDType Hv_Mw_InputPort_GetCurrentEdidType(LinkPortIndex enPortIndex)
{
    EDIDType enEDIDType = EDID_TYPE_DEFAULT;
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        {
            enEDIDType = s_stInputPortManager.stHDMIManager.astHdmiData[0].enEdidConfiged;
            break;
        }
#if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID)
        case LINK_PORT_INDEX_HDMI_RX1:
        {            
            if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID)
            {
                enEDIDType = s_stInputPortManager.stHDMIManager.astHdmiData[1].enEdidConfiged;
            }
            else
            {
                enEDIDType = s_stInputPortManager.stHDMIManager.astHdmiData[0].enEdidConfiged;
            }
            break;
        }
#endif
        case LINK_PORT_INDEX_DP_RX0:
        {
            enEDIDType = s_stInputPortManager.stDisplayPortManager.astDpCtrl[0].enCurEdidType;
            break;
        }
#if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID)
        case LINK_PORT_INDEX_DP_RX1:
        {
            if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
            {
                enEDIDType = s_stInputPortManager.stDisplayPortManager.astDpCtrl[1].enCurEdidType;
            }
            else
            {
                enEDIDType = s_stInputPortManager.stDisplayPortManager.astDpCtrl[0].enCurEdidType;
            }
            break;
        }
#endif
        case LINK_PORT_INDEX_INVALID:
        {
            enEDIDType = EDID_TYPE_DEFAULT;
            break;
        }
        default:
        {
            enEDIDType = EDID_TYPE_DEFAULT;
            break;
        }
    }
    return enEDIDType;
}

InputPortState Hv_Mw_InputPort_GetInputPortStatus(LinkPortIndex enPortIndex)
{
    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        {
            return (s_stInputPortManager.stHDMIManager.astHdmiData[0].enCurrentPortState);
        }
#if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID)
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID)
            {
                return s_stInputPortManager.stHDMIManager.astHdmiData[1].enCurrentPortState;
            }
            else
            {
                return s_stInputPortManager.stHDMIManager.astHdmiData[0].enCurrentPortState;
            }
        }
#endif
        case LINK_PORT_INDEX_DP_RX0:
        {
            return s_stInputPortManager.stDisplayPortManager.astDpCtrl[0].enCurrentPortState;
        }
#if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID)
        case LINK_PORT_INDEX_DP_RX1:
        {
            if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
            {
                return s_stInputPortManager.stDisplayPortManager.astDpCtrl[1].enCurrentPortState;
            }
            else
            {
                return s_stInputPortManager.stDisplayPortManager.astDpCtrl[0].enCurrentPortState;
            }
        }
#endif
        default:
        {
            HV_LOG_ERROR(INPUTPORT, "unknown InputPortEvent! enPortIndex=%u", enPortIndex);
            return INPUT_PORT_STATE_IDLE;
        }
    }

    return INPUT_PORT_STATE_IDLE;
}

#ifndef HV_PLAT_BOARD

Status Hv_Mw_InputPort_SetHpdStatus(LinkPortIndex enPortIndex, BOOL bHpdStatus)
{
    Status uiResult = HV_FAILURE;

    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            HV_ASSERT_VALID_PTR(s_stInputPortManager.stHDMIManager.pfHPDAction);
            uiResult = s_stInputPortManager.stHDMIManager.pfHPDAction(enPortIndex, bHpdStatus);
            break;
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            HV_ASSERT_VALID_PTR(s_stInputPortManager.stDisplayPortManager.pfHPDAction);
            uiResult = s_stInputPortManager.stDisplayPortManager.pfHPDAction(enPortIndex, bHpdStatus);
            break;
        }
        default:
        {
            HV_LOG_ERROR(INPUTPORT, "SetHpdStatus unSupport enPortIndex=%u", enPortIndex);
        }
    }

    return uiResult;
}

BOOL Hv_Mw_InputPort_GetHpdStatus(LinkPortIndex enPortIndex)
{
    BOOL bHpdStatus = HV_FALSE;

    switch (enPortIndex)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        {
            bHpdStatus = (s_stInputPortManager.stHDMIManager.astHdmiData)[0].bHPDStatus;
            break;
        }
#if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID)
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID)
            {
                bHpdStatus = (s_stInputPortManager.stHDMIManager.astHdmiData)[1].bHPDStatus;
            }
            else
            {
                bHpdStatus = (s_stInputPortManager.stHDMIManager.astHdmiData)[0].bHPDStatus;
            }
            break;
        }
#endif
        case LINK_PORT_INDEX_DP_RX0:
        {
            bHpdStatus = ((s_stInputPortManager.stDisplayPortManager.astDpCtrl)[0].ucHpdLevel == 1);
            break;
        }
#if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID)
        case LINK_PORT_INDEX_DP_RX1:
        {
            if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
            {
                bHpdStatus = ((s_stInputPortManager.stDisplayPortManager.astDpCtrl)[1].ucHpdLevel == 1);
            }
            else
            {
                bHpdStatus = ((s_stInputPortManager.stDisplayPortManager.astDpCtrl)[0].ucHpdLevel == 1);
            }
            break;
        }
#endif

        default:
        {
            HV_LOG_ERROR(INPUTPORT, "GetHpdStatus unSupport enPortIndex=%u", enPortIndex);
        }
    }

    return bHpdStatus;
}

#endif

Status Hv_Mw_InputPort_GetEdidChecksum(LinkPortIndex enPortId, EDIDType enType, UCHAR8 ucBlock, UCHAR8 *pucChecksum)
{
    // HdmiEdidDBRegion *pstHdmiEdid;
    //HdmiCtrlData *pstHdmiDataPtr;

    UCHAR8 *pucEdid = NULL;
    UINT32 uiEdidMaxLen;
    UINT32 uiOffset;
    UCHAR8 aucHead[] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 };
    UCHAR8 aucEdidData[DP_EDID_MAX_LENGTH] = {0};

    switch (enPortId)
    {
        case LINK_PORT_INDEX_HDMI_RX0:
        case LINK_PORT_INDEX_HDMI_RX1:
        {
            uiEdidMaxLen = 0;
            // use default or flash edid (HdmiEdidDBRegion s_stHdmiEdidDBRegion) ?
            HdmiEdidDBRegion* pstHdmiEdid = ((enPortId == LINK_PORT_INDEX_HDMI_RX0) ? Hv_Common_Db_GetHdmiEdidDBRegionPtr() : Hv_Common_Db_GetHdmi1EdidDBRegionPtr());

            for(UINT32 uiLoop = 0; uiLoop < pstHdmiEdid->ucNumber && uiLoop < HDMI_EDID_MAX_NUMBER; uiLoop++)
            {
                if(enType == (pstHdmiEdid->astHdmiEdid)[uiLoop].eEdidType)
                {
                    pucEdid = (pstHdmiEdid->astHdmiEdid)[uiLoop].acEdid;
                    uiEdidMaxLen = (pstHdmiEdid->astHdmiEdid)[uiLoop].uiEdidLen;
                }
            }
            break;
        }
        case LINK_PORT_INDEX_DP_RX0:
        case LINK_PORT_INDEX_DP_RX1:
        {
            pucEdid = &aucEdidData[0];
            uiEdidMaxLen = sizeof(aucEdidData);
            Hv_Mw_DpRx_GetEdid(enPortId, pucEdid);
            break;
        }
        default:
        {
            HV_LOG_ERROR(HDMI, "edid port error, port: %u, type: %u, block: %u", 
                enPortId, enType, ucBlock);
            return HV_FAILURE;
        }
    }

    uiOffset = (ucBlock + 1) * HV_EDID_BLOCK_DATA_SIZE - 1;
    if (uiOffset >= uiEdidMaxLen)
    {
        HV_LOG_ERROR(HDMI, "get edid checksum overflow, port: %u, type: %u, block: %u", 
            enPortId, enType, ucBlock);
        return HV_FAILURE;
    }

    // 判断edid的block是否有效
    if (ucBlock == 0)
    {
        if (0 != memcmp(pucEdid, aucHead, sizeof(aucHead)))
        {
            HV_LOG_ERROR(HDMI, "edid head error, port: %u, type: %u, block: %u", 
                enPortId, enType, ucBlock);
            return HV_FAILURE;
        }
    }
    else
    {
        if (pucEdid[HV_EDID_BLOCK_DATA_SIZE - 2] < ucBlock)
        {
            HV_LOG_ERROR(HDMI, "edid extra block error, port: %u, type: %u, block: %u", 
                enPortId, enType, ucBlock);
            return HV_FAILURE;
        }
    }
    
    *pucChecksum = pucEdid[uiOffset];

    return HV_SUCCESS;
}

