/**
 * @file hv_edid_UpdateEdid.c
 * @brief EDID configure of HDMI.
 *
 * @verbatim
 * ==============================================================================
 *                        ##### How to use #####
 * ==============================================================================
 * (+) .
 *
 @ endverbatim
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2023-12-04
 */

#include "hv_edid_UpdateEdid.h"

static Status UpdateEdidHdmi(LinkPortIndex enMwPortIndex , BOOL bVrrEn, BOOL bHdrEn)
{
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    UCHAR8 ucHdmiFormat = 0;
    if(LINK_PORT_INDEX_HDMI_RX0 == enMwPortIndex)
    {
        ucHdmiFormat = HV_COMMON_DATABASE_GET(UserData, ucHdmi0Format);
    }
    else
    {
        ucHdmiFormat = HV_COMMON_DATABASE_GET(UserData, ucHdmi1Format);
    }
    if(bVrrEn)
    {
        if(0 == ucHdmiFormat)
        {
            return (pstInputPortManager->pfUpdateEdid(enMwPortIndex, bHdrEn ? EDID_TYPE_TMDS_VRR : (EDID_TYPE_TMDS_VRR | EDID_TYPE_CLOSE_HDR)));
        }
        else if(1 == ucHdmiFormat)
        {
            return (pstInputPortManager->pfUpdateEdid(enMwPortIndex, bHdrEn ? EDID_TYPE_FRL_VRR : (EDID_TYPE_FRL_VRR | EDID_TYPE_CLOSE_HDR)));
        }
        else
        {
            return (pstInputPortManager->pfUpdateEdid(enMwPortIndex, bHdrEn ? EDID_TYPE_FRL_ENHANCED_VRR : (EDID_TYPE_FRL_ENHANCED_VRR | EDID_TYPE_CLOSE_HDR)));
        }
    }
    else
    {
        if(0 == ucHdmiFormat)
        {
            return (pstInputPortManager->pfUpdateEdid(enMwPortIndex, bHdrEn ? EDID_TYPE_TMDS : (EDID_TYPE_TMDS | EDID_TYPE_CLOSE_HDR)));
        }
        else if(1 == ucHdmiFormat)
        {
            return (pstInputPortManager->pfUpdateEdid(enMwPortIndex, bHdrEn ? EDID_TYPE_FRL : (EDID_TYPE_FRL | EDID_TYPE_CLOSE_HDR)));
        }
        else
        {
            return (pstInputPortManager->pfUpdateEdid(enMwPortIndex, bHdrEn ? EDID_TYPE_FRL_ENHANCED : (EDID_TYPE_FRL_ENHANCED | EDID_TYPE_CLOSE_HDR)));
        }
    }
    return HV_SUCCESS;
}

static Status UpdateEdidAll(BOOL bVrrEn, BOOL bHdrEn, LinkPortIndex enMwPortIndex)
{
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    EDIDType enEdidType = (bVrrEn > 0) ? EDID_TYPE_ADAPTIVESYNC : EDID_TYPE_DEFAULT;
    enEdidType = (bHdrEn == HV_TRUE) ? enEdidType : (enEdidType | EDID_TYPE_CLOSE_HDR);
    BOOL bProEsPort = HV_COMMON_DATABASE_GET(UserData, ucProEsportSwitch);
    Status eRet = HV_SUCCESS;
    Status eStat = HV_SUCCESS;

    if (HV_TRUE == bProEsPort)
    {
        enEdidType = (bHdrEn == HV_TRUE) ? EDID_TYPE_PRO_ESPORT : (EDID_TYPE_PRO_ESPORT | EDID_TYPE_CLOSE_HDR);
#if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID)
        eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_HDMI_RX0, enEdidType);
        if (LINK_PORT_INDEX_HDMI_RX0 == enMwPortIndex)
        {
            eRet = eStat;
        }
#endif
#if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID)
        eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_HDMI_RX1, enEdidType);
        if (LINK_PORT_INDEX_HDMI_RX1 == enMwPortIndex)
        {
            eRet = eStat;
        }
#endif
#if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
        eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_DP_RX0, enEdidType);
        if (LINK_PORT_INDEX_DP_RX0 == enMwPortIndex)
        {
            eRet = eStat;
        }
#endif
#if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID)
        eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_DP_RX1, enEdidType);
        if (LINK_PORT_INDEX_DP_RX1 == enMwPortIndex)
        {
            eRet = eStat;
        }
#endif
        return eRet;
    }

#if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID)
    eStat = UpdateEdidHdmi(LINK_PORT_INDEX_HDMI_RX0, bVrrEn, bHdrEn);
    if (LINK_PORT_INDEX_HDMI_RX0 == enMwPortIndex)
    {
        eRet = eStat;
    }
#endif
#if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID)
    eStat = UpdateEdidHdmi(LINK_PORT_INDEX_HDMI_RX1, bVrrEn, bHdrEn);
    if (LINK_PORT_INDEX_HDMI_RX1 == enMwPortIndex)
    {
        eRet = eStat;
    }
#endif
#if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
    eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_DP_RX0, enEdidType);
    if (LINK_PORT_INDEX_DP_RX0 == enMwPortIndex)
    {
        eRet = eStat;
    }
#endif
#if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID)
    eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_DP_RX1, enEdidType);
    if (LINK_PORT_INDEX_DP_RX1 == enMwPortIndex)
    {
        eRet = eStat;
    }
#endif
    return eRet;
}

Status Hw_Mw_Channel_Update_EDID(const ChannelData* pstChannelData, LinkPortIndex enMwPortIndex)
{
    const InputPortManager* pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    BOOL bVrrEn = HV_COMMON_DATABASE_GET(UserData, ucFreeSync);
#if (HV_PROJECT_CONFIG_PQ_HDR_CHANGEEDID == HV_CONFIG_ON)
    BOOL bHdrEn = HV_COMMON_DATABASE_GET(UserData, enHdrSwitch);
#else
    BOOL bHdrEn = HV_TRUE;
#endif
    Status eRet = HV_SUCCESS;
    Status eStat = HV_SUCCESS;

#if ((HV_CONFIG_ON == HV_PROJECT_CONFIG_PXP) || (HV_CONFIG_ON == HV_PROJECT_CONFIG_MAGNIFY))
    PxpMode enPxpMode = Hv_Mw_Channel_GetPxpMode();
    if (PXP_MODE_CLOSE == enPxpMode)
#endif
    {
        HV_LOG_DEBUG(CHANNEL, "Update EDID,Vrr %u,Channel %u", bVrrEn, pstChannelData->enChannelType);
        return (UpdateEdidAll(bVrrEn, bHdrEn, enMwPortIndex));
    }
#if ((HV_CONFIG_ON == HV_PROJECT_CONFIG_PXP) || (HV_CONFIG_ON == HV_PROJECT_CONFIG_MAGNIFY))
    else if (PXP_MODE_PIP_ENABLE == enPxpMode)
    {
        HV_LOG_DEBUG(CHANNEL, "Update EDID,PIP,Vrr %u,Channel %u", bVrrEn, pstChannelData->enChannelType);
        if (CHANNEL_TYPE_SUB == pstChannelData->enChannelType)
        {
            /*除了主通道其他通道全部切为PIP子窗口的EDID*/
            return (pstInputPortManager->pfUpdateEdid(enMwPortIndex, EDID_TYPE_PIP));
        }
        else
        {
            EDIDType enDpEdidType = (bVrrEn > 0) ? (EDID_TYPE_ADAPTIVESYNC  | EDID_TYPE_CLOSE_HDR) : (EDID_TYPE_DEFAULT | EDID_TYPE_CLOSE_HDR);
            if((LINK_PORT_INDEX_HDMI_RX0 == enMwPortIndex) || (LINK_PORT_INDEX_HDMI_RX1 == enMwPortIndex))
            {
                return (UpdateEdidHdmi(enMwPortIndex, bVrrEn, HV_FALSE));
            }

            if((LINK_PORT_INDEX_DP_RX0 == enMwPortIndex) || (LINK_PORT_INDEX_DP_RX1 == enMwPortIndex))
            {
                return (pstInputPortManager->pfUpdateEdid(enMwPortIndex, enDpEdidType));
            }
        }
    }
    else if (PXP_MODE_PBP_ENABLE == enPxpMode)
    {
        HV_LOG_DEBUG(CHANNEL, "Update EDID,PBP,Vrr %u,Channel %u", bVrrEn, pstChannelData->enChannelType);
        /*PBP场景暂不支持 PBP VRR EDID；PBP下更新所有通道EDID为PBP*/
#if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
        eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_DP_RX0, EDID_TYPE_PBP);
        if (LINK_PORT_INDEX_DP_RX0 == enMwPortIndex)
        {
            eRet = eStat;
        }
#endif
#if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID)
        eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_HDMI_RX0, EDID_TYPE_PBP);
        if (LINK_PORT_INDEX_HDMI_RX0 == enMwPortIndex)
        {
            eRet = eStat;
        }
#endif
#if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID)
        eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_DP_RX1, EDID_TYPE_PBP);
        if (LINK_PORT_INDEX_DP_RX1 == enMwPortIndex)
        {
            eRet = eStat;
        }
#endif
#if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID)
        eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_HDMI_RX1, EDID_TYPE_PBP);
        if (LINK_PORT_INDEX_HDMI_RX1 == enMwPortIndex)
        {
            eRet = eStat;
        }
#endif
        return eRet;
    }
    else if (PXP_MODE_MAGNIFY_GLASS_ENABLE == enPxpMode)
    {
        HV_LOG_DEBUG(CHANNEL, "Update EDID,Magnifyglass,Vrr %u,Channel %u", bVrrEn, pstChannelData->enChannelType);
        return (UpdateEdidAll(bVrrEn, bHdrEn, enMwPortIndex));
    }
#endif
    return HV_SUCCESS;
}

Status Hw_Mw_Channel_ChangeFreesync(ChannelData *pstChannelData)
{
    const InputPortManager *pstInputPortManager = Hv_Mw_InputPort_GetManagerPtr();
    BOOL bVrrEn = HV_COMMON_DATABASE_GET(UserData, ucFreeSync);
#if (HV_PROJECT_CONFIG_PQ_HDR_CHANGEEDID == HV_CONFIG_ON)
    BOOL bHdrEn = HV_COMMON_DATABASE_GET(UserData, enHdrSwitch);
#else
    BOOL bHdrEn = HV_TRUE;
#endif
    LinkPortIndex enMwPortIndex = pstChannelData->enChannelSrcLinkPortIndex;
    PxpMode enPxpMode = Hv_Mw_Channel_GetPxpMode();
    EDIDType enDpEdidType = (bVrrEn == HV_TRUE) ? EDID_TYPE_ADAPTIVESYNC : EDID_TYPE_DEFAULT;
    enDpEdidType = (bHdrEn == HV_TRUE) ? enDpEdidType : (enDpEdidType | EDID_TYPE_CLOSE_HDR);
    Status eRet = HV_SUCCESS;
    Status eStat = HV_SUCCESS;

    // hdmi直接拉hpd，通知source询问sink
#if (HV_BOARD_CONFIG_HDMI_0 == PORT_VALID)
    Hv_Mw_InputPort_ToggleHpd(LINK_PORT_INDEX_HDMI_RX0);
#endif
#if (HV_BOARD_CONFIG_HDMI_1 == PORT_VALID)
    Hv_Mw_InputPort_ToggleHpd(LINK_PORT_INDEX_HDMI_RX1);
#endif

#if ((HV_CONFIG_ON == HV_PROJECT_CONFIG_PXP) || (HV_CONFIG_ON == HV_PROJECT_CONFIG_MAGNIFY))

    if (PXP_MODE_CLOSE == enPxpMode)
    {
#if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
        eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_DP_RX0, enDpEdidType);
        if (LINK_PORT_INDEX_DP_RX0 == enMwPortIndex)
        {
            eRet = eStat;
        }
#endif
#if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID)
        eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_DP_RX1, enDpEdidType);
        if (LINK_PORT_INDEX_DP_RX1 == enMwPortIndex)
        {
            eRet = eStat;
        }
#endif
        return eRet;
    }
    else if (PXP_MODE_PIP_ENABLE == enPxpMode)
    {
        HV_LOG_DEBUG(CHANNEL, "Update EDID,PIP,Vrr %u,Channel %u", bVrrEn, pstChannelData->enChannelType);

        if (enMwPortIndex == LINK_PORT_INDEX_HDMI_RX0 || enMwPortIndex == LINK_PORT_INDEX_HDMI_RX1)
        {
            // hdmi已经拉了hpd，此处不处理
            return HV_SUCCESS;
        }

        if (CHANNEL_TYPE_SUB == pstChannelData->enChannelType)
        {
            return (pstInputPortManager->pfUpdateEdid(enMwPortIndex, EDID_TYPE_PIP));
        }
        else
        {
            EDIDType enDpEdidType = (bVrrEn > 0) ? (EDID_TYPE_ADAPTIVESYNC  | EDID_TYPE_CLOSE_HDR) : (EDID_TYPE_DEFAULT | EDID_TYPE_CLOSE_HDR);
            if ((LINK_PORT_INDEX_DP_RX0 == enMwPortIndex) || (LINK_PORT_INDEX_DP_RX1 == enMwPortIndex))
            {
                return (pstInputPortManager->pfUpdateEdid(enMwPortIndex, enDpEdidType));
            }
        }
    }
    else if (PXP_MODE_PBP_ENABLE == enPxpMode)
    {
        HV_LOG_DEBUG(CHANNEL, "Update EDID,PBP,Vrr %u,Channel %u", bVrrEn, pstChannelData->enChannelType);

#if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
        eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_DP_RX0, EDID_TYPE_PBP);
        if (LINK_PORT_INDEX_DP_RX0 == enMwPortIndex)
        {
            eRet = eStat;
        }
#endif
#if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID)
        eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_DP_RX1, EDID_TYPE_PBP);
        if (LINK_PORT_INDEX_DP_RX1 == enMwPortIndex)
        {
            eRet = eStat;
        }
#endif
        return eRet;
    }
    else
    {
        HV_LOG_DEBUG(CHANNEL, "Update EDID,Magnifyglass,Vrr %u,Channel %u", bVrrEn, pstChannelData->enChannelType);

#if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
        eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_DP_RX0, enDpEdidType);
        if (LINK_PORT_INDEX_DP_RX0 == enMwPortIndex)
        {
            eRet = eStat;
        }
#endif
#if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID)
        eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_DP_RX1, enDpEdidType);
        if (LINK_PORT_INDEX_DP_RX1 == enMwPortIndex)
        {
            eRet = eStat;
        }
#endif
        return eRet;
    }
#else

#if (HV_BOARD_CONFIG_DISPLAYPORT_0 == PORT_VALID)
    eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_DP_RX0, enDpEdidType);
    if (LINK_PORT_INDEX_DP_RX0 == enMwPortIndex)
    {
        eRet = eStat;
    }
#endif
#if (HV_BOARD_CONFIG_DISPLAYPORT_1 == PORT_VALID)
    eStat = pstInputPortManager->pfUpdateEdid(LINK_PORT_INDEX_DP_RX1, enDpEdidType);
    if (LINK_PORT_INDEX_DP_RX1 == enMwPortIndex)
    {
        eRet = eStat;
    }
#endif
    return eRet;
#endif

    return HV_SUCCESS;
}

