//<MStar Software>
//******************************************************************************
// MStar Software
// Copyright (c) 2010 - 2012 MStar Semiconductor, Inc. All rights reserved.
// All software, firmware and related documentation herein ("MStar Software") are
// intellectual property of MStar Semiconductor, Inc. ("MStar") and protected by
// law, including, but not limited to, copyright law and international treaties.
// Any use, modification, reproduction, retransmission, or republication of all
// or part of MStar Software is expressly prohibited, unless prior written
// permission has been granted by MStar.
//
// By accessing, browsing and/or using MStar Software, you acknowledge that you
// have read, understood, and agree, to be bound by below terms ("Terms") and to
// comply with all applicable laws and regulations:
//
// 1. MStar shall retain any and all right, ownership and interest to MStar
//    Software and any modification/derivatives thereof.
//    No right, ownership, or interest to MStar Software and any
//    modification/derivatives thereof is transferred to you under Terms.
//
// 2. You understand that MStar Software might include, incorporate or be
//    supplied together with third party`s software and the use of MStar
//    Software may require additional licenses from third parties.
//    Therefore, you hereby agree it is your sole responsibility to separately
//    obtain any and all third party right and license necessary for your use of
//    such third party`s software.
//
// 3. MStar Software and any modification/derivatives thereof shall be deemed as
//    MStar`s confidential information and you agree to keep MStar`s
//    confidential information in strictest confidence and not disclose to any
//    third party.
//
// 4. MStar Software is provided on an "AS IS" basis without warranties of any
//    kind. Any warranties are hereby expressly disclaimed by MStar, including
//    without limitation, any warranties of merchantability, non-infringement of
//    intellectual property rights, fitness for a particular purpose, error free
//    and in conformity with any international standard.  You agree to waive any
//    claim against MStar for any loss, damage, cost or expense that you may
//    incur related to your use of MStar Software.
//    In no event shall MStar be liable for any direct, indirect, incidental or
//    consequential damages, including without limitation, lost of profit or
//    revenues, lost or damage of data, and unauthorized system use.
//    You agree that this Section 4 shall still apply without being affected
//    even if MStar Software has been modified by MStar in accordance with your
//    request or instruction for your use, except otherwise agreed by both
//    parties in writing.
//
// 5. If requested, MStar may from time to time provide technical supports or
//    services in relation with MStar Software to you for your use of
//    MStar Software in conjunction with your or your customer`s product
//    ("Services").
//    You understand and agree that, except otherwise agreed by both parties in
//    writing, Services are provided on an "AS IS" basis and the warranty
//    disclaimer set forth in Section 4 above shall apply.
//
// 6. Nothing contained herein shall be construed as by implication, estoppels
//    or otherwise:
//    (a) conferring any license or right to use MStar name, trademark, service
//        mark, symbol or any other identification;
//    (b) obligating MStar or any of its affiliates to furnish any person,
//        including without limitation, you and your customers, any assistance
//        of any kind whatsoever, or any information; or
//    (c) conferring any license or right under any intellectual property right.
//
// 7. These terms shall be governed by and construed in accordance with the laws
//    of Taiwan, R.O.C., excluding its conflict of law rules.
//    Any and all dispute arising out hereof or related hereto shall be finally
//    settled by arbitration referred to the Chinese Arbitration Association,
//    Taipei in accordance with the ROC Arbitration Law and the Arbitration
//    Rules of the Association by three (3) arbitrators appointed in accordance
//    with the said Rules.
//    The place of arbitration shall be in Taipei, Taiwan and the language shall
//    be English.
//    The arbitration award shall be final and binding to both parties.
//
//******************************************************************************
//<MStar Software>
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006-2009 MStar Semiconductor, Inc.
// All rights reserved.
//
// Unless otherwise stipulated in writing, any and all information contained
// herein regardless in any format shall remain the sole proprietary of
// MStar Semiconductor Inc. and be kept in strict confidence
// (¡§MStar Confidential Information¡¨) by the recipient.
// Any unauthorized act including without limitation unauthorized disclosure,
// copying, use, reproduction, sale, distribution, modification, disassembling,
// reverse engineering and compiling of the contents of MStar Confidential
// Information is unlawful and strictly prohibited. MStar hereby reserves the
// rights to any and all damages, losses, costs and expenses resulting therefrom.
//
////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////
///
/// file    apiXC_PCMonitor.c
/// @brief  Scaler API layer Interface
/// @author MStar Semiconductor Inc.
///////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef MSOS_TYPE_NUTTX

#ifndef _API_XC_PC_MONITOR_C_
#define _API_XC_PC_MONITOR_C_

//-------------------------------------------------------------------------------------------------
//  Include Files
//-------------------------------------------------------------------------------------------------
// Common Definition
#define PCMSG(x)    //x

// Common
#ifdef MSOS_TYPE_LINUX_KERNEL
#include <linux/string.h>
#include <asm/div64.h>
#else
#include <string.h>
#define do_div(x,y) ((x)/=(y))
#endif
#include "MsCommon.h"
#include "utopia.h"
#include "utopia_dapi.h"
// Driver
#include "drvXC_IOPort.h"
#include "mhal_xc_chip_config.h"
#include "xc_hwreg_utility2.h"
#include "apiXC.h"
#include "drvXC_HDMI_Internal.h"
#include "drvXC_HDMI_if.h"
#include "mhal_hdmi.h"
#include "mhal_ip.h"
#include "apiXC_Adc.h"
#include "apiXC_Auto.h"
#include "drv_sc_display.h"
#include "drv_sc_isr.h"
#include "apiXC_PCMonitor.h"
#include "apiXC_ModeParse.h"
#include "mhal_xc_chip_config.h"
#include "mvideo_context.h"
#include "drv_sc_ip.h"
#include "drv_sc_mux.h"
#if (LD_ENABLE==1)
#include "mdrv_ld.h"
#include "mdrv_ldalgo.h"
#endif
#include "mdrv_sc_3d.h"
#include "drv_sc_menuload.h"
#include "drvXC_ADC_Internal.h"
#include "mhal_sc.h"
#if FRC_INSIDE
#include "mdrv_frc.h"
#include "mhal_frc.h"
#endif
#include "XC_private.h"
#include "apiXC_v2.h"
#include "drv_sc_scaling.h"
#include "apiXC_PCMonitor_v2.h"
#include "mhal_mux.h"

//-------------------------------------------------------------------------------------------------
//  Driver Compiler Options
//-------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------
//  Local Defines
//-------------------------------------------------------------------------------------------------

#define PC_POLLING_COUNTER          30  // (30/TIMER_PERIOD), unit ms

#define MD_TIMING_SOG_DETECT        20
#if 1//(INPUT_HDMI_VIDEO_COUNT > 0)
  #if 1
    // Change these count value just for HDMI fast to recover video,
    // But have to delay 200mSec to reduce flash blue screen when plug-in/out HDMI fast,
    #define MD_TIMING_STABLE_COUNT    (MDrv_XC_PCMonitor_GetStableCounter(pInstance, eWindow))
    #define MD_TIMING_NOSYNC_COUNT    (MDrv_XC_PCMonitor_GetNoSyncCounter(pInstance, eWindow))
  #else
    #define MD_TIMING_STABLE_COUNT    (((IsSrcTypeHDMI(psPCMONITOR_HK_Info[eWindow]->eCurrentSrc)?120:25))
    #define MD_TIMING_NOSYNC_COUNT    (((IsSrcTypeHDMI(psPCMONITOR_HK_Info[eWindow]->eCurrentSrc)?80:40))
  #endif
#else
    #define MD_TIMING_STABLE_COUNT    25 // input timing stable counter
    #define MD_TIMING_NOSYNC_COUNT    40
#endif

#define TIMING_CHANGE_DEBOUNCE_FOR_STR 3
#define QUICKSTABLECNT_HFR  (2)

//-------------------------------------------------------------------------------------------------
//  Local Structurs
//-------------------------------------------------------------------------------------------------
static INPUT_SOURCE_TYPE_t _geSubCurrentSrc = INPUT_SOURCE_NONE;
static INPUT_SOURCE_TYPE_t _geMainCurrentSrc = INPUT_SOURCE_NONE;

//-------------------------------------------------------------------------------------------------
//  Global Variables
//-------------------------------------------------------------------------------------------------
#if (defined(MSOS_TYPE_LINUX_KERNEL) && defined(CONFIG_MSTAR_XC_HDR_SUPPORT))
extern MS_BOOL KDrv_XC_SetHdmiShareMemInfo(ST_KDRV_HDMI_SHARE_MEMORY_INFO *pstShmemInfo);
#endif
//-------------------------------------------------------------------------------------------------
//  Local Variables
//-------------------------------------------------------------------------------------------------
static MS_S64 _gs64PcStableSyncTimeStart = 0;
static MS_S64 _gs64PcStableSyncTimeEnd = 0;

//-------------------------------------------------------------------------------------------------
//  Debug Functions
//-------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------
//  Local Functions
//-------------------------------------------------------------------------------------------------

//*************************************************************************
//Function name:    _MApi_XC_PCMonitor_SetSyncStatusFlag
//Passing parameter:    MS_U8 u8TempSyncStatus:    b0: VSync polarity
//                                      b1: HSync polarity
//                                      b2: Hsync active
//                                      b3: Vsync active
//Return parameter: none
//Description:          Set signal sync status flags
//*************************************************************************
static void _MApi_XC_PCMonitor_SetSyncStatusFlag (void *pInstance, MS_U8 u8TempSyncStatus, SCALER_WIN eWindow, INPUT_SOURCE_TYPE_t enSrcType)
{
    XC_PCMONITOR_HK_INFO stPCMonitorInfo;
    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, enSrcType);
    stPCMonitorInfo.u8SyncStatus = u8TempSyncStatus;
    MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, enSrcType);
}

//*************************************************************************
//------------------------------ Warning ----------------------------------
//Attention: !!!!!!------ Don't add UI variable or unneeded code in this file
//
//           Don't modify this procedure !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//*************************************************************************
//*************************************************************************
//Function name:    _MApi_XC_PCMonitor_DetectSync
//Passing parameter:    none
//Return parameter: MS_BOOL:  true: sync loss    false: sync active
//Description:          Get signal sync status, true for sync loss, false for sync active
//*************************************************************************
static MS_BOOL _MApi_XC_PCMonitor_DetectSync (void *pInstance, INPUT_SOURCE_TYPE_t eCurrentSrc , SCALER_WIN eWindow )
{
    PCMSG(static MS_BOOL bSyncLoss = TRUE);

    MS_BOOL bResult = FALSE;
    XC_IP_SYNC_STATUS sXC_Sync_Status;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    XC_RESOURCE_PRIVATE* pXCResourcePrivate = NULL;
    UtopiaResourceGetPrivate(g_pXCResource[_XC_SELECT_INTERNAL_VARIABLE(psXCInstPri->u32DeviceID)],(void**)(&pXCResourcePrivate));
    XC_PCMONITOR_HK_INFO stPCMonitorInfo;
    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, eCurrentSrc);
    memset(&sXC_Sync_Status, 0, sizeof(XC_IP_SYNC_STATUS));

#if (XC_SUPPORT_FASTSWITCH_BY_IP1GP==TRUE)
    MHal_XC_SetOfflineSource(pInstance, eWindow, eCurrentSrc);
#endif

    if(MDrv_XC_IsFSSEnabled(pInstance, eWindow) && (eWindow == MAX_WINDOW)) // for offline detect
    {
        MDrv_XC_GetSyncStatus(pInstance, eCurrentSrc, &sXC_Sync_Status, eWindow);
    }
    else
    {
        _XC_ENTRY(pInstance);
        MDrv_XC_GetSyncStatus(pInstance, eCurrentSrc, &sXC_Sync_Status, eWindow);
        _XC_RETURN(pInstance);
    }
    if ( sXC_Sync_Status.u8SyncStatus & XC_MD_SYNC_LOSS ) // check no signal
    {
        PCMSG(if(!bSyncLoss) printf("XC_MD_SYNC_LOSS 0x%x\n", sXC_Sync_Status.u8SyncStatus); bSyncLoss = TRUE);

        if( IsSrcTypeVga(eCurrentSrc) || IsSrcTypeYPbPr(eCurrentSrc))
        {
            MDrv_ADC_ISOG_SetDetectMode(pInstance, E_ADC_ISOG_STANDBY_MODE);
        }

        if (MDrv_XC_GetVGASogEn(pInstance))   // Daten FixMe -> Please refine VGA SOG flow
        {
            if( IsSrcTypeVga(eCurrentSrc)&&
                ((stPCMonitorInfo.ucInputTimingStableCounter % MD_TIMING_SOG_DETECT)==0))
            {
                Hal_SC_ip_sog_detect(pInstance); // toggle analog input and detect next time
            }
        }

        if (pXCResourcePrivate->stdrvXC_MVideo_Context._bEnableEuro)
        {
            if( IsSrcTypeYPbPr(eCurrentSrc) )
            {
                MApi_XC_EuroHdtvHandler(pInstance, eWindow, eCurrentSrc);
            }
            else
            {
                MDrv_XC_HWAuto_SyncSeparate(pInstance, eWindow, eCurrentSrc);
            }
        }
    }
    else // have signal
    {

        if (MDrv_XC_GetVGASogEn(pInstance))   // Daten FixMe -> Please refine VGA SOG flow
        {
            if(eWindow != MAX_WINDOW)
            {
                _XC_ENTRY(pInstance);
            }
            if( IsSrcTypeVga(eCurrentSrc)&&
                ((stPCMonitorInfo.ucInputTimingStableCounter % MD_TIMING_SOG_DETECT)==0)
#if (XC_SUPPORT_FASTSWITCH_BY_IP1GP==TRUE)
                 && (SC_R2BYTEMSK(psXCInstPri->u32DeviceID,MHal_XC_FSS_BankTransfer(pInstance, REG_SC_BK01_02_L, eWindow),0x70)!=0x70)
#else
                 && (SC_R2BYTEMSK(psXCInstPri->u32DeviceID,REG_SC_BK01_02_L,0x70)!=0x70)
#endif
                 && (stPCMonitorInfo.ucInputTimingStableCounter <=0x14))
            {
                Hal_SC_ip_sog_detect(pInstance); // toggle analog input and detect next time
            }
            if(eWindow != MAX_WINDOW)
            {
                _XC_RETURN(pInstance);
            }
        }

        bResult = TRUE;

        if( IsSrcTypeVga(eCurrentSrc) || IsSrcTypeYPbPr(eCurrentSrc))
        {
            MDrv_ADC_ISOG_SetDetectMode(pInstance, E_ADC_ISOG_NORMAL_MODE);
        }

        PCMSG(if(bSyncLoss) printf("MD_SYNC_DETECT 0x%x\n", sXC_Sync_Status.u8SyncStatus); bSyncLoss = FALSE);
    }

    if ( bResult ) // neet to update flag
    {
        _MApi_XC_PCMonitor_SetSyncStatusFlag(pInstance, sXC_Sync_Status.u8SyncStatus, eWindow, eCurrentSrc);
    } // set global sync status flag

    return bResult;
}

// If IP1 detect P mode, but IPM set I mode for 3D FramePacking I 60/50hz.
// It is possible IPM detect wrong field from IP2. Only for A5/A3 serial scaler.
// Affected chips
//               Old Patch Method: Force interlace
//                                 A3/A5/A6/Agate U01/Eagle U01/J2
//               New Patch Method: Register REG_SC_BK12_05[10] to let HW auto force i
//                                 Agate U02/Edison/Eagle U02/Emerald/Kaiser/Macaw12
//
static void _MApi_XC_PCMonitor_FPi_Patch(void *pInstance, SCALER_WIN eWindow, INPUT_SOURCE_TYPE_t enSrcType)
{
    MS_WINDOW_TYPE sWin;
    memset(&sWin, 0 , sizeof(MS_WINDOW_TYPE));

    if (MDrv_SC_Get_DE_Bypass_Mode(pInstance, eWindow, enSrcType) == FALSE)
    {
        if(MDrv_XC_IsFSSEnabled(pInstance, eWindow) && (eWindow == MAX_WINDOW))
        {
            MDrv_XC_GetDEWindow(pInstance, &sWin, eWindow, enSrcType);
        }
        else
        {
            _XC_ENTRY(pInstance);
            MDrv_XC_GetDEWindow(pInstance, &sWin, eWindow, enSrcType);
            _XC_RETURN(pInstance);
        }
    }
    else
    {
        if(eWindow != MAX_WINDOW)
        {
            MDrv_XC_GetDEWidthHeightInDEByPassMode(pInstance, &sWin.width, &sWin.height, eWindow, enSrcType);
        }
    }

    if(eWindow != MAX_WINDOW)
    {
        // Check DE for framepacking I
        if ( ( sWin.height >  ( DOUBLEHD_1080X2I_VSIZE - 5) )
               && ( sWin.height <  ( DOUBLEHD_1080X2I_VSIZE + 5) )
               && ( sWin.width <  ( DOUBLEHD_1080X2I_HSIZE + 5) )
               && ( sWin.width >  ( DOUBLEHD_1080X2I_HSIZE - 5) ) )
        {
            MDrv_SC_ForceInterlaceInPMode(pInstance, ENABLE, eWindow, enSrcType);
            MsOS_DelayTask(150);
        }
    }
}

static void _MApi_XC_PCMonitor_InitRegInTimingChange(void *pInstance, SCALER_WIN eWindow, INPUT_SOURCE_TYPE_t enSrcType)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    XC_RESOURCE_PRIVATE* pXCResourcePrivate = NULL;
    UtopiaResourceGetPrivate(g_pXCResource[_XC_SELECT_INTERNAL_VARIABLE(psXCInstPri->u32DeviceID)],(void**)(&pXCResourcePrivate));

    XC_PCMONITOR_HK_INFO stPCMonitorInfo;
    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, enSrcType);
    if((IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc) || IsSrcTypeDVI(stPCMonitorInfo.eCurrentSrc))
        && eWindow != MAX_WINDOW)
    {
        //ToDo HDMI
        Hal_HDMI_audio_output(DISABLE);
        if ( MDrv_SC_GetInterlaceInPModeStatus(pInstance, eWindow, enSrcType) )
        {
            MDrv_SC_ForceInterlaceInPMode(pInstance, DISABLE,eWindow, enSrcType);
        }
    }
    if(eWindow != MAX_WINDOW)
    {
        _XC_ENTRY(pInstance);
    }
    if(eWindow == MAIN_WINDOW || (MDrv_XC_IsFSSEnabled(pInstance, eWindow) && (eWindow == MAX_WINDOW)))
    {
        if(eWindow == MAX_WINDOW)
        {
            if(pXCResourcePrivate->stdrvXC_MVideo_Context.enFSSSrcType != stPCMonitorInfo.eCurrentSrc)
            {
                //prevent from offline ipreset when online is the same source
                MDrv_XC_SoftwareReset(pInstance, REST_IP_F2, eWindow, stPCMonitorInfo.eCurrentSrc);
            }
        }
        else
        {
            MDrv_XC_SoftwareReset(pInstance, REST_IP_F2, eWindow, stPCMonitorInfo.eCurrentSrc);
        }
    }
    else
    {
        MDrv_XC_SoftwareReset(pInstance, REST_IP_F1, eWindow, stPCMonitorInfo.eCurrentSrc);
    }
    if(eWindow != MAX_WINDOW)
    {
        _XC_RETURN(pInstance);
    }
// 20081226 - DVI+HDCP snow noise patch - start ...
//Note: Don't use rest function after HPD Hi/Low or it will cause snow image in a while.
//    MDrv_XC_ADC_reset(REST_DVI|REST_HDCP|REST_HDMI); // Bright20080918
// 20081226 - DVI+HDCP snow noise patch - end ...
    MApi_XC_TimingChangeInit(pInstance, eWindow, stPCMonitorInfo.eCurrentSrc);

    if(IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc))
    {
        MApi_XC_VsyncPolarityDetectMode(pInstance, ENABLE, eWindow, stPCMonitorInfo.eCurrentSrc);
    }
    else
    {
        MApi_XC_VsyncPolarityDetectMode(pInstance, DISABLE, eWindow, stPCMonitorInfo.eCurrentSrc);
    }
}

//*************************************************************************
//------------------------------ Warning ----------------------------------
//Attention: !!!!!!------ Don't add UI variable or unneeded code in this file
//
//           Don't modify this procedure !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//*************************************************************************
//*************************************************************************
//Function name:    _MApi_XC_PCMonitor_PrepareForTimingChange
//Passing parameter:    none
//Return parameter:     none
//Description:  This function will pre-set flags and registers for timing change
//*************************************************************************
static void _MApi_XC_PCMonitor_PrepareForTimingChange(void *pInstance, SCALER_WIN eWindow, INPUT_SOURCE_TYPE_t enSrcType)
{
    // variables and structures
    XC_PCMONITOR_HK_INFO stPCMonitorInfo;

    PCMSG(printf("PrepareForTimingChange\n"));
    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, enSrcType);

    if ( stPCMonitorInfo.bInputTimingStable )
    {
        if(IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc) || IsSrcTypeDVI(stPCMonitorInfo.eCurrentSrc))
        {
            MS_BOOL bTimingStable = FALSE;

            // get hdmi signal status
            bTimingStable = MDrv_XC_PCMonitor_HDMISignalStable(pInstance, stPCMonitorInfo.eCurrentSrc);
            if(bTimingStable == TRUE)
            {
                // reset input timing stable and wait for timing stable
                stPCMonitorInfo.bInputTimingStable = FALSE;
                PCMSG(printf("window : %d, HDMI ipreset\n", eWindow));

                _MApi_XC_PCMonitor_InitRegInTimingChange(pInstance, eWindow, enSrcType);

                if(eWindow == MAIN_WINDOW)
                {
#if (defined(MSOS_TYPE_LINUX_KERNEL) && defined(CONFIG_MSTAR_XC_HDR_SUPPORT))
                    ST_KDRV_HDMI_SHARE_MEMORY_INFO stHdmiShareMemInfo;
                    memset(&stHdmiShareMemInfo, 0, sizeof(ST_KDRV_HDMI_SHARE_MEMORY_INFO));
                    stHdmiShareMemInfo.bIsStartEmpDma= TRUE;

                    KDrv_XC_SetHdmiShareMemInfo(&stHdmiShareMemInfo);
#endif
                }
            }
            else
            {
                PCMSG(printf("HDMI timing in unstable\n"));
                PCMSG(printf("window : %d, bTimingStable : %d\n", eWindow, bTimingStable));
                stPCMonitorInfo.bInputTimingChange = TRUE;
            }
        }
        else
        {
            // reset input timing stable and wait for timing stable
            stPCMonitorInfo.bInputTimingStable = FALSE;

            _MApi_XC_PCMonitor_InitRegInTimingChange(pInstance, eWindow, enSrcType);
        }
    }

    // reset timing stable counter
    stPCMonitorInfo.ucInputTimingStableCounter = 0;

    if( IsSrcTypeYPbPr(stPCMonitorInfo.eCurrentSrc) || IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc) || IsSrcTypeDVI(stPCMonitorInfo.eCurrentSrc))
    {
        MApi_XC_InitRegInTimingChange_Post(pInstance, stPCMonitorInfo.u8SyncStatus, eWindow, enSrcType);
    }

    MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, enSrcType);
}

/*
void _MApi_XC_PCMonitor_ModeParse(SCALER_WIN eWindow)
{


    // to match mode, we need these information
    // H/V freq., Vtt
    // Sync polarity
    // Interlaced or Progrssive
    psPCMONITOR_HK_Info[eWindow]->sModeParseInputInfo.eSrcType = psPCMONITOR_HK_Info[eWindow]->eCurrentSrc;
    psPCMONITOR_HK_Info[eWindow]->sModeParseInputInfo.u16HFreqx10 = MApi_XC_CalculateHFreqx10(psPCMONITOR_HK_Info[eWindow]->u16Hperiod);
    psPCMONITOR_HK_Info[eWindow]->sModeParseInputInfo.u16VFreqx10 = MApi_XC_CalculateVFreqx10(psPCMONITOR_HK_Info[eWindow]->sModeParseInputInfo.u16HFreqx10, psPCMONITOR_HK_Info[eWindow]->u16Vtotal);

    if(psPCMONITOR_HK_Info[eWindow]->u8SyncStatus & XC_MD_INTERLACE_BIT)
    {
        psPCMONITOR_HK_Info[eWindow]->sModeParseInputInfo.u16VFreqx10 *=2;
    }

    psPCMONITOR_HK_Info[eWindow]->sModeParseInputInfo.u16Vtotal = psPCMONITOR_HK_Info[eWindow]->u16Vtotal;
    psPCMONITOR_HK_Info[eWindow]->sModeParseInputInfo.u8SyncStatus = psPCMONITOR_HK_Info[eWindow]->u8SyncStatus;
    //psPCMONITOR_HK_Info[eWindow]->sModeParseInputInfo.eEuroHDTVStatus = EURO_AUS_HDTV_NORMAL;
    memcpy(&(psPCMONITOR_HK_Info[eWindow]->sModeParseInputInfo.sDVI_HDMI_DE_Info), &(psPCMONITOR_HK_Info[eWindow]->sDVI_HDMI_DE_Info), sizeof(MS_WINDOW_TYPE));

#if (INPUT_HDMI_VIDEO_COUNT > 0)
    // search mode
    if(IsSrcTypeHDMI(psPCMONITOR_HK_Info[eWindow]->eCurrentSrc))
    {
        // check if HDMI or DVI
        MApi_XC_HDMI_CheckModeChanged(TRUE);
    }
#endif

    psPCMONITOR_HK_Info[eWindow]->eModeParseResult = MApi_XC_ModeParse_SearchMode(&(psPCMONITOR_HK_Info[eWindow]->sModeParseInputInfo));

    if(psPCMONITOR_HK_Info[eWindow]->sModeParseInputInfo.u8SyncStatus & XC_MD_USER_MODE_BIT)
    {
        // mode parse indicate this is a user mode
        psPCMONITOR_HK_Info[eWindow]->u8SyncStatus |= XC_MD_USER_MODE_BIT;
    }

    if(psPCMONITOR_HK_Info[eWindow]->eModeParseResult == XC_MODEPARSE_SUPPORT_MODE)
    {
        psPCMONITOR_HK_Info[eWindow]->eCurrentState = E_XC_PCMONITOR_STABLE_SUPPORT_MODE;
    }
    else
    {
        psPCMONITOR_HK_Info[eWindow]->eCurrentState = E_XC_PCMONITOR_STABLE_UN_SUPPORT;
    }
}
*/

//-------------------------------------------------------------------------------------------------
//  Global Functions
//-------------------------------------------------------------------------------------------------

//*************************************************************************
//Function name:    MApi_XC_PCMonitor_InvalidTimingDetect
//Passing parameter:    none
//Return parameter: MS_BOOL : timing is valid or not
//Description:          Detect invalid timing. true: timing invalid   false : timing valid
//*************************************************************************
MS_BOOL MApi_XC_PCMonitor_InvalidTimingDetect_U2( void* pInstance, MS_BOOL bPollingOnly, SCALER_WIN eWindow)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    MS_BOOL bReturn = FALSE;
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    _XC_ENTRY(pInstance);
    MDrv_XC_CheckSubWinForFSS(pInstance, &eWindow);
    if(eWindow == MAIN_WINDOW)
    {
        bReturn = MDrv_XC_PCMonitor_InvalidTimingDetect(pInstance, bPollingOnly, eWindow, _geMainCurrentSrc);
    }
    else
    {
        bReturn = MDrv_XC_PCMonitor_InvalidTimingDetect(pInstance, bPollingOnly, eWindow, _geSubCurrentSrc);
    }
    _XC_RETURN(pInstance);
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    return bReturn;
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
MS_BOOL MApi_XC_PCMonitor_InvalidTimingDetect(  MS_BOOL bPollingOnly, SCALER_WIN eWindow)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return FALSE;
    }

    stXC_PCMONITOR_INVALIDTIMINGDETECT XCArgs;
    XCArgs.bPollingOnly = bPollingOnly;
    XCArgs.eWindow = eWindow;
    XCArgs.bReturnValue = FALSE;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_INVALIDTIMINGDETECT, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return FALSE;
    }
    else
    {
        return XCArgs.bReturnValue;
    }
}
#endif
void MApi_XC_PCMonitor_Restart_U2(void* pInstance, SCALER_WIN eWindow)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    MDrv_XC_CheckSubWinForFSS(pInstance, &eWindow);
    if(eWindow != MAX_WINDOW)
    {
        MDrv_XC_PCMonitor_Restart(pInstance, eWindow, INPUT_SOURCE_NONE);
    }
    _XC_ENTRY(pInstance);
    MDrv_DVI_Accumulator_Monitor();
    _XC_RETURN(pInstance);

    if(eWindow == MAIN_WINDOW)
    {
        _gs64PcStableSyncTimeStart = 0;
        _gs64PcStableSyncTimeEnd = 0;
    }

    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
void MApi_XC_PCMonitor_Restart(SCALER_WIN eWindow)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return;
    }

    stXC_PCMONITOR_RESTART XCArgs;
    XCArgs.eWindow = eWindow;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_RESTART, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return;
    }
    else
    {
        return;
    }
}
#endif
MS_BOOL MApi_XC_PCMonitor_Init_U2(void* pInstance, MS_U8 u8MaxWindowNum)
{
    MS_U8 i;
    SCALER_WIN eWindow = MAIN_WINDOW;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    XC_RESOURCE_PRIVATE* pXCResourcePrivate = NULL;
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    UtopiaResourceGetPrivate(g_pXCResource[_XC_SELECT_INTERNAL_VARIABLE(psXCInstPri->u32DeviceID)],(void**)(&pXCResourcePrivate));
    // initialize House keeping info
    MDrv_XC_PCMonitor_Init(pInstance, u8MaxWindowNum);
    for(i = 0; i < u8MaxWindowNum; i++)
    {
        switch(i)
        {
            case 0:
                MDrv_XC_PCMonitor_Restart(pInstance, MAIN_WINDOW, INPUT_SOURCE_NONE);
                eWindow = MAIN_WINDOW;
                break;

            case 1:
                MDrv_XC_CheckSubWinForFSS(pInstance, &eWindow);
                MDrv_XC_PCMonitor_Restart(pInstance, eWindow, _geSubCurrentSrc);
                eWindow = SUB_WINDOW;
                break;

            default:
                // un-supported
                break;
        }

        pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter[eWindow] = MD_TIMING_STABLE_COUNT;
        pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter[eWindow] = MD_TIMING_NOSYNC_COUNT;
        pXCResourcePrivate->stdrvXC_IP.sPCMONITOR_status[eWindow].eCurrentSrc = INPUT_SOURCE_NONE;

    }
    pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_VGA = MD_TIMING_STABLE_COUNT;
    pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_VGA = MD_TIMING_NOSYNC_COUNT;
    pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_YPBPR = MD_TIMING_STABLE_COUNT;
    pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_YPBPR = MD_TIMING_NOSYNC_COUNT;
    pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_HDMI = MD_TIMING_STABLE_COUNT;
    pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_HDMI = MD_TIMING_NOSYNC_COUNT;
    _gs64PcStableSyncTimeStart = 0;
    _gs64PcStableSyncTimeEnd = 0;
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    return TRUE;
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
MS_BOOL MApi_XC_PCMonitor_Init(MS_U8 u8MaxWindowNum)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return FALSE;
    }

    stXC_PCMONITOR_INIT XCArgs;
    XCArgs.u8MaxWindowNum = u8MaxWindowNum;
    XCArgs.bReturnValue = FALSE;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_INIT, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return FALSE;
    }
    else
    {
        return XCArgs.bReturnValue;
    }
}
#endif

void MApi_XC_PCMonitor_SetTimingCount_U2(void* pInstance, MS_U16 u16TimingStableCounter, MS_U16 u16TimingNosyncCounter)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    XC_RESOURCE_PRIVATE* pXCResourcePrivate = NULL;
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    UtopiaResourceGetPrivate(g_pXCResource[_XC_SELECT_INTERNAL_VARIABLE(psXCInstPri->u32DeviceID)],(void**)(&pXCResourcePrivate));
    pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_VGA = u16TimingStableCounter;
    pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_VGA = u16TimingNosyncCounter;
    pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_YPBPR = u16TimingStableCounter;
    pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_YPBPR = u16TimingNosyncCounter;
    pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_HDMI = u16TimingStableCounter;
    pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_HDMI = u16TimingNosyncCounter;
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
void MApi_XC_PCMonitor_SetTimingCount(MS_U16 u16TimingStableCounter, MS_U16 u16TimingNosyncCounter)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return;
    }

    stXC_PCMONITOR_SETTIMINGCOUNT XCArgs;
    XCArgs.u16TimingStableCounter = u16TimingStableCounter;
    XCArgs.u16TimingNosyncCounter = u16TimingNosyncCounter;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_SETTIMINGCOUNT, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return;
    }
    else
    {
        return;
    }
}
#endif
E_APIXC_ReturnValue MApi_XC_PCMonitor_SetTimingCountEx_U2(void* pInstance, INPUT_SOURCE_TYPE_t eCurrentSrc, MS_U16 u16TimingStableCounter, MS_U16 u16TimingNosyncCounter)
{
    E_APIXC_ReturnValue eResult = E_APIXC_RET_FAIL;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    XC_RESOURCE_PRIVATE* pXCResourcePrivate = NULL;

    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    UtopiaResourceGetPrivate(g_pXCResource[_XC_SELECT_INTERNAL_VARIABLE(psXCInstPri->u32DeviceID)],(void**)(&pXCResourcePrivate));
    if (IsSrcTypeVga(eCurrentSrc))
    {
        pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_VGA = u16TimingStableCounter;
        pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_VGA = u16TimingNosyncCounter;
        eResult = E_APIXC_RET_OK;
    }
    else if (IsSrcTypeYPbPr(eCurrentSrc))
    {
        pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_YPBPR= u16TimingStableCounter;
        pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_YPBPR= u16TimingNosyncCounter;
        eResult = E_APIXC_RET_OK;
    }
    else if (IsSrcTypeHDMI(eCurrentSrc) || IsSrcTypeDVI(eCurrentSrc))
    {
        pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_HDMI= u16TimingStableCounter;
        pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_HDMI= u16TimingNosyncCounter;
        eResult = E_APIXC_RET_OK;
    }
    else
    {
        printf("<ATTENTION> Not support this source type for timing count setting ! \n");
        eResult = E_APIXC_RET_FAIL_INVALID_PARAMETER;
    }
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    return eResult;
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
E_APIXC_ReturnValue MApi_XC_PCMonitor_SetTimingCountEx(INPUT_SOURCE_TYPE_t eCurrentSrc, MS_U16 u16TimingStableCounter, MS_U16 u16TimingNosyncCounter)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return E_APIXC_RET_FAIL;
    }

    stXC_PCMONITOR_SETTIMINGCOUNTEX XCArgs;
    XCArgs.eCurrentSrc = eCurrentSrc;
    XCArgs.u16TimingStableCounter = u16TimingStableCounter;
    XCArgs.u16TimingNosyncCounter = u16TimingNosyncCounter;
    XCArgs.eReturnValue = E_APIXC_RET_FAIL;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_SETTIMINGCOUNTEX, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return E_APIXC_RET_FAIL;
    }
    else
    {
        return XCArgs.eReturnValue;
    }
}
#endif
XC_PCMONITOR_STATUS MApi_XC_PCMonitor_GetCurrentState_U2(void* pInstance, SCALER_WIN eWindow)
{
    XC_PCMONITOR_HK_INFO stPCMonitorInfo;
    XC_PCMONITOR_STATUS eReturn = E_XC_PCMONITOR_STABLE_NOSYNC;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    MDrv_XC_CheckSubWinForFSS(pInstance, &eWindow);
    if(eWindow == MAIN_WINDOW)
    {
        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, _geMainCurrentSrc);
    }
    else
    {
        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, _geSubCurrentSrc);
    }
    eReturn = stPCMonitorInfo.eCurrentState;
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    return eReturn;
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
XC_PCMONITOR_STATUS MApi_XC_PCMonitor_GetCurrentState(SCALER_WIN eWindow)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return E_XC_PCMONITOR_STABLE_NOSYNC;
    }

    stXC_PCMONITOR_GETCURRENTSTATE XCArgs;
    XCArgs.eWindow = eWindow;
    XCArgs.eReturnValue = E_XC_PCMONITOR_STABLE_NOSYNC;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_GETCURRENTSTATE, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return E_XC_PCMONITOR_STABLE_NOSYNC;
    }
    else
    {
        return XCArgs.eReturnValue;
    }
}
#endif
//*************************************************************************
//------------------------------ Warning ----------------------------------
//Attention: !!!!!!------ Don't add UI variable or unneeded code in this file
//
//           Don't modify this procedure !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//*************************************************************************
//*************************************************************************
//Function name:    MApi_XC_PCMonitor_SyncLoss
//Passing parameter:    none
//Return parameter: MS_BOOL:  true: sync loss    false: sync active
//Description:          Get signal sync status, true for sync loss, false for sync active
//*************************************************************************
MS_BOOL MApi_XC_PCMonitor_SyncLoss_U2(void* pInstance, SCALER_WIN eWindow)
{
    MS_BOOL bReturn = FALSE;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    MDrv_XC_CheckSubWinForFSS(pInstance, &eWindow);
    if(eWindow == MAIN_WINDOW)
    {
        bReturn = MDrv_XC_PCMonitor_SyncLoss(pInstance, eWindow, _geMainCurrentSrc);
    }
    else
    {
        bReturn = MDrv_XC_PCMonitor_SyncLoss(pInstance, eWindow, _geSubCurrentSrc);
    }
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    return bReturn;
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
MS_BOOL MApi_XC_PCMonitor_SyncLoss(SCALER_WIN eWindow)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return FALSE;
    }

    stXC_PCMONITOR_SYNCLOSS XCArgs;
    XCArgs.eWindow = eWindow;
    XCArgs.bReturnValue = FALSE;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_SYNCLOSS, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return FALSE;
    }
    else
    {
        return XCArgs.bReturnValue;
    }
}
#endif
MS_U8 MApi_XC_PCMonitor_GetSyncStatus_U2(void* pInstance, SCALER_WIN eWindow)
{
    XC_PCMONITOR_HK_INFO stPCMonitorInfo;
    MS_U8 u8Return = 0;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    MDrv_XC_CheckSubWinForFSS(pInstance, &eWindow);
    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, _geSubCurrentSrc);
    u8Return = stPCMonitorInfo.u8SyncStatus;
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    return u8Return;
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
MS_U8 MApi_XC_PCMonitor_GetSyncStatus(SCALER_WIN eWindow)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return 0;
    }

    stXC_PCMONITOR_GETSYNCSTATUS XCArgs;
    XCArgs.eWindow = eWindow;
    XCArgs.u8ReturnValue = 0;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_GETSYNCSTATUS, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return 0;
    }
    else
    {
        return XCArgs.u8ReturnValue;
    }
}
#endif
MS_U8 MDrv_XC_PCMonitor_GetVSyncTime(void *pInstance, SCALER_WIN eWindow, INPUT_SOURCE_TYPE_t enSrcType)
{
    XC_PCMONITOR_HK_INFO stPCMonitorInfo;
    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, enSrcType);

    if((stPCMonitorInfo.eCurrentState == E_XC_PCMONITOR_UNSTABLE) || (stPCMonitorInfo.eCurrentState == E_XC_PCMONITOR_STABLE_NOSYNC))
    {
        return 0;
    }
    else
    {
        return stPCMonitorInfo.u16VSyncTime;
    }
}
void MApi_XC_PCMonitor_Get_Dvi_Hdmi_De_Info_U2(void* pInstance, SCALER_WIN eWindow,MS_WINDOW_TYPE* msWin)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    MDrv_XC_CheckSubWinForFSS(pInstance, &eWindow);
    if(eWindow == MAIN_WINDOW)
    {
        MDrv_XC_PCMonitor_Get_Dvi_Hdmi_De_Info(pInstance, eWindow, msWin, _geMainCurrentSrc);
    }
    else
    {
        MDrv_XC_PCMonitor_Get_Dvi_Hdmi_De_Info(pInstance, eWindow, msWin, _geSubCurrentSrc);
    }
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
void MApi_XC_PCMonitor_Get_Dvi_Hdmi_De_Info(SCALER_WIN eWindow,MS_WINDOW_TYPE* msWin)
{
    stXC_PCMONITOR_GET_DVI_HDMI_DE_INFO XCArgs;
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return;
    }

    XCArgs.eWindow = eWindow;
    XCArgs.msWin = msWin;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_GET_DVI_HDMI_DE_INFO, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return;
    }
    else
    {
        return;
    }

}
#endif
MS_U16 MApi_XC_PCMonitor_Get_HFreqx10_U2(void* pInstance, SCALER_WIN eWindow)
{
    MS_U16 u16Return = 0;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    MDrv_XC_CheckSubWinForFSS(pInstance, &eWindow);
    if(eWindow == MAIN_WINDOW)
    {
        u16Return = MDrv_XC_PCMonitor_Get_HFreqx10(pInstance, eWindow, _geMainCurrentSrc);
    }
    else
    {
        u16Return = MDrv_XC_PCMonitor_Get_HFreqx10(pInstance, eWindow, _geSubCurrentSrc);
    }
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    return u16Return;
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
MS_U16 MApi_XC_PCMonitor_Get_HFreqx10(SCALER_WIN eWindow)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return 0;
    }

    stXC_PCMONITOR_GET_HFREQX10 XCArgs;
    XCArgs.eWindow = eWindow;
    XCArgs.u16ReturnValue = 0;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_GET_HFREQX10, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return 0;
    }
    else
    {
        return XCArgs.u16ReturnValue;
    }
}
#endif
MS_U32 MApi_XC_PCMonitor_Get_HFreqx1K_U2(void* pInstance, SCALER_WIN eWindow)
{
    XC_PCMONITOR_HK_INFO stPCMonitorInfo;
    MS_U32 u32HFreq = 0;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    MDrv_XC_CheckSubWinForFSS(pInstance, &eWindow);
    if(eWindow == MAIN_WINDOW)
    {
        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, _geMainCurrentSrc);
    }
    else
    {
        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, _geSubCurrentSrc);
    }
    if((stPCMonitorInfo.eCurrentState == E_XC_PCMONITOR_UNSTABLE) || (stPCMonitorInfo.eCurrentState == E_XC_PCMONITOR_STABLE_NOSYNC))
    {
        u32HFreq = 0;
    }
    else
    {
        u32HFreq = MDrv_XC_CalculateHFreqx1K(pInstance, stPCMonitorInfo.u16Hperiod);

    }
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    return u32HFreq;
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
MS_U32 MApi_XC_PCMonitor_Get_HFreqx1K(SCALER_WIN eWindow)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return 0;
    }

    stXC_PCMONITOR_GET_HFREQX1K XCArgs;
    XCArgs.eWindow = eWindow;
    XCArgs.u32ReturnValue = 0;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_GET_HFREQX1K, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return 0;
    }
    else
    {
        return XCArgs.u32ReturnValue;
    }
}
#endif
MS_U16 MDrv_XC_PCMonitor_Get_VFreqx10(void *pInstance, SCALER_WIN eWindow, INPUT_SOURCE_TYPE_t enSrcType)
{
    MS_U16 u16VFreq = 0, u16AccurateVFreq = 0;
    MS_U32 u32AccurateVPeriod = 0;
    XC_PCMONITOR_HK_INFO stPCMonitorInfo;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    XC_RESOURCE_PRIVATE* pXCResourcePrivate = NULL;
    UtopiaResourceGetPrivate(g_pXCResource[_XC_SELECT_INTERNAL_VARIABLE(psXCInstPri->u32DeviceID)],(void**)(&pXCResourcePrivate));
    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, enSrcType);

    if((stPCMonitorInfo.eCurrentState == E_XC_PCMONITOR_UNSTABLE) || (stPCMonitorInfo.eCurrentState == E_XC_PCMONITOR_STABLE_NOSYNC))
    {
        // Original return value is 1
        // Change to 1 to prevent 4K2K home screen (4K2K 30Hz) force SetPanelTiming with no signal cause core dump issue.
        return 1;
    }
    else
    {
        if(FALSE == (pXCResourcePrivate->stdrvXC_MVideo_Context.g_bFast_Get_VFreq))
        {
            u16VFreq = MDrv_XC_CalculateVFreqx10(pInstance, MDrv_XC_PCMonitor_Get_HFreqx10(pInstance, eWindow, enSrcType), stPCMonitorInfo.u16Vtotal);
            if(stPCMonitorInfo.u8SyncStatus& XC_MD_INTERLACE_BIT)
            {
                u16VFreq *= 2;
            }
            else
            {

                /// for more correct Vfreq to instead
                u32AccurateVPeriod = MDrv_SC_ip_get_verticalperiod(pInstance, eWindow, enSrcType);
                if(u32AccurateVPeriod != 0)
                {
                      u16AccurateVFreq = (MS_U16)((pXCResourcePrivate->stdrvXC_MVideo_Context.g_XC_InitData.u32XTAL_Clock * 10 +u32AccurateVPeriod /2) / u32AccurateVPeriod);
                }

                XC_LOG_TRACE(XC_DBGLEVEL_MODEPARSE, "InputVFreq=%u->%u, Tolerance=%u\n", u16VFreq, u16AccurateVFreq, (MS_U8)ACCURATE_VFREQ_TOLERANCE);
                if(abs(u16VFreq - u16AccurateVFreq) < ACCURATE_VFREQ_TOLERANCE)
                {
                    u16VFreq = u16AccurateVFreq; //In tolerance range, using new accurate vfreq
                }
            }
        }
        else
        {
            u16VFreq =(MS_U16)(stPCMonitorInfo.u32FrameRatex1K/100);
        }

        XC_LOG_TRACE(XC_DBGLEVEL_MODEPARSE, "Final VFreq=%tu \n", (ptrdiff_t)u16VFreq);
        return u16VFreq;
    }
}

MS_U16 MApi_XC_PCMonitor_Get_VFreqx10_U2(void* pInstance, SCALER_WIN eWindow)
{
    MS_U16 u16Return = 0;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    _XC_ENTRY(pInstance);
    MDrv_XC_CheckSubWinForFSS(pInstance, &eWindow);
    if(eWindow == MAIN_WINDOW)
    {
        u16Return = MDrv_XC_PCMonitor_Get_VFreqx10(pInstance, eWindow, _geMainCurrentSrc);
    }
    else
    {
        u16Return = MDrv_XC_PCMonitor_Get_VFreqx10(pInstance, eWindow, _geSubCurrentSrc);
    }
    _XC_RETURN(pInstance);
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    return u16Return;
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
MS_U16 MApi_XC_PCMonitor_Get_VFreqx10(SCALER_WIN eWindow)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return 0;
    }

    stXC_PCMONITOR_GET_VFREQX10 XCArgs;
    XCArgs.eWindow = eWindow;
    XCArgs.u16ReturnValue = 0;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_GET_VFREQX10, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return 0;
    }
    else
    {
        return XCArgs.u16ReturnValue;
    }
}
#endif
//comparing with MApi_XC_PCMonitor_Get_VFreqx1K, MDrv_XC_PCMonitor_Get_FrameRatex1K gets Frame rate without judging Input timing stable.
MS_U32 MDrv_XC_PCMonitor_Get_FrameRatex1K(void* pInstance, SCALER_WIN eWindow, INPUT_SOURCE_TYPE_t enSrcType)
{
    MS_U32 u32VFreq = 0, u32HFreq=0, u32AccurateVFreq = 0, u32AccurateVPeriod = 0 /*,u32PrevAccurateVPeriod = 0*/;
    MS_U64 u64XTALClk = 0;
    XC_PCMONITOR_HK_INFO stPCMonitorInfo;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    XC_RESOURCE_PRIVATE* pXCResourcePrivate = NULL;
    //MS_U8 u8VSyncTime=0, u8Count=0;
    UtopiaResourceGetPrivate(g_pXCResource[E_XC_POOL_ID_INTERNAL_VARIABLE],(void**)(&pXCResourcePrivate));
    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, enSrcType);
#if (XC_SUPPORT_FASTSWITCH_BY_IP1GP==TRUE)
    MHal_XC_SetOfflineSource(pInstance, eWindow, enSrcType);
#endif
    u32HFreq = MDrv_XC_CalculateHFreqx1K(pInstance, stPCMonitorInfo.u16Hperiod);
    u32VFreq = MDrv_XC_CalculateVFreqx1K(pInstance, u32HFreq, stPCMonitorInfo.u16Vtotal);
    if(stPCMonitorInfo.u8SyncStatus& XC_MD_INTERLACE_BIT)
    {
        u32VFreq *= 2;
    }
    else
    {
        u32AccurateVPeriod = HAL_SC_ip_get_verticalperiod(pInstance, eWindow);

        XC_LOG_TRACE(XC_DBGLEVEL_MODEPARSE, "u32AccurateVPeriod = %tu\n", (ptrdiff_t)u32AccurateVPeriod);

        if(u32AccurateVPeriod != 0)
        {
            u64XTALClk = (MS_U64)pXCResourcePrivate->stdrvXC_MVideo_Context.g_XC_InitData.u32XTAL_Clock * 1000;
            do_div(u64XTALClk,u32AccurateVPeriod);
            u32AccurateVFreq = (MS_U32)(u64XTALClk);
            //u32AccurateVFreq = (MS_U32)(u64XTALClk / u32AccurateVPeriod);
        }

        XC_LOG_TRACE(XC_DBGLEVEL_MODEPARSE, "u32AccurateVFreq = %tu, InputVFreq=%tu->%tu, Tolerance=%tu\n",
                (ptrdiff_t)u32AccurateVFreq, (ptrdiff_t)u32VFreq, (ptrdiff_t)u32AccurateVFreq, (ptrdiff_t)(ACCURATE_VFREQ_TOLERANCE * 100));

        if(abs(u32VFreq - u32AccurateVFreq) < ACCURATE_VFREQ_TOLERANCE * 100)
        {
            u32VFreq = u32AccurateVFreq; //In tolerance range, using new accurate vfreq
        }
    }
    XC_LOG_TRACE(XC_DBGLEVEL_MODEPARSE, "u32VFreq = %tu\n", (ptrdiff_t)u32VFreq);
    return u32VFreq;
}

MS_U32 MApi_XC_PCMonitor_Get_VFreqx1K_U2(void* pInstance, SCALER_WIN eWindow)
{
    MS_U32 u32VFreq = 0;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    _XC_ENTRY(pInstance);
    MDrv_XC_CheckSubWinForFSS(pInstance, &eWindow);
    if(eWindow == MAIN_WINDOW)
    {
        u32VFreq = MDrv_XC_PCMonitor_Get_VFreqx1K(pInstance, eWindow, _geMainCurrentSrc);
    }
    else
    {
        u32VFreq = MDrv_XC_PCMonitor_Get_VFreqx1K(pInstance, eWindow, _geSubCurrentSrc);
    }
    _XC_RETURN(pInstance);
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    return u32VFreq;
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
MS_U32 MApi_XC_PCMonitor_Get_VFreqx1K(SCALER_WIN eWindow)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return 0;
    }

    stXC_PCMONITOR_GET_VFREQX1K XCArgs;
    XCArgs.eWindow = eWindow;
    XCArgs.u32ReturnValue = 0;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_GET_VFREQX1K, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return 0;
    }
    else
    {
        return XCArgs.u32ReturnValue;
    }
}
#endif
MS_U16 MApi_XC_PCMonitor_Get_VFreqx10NoDelay_U2(void* pInstance, SCALER_WIN eWindow, EN_XC_PCMONITOR_VFREQ_CHECKING_TYPE eType)
{
    MS_U16 u16VFreq = 0;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    _XC_ENTRY(pInstance);
    MDrv_XC_CheckSubWinForFSS(pInstance, &eWindow);
    u16VFreq = MDrv_XC_PCMonitor_Get_VFreqx10NoDelay(pInstance, eWindow, eType, _geSubCurrentSrc);
    _XC_RETURN(pInstance);
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    return u16VFreq;
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
MS_U16 MApi_XC_PCMonitor_Get_VFreqx10NoDelay(SCALER_WIN eWindow, EN_XC_PCMONITOR_VFREQ_CHECKING_TYPE eType)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return 0;
    }

    stXC_PCMONITOR_GET_VFREQX10NODELAY XCArgs;
    XCArgs.eWindow = eWindow;
    XCArgs.u16ReturnValue = 0;
    XCArgs.eType = eType;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_GET_VFREQX10NODELAY, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return 0;
    }
    else
    {
        return XCArgs.u16ReturnValue;
    }
}
#endif
MS_U32 MApi_XC_PCMonitor_Get_VFreqx1KNoDelay_U2(void* pInstance, SCALER_WIN eWindow, EN_XC_PCMONITOR_VFREQ_CHECKING_TYPE eType)
{
    MS_U32 u32VFreq = 0;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    _XC_ENTRY(pInstance);
    MDrv_XC_CheckSubWinForFSS(pInstance, &eWindow);
    if(eWindow == MAIN_WINDOW)
    {
        u32VFreq = MDrv_XC_PCMonitor_Get_VFreqx1KNoDelay(pInstance, eWindow, eType, _geMainCurrentSrc);
    }
    else
    {
        u32VFreq = MDrv_XC_PCMonitor_Get_VFreqx1KNoDelay(pInstance, eWindow, eType, _geSubCurrentSrc);
    }
    _XC_RETURN(pInstance);
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    return u32VFreq;
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
MS_U32 MApi_XC_PCMonitor_Get_VFreqx1KNoDelay(SCALER_WIN eWindow, EN_XC_PCMONITOR_VFREQ_CHECKING_TYPE eType)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return 0;
    }

    stXC_PCMONITOR_GET_VFREQX1KNODELAY XCArgs;
    XCArgs.eWindow = eWindow;
    XCArgs.u32ReturnValue = 0;
    XCArgs.eType = eType;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_GET_VFREQX1KNODELAY, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return 0;
    }
    else
    {
        return XCArgs.u32ReturnValue;
    }
}
#endif

MS_BOOL MDrv_XC_PCMonitor_GetDEWidthHeightInDEByPassMode(void* pInstance, MS_U16* pu16Width, MS_U16* pu16Height, SCALER_WIN eWindow, INPUT_SOURCE_TYPE_t enSrcType)
{
    if(MDrv_SC_Get_DE_Bypass_Mode(pInstance, eWindow, enSrcType) == FALSE)
    {
        printf("[%s,%5d] Cannot get HV width and height under DE mode!! please check your xc lib!\n", __FUNCTION__,__LINE__);
        return FALSE;
    }
    XC_PCMONITOR_HK_INFO stPCMonitorInfo;
    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, enSrcType);

    MDrv_XC_GetDEWidthHeightInDEByPassMode(pInstance, pu16Width, pu16Height, eWindow, enSrcType);
    stPCMonitorInfo.sDVI_HDMI_DE_Info.width  = *pu16Width;
    stPCMonitorInfo.sDVI_HDMI_DE_Info.height = *pu16Height;
    MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, enSrcType);
    return TRUE;
}

MS_U16 MApi_XC_PCMonitor_Get_Vtotal_U2(void* pInstance, SCALER_WIN eWindow)
{
    MS_U16 u16Return = 0;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    MDrv_XC_CheckSubWinForFSS(pInstance, &eWindow);
    if(eWindow == MAIN_WINDOW)
    {
        u16Return = MDrv_XC_PCMonitor_Get_Vtotal(pInstance, eWindow, _geMainCurrentSrc);
    }
    else
    {
        u16Return = MDrv_XC_PCMonitor_Get_Vtotal(pInstance, eWindow, _geSubCurrentSrc);
    }
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    return  u16Return;
}
#ifndef UTOPIAXP_REMOVE_WRAPPER
MS_U16 MApi_XC_PCMonitor_Get_Vtotal(SCALER_WIN eWindow)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return 0;
    }

    stXC_PCMONITOR_GET_VTOTAL XCArgs;
    XCArgs.eWindow = eWindow;
    XCArgs.u16ReturnValue = 0;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_GET_VTOTAL, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return 0;
    }
    else
    {
        return XCArgs.u16ReturnValue;
    }
}
#endif
void MDrv_XC_PCMonitor_Update_TimingCount(void *pInstance, INPUT_SOURCE_TYPE_t eCurrentSrc, SCALER_WIN eWindow)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    XC_RESOURCE_PRIVATE* pXCResourcePrivate = NULL;

    UtopiaResourceGetPrivate(g_pXCResource[_XC_SELECT_INTERNAL_VARIABLE(psXCInstPri->u32DeviceID)],(void**)(&pXCResourcePrivate));
#if (XC_SUPPORT_FASTSWITCH_BY_IP1GP==TRUE)
    if(MDrv_XC_IsFSSEnabled(pInstance, eWindow) && eWindow == MAX_WINDOW)
    {
        if (IsSrcTypeVga(eCurrentSrc))
        {
            pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingStableCounterOffline[E_PCMONITOR_SOURCE_VGA] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_VGA;
            pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingNosyncCounterOffline[E_PCMONITOR_SOURCE_VGA] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_VGA;
        }
        else if (IsSrcTypeYPbPr(eCurrentSrc))
        {
            pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingStableCounterOffline[E_PCMONITOR_SOURCE_YPBPR] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_YPBPR;
            pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingNosyncCounterOffline[E_PCMONITOR_SOURCE_YPBPR] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_YPBPR;
        }
        else if (IsSrcTypeHDMI(eCurrentSrc) || IsSrcTypeDVI(eCurrentSrc))
        {
            pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingStableCounterOffline[E_PCMONITOR_SOURCE_HDMI] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_HDMI;
            pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingNosyncCounterOffline[E_PCMONITOR_SOURCE_HDMI] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_HDMI;
            pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingStableCounterOffline[E_PCMONITOR_SOURCE_HDMI2] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_HDMI;
            pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingNosyncCounterOffline[E_PCMONITOR_SOURCE_HDMI2] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_HDMI;
            pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingStableCounterOffline[E_PCMONITOR_SOURCE_HDMI3] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_HDMI;
            pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingNosyncCounterOffline[E_PCMONITOR_SOURCE_HDMI3] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_HDMI;
            pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingStableCounterOffline[E_PCMONITOR_SOURCE_HDMI4] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_HDMI;
            pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingNosyncCounterOffline[E_PCMONITOR_SOURCE_HDMI4] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_HDMI;
        }
        else
        {
            printf("<ATTENTION> Not support timing count for this source, use default vaule \n");
        }
    }
    else if(eWindow != MAX_WINDOW)
#endif
    {
        if (IsSrcTypeVga(eCurrentSrc))
        {
            pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter[eWindow] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_VGA;
            pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter[eWindow] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_VGA;
        }
        else if (IsSrcTypeYPbPr(eCurrentSrc))
        {
            pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter[eWindow] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_YPBPR;
            pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter[eWindow] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_YPBPR;
        }
        else if (IsSrcTypeHDMI(eCurrentSrc) || IsSrcTypeDVI(eCurrentSrc))
        {
            pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter[eWindow] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter_HDMI;
            pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter[eWindow] = pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter_HDMI;
        }
        else
        {
            printf("<ATTENTION> Not support timing count for this source, use default vaule \n");
            pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter[eWindow] = MD_TIMING_STABLE_COUNT;
            pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter[eWindow] = MD_TIMING_NOSYNC_COUNT;
        }
    }
}

static void MDrv_XC_NewModeInterlacedDetect(void *pInstance, SCALER_WIN eWindow, INPUT_SOURCE_TYPE_t enSrcType)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    XC_RESOURCE_PRIVATE* pXCResourcePrivate = NULL;
    UtopiaResourceGetPrivate(g_pXCResource[_XC_SELECT_INTERNAL_VARIABLE(psXCInstPri->u32DeviceID)],(void**)(&pXCResourcePrivate));
    XC_PCMONITOR_HK_INFO stPCMonitorInfo;
#if (XC_SUPPORT_FASTSWITCH_BY_IP1GP==TRUE)
    MHal_XC_SetOfflineSource(pInstance, eWindow, enSrcType);
#endif
    // enable H/V sync status check
    MDrv_XC_SetHVSyncStatusCheck(pInstance, ENABLE, eWindow, enSrcType);
    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, enSrcType);
    if((IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc)
        || IsSrcTypeDVI(stPCMonitorInfo.eCurrentSrc)
        || IsSrcTypeYPbPr(stPCMonitorInfo.eCurrentSrc))
        && (stPCMonitorInfo.eCurrentState == E_XC_PCMONITOR_STABLE_SYNC))
    {
        MS_WINDOW_TYPE stCapWin;
        MS_U16 u16HFreqx10, u16VFreqx10, u16Vtotal;
        MDrv_XC_GetCaptureWindow(pInstance, &stCapWin, eWindow);

        if((stCapWin.width > 1915) && (stCapWin.width < 1925)
            && (stCapWin.height > 535) && (stCapWin.height < 545)
            && ((u16HFreqx10 = MDrv_XC_PCMonitor_Get_HFreqx10(pInstance, eWindow, enSrcType)) > 305) && (u16HFreqx10 < 315)
            && ((u16VFreqx10 = MDrv_XC_PCMonitor_Get_VFreqx10NoDelay(pInstance, eWindow, E_XC_PCMONITOR_VFREQ_CHECKING_NODELAY, enSrcType)) > 498) && (u16VFreqx10 < 502)
            && ((u16Vtotal = MDrv_XC_PCMonitor_Get_Vtotal(pInstance, eWindow, enSrcType)) > 620) && (u16Vtotal < 630)
            && (Hal_SC_ip_get_interlace_status(pInstance, eWindow) == 0))
        {
            // enable new mode interlaced detect
            MDrv_XC_SetNewModeInterlacedDetect(pInstance, ENABLE, 2, ENABLE, TRUE, FALSE, eWindow, enSrcType);
            stPCMonitorInfo.eCurrentState = E_XC_PCMONITOR_UNSTABLE;
            pXCResourcePrivate->stapiXC_PCMonitor._bNewModeInterlacedDetect = TRUE;
        }
        else if((pXCResourcePrivate->stapiXC_PCMonitor._bNewModeInterlacedDetect == TRUE)
            && (!(((u16HFreqx10 = MDrv_XC_PCMonitor_Get_HFreqx10(pInstance, eWindow, enSrcType)) > 305) && (u16HFreqx10 < 315)
            && ((u16VFreqx10 = MDrv_XC_PCMonitor_Get_VFreqx10NoDelay(pInstance, eWindow, E_XC_PCMONITOR_VFREQ_CHECKING_NODELAY, enSrcType)) > 498) && (u16VFreqx10 < 502)
            && ((u16Vtotal = MDrv_XC_PCMonitor_Get_Vtotal(pInstance, eWindow, enSrcType)) > 1245) && (u16Vtotal < 1255)
            && (Hal_SC_ip_get_interlace_status(pInstance, eWindow) == 1))))
        {
            // disable new mode interlaced detect
            MDrv_XC_SetNewModeInterlacedDetect(pInstance, DISABLE, 0, DISABLE, FALSE, FALSE, eWindow, enSrcType);
            pXCResourcePrivate->stapiXC_PCMonitor._bNewModeInterlacedDetect = FALSE;
        }
    }
    MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, enSrcType);
}

E_APIXC_ReturnValue MDrv_XC_PCMonitor_GetTimingInfo(void* pInstance, SCALER_WIN eWindow, ST_XC_PCMONITOR_TIMING_INFO* pstPcMonitorTimingInfo)
{
    ST_XC_PCMONITOR_TIMING_INFO stPcMonitorTimingInfo;
    memset(&stPcMonitorTimingInfo, 0x00, sizeof(ST_XC_PCMONITOR_TIMING_INFO));
    MS_U32 u32CopiedLength = sizeof(ST_XC_PCMONITOR_TIMING_INFO);
    stPcMonitorTimingInfo.u32PcMonitorTimingInfoVersion = ST_XC_PCMONITOR_TIMING_INFO_VERSION;

    if(pstPcMonitorTimingInfo->u32PcMonitorTimingInfoVersion < 1)
    {
        //We cosider compatible operation form version1 , so reject the info init when version invalid
        XC_LOG_TRACE(XC_DBGLEVEL_SETTIMING, "MDrv_XC_PCMonitor_GetTimingInfo: please check your u32PcMonitorTimingInfoVersion, it should not set to 0!!\n");
        return E_APIXC_RET_FAIL;
    }

    //new AP + old lib, only the length corresponding to old lib has meaning.
    if(pstPcMonitorTimingInfo->u32PcMonitorTimingInfoVersion > ST_XC_PCMONITOR_TIMING_INFO_VERSION)
    {
        //We cosider compatible operation form version1 , so reject the info init when version invalid
#if defined (__aarch64__)
        XC_LOG_TRACE(XC_DBGLEVEL_SETTIMING, "MDrv_XC_PCMonitor_GetTimingInfo: this old version XC lib has only length:%lu driver status!!\n",
                     sizeof(ST_XC_PCMONITOR_TIMING_INFO))
#else
        XC_LOG_TRACE(XC_DBGLEVEL_SETTIMING, "MDrv_XC_PCMonitor_GetTimingInfo: this old version XC lib has only length:%u driver status!!\n",
                     sizeof(ST_XC_PCMONITOR_TIMING_INFO))
#endif
        //we still copy the min size of both structure, but AP should take care of it.
        u32CopiedLength = sizeof(ST_XC_PCMONITOR_TIMING_INFO);
    }

    //old AP + new lib, driver shouldn't access to the space which doesn't exist in old structure
    if((pstPcMonitorTimingInfo->u32PcMonitorTimingInfoVersion < ST_XC_PCMONITOR_TIMING_INFO_VERSION) || (pstPcMonitorTimingInfo->u32PcMonitorTimingInfoLength < sizeof(ST_XC_PCMONITOR_TIMING_INFO)))
    {
        //We cosider compatible operation form version1 , so reject the info init when version invalid
        XC_LOG_TRACE(XC_DBGLEVEL_SETTIMING, "MDrv_XC_PCMonitor_GetTimingInfo: new version XC lib shouldn't access to the space which doesn't exist in old structure!!\n")
        u32CopiedLength = pstPcMonitorTimingInfo->u32PcMonitorTimingInfoLength;
    }

    stPcMonitorTimingInfo.u32PcMonitorTimingInfoLength = u32CopiedLength;

    XC_PCMONITOR_HK_INFO stPCMonitorInfo;
    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, pstPcMonitorTimingInfo->enCurrentSrc);
    stPcMonitorTimingInfo.enCurrentSrc = pstPcMonitorTimingInfo->enCurrentSrc;
    stPcMonitorTimingInfo.enCurrentState = stPCMonitorInfo.eCurrentState;
    stPcMonitorTimingInfo.u8SyncStatus = stPCMonitorInfo.u8SyncStatus;
    stPcMonitorTimingInfo.u16InputVTotal = stPCMonitorInfo.u16Vtotal;
    stPcMonitorTimingInfo.u16InputHTotal = stPCMonitorInfo.u16Hperiod;
    stPcMonitorTimingInfo.u16InputVFreq = MDrv_XC_PCMonitor_Get_VFreqx10(pInstance, eWindow, stPCMonitorInfo.eCurrentSrc);
    stPcMonitorTimingInfo.u16InputHFreq = MDrv_XC_PCMonitor_Get_HFreqx10(pInstance, eWindow, stPCMonitorInfo.eCurrentSrc);
    stPcMonitorTimingInfo.en3dinputmode = MDrv_XC_Get_3D_Input_Mode(pInstance, eWindow);

    if(pstPcMonitorTimingInfo->u32PcMonitorTimingInfoVersion >= 2)
    {
        stPcMonitorTimingInfo.enUnstableType = stPCMonitorInfo.enUnstableType;
    }

    MDrv_XC_PCMonitor_Get_Dvi_Hdmi_De_Info(pInstance, eWindow, &(stPcMonitorTimingInfo.stCapWin), stPCMonitorInfo.eCurrentSrc);

    memcpy(pstPcMonitorTimingInfo, &stPcMonitorTimingInfo, u32CopiedLength);

    return E_APIXC_RET_OK;
}

E_APIXC_ReturnValue MApi_XC_PCMonitor_GetTimingInfo_U2(void* pInstance, SCALER_WIN eWindow, ST_XC_PCMONITOR_TIMING_INFO* pstPcMonitorTimingInfo)
{
    E_APIXC_ReturnValue eResult = E_APIXC_RET_FAIL;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    _XC_ENTRY(pInstance);

    eResult = MDrv_XC_PCMonitor_GetTimingInfo(pInstance, eWindow, pstPcMonitorTimingInfo);

    _XC_RETURN(pInstance);
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    return eResult;
}

#ifndef UTOPIAXP_REMOVE_WRAPPER
E_APIXC_ReturnValue MApi_XC_PCMonitor_GetTimingInfo(SCALER_WIN eWindow, ST_XC_PCMONITOR_TIMING_INFO* pstPcMonitorTimingInfo)
{
    stXC_PCMONITOR_GETTIMINGINFO XCArgs;

    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return E_APIXC_RET_FAIL;
    }

    XCArgs.eWindow = eWindow;
    XCArgs.pstPcMonitorTimngInfo = pstPcMonitorTimingInfo;
    XCArgs.eReturnValue = E_APIXC_RET_FAIL;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD_GETTIMINGINFO, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return E_APIXC_RET_FAIL;
    }
    else
    {
        return XCArgs.eReturnValue;
    }
}
#endif

static MS_BOOL _MApi_XC_PCMonitor_SkipUnstableDebounce(void *pInstance, SCALER_WIN enWindow, INPUT_SOURCE_TYPE_t enSrcType)
{
    E_MUX_INPUTPORT enMuxSrc = INPUT_PORT_NONE_PORT;
    XC_PCMONITOR_HK_INFO stPCMonitorInfo;
    MS_BOOL bSkip = FALSE;

    memset(&stPCMonitorInfo, 0, sizeof(XC_PCMONITOR_HK_INFO));
    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, enWindow, enSrcType);

    if((IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc)) || (IsSrcTypeDVI(stPCMonitorInfo.eCurrentSrc)))
    {
        MS_BOOL bTimingStable = FALSE;

        bTimingStable = MDrv_XC_PCMonitor_HDMISignalStable(pInstance, stPCMonitorInfo.eCurrentSrc);

        if(bTimingStable == FALSE)
        {
            // hdmi clock unstable
            bSkip = TRUE;
        }
    }

    return bSkip;
}

#if (XC_SUPPORT_FASTSWITCH_BY_IP1GP == TRUE)

#define PCMONITOR_OFFLINE_STABLE_MAX (40)

EN_PCMONITOR_SOURCE_TYPE_t enPCMonitorOfflineFSM = E_PCMONITOR_SOURCE_VGA;
XC_PCMONITOR_STATUS enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_NUM] = {E_XC_PCMONITOR_STABLE_NOSYNC, E_XC_PCMONITOR_STABLE_NOSYNC, E_XC_PCMONITOR_STABLE_NOSYNC, E_XC_PCMONITOR_STABLE_NOSYNC, E_XC_PCMONITOR_STABLE_NOSYNC, E_XC_PCMONITOR_STABLE_NOSYNC};

MS_U16 gu16SrcConected = 0;
MS_U16 gu16OnLineSrcConected[MAX_WINDOW] = {0};
INPUT_SOURCE_TYPE_t genPCMonitorSource[E_PCMONITOR_SOURCE_NUM] = {INPUT_SOURCE_NONE, INPUT_SOURCE_NONE, INPUT_SOURCE_NONE, INPUT_SOURCE_NONE, INPUT_SOURCE_NONE, INPUT_SOURCE_NONE};
INPUT_SOURCE_TYPE_t genPCMonitorMapping[E_PCMONITOR_SOURCE_NUM] = {INPUT_SOURCE_VGA, INPUT_SOURCE_YPBPR, INPUT_SOURCE_HDMI, INPUT_SOURCE_HDMI2, INPUT_SOURCE_HDMI3, INPUT_SOURCE_HDMI4};
MS_U8 genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_NUM] = {0};


XC_PCMONITOR_STATUS _MApi_XC_PCMonitor_Offline_Detect(void* pInstance, EN_PCMONITOR_SOURCE_TYPE_t enPcMonitorSrcType)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    XC_RESOURCE_PRIVATE* pXCResourcePrivate = NULL;
    XC_PCMONITOR_HK_INFO stPCMonitorInfo;
    MS_U8 u8Interlace = 0;
    EN_PCMONITOR_SOURCE_TYPE_t enPcMonitorSrc = E_PCMONITOR_SOURCE_INVALID;

    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, MAX_WINDOW, genPCMonitorSource[enPcMonitorSrcType]);

    if(stPCMonitorInfo.eCurrentSrc != genPCMonitorSource[enPcMonitorSrcType])
    {
        XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "eCurrentState[%d] eCurrentSrc[%d]\n", stPCMonitorInfo.eCurrentState, stPCMonitorInfo.eCurrentSrc);

        MDrv_XC_PCMonitor_Restart(pInstance, MAX_WINDOW, genPCMonitorSource[enPcMonitorSrcType]);
        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, MAX_WINDOW, genPCMonitorSource[enPcMonitorSrcType]);
        stPCMonitorInfo.eCurrentSrc = genPCMonitorSource[enPcMonitorSrcType];
        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);

        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
        MDrv_XC_PCMonitor_Update_TimingCount(pInstance, stPCMonitorInfo.eCurrentSrc, MAX_WINDOW);
        MHal_XC_SetOfflineSource(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
    }
    MHal_XC_SetOfflineSource(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);

    enPcMonitorSrc = MHal_XC_InputSrcToPCMonitorSrc(pInstance, stPCMonitorInfo.eCurrentSrc);
    if(enPcMonitorSrc == E_PCMONITOR_SOURCE_INVALID)
    {
        return E_XC_PCMONITOR_UNSTABLE; //if MHal_XC_InputSrcToPCMonitorSrc=E_PCMONITOR_SOURCE_NUM, it will access memory out of bonds.
    }

    if (MDrv_XC_IsSupportVRR())
    {
        if (IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc) && (MHal_XC_GetVRREnableFromHDMI(pInstance) == TRUE))
        {
            stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, MAX_WINDOW, genPCMonitorSource[enPcMonitorSrcType]);
            stPCMonitorInfo.eCurrentState = E_XC_PCMONITOR_STABLE_SYNC;
            stPCMonitorInfo.eCurrentSrc = genPCMonitorSource[enPcMonitorSrcType];
            MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
            return stPCMonitorInfo.eCurrentState;
        }
    }

    if((FALSE == stPCMonitorInfo.bInputTimingChange) &&
        (MsOS_GetSystemTime() - stPCMonitorInfo.u32LastExecutedTime < PC_POLLING_COUNTER))
    {
        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
        XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "eCurrentState[%d] eCurrentSrc[%d]\n", stPCMonitorInfo.eCurrentState, stPCMonitorInfo.eCurrentSrc);
        return stPCMonitorInfo.eCurrentState;
    }
    else
    {
        // update last executed time
        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
        stPCMonitorInfo.u32LastExecutedTime = MsOS_GetSystemTime();
        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
    }

    // DE-Bypass is applied in HDMI HV mode. It will ignore pixel repetition package from HDMI.
    // We use the software mointor to monitor this package.
    UtopiaResourceGetPrivate(g_pXCResource[_XC_SELECT_INTERNAL_VARIABLE(psXCInstPri->u32DeviceID)],(void**)(&pXCResourcePrivate));

    if( (IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc) || IsSrcTypeDVI(stPCMonitorInfo.eCurrentSrc) )
      &&(MDrv_XC_GetHdmiSyncMode(pInstance) == HDMI_SYNC_HV))
    {
        MS_U8 u8CurHDMIPixelRep = MDrv_HDMI_avi_infoframe_info(_BYTE_5)& 0x0F;
        MS_U8 u8IpPixelRep = 0;

        u8IpPixelRep = pXCResourcePrivate->stdrvXC_IP.u8IpPixelRepOffline[enPcMonitorSrc];
        if( u8CurHDMIPixelRep != u8IpPixelRep)
        {
            if( u8CurHDMIPixelRep )
            {
                Hal_SC_ip_set_fir_down_sample_divider(pInstance, ENABLE, 0x01, MAX_WINDOW);
            }
            else
            {
                Hal_SC_ip_set_fir_down_sample_divider(pInstance, ENABLE, 0x00, MAX_WINDOW);
            }

            stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
            stPCMonitorInfo.bInputTimingChange = TRUE;
            MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);

            pXCResourcePrivate->stdrvXC_IP.u8IpPixelRepOffline[enPcMonitorSrc] = u8CurHDMIPixelRep;
        }
        XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "eCurrentState[%d] eCurrentSrc[%d]\n", stPCMonitorInfo.eCurrentState, stPCMonitorInfo.eCurrentSrc);
    }

    //--------------------------------------------------
    //display active or no signal?
    if( stPCMonitorInfo.bInputTimingChange == FALSE ) // check timing change flag have be setting
    {
        if( MDrv_XC_PCMonitor_SyncLoss(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc) ) // no sync
        {
            MDrv_XC_SetSogDetectStatus(pInstance, pXCResourcePrivate->stapiXCPCMonitorOffline.g_u8RGBSOG_DetectStatus);
            if ( _MApi_XC_PCMonitor_DetectSync(pInstance, stPCMonitorInfo.eCurrentSrc, MAX_WINDOW) ) // check signal active
            {
                stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
                stPCMonitorInfo.bInputTimingChange = TRUE;
                MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
            }
            else
            {
                XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "eCurrentState[%d] eCurrentSrc[%d]\n", stPCMonitorInfo.eCurrentState, stPCMonitorInfo.eCurrentSrc);
            }
        }
        else //have sync?
        {
            if(pXCResourcePrivate->stapiXCPCMonitorOffline.bEnableAutoNoSignalDetectOffline[enPcMonitorSrc])
            {
                // check invalid
                if(( MDrv_XC_PCMonitor_InvalidTimingDetect(pInstance, TRUE, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc))
                    ||((stPCMonitorInfo.eCurrentState==E_XC_PCMONITOR_STABLE_SYNC)&&(MDrv_XC_IsInputSourceDisabled(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc))))
                {
                    ++pXCResourcePrivate->stapiXCPCMonitorOffline.u8DeNoiseCountOffline[enPcMonitorSrc];

                    // PC monitor have to changed when auto nosignal enabled.
                    // If no signal bit is enabled, that's treaded as no-signal
                    // Here have to update variables for hw-detected-no-signal.
                    if ((pXCResourcePrivate->stapiXCPCMonitorOffline.u8DeNoiseCountOffline[enPcMonitorSrc] > 3) ||
                        (_MApi_XC_PCMonitor_SkipUnstableDebounce(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc) == TRUE))
                    {
                        //CID:328612, Unchecked return value, add checking condition @Crixus 20180517
                        if(!MDrv_XC_PCMonitor_InvalidTimingDetect(pInstance, FALSE, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc))
                        {
                            XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "return value is false.\n");
                        }
                        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
                        stPCMonitorInfo.u8SyncStatus |= XC_MD_SYNC_LOSS;
                        stPCMonitorInfo.bInputTimingChange = TRUE;
                        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
                        pXCResourcePrivate->stapiXCPCMonitorOffline.u8DeNoiseCountOffline[enPcMonitorSrc] = 0;
                    }
                }
                else // time stable
                {
                    if( MDrv_XC_IsInputSourceDisabled(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc)&&(pXCResourcePrivate->stapiXCPCMonitorOffline.u8DeNoiseCountOffline[enPcMonitorSrc]!=0)
                    &&(stPCMonitorInfo.eCurrentState == E_XC_PCMONITOR_STABLE_SYNC) )
                    {
                        pXCResourcePrivate->stapiXCPCMonitorOffline.u8DeStableCntOffline[enPcMonitorSrc] = 0;
                    }
                    else
                    {
                        pXCResourcePrivate->stapiXCPCMonitorOffline.u8DeStableCntOffline[enPcMonitorSrc]++;
                    }

                    if((pXCResourcePrivate->stapiXCPCMonitorOffline.u8DeStableCntOffline[enPcMonitorSrc] ==20) && MDrv_XC_IsInputSourceDisabled(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc)) // to check the input source status
                    {
                        pXCResourcePrivate->stapiXCPCMonitorOffline.u8DeStableCntOffline[enPcMonitorSrc]=0;
                    }

                    if(pXCResourcePrivate->stapiXCPCMonitorOffline.u8DeStableCntOffline[enPcMonitorSrc] >=20)
                    {
                        pXCResourcePrivate->stapiXCPCMonitorOffline.u8DeStableCntOffline[enPcMonitorSrc] = 0;
                    }

                    pXCResourcePrivate->stapiXCPCMonitorOffline.u8DeNoiseCountOffline[enPcMonitorSrc] = 0;
                }
            }
            else if ( MDrv_XC_PCMonitor_InvalidTimingDetect(pInstance, FALSE, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc) ) // check invalid sync
            {
                stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
                stPCMonitorInfo.u8SyncStatus |= XC_MD_SYNC_LOSS;
                stPCMonitorInfo.bInputTimingChange = TRUE;
                MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
            }
        }
    }

    //is input timing changed and check debounce
    //--------------------------------------------------
    if ( stPCMonitorInfo.bInputTimingChange) // input timing is unstable
    {
        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
        stPCMonitorInfo.bInputTimingChange = FALSE;
        stPCMonitorInfo.ucTimingChangeDebounce++;

        if ( !MDrv_XC_PCMonitor_SyncLoss(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc) ) // have signal
        {
            if ( stPCMonitorInfo.ucTimingChangeDebounce <= 3 ) // prevent from SOG
            {
                stPCMonitorInfo.u8SyncStatus |= XC_MD_SYNC_LOSS;
                MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
                XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "eCurrentState[%d] eCurrentSrc[%d]\n", stPCMonitorInfo.eCurrentState, stPCMonitorInfo.eCurrentSrc);
                return stPCMonitorInfo.eCurrentState;
            }
        }
        else
        {
            if ( IsSrcTypeYPbPr(stPCMonitorInfo.eCurrentSrc ) ||
                 IsSrcTypeVga(stPCMonitorInfo.eCurrentSrc )  )
            {
                // System have to set free run as soon as possible when timing unstable.
                MDrv_XC_ADC_Set_Freerun(pInstance, TRUE);
            }
        }

        stPCMonitorInfo.eCurrentState = E_XC_PCMONITOR_UNSTABLE;
        XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "eCurrentState[%d] eCurrentSrc[%d]\n", stPCMonitorInfo.eCurrentState, stPCMonitorInfo.eCurrentSrc);
        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);

        _MApi_XC_PCMonitor_PrepareForTimingChange(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);

        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);

        // Enable input source when timing changes
        MDrv_XC_DisableInputSource(pInstance, DISABLE, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
    }
    else // input timing is stable
    {
        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
        stPCMonitorInfo.ucTimingChangeDebounce = 0; // reset timing change debounce counter

        stPCMonitorInfo.ucInputTimingStableCounter++; // timing stable counter

        if ( stPCMonitorInfo.ucInputTimingStableCounter == 0 )
        {
            stPCMonitorInfo.ucInputTimingStableCounter = 1;
        }

        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
        if ( !stPCMonitorInfo.bInputTimingStable )
        {
#ifndef MSOS_TYPE_LINUX_KERNEL
            if(enPcMonitorSrc < E_PCMONITOR_SOURCE_NUM)
            {
                MS_ASSERT(pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingStableCounterOffline[enPcMonitorSrc] > 0);
                MS_ASSERT(pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingNosyncCounterOffline[enPcMonitorSrc] > 0);
            }
#endif
            if( ((!MDrv_XC_PCMonitor_SyncLoss(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc)) && (stPCMonitorInfo.ucInputTimingStableCounter >= pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingStableCounterOffline[MHal_XC_InputSrcToPCMonitorSrc(pInstance, stPCMonitorInfo.eCurrentSrc)])) ||
                (MDrv_XC_PCMonitor_SyncLoss(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc) && (stPCMonitorInfo.ucInputTimingStableCounter >= pXCResourcePrivate->stapiXCPCMonitorOffline.u16TimingNosyncCounterOffline[MHal_XC_InputSrcToPCMonitorSrc(pInstance, stPCMonitorInfo.eCurrentSrc)])) )
            {
                stPCMonitorInfo.bInputTimingStable = TRUE;
                MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
                pXCResourcePrivate->stapiXCPCMonitorOffline.g_u8RGBSOG_DetectStatus = MDrv_XC_GetSogDetectStatus(pInstance);

                if (MDrv_XC_GetVGASogEn(pInstance))     // Daten FixMe -> Please refine VGA SOG flow
                {
                    if(IsSrcTypeVga(stPCMonitorInfo.eCurrentSrc) &&  // Is RGB in
                        (!MDrv_XC_PCMonitor_SyncLoss(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc)) &&                     // Has signal
                        ((pXCResourcePrivate->stapiXCPCMonitorOffline.g_u8RGBSOG_DetectStatus & (0x0001) ) == (0x0001)) &&          // In detecting SOG
                        (!((pXCResourcePrivate->stapiXCPCMonitorOffline.g_u8RGBSOG_DetectStatus & (0x0002)) == (0x0002))))         // 1st time detecting SOG

                    {
                        // only if RGB input, has sync and in SOG detecting enter here
                        // force to check from other sync type again.
                        pXCResourcePrivate->stapiXCPCMonitorOffline.g_u8RGBSOG_DetectStatus |= (0x0002);
                        stPCMonitorInfo.u8SyncStatus ^= XC_MD_VSYNC_POR_BIT;

                        stPCMonitorInfo.bInputTimingStable = TRUE;
                        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
                    }
                    else
                    {
                        if(!MDrv_XC_PCMonitor_SyncLoss(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc))
                        {
                            // has sync, no matter what sync detected, clear the SOG_DETECTED_BIT
                            pXCResourcePrivate->stapiXCPCMonitorOffline.g_u8RGBSOG_DetectStatus &= ~(0x0002);
                        }
                        if((pXCResourcePrivate->stapiXCPCMonitorOffline.g_u8RGBSOG_DetectStatus & (0x0001)) &&
                             (MDrv_XC_PCMonitor_SyncLoss(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc)))
                        {
                            // in detecting the SOG and no Sync, clear the SOG_DETECTED_BIT
                            pXCResourcePrivate->stapiXCPCMonitorOffline.g_u8RGBSOG_DetectStatus &= ~(0x0002);
                        }
                        stPCMonitorInfo.bInputTimingStable = TRUE;
                        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
                    }
                }

                if(MDrv_XC_PCMonitor_SyncLoss(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc))
                {
                    stPCMonitorInfo.eCurrentState = E_XC_PCMONITOR_STABLE_NOSYNC;
                    XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "eCurrentState[%d] eCurrentSrc[%d]\n", stPCMonitorInfo.eCurrentState, stPCMonitorInfo.eCurrentSrc);
                    MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
                }
                else
                {
                    stPCMonitorInfo.eCurrentState = E_XC_PCMONITOR_STABLE_SYNC;

                    Hal_SC_ip_set_IPAutoNoSignal(pInstance, ENABLE,MAX_WINDOW);
                    MDrv_XC_DisableInputSource(pInstance, DISABLE, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc); //enable the input source

                    XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "eCurrentState[%d] eCurrentSrc[%d]\n", stPCMonitorInfo.eCurrentState, stPCMonitorInfo.eCurrentSrc);
                    // for get accurate v freq, need call msAPI_Scaler_Field_Detect and MDrv_XC_ADC_Set_Freerun
                    u8Interlace = Hal_SC_ip_get_interlace_status(pInstance, MAX_WINDOW);
                    msAPI_Scaler_Field_Detect(pInstance, stPCMonitorInfo.eCurrentSrc, ((u8Interlace == 1)?SCAN_INTERLACE:SCAN_PROGRESSIVE), MAX_WINDOW);
                    if ( IsSrcTypeYPbPr(stPCMonitorInfo.eCurrentSrc ) ||
                        IsSrcTypeVga(stPCMonitorInfo.eCurrentSrc )  )
                    {
                        Hal_SC_ip_set_IPAutoNoSignal(pInstance, DISABLE, MAX_WINDOW);
                        MDrv_XC_ADC_Set_Freerun(pInstance, FALSE);
                    }
                    // Update V sync time when timing stable.
                    stPCMonitorInfo.u16VSyncTime = MApi_XC_CalculateVsyncTime(pInstance, stPCMonitorInfo.u16Vtotal, stPCMonitorInfo.u16Hperiod);
                    MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
                    if ( IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc ) )
                    {
                        _MApi_XC_PCMonitor_FPi_Patch(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
                    }

                    XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "eCurrentState[%d] eCurrentSrc[%d] u16VSyncTime[%d]\n", stPCMonitorInfo.eCurrentState, stPCMonitorInfo.eCurrentSrc, stPCMonitorInfo.u16VSyncTime);
                }

                XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "eCurrentState[%d] eCurrentSrc[%d]\n", stPCMonitorInfo.eCurrentState, stPCMonitorInfo.eCurrentSrc);
                return stPCMonitorInfo.eCurrentState;
            }
        }

    }

    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);
    stPCMonitorInfo.ePreMonitorState = stPCMonitorInfo.eCurrentState;
    MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, MAX_WINDOW, stPCMonitorInfo.eCurrentSrc);

    XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "enPcMonitorSrcType[%d] = [%d] eCurrentState[%d]\n", enPcMonitorSrcType, genPCMonitorSource[enPcMonitorSrcType], stPCMonitorInfo.eCurrentState);
    return stPCMonitorInfo.eCurrentState;
}

void _MApi_XC_PCMonitor_Offline_ISR(SC_INT_SRC eIntNum, void * pParam)
{
    MS_U32 u32CurTime = MsOS_GetSystemTime();

    void *pInstance = pu32XCInst_private;
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    XC_RESOURCE_PRIVATE* pXCResourcePrivate = NULL;
    UtopiaResourceGetPrivate(g_pXCResource[_XC_SELECT_INTERNAL_VARIABLE(psXCInstPri->u32DeviceID)],(void**)(&pXCResourcePrivate));
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);

    // Get current source type
    EN_XC_INPUT_FSS_TYPE _enFSSSrcType = E_XC_INPUT_FSS_ADCA; //default set to 0
    _enFSSSrcType = MHal_XC_InputSrcToFssSrc(pInstance, pXCResourcePrivate->stdrvXC_MVideo_Context.enFSSSrcType);

    switch(enPCMonitorOfflineFSM)
    {
        case E_PCMONITOR_SOURCE_VGA:
            if((gu16SrcConected&BIT(E_PCMONITOR_SOURCE_VGA)) && (_enFSSSrcType != E_XC_INPUT_FSS_ADCA))
            {
                enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_VGA] = _MApi_XC_PCMonitor_Offline_Detect(pInstance, E_PCMONITOR_SOURCE_VGA);
                if(enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_VGA]==E_XC_PCMONITOR_STABLE_SYNC
                    || genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_VGA]>=PCMONITOR_OFFLINE_STABLE_MAX)
                {
                    genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_VGA] = 0;
                    enPCMonitorOfflineFSM = E_PCMONITOR_SOURCE_YPBPR;
                }
                else
                {
                    genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_VGA]++;
                }
            }
            else
            {
                enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_VGA] = E_XC_PCMONITOR_STABLE_NOSYNC;
                enPCMonitorOfflineFSM = E_PCMONITOR_SOURCE_YPBPR;
            }
            XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "genPCMonitorOfflineUnStableCnt[%u] = [%u] \n", enPCMonitorOfflineFSM, genPCMonitorOfflineUnStableCnt[enPCMonitorOfflineFSM]);
            break;
        case E_PCMONITOR_SOURCE_YPBPR:
            if((gu16SrcConected&BIT(E_PCMONITOR_SOURCE_YPBPR)) && (_enFSSSrcType != E_XC_INPUT_FSS_ADCA))
            {
                enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_YPBPR] = _MApi_XC_PCMonitor_Offline_Detect(pInstance, E_PCMONITOR_SOURCE_YPBPR);
                if(enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_YPBPR]==E_XC_PCMONITOR_STABLE_SYNC
                    || genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_YPBPR]>=PCMONITOR_OFFLINE_STABLE_MAX)
                {
                    genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_YPBPR] = 0;
                    enPCMonitorOfflineFSM = E_PCMONITOR_SOURCE_HDMI;
                }
                else
                {
                    genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_YPBPR]++;
                }
            }
            else
            {
                enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_YPBPR] = E_XC_PCMONITOR_STABLE_NOSYNC;
                enPCMonitorOfflineFSM = E_PCMONITOR_SOURCE_HDMI;
            }
            XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "genPCMonitorOfflineUnStableCnt[%u] = [%u] \n", enPCMonitorOfflineFSM, genPCMonitorOfflineUnStableCnt[enPCMonitorOfflineFSM]);
            break;
        case E_PCMONITOR_SOURCE_HDMI:
            if(gu16SrcConected&BIT(E_PCMONITOR_SOURCE_HDMI))
            {
                enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_HDMI] = _MApi_XC_PCMonitor_Offline_Detect(pInstance, E_PCMONITOR_SOURCE_HDMI);
                if(enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_HDMI]==E_XC_PCMONITOR_STABLE_SYNC
                    || genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_HDMI]>=PCMONITOR_OFFLINE_STABLE_MAX)
                {
                    genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_HDMI] = 0;
                    enPCMonitorOfflineFSM = E_PCMONITOR_SOURCE_HDMI2;
                }
                else
                {
                    genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_HDMI]++;
                }
            }
            else
            {
                enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_HDMI] = E_XC_PCMONITOR_STABLE_NOSYNC;
                enPCMonitorOfflineFSM = E_PCMONITOR_SOURCE_HDMI2;
            }
            XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "genPCMonitorOfflineUnStableCnt[%u] = [%u] \n", enPCMonitorOfflineFSM, genPCMonitorOfflineUnStableCnt[enPCMonitorOfflineFSM]);
            break;
        case E_PCMONITOR_SOURCE_HDMI2:
            if(gu16SrcConected&BIT(E_PCMONITOR_SOURCE_HDMI2))
            {
                enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_HDMI2] = _MApi_XC_PCMonitor_Offline_Detect(pInstance, E_PCMONITOR_SOURCE_HDMI2);
                if(enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_HDMI2]==E_XC_PCMONITOR_STABLE_SYNC
                    || genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_HDMI2]>=PCMONITOR_OFFLINE_STABLE_MAX)
                {
                    genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_HDMI2] = 0;
                    enPCMonitorOfflineFSM = E_PCMONITOR_SOURCE_HDMI3;
                }
                else
                {
                    genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_HDMI2]++;
                }
            }
            else
            {
                enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_HDMI2] = E_XC_PCMONITOR_STABLE_NOSYNC;
                enPCMonitorOfflineFSM = E_PCMONITOR_SOURCE_HDMI3;
            }
            XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "genPCMonitorOfflineUnStableCnt[%u] = [%u] \n", enPCMonitorOfflineFSM, genPCMonitorOfflineUnStableCnt[enPCMonitorOfflineFSM]);
            break;
        case E_PCMONITOR_SOURCE_HDMI3:
            if(gu16SrcConected&BIT(E_PCMONITOR_SOURCE_HDMI3))
            {
                enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_HDMI3] = _MApi_XC_PCMonitor_Offline_Detect(pInstance, E_PCMONITOR_SOURCE_HDMI3);
                if(enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_HDMI3]==E_XC_PCMONITOR_STABLE_SYNC
                    || genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_HDMI3]>=PCMONITOR_OFFLINE_STABLE_MAX)
                {
                    genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_HDMI3] = 0;
                    enPCMonitorOfflineFSM = E_PCMONITOR_SOURCE_HDMI4;
                }
                else
                {
                    genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_HDMI3]++;
                }
            }
            else
            {
                enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_HDMI3] = E_XC_PCMONITOR_STABLE_NOSYNC;
                enPCMonitorOfflineFSM = E_PCMONITOR_SOURCE_HDMI4;
            }
            XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "genPCMonitorOfflineUnStableCnt[%u] = [%u] \n", enPCMonitorOfflineFSM, genPCMonitorOfflineUnStableCnt[enPCMonitorOfflineFSM]);
            break;
        case E_PCMONITOR_SOURCE_HDMI4:
            if(gu16SrcConected&BIT(E_PCMONITOR_SOURCE_HDMI4))
            {
                enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_HDMI4] = _MApi_XC_PCMonitor_Offline_Detect(pInstance, E_PCMONITOR_SOURCE_HDMI4);
                if(enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_HDMI4]==E_XC_PCMONITOR_STABLE_SYNC
                    || genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_HDMI4]>=PCMONITOR_OFFLINE_STABLE_MAX)
                {
                    genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_HDMI4] = 0;
                    enPCMonitorOfflineFSM = E_PCMONITOR_SOURCE_VGA;
                }
                else
                {
                    genPCMonitorOfflineUnStableCnt[E_PCMONITOR_SOURCE_HDMI4]++;
                }
            }
            else
            {
                enPCMOnitorOfflineStatus[E_PCMONITOR_SOURCE_HDMI4] = E_XC_PCMONITOR_STABLE_NOSYNC;
                enPCMonitorOfflineFSM = E_PCMONITOR_SOURCE_VGA;
            }
            XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "genPCMonitorOfflineUnStableCnt[%u] = [%u] \n", enPCMonitorOfflineFSM, genPCMonitorOfflineUnStableCnt[enPCMonitorOfflineFSM]);
            break;
        case E_PCMONITOR_SOURCE_INVALID:
            enPCMonitorOfflineFSM = E_PCMONITOR_SOURCE_VGA;
            XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "enPCMonitorOfflineFSM[%u] \n", enPCMonitorOfflineFSM);
            break;
        default:
            enPCMonitorOfflineFSM = E_PCMONITOR_SOURCE_VGA;
            XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "enPCMonitorOfflineFSM[%u] \n", enPCMonitorOfflineFSM);
            break;

    }

    XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "time cost[%tu] enPCMonitorOfflineFSM[%u] gu16SrcConected[0x%x] gu16OnLineSrcConected[MAIN][%u] gu16OnLineSrcConected[SUB][%u]\n",
        (ptrdiff_t)(MsOS_GetSystemTime()-u32CurTime), enPCMonitorOfflineFSM, gu16SrcConected, gu16OnLineSrcConected[MAIN_WINDOW], gu16OnLineSrcConected[SUB_WINDOW]);
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
}

MS_BOOL _MApi_XC_PCMonitor_Offline_DoesCurrentSourceSupportFSS(void* pInstance, INPUT_SOURCE_TYPE_t enCurrentSrc)
{
    if(gu16SrcConected & BIT(MHal_XC_InputSrcToPCMonitorSrc(pInstance, enCurrentSrc)))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}
#endif

MS_BOOL MDrv_XC_PCMonitor_Offline(void* pInstance, SCALER_WIN eWindow, INPUT_SOURCE_TYPE_t enCurrentSrc, MS_BOOL bEnable)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    XC_RESOURCE_PRIVATE* pXCResourcePrivate = NULL;
    UtopiaResourceGetPrivate(g_pXCResource[_XC_SELECT_INTERNAL_VARIABLE(psXCInstPri->u32DeviceID)],(void**)(&pXCResourcePrivate));

    MS_BOOL bReturn = FALSE;
#if (XC_SUPPORT_FASTSWITCH_BY_IP1GP == TRUE)
    E_MUX_INPUTPORT enSrcPort[3] = {INPUT_PORT_NONE_PORT, INPUT_PORT_NONE_PORT, INPUT_PORT_NONE_PORT};
    EN_PCMONITOR_SOURCE_TYPE_t enPcMonitorSrcType = MHal_XC_InputSrcToPCMonitorSrc(pInstance, enCurrentSrc);
    EN_PCMONITOR_SOURCE_TYPE_t enInitialPcMonitorSrcType = MHal_XC_InputSrcToPCMonitorSrc(pInstance, gSrcInfo[MAIN_WINDOW].enInputSourceType);
    MS_U8 u8EnablePort = 0;
    MS_U8 u8Index;

    if(eWindow == MAX_WINDOW)
    {
        if(bEnable) // add offline source
        {
            for(u8Index = 0; u8Index < E_PCMONITOR_SOURCE_NUM; u8Index++)
            {
                u8EnablePort = 0;
                gu16SrcConected |= BIT(u8Index);
                genPCMonitorSource[u8Index] = genPCMonitorMapping[u8Index];
                MDrv_XC_Mux_GetPort(pInstance, genPCMonitorSource[u8Index], enSrcPort, &u8EnablePort);

                if(u8EnablePort == 0)
                {
                    gu16SrcConected &= ~(BIT(u8Index));
                    genPCMonitorSource[u8Index] = INPUT_SOURCE_NONE;
                }
            }

            // HW patch for disable VGA source offline detect
            gu16SrcConected &= ~(BIT(E_PCMONITOR_SOURCE_VGA));
            genPCMonitorSource[E_PCMONITOR_SOURCE_VGA] = INPUT_SOURCE_NONE;
            // initialize first FSS offline detection source
            enPCMOnitorOfflineStatus[enInitialPcMonitorSrcType] = E_XC_PCMONITOR_STABLE_NOSYNC;
            genPCMonitorOfflineUnStableCnt[enInitialPcMonitorSrcType] = 0;
            enPCMonitorOfflineFSM = enInitialPcMonitorSrcType;
        }
    }
    else
    {
        return bReturn;
    }

    if(TRUE == MDrv_XC_InterruptIsAttached(pInstance, SC_INT_VSINT, _MApi_XC_PCMonitor_Offline_ISR, (void *)NULL))
    {
        if(gu16SrcConected==0) // no source connect in
        {
            MDrv_XC_InterruptDeAttachWithoutMutex(pInstance, SC_INT_VSINT, _MApi_XC_PCMonitor_Offline_ISR, (void *)NULL);
            bReturn = TRUE;
        }
        XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "already attached ISR genPCMonitorSource[%d] = [%d]\n", enPcMonitorSrcType, genPCMonitorSource[enPcMonitorSrcType]);
    }
    else
    {
        MDrv_XC_InterruptAttachWithoutMutex(pInstance, SC_INT_VSINT, _MApi_XC_PCMonitor_Offline_ISR, (void *)NULL);
        XC_LOG_TRACE(XC_DBGLEVEL_FSS_MONITOR, "attached ISR\n");
        bReturn = TRUE;
    }
#endif

    return bReturn;
}

void _MApi_XC_PCMonitorCheckHfr(void* pInstance, XC_PCMONITOR_HK_INFO stPCMonitorInfo, SCALER_WIN eWindow)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    XC_RESOURCE_PRIVATE* pXCResourcePrivate = NULL;
    UtopiaResourceGetPrivate(g_pXCResource[_XC_SELECT_INTERNAL_VARIABLE(psXCInstPri->u32DeviceID)],(void**)(&pXCResourcePrivate));

    MS_BOOL bHdmi21 = FALSE;
    MS_BOOL bWaitStb = FALSE;
    MS_BOOL bQuickLock = FALSE;

    bWaitStb = ((!MDrv_XC_PCMonitor_SyncLoss(pInstance, eWindow, stPCMonitorInfo.eCurrentSrc))
                        && (stPCMonitorInfo.ucInputTimingStableCounter >= QUICKSTABLECNT_HFR)
                        && (stPCMonitorInfo.eCurrentState == E_XC_PCMONITOR_UNSTABLE));

    bQuickLock = (bWaitStb || (stPCMonitorInfo.eCurrentState == E_XC_PCMONITOR_STABLE_SYNC));

    if(IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc))
    {
        E_MUX_INPUTPORT enSrcPort = INPUT_PORT_NONE_PORT;
        enSrcPort = MDrv_XC_Mux_GetHDMIPort(pInstance, stPCMonitorInfo.eCurrentSrc);
        bHdmi21 = (MDrv_HDMI_GetSourceVersion(enSrcPort) == PCHDMI_SOURCE_VERSION_HDMI21);
    }

    // hdmi 2.1 input
    if(bHdmi21 == TRUE)
    {
        MDrv_XC_SetIp8pMode(pInstance, ENABLE, eWindow);
        MDrv_XC_SetIpHfrEnable(pInstance, stPCMonitorInfo.eCurrentSrc, TRUE);
    }
    else
    {
        MDrv_XC_SetIp8pMode(pInstance, DISABLE, eWindow);
        MDrv_XC_SetIpHfrEnable(pInstance, stPCMonitorInfo.eCurrentSrc, FALSE);
    }

    // real HFR path
    if((stPCMonitorInfo.eCurrentState == E_XC_PCMONITOR_STABLE_SYNC)
        && (stPCMonitorInfo.u32FrameRatex1K >= FRAMERATE_HFR_MIN*1000)
        && (bHdmi21 == TRUE))
    {
        MDrv_XC_SetHfrPathEnable(pInstance, ENABLE, bQuickLock);
    }
    else
    {
        MDrv_XC_SetHfrPathEnable(pInstance, DISABLE, bQuickLock);
    }
}

static MS_BOOL _MApi_XC_PCMonitor_IsStartOfStablizationPeriod(void* pInstance, SCALER_WIN eWindow)
{
    if((eWindow == MAIN_WINDOW) && (_gs64PcStableSyncTimeStart == 0) && (_gs64PcStableSyncTimeEnd == 0))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

static MS_BOOL _MApi_XC_PCMonitor_IsEndOfStablizationPeriod(void* pInstance, SCALER_WIN eWindow, XC_PCMONITOR_STATUS enStatus)
{
    if((eWindow == MAIN_WINDOW) && (enStatus == E_XC_PCMONITOR_STABLE_SYNC) && (_gs64PcStableSyncTimeStart != 0) && (_gs64PcStableSyncTimeEnd == 0))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

MS_BOOL _MApi_XC_PCMonitor_Update_IP_and_VRRFSM(void *pInstance, XC_PCMONITOR_HK_INFO stPCMonitorInfo, SCALER_WIN eWindow)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    XC_RESOURCE_PRIVATE* pXCResourcePrivate = NULL;
    UtopiaResourceGetPrivate(g_pXCResource[_XC_SELECT_INTERNAL_VARIABLE(psXCInstPri->u32DeviceID)],(void**)(&pXCResourcePrivate));
    MS_BOOL bVRR_en = FALSE;

    bVRR_en = MHal_XC_GetVRREnableFromHDMI(pInstance) && pXCResourcePrivate->stdrvXC_MVideo_Context.g_bSetVRROn;

    if (IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc))
    {
        if (bVRR_en)
        {
            if (MHal_XC_GetVRRFSM_Enable(pInstance) == FALSE)
            {
                if (gSrcInfo[eWindow].bAutoNoSignalEnabled)
                {
                    PCMSG(printf("[VRR] disable auto no signal function\n"));
                    pXCResourcePrivate->stapiXC_PCMonitor._bEnableAutoNoSignalDetect[eWindow] = FALSE;
                    Hal_SC_ip_set_IPAutoNoSignal(pInstance, DISABLE, eWindow);
                    Hal_SC_ip_ForceDisableAutoNoSignal(pInstance, ENABLE, eWindow);
                }
                Hal_SC_Disable_AVMute(pInstance, eWindow);
                Hal_SC_ip_set_de_only_mode(pInstance, DISABLE, eWindow);
#if (XC_SUPPORT_FASTSWITCH_BY_IP1GP==TRUE)
                SC_W2BYTEMSK(psXCInstPri->u32DeviceID, MHal_XC_FSS_BankTransfer(pInstance, REG_SC_BK01_03_L, eWindow), 0, BIT(7));
#else
                SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK01_03_L, 0, BIT(7));
#endif
                Hal_SC_ip_set_user_def_interlace_status(pInstance, ENABLE, DISABLE, eWindow); //force p mode

                //enable VRR FSM
                MHal_XC_SetVRRFSM_Enable(pInstance, TRUE);
                PCMSG(printf("[VRR] FSM enable\n"));
            }

            return TRUE;
        }
        else //vrr disable
        {
            if (MHal_XC_GetVRRFSM_Enable(pInstance))
            {
                if (gSrcInfo[eWindow].bAutoNoSignalEnabled)
                {
                    PCMSG(printf("[VRR] enable auto no signal function\n"));
                    pXCResourcePrivate->stapiXC_PCMonitor._bEnableAutoNoSignalDetect[eWindow] = TRUE;
                    Hal_SC_ip_set_IPAutoNoSignal(pInstance, ENABLE, eWindow);
                    Hal_SC_ip_ForceDisableAutoNoSignal(pInstance, DISABLE, eWindow);
                }
                Hal_SC_Enable_AVMute(pInstance, eWindow);
                Hal_SC_ip_set_de_only_mode(pInstance, ENABLE, eWindow);
#if (XC_SUPPORT_FASTSWITCH_BY_IP1GP==TRUE)
                SC_W2BYTEMSK(psXCInstPri->u32DeviceID, MHal_XC_FSS_BankTransfer(pInstance, REG_SC_BK01_03_L, eWindow), BIT(7), BIT(7));
#else
                SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK01_03_L, BIT(7), BIT(7));
#endif
                Hal_SC_ip_set_user_def_interlace_status(pInstance, DISABLE, DISABLE, eWindow);

                //disable VRR FSM
                MHal_XC_SetVRRFSM_Enable(pInstance, FALSE);
                PCMSG(printf("[VRR] FSM disable\n"));
            }

            return FALSE;
        }
    }
    else //non-hdmi source
    {
        PCMSG(printf("[VRR] non-hdmi source\n"));

        if (MHal_XC_GetVRRFSM_Enable(pInstance))
        {
            if (gSrcInfo[eWindow].bAutoNoSignalEnabled)
            {
                PCMSG(printf("[VRR] enable auto no signal function\n"));
                pXCResourcePrivate->stapiXC_PCMonitor._bEnableAutoNoSignalDetect[eWindow] = TRUE;
                Hal_SC_ip_set_IPAutoNoSignal(pInstance, ENABLE, eWindow);
                Hal_SC_ip_ForceDisableAutoNoSignal(pInstance, DISABLE, eWindow);
            }
            Hal_SC_Enable_AVMute(pInstance, eWindow);
            Hal_SC_ip_set_de_only_mode(pInstance, ENABLE, eWindow);
#if (XC_SUPPORT_FASTSWITCH_BY_IP1GP==TRUE)
            SC_W2BYTEMSK(psXCInstPri->u32DeviceID, MHal_XC_FSS_BankTransfer(pInstance, REG_SC_BK01_03_L, eWindow), BIT(7), BIT(7));
#else
            SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK01_03_L, BIT(7), BIT(7));
#endif
            Hal_SC_ip_set_user_def_interlace_status(pInstance, DISABLE, DISABLE, eWindow);

            //disable VRR FSM
            MHal_XC_SetVRRFSM_Enable(pInstance, FALSE);
            PCMSG(printf("[VRR] FSM disable\n"));
        }

        return FALSE;
    }

    return FALSE;
}

//*************************************************************************
//Function name:    MApi_XC_PCMonitor
//Passing parameter:    none
//Return parameter: none
//Description:          Monitor signal timing from analog port
//
//Attention: !!!!!!------ Don't put UI/CC code in this function,
//           if need, you can use in "MApp_PCMode_PrepareForTimingChange" ------!!!!!!
//
//*************************************************************************
XC_PCMONITOR_STATUS MApi_XC_PCMonitor_U2(void* pInstance, INPUT_SOURCE_TYPE_t eCurrentSrc, SCALER_WIN eWindow)
{
//#ifdef VGA_PATH_WITH_AUDIO
    //static bit bNoSyncStatus=0;
//#endif
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    PCMSG(static MS_BOOL bNoSyncStatus = TRUE);
    XC_PCMONITOR_HK_INFO stPCMonitorInfo = {0};
#if (XC_SUPPORT_FASTSWITCH_BY_IP1GP==TRUE)
    EN_PCMONITOR_SOURCE_TYPE_t enPcMonitorSrc = MHal_XC_InputSrcToPCMonitorSrc(pInstance, eCurrentSrc);
#endif

    MDrv_XC_CheckSubWinForFSS(pInstance, &eWindow);

    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, INPUT_SOURCE_NONE);
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);

#if (XC_SUPPORT_FASTSWITCH_BY_IP1GP==TRUE)
    if(MDrv_XC_IsFSSEnabled(pInstance, eWindow))
    {
        if(eWindow == MAIN_WINDOW)
        {
            _geMainCurrentSrc = eCurrentSrc;
        }
        else
        {
            _geSubCurrentSrc = eCurrentSrc;
            if(enPcMonitorSrc == E_PCMONITOR_SOURCE_INVALID)
            {
                return stPCMonitorInfo.eCurrentState; //if MHal_XC_InputSrcToPCMonitorSrc=E_PCMONITOR_SOURCE_NUM, it will access memory out of bonds.
            }

            return enPCMOnitorOfflineStatus[enPcMonitorSrc];
        }
    }
#endif
    XC_RESOURCE_PRIVATE* pXCResourcePrivate = NULL;
    MS_U8 u8Interlace = 0;

    if(MDrv_SC_Check_IP_Gen_Timing(pInstance))
    {
        //it ip gen timing case, we need to return previous state to AP to keep everything unchanged.
        return stPCMonitorInfo.eCurrentState;
    }

    if(stPCMonitorInfo.eCurrentSrc != eCurrentSrc)
    {
        PCMSG(printf("Restart src %d\n", eCurrentSrc));
        if (MDrv_XC_IsSupportVRR())
        {
            MDrv_XC_PCMonitor_VRR_RestoreHDMIStatus(pInstance, eWindow);
        }
        _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR)
        MDrv_XC_PCMonitor_Restart(pInstance, eWindow, INPUT_SOURCE_NONE);             // source changed, restart monitor
        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, INPUT_SOURCE_NONE);
        stPCMonitorInfo.eCurrentSrc = eCurrentSrc;
        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);

        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, INPUT_SOURCE_NONE);
        MDrv_XC_PCMonitor_Update_TimingCount(pInstance, eCurrentSrc, eWindow);
#if (XC_SUPPORT_FASTSWITCH_BY_IP1GP==TRUE)
        if(MDrv_XC_IsFSSEnabled(pInstance, eWindow))
        {
            UtopiaResourceGetPrivate(g_pXCResource[_XC_SELECT_INTERNAL_VARIABLE(psXCInstPri->u32DeviceID)],(void**)(&pXCResourcePrivate));
            stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, MAX_WINDOW, eCurrentSrc);
            if(_MApi_XC_PCMonitor_Offline_DoesCurrentSourceSupportFSS(pInstance, eCurrentSrc))
            {
                MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);

                if (stPCMonitorInfo.eCurrentState == E_XC_PCMONITOR_STABLE_SYNC)
                {
#if (defined(MSOS_TYPE_LINUX_KERNEL) && defined(CONFIG_MSTAR_XC_HDR_SUPPORT))
                    ST_KDRV_HDMI_SHARE_MEMORY_INFO stHdmiShareMemInfo;
                    memset(&stHdmiShareMemInfo, 0, sizeof(ST_KDRV_HDMI_SHARE_MEMORY_INFO));
                    stHdmiShareMemInfo.bIsStartEmpDma= TRUE;

                    KDrv_XC_SetHdmiShareMemInfo(&stHdmiShareMemInfo);
#endif
                }

                if(enPcMonitorSrc == E_PCMONITOR_SOURCE_INVALID)
                {
                    return stPCMonitorInfo.eCurrentState; //if MHal_XC_InputSrcToPCMonitorSrc=E_PCMONITOR_SOURCE_NUM, it will access memory out of bonds.
                }
                gSrcInfo[eWindow].Status2.u8IP_PixelRep = pXCResourcePrivate->stdrvXC_IP.u8IpPixelRepOffline[enPcMonitorSrc];
            }
        }
#endif

        _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    }

    if (MDrv_XC_IsSupportVRR())
    {
        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, INPUT_SOURCE_NONE);
        _MApi_XC_PCMonitor_Update_IP_and_VRRFSM(pInstance, stPCMonitorInfo, eWindow);
    }

    //printf("PCMonitor %d, %ld, %ld\n", psPCMONITOR_HK_Info[eWindow]->bInputTimingChange,
    //        psPCMONITOR_HK_Info[eWindow]->u32LastExecutedTime,
    //        OS_SYSTEM_TIME());

    if((IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc) || IsSrcTypeDVI(stPCMonitorInfo.eCurrentSrc)) &&
        (stPCMonitorInfo.eCurrentState == E_XC_PCMONITOR_STABLE_SYNC) &&
        (MDrv_XC_PCMonitor_HDMISignalStable(pInstance, stPCMonitorInfo.eCurrentSrc) == FALSE))
    {
        // update last executed time
        _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR)
        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, INPUT_SOURCE_NONE);
        stPCMonitorInfo.u32LastExecutedTime = MsOS_GetSystemTime();
        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);
        _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    }
    else if((FALSE == stPCMonitorInfo.bInputTimingChange) &&
        (MsOS_GetSystemTime() - stPCMonitorInfo.u32LastExecutedTime < PC_POLLING_COUNTER))
    {
        _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR);
        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);
        _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
        PCMSG(printf("Please wait %ums until next polling\n", PC_POLLING_COUNTER));

        return stPCMonitorInfo.eCurrentState;
    }
    else
    {
        // update last executed time
        _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR)
        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, INPUT_SOURCE_NONE);
        stPCMonitorInfo.u32LastExecutedTime = MsOS_GetSystemTime();
        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);
        _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
    }

    if(_MApi_XC_PCMonitor_IsStartOfStablizationPeriod(pInstance, eWindow))
    {
        PC_GET_SYSTEM_TIME(_gs64PcStableSyncTimeStart);
    }

    // DE-Bypass is applied in HDMI HV mode. It will ignore pixel repetition package from HDMI.
    // We use the software mointor to monitor this package.
    _XC_SEMAPHORE_ENTRY(pInstance,E_XC_ID_VAR)
    UtopiaResourceGetPrivate(g_pXCResource[_XC_SELECT_INTERNAL_VARIABLE(psXCInstPri->u32DeviceID)],(void**)(&pXCResourcePrivate));
    if( (IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc) || IsSrcTypeDVI(eCurrentSrc) )
      &&(MDrv_XC_GetHdmiSyncMode(pInstance) == HDMI_SYNC_HV)
      &&(eWindow == MAIN_WINDOW) )
    {
        MS_U8 u8CurHDMIPixelRep = MDrv_HDMI_avi_infoframe_info(_BYTE_5)& 0x0F;

        MS_U8 u8IpPixelRep = gSrcInfo[eWindow].Status2.u8IP_PixelRep;
        if( u8CurHDMIPixelRep != u8IpPixelRep)
        {
            if( u8CurHDMIPixelRep )
            {
                //printf("daniel_test PC HV mode: Pixel-Rep=1 FIR=81\n");
                // If avi pkg report pixel repetition, IP1 should enable divider.
                MApi_XC_SetFIRDownSampleDivider(pInstance, ENABLE,0x01,eWindow);
            }
            else
            {
                //printf("daniel_test PC HV mode: Pixel-Rep=0 FIR=0\n");
                MApi_XC_SetFIRDownSampleDivider(pInstance, DISABLE,0x00,eWindow);
            }
            //_s_u32LastResetTime = MsOS_GetSystemTime();
            //MApi_XC_SoftwareReset(REST_IP_F2, eWindow);

            stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, INPUT_SOURCE_NONE);
            stPCMonitorInfo.bInputTimingChange = TRUE;
            MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);

            //printf("@@@--- HDMI Pixel-Rep change from [%u] to [%u]\n", gSrcInfo[eWindow].Status2.u8IP_PixelRep, u8CurHDMIPixelRep);
            gSrcInfo[eWindow].Status2.u8IP_PixelRep = u8CurHDMIPixelRep;
        }
    }

    //--------------------------------------------------
    //display active or no signal?
    if ( stPCMonitorInfo.bInputTimingChange == FALSE ) // check timing change flag have be setting
    {
        if ( MDrv_XC_PCMonitor_SyncLoss(pInstance, eWindow, INPUT_SOURCE_NONE) ) // no sync
        {
            MDrv_XC_SetSogDetectStatus(pInstance, pXCResourcePrivate->stapiXC_PCMonitor.g_u8RGBSOG_DetectStatus);
            if ( _MApi_XC_PCMonitor_DetectSync(pInstance, stPCMonitorInfo.eCurrentSrc,eWindow) ) // check signal active
            {
                stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, INPUT_SOURCE_NONE);
                stPCMonitorInfo.bInputTimingChange = TRUE;
                MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);
                PCMSG(if(bNoSyncStatus) printf("NewSync\n"); bNoSyncStatus = FALSE);
            }
            else
            {
                PCMSG(if(!bNoSyncStatus) printf("NoSync\n"); bNoSyncStatus = TRUE);
            }
        }
        else //have sync?
        {
            _XC_ENTRY(pInstance);
            if(gSrcInfo[eWindow].bAutoNoSignalEnabled && pXCResourcePrivate->stapiXC_PCMonitor._bEnableAutoNoSignalDetect[eWindow])
            {
                // check invalid
                if (( MDrv_XC_PCMonitor_InvalidTimingDetect(pInstance, TRUE, eWindow, INPUT_SOURCE_NONE)))
                {
                    ++pXCResourcePrivate->stapiXC_PCMonitor.u8DeNoiseCount[eWindow];

                    // PC monitor have to changed when auto nosignal enabled.
                    // If no signal bit is enabled, that's treaded as no-signal
                    // Here have to update variables for hw-detected-no-signal.
                    if ((pXCResourcePrivate->stapiXC_PCMonitor.u8DeNoiseCount[eWindow] > 3) ||
                        (_MApi_XC_PCMonitor_SkipUnstableDebounce(pInstance, eWindow, INPUT_SOURCE_NONE) == TRUE))
                    {
                        Hal_SC_ip_set_IPAutoNoSignal(pInstance, DISABLE, MAIN_WINDOW);
                        #if ((HW_DESIGN_4K2K_VER >= 4) || (HW_DESIGN_4K2K_VER == 1))
                        // if enable input source before video mute, it would shows temp garbage
                        // so need to mute video first before enable input source
                        MDrv_SC_GenerateBlackVideo(pInstance, TRUE, eWindow );
                        #if (HW_DESIGN_4K2K_VER >= 4)
                        if( (MDrv_XC_Get_3D_Output_Mode(pInstance) == E_XC_3D_OUTPUT_TOP_BOTTOM_HW)
                            || (MDrv_XC_Get_3D_Output_Mode(pInstance) == E_XC_3D_OUTPUT_TOP_BOTTOM)
                            || (MDrv_XC_Get_3D_Output_Mode(pInstance) == E_XC_3D_OUTPUT_SIDE_BY_SIDE_HALF_HW)
                            || (MDrv_XC_Get_3D_Output_Mode(pInstance) == E_XC_3D_OUTPUT_SIDE_BY_SIDE_HALF)
                            || (MDrv_XC_Get_3D_Output_Mode(pInstance) == E_XC_3D_OUTPUT_FRAME_PACKING)
                            || (MDrv_XC_Get_3D_Output_Mode(pInstance) == E_XC_3D_OUTPUT_LINE_ALTERNATIVE)
                        )
                        {
                        #if PIP_PATCH_USING_SC1_MAIN_AS_SC0_SUB
                            MDrv_SC_GenerateBlackVideo(g_pDevice1Instance, TRUE,  MAIN_WINDOW);
                        #else
                            MDrv_SC_GenerateBlackVideo(pInstance, TRUE,  SUB_WINDOW);
                        #endif
                        }

                        // Only SW patch for YPbPr timing change case, reset IP1 to avoid HW Auto No signal not work
                        if((MAIN_WINDOW == eWindow) && IsSrcTypeYPbPr(stPCMonitorInfo.eCurrentSrc))
                        {
                            Hal_SC_ip_software_reset(pInstance, REST_IP_F2, MAIN_WINDOW);
                        }
                        #endif
                        #endif
                        MDrv_XC_DisableInputSource(pInstance, DISABLE, eWindow, stPCMonitorInfo.eCurrentSrc); //enable the input source
                        if(MDrv_XC_PCMonitor_InvalidTimingDetect(pInstance, FALSE, eWindow, INPUT_SOURCE_NONE))
                        {
                            printf("Do nothing\n");
                        }
                        PCMSG(printf("InvalidTimingDetect GO TO UNSTABLE! \n" )) ;
                        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, INPUT_SOURCE_NONE);
                        stPCMonitorInfo.u8SyncStatus |= XC_MD_SYNC_LOSS;
                        stPCMonitorInfo.bInputTimingChange = TRUE;
                        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);
                        pXCResourcePrivate->stapiXC_PCMonitor.u8DeNoiseCount[eWindow] = 0;
                    }
                }
                else // time stable
                {
                    if( gSrcInfo[eWindow].bAutoNoSignalEnabled )
                    {
                        if( MDrv_XC_IsInputSourceDisabled(pInstance, eWindow, stPCMonitorInfo.eCurrentSrc)&&(pXCResourcePrivate->stapiXC_PCMonitor.u8DeNoiseCount[eWindow]!=0)
                        &&(stPCMonitorInfo.eCurrentState == E_XC_PCMONITOR_STABLE_SYNC) )
                        {
                            MDrv_XC_DisableInputSource(pInstance, DISABLE, eWindow, stPCMonitorInfo.eCurrentSrc); //enable the input source
                            pXCResourcePrivate->stapiXC_PCMonitor.u8DeStableCnt[eWindow] = 0;
                        }
                        else
                        {
                            pXCResourcePrivate->stapiXC_PCMonitor.u8DeStableCnt[eWindow]++;
                        }
                    }

                    if((pXCResourcePrivate->stapiXC_PCMonitor.u8DeStableCnt[eWindow] ==20) && MDrv_XC_IsInputSourceDisabled(pInstance, eWindow, stPCMonitorInfo.eCurrentSrc)) // to check the input source status
                    {
                        MDrv_XC_DisableInputSource(pInstance, DISABLE, eWindow, stPCMonitorInfo.eCurrentSrc);
                        pXCResourcePrivate->stapiXC_PCMonitor.u8DeStableCnt[eWindow]=0;
                    }

                    if(pXCResourcePrivate->stapiXC_PCMonitor.u8DeStableCnt[eWindow] >=20)
                    {
                        pXCResourcePrivate->stapiXC_PCMonitor.u8DeStableCnt[eWindow] = 0;
                    }

                    pXCResourcePrivate->stapiXC_PCMonitor.u8DeNoiseCount[eWindow] = 0;
                }
            }
            else if ( MDrv_XC_PCMonitor_InvalidTimingDetect(pInstance, FALSE, eWindow, INPUT_SOURCE_NONE) ) // check invalid sync
            {
                PCMSG(printf("InvalidTimingDetect GO TO UNSTABLE! \n" )) ;
                stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, INPUT_SOURCE_NONE);
                stPCMonitorInfo.u8SyncStatus |= XC_MD_SYNC_LOSS;
                stPCMonitorInfo.bInputTimingChange = TRUE;
                MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);
                MDrv_DVI_Accumulator_Monitor();
            }

            _XC_RETURN(pInstance);

            #if ENABLE_IP_AUTO_COAST
            if ( IsSrcTypeVideo(stPCMonitorInfo.eCurrentSrc) )
            {
                msAPI_Scaler_IPAutoCoastHandler();
            }
            #endif
        }
    }

    //is input timing changed and check debounce
    //--------------------------------------------------
    if ( stPCMonitorInfo.bInputTimingChange) // input timing is unstable
    {
        PCMSG(printf("TimingChg\n"));
        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, INPUT_SOURCE_NONE);
        stPCMonitorInfo.bInputTimingChange = FALSE;
        stPCMonitorInfo.ucTimingChangeDebounce++;

        PCMSG(printf("Deb=%d\n", stPCMonitorInfo.ucTimingChangeDebounce));

        if ( !MDrv_XC_PCMonitor_SyncLoss(pInstance, eWindow, INPUT_SOURCE_NONE) ) // have signal
        {
            if ( stPCMonitorInfo.ucTimingChangeDebounce <= 3 ) // prevent from SOG
            {
                if ( IsSrcTypeYPbPr(stPCMonitorInfo.eCurrentSrc ) ||
                     IsSrcTypeVga(stPCMonitorInfo.eCurrentSrc )  )
                {
                    stPCMonitorInfo.u8SyncStatus |= XC_MD_SYNC_LOSS;
                    MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);
                    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
                    return stPCMonitorInfo.eCurrentState;
                }
            }
        }
        else
        {
            if ( IsSrcTypeYPbPr(stPCMonitorInfo.eCurrentSrc ) ||
                 IsSrcTypeVga(stPCMonitorInfo.eCurrentSrc )  )
            {
                // System have to set free run as soon as possible when timing unstable.
                MDrv_XC_ADC_Set_Freerun(pInstance, TRUE);
                MDrv_XC_ADC_ATOP_iClamp_RGB_PowerDown(pInstance, TRUE);
            }
        }

        stPCMonitorInfo.eCurrentState = E_XC_PCMONITOR_UNSTABLE;
        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);

        _MApi_XC_PCMonitor_PrepareForTimingChange(pInstance, eWindow, INPUT_SOURCE_NONE);

        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, INPUT_SOURCE_NONE);
        // Already enter timing change, turn off AutoNoSignal
        if( gSrcInfo[eWindow].bAutoNoSignalEnabled )
        {
            //MApi_XC_EnableIPAutoNoSignal(FALSE, eWindow);
            pXCResourcePrivate->stapiXC_PCMonitor._bEnableAutoNoSignalDetect[eWindow] = FALSE;
            Hal_SC_ip_set_IPAutoNoSignal(pInstance, DISABLE, eWindow);
            MDrv_XC_DisableInputSource(pInstance, DISABLE, eWindow, stPCMonitorInfo.eCurrentSrc);
            // HW PIP architeucture
            // sub's input source and extra request should always enable/disable together
            if(MDrv_XC_IsInputSourceDisabled(pInstance, eWindow, stPCMonitorInfo.eCurrentSrc) && (eWindow == SUB_WINDOW))
            {
                MDrv_XC_Enable_Extra_Request(pInstance, FALSE);
            }
            //printf("daniel_test AutoNoSignal=0 t=%lu %s\n", MsOS_GetSystemTime(), __FUNCTION__);
        }
    }
    else // input timing is stable
    {
        stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, INPUT_SOURCE_NONE);
        stPCMonitorInfo.ucTimingChangeDebounce = 0; // reset timing change debounce counter

        stPCMonitorInfo.ucInputTimingStableCounter++; // timing stable counter

        if ( stPCMonitorInfo.ucInputTimingStableCounter == 0 )
            stPCMonitorInfo.ucInputTimingStableCounter = 1;

        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);
        if ( !stPCMonitorInfo.bInputTimingStable )
        {
#ifndef MSOS_TYPE_LINUX_KERNEL
            MS_ASSERT(pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter[eWindow] > 0);
            MS_ASSERT(pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter[eWindow] > 0);
#endif
            if( ((!MDrv_XC_PCMonitor_SyncLoss(pInstance, eWindow, INPUT_SOURCE_NONE)) && (stPCMonitorInfo.ucInputTimingStableCounter >= pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter[eWindow])) ||
                (MDrv_XC_PCMonitor_SyncLoss(pInstance, eWindow, INPUT_SOURCE_NONE) && (stPCMonitorInfo.ucInputTimingStableCounter >= pXCResourcePrivate->stapiXC_PCMonitor._u16TimingNosyncCounter[eWindow])) )
            {
                stPCMonitorInfo.bInputTimingStable = TRUE;
                MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);
                //g_PcadcModeSetting.u8ModeIndex = 0;  // reset mode index
                pXCResourcePrivate->stapiXC_PCMonitor.g_u8RGBSOG_DetectStatus = MDrv_XC_GetSogDetectStatus(pInstance);

                if (MDrv_XC_GetVGASogEn(pInstance))     // Daten FixMe -> Please refine VGA SOG flow
                {
                    if(IsSrcTypeVga(stPCMonitorInfo.eCurrentSrc) &&  // Is RGB in
                        (!MDrv_XC_PCMonitor_SyncLoss(pInstance, eWindow, INPUT_SOURCE_NONE)) &&                     // Has signal
                        ((pXCResourcePrivate->stapiXC_PCMonitor.g_u8RGBSOG_DetectStatus & (0x0001) ) == (0x0001)) &&          // In detecting SOG
                        (!((pXCResourcePrivate->stapiXC_PCMonitor.g_u8RGBSOG_DetectStatus & (0x0002)) == (0x0002))))         // 1st time detecting SOG

                    {
                        // only if RGB input, has sync and in SOG detecting enter here
                        // force to check from other sync type again.
                        pXCResourcePrivate->stapiXC_PCMonitor.g_u8RGBSOG_DetectStatus |= (0x0002);
                        stPCMonitorInfo.u8SyncStatus ^= XC_MD_VSYNC_POR_BIT;

                        stPCMonitorInfo.bInputTimingStable = TRUE;
                        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);
                    }
                    else
                    {
                        if(!MDrv_XC_PCMonitor_SyncLoss(pInstance, eWindow, INPUT_SOURCE_NONE))
                        {
                            // has sync, no matter what sync detected, clear the SOG_DETECTED_BIT
                            pXCResourcePrivate->stapiXC_PCMonitor.g_u8RGBSOG_DetectStatus &= ~(0x0002);
                        }
                        if((pXCResourcePrivate->stapiXC_PCMonitor.g_u8RGBSOG_DetectStatus & (0x0001)) &&
                             (MDrv_XC_PCMonitor_SyncLoss(pInstance, eWindow, INPUT_SOURCE_NONE)))
                        {
                            // in detecting the SOG and no Sync, clear the SOG_DETECTED_BIT
                            pXCResourcePrivate->stapiXC_PCMonitor.g_u8RGBSOG_DetectStatus &= ~(0x0002);
                        }
                        stPCMonitorInfo.bInputTimingStable = TRUE;

                        MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);
                    }
                }

                if(MDrv_XC_PCMonitor_SyncLoss(pInstance, eWindow, INPUT_SOURCE_NONE))
                {
                    stPCMonitorInfo.eCurrentState = E_XC_PCMONITOR_STABLE_NOSYNC;
                    MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);
                }
                else
                {
                    stPCMonitorInfo.eCurrentState = E_XC_PCMONITOR_STABLE_SYNC;
                    // for get accurate v freq, need call msAPI_Scaler_Field_Detect and MDrv_XC_ADC_Set_Freerun
                    u8Interlace = Hal_SC_ip_get_interlace_status(pInstance, eWindow);
                    msAPI_Scaler_Field_Detect(pInstance, stPCMonitorInfo.eCurrentSrc, ((u8Interlace == 1)?SCAN_INTERLACE:SCAN_PROGRESSIVE), eWindow);
                    if ( IsSrcTypeYPbPr(stPCMonitorInfo.eCurrentSrc ) ||
                        IsSrcTypeVga(stPCMonitorInfo.eCurrentSrc )  )
                    {
                        MDrv_XC_ADC_Set_Freerun(pInstance, FALSE);
                    }
                    // Update V sync time when timing stable.
                    stPCMonitorInfo.u16VSyncTime = MApi_XC_CalculateVsyncTime(pInstance, stPCMonitorInfo.u16Vtotal, stPCMonitorInfo.u16Hperiod);
                    MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);
                    if ( IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc ) )
                    {
                        _MApi_XC_PCMonitor_FPi_Patch(pInstance, eWindow, stPCMonitorInfo.eCurrentSrc);
                    }
                    // error flow: setwindow ->MDrv_XC_ADC_Reload -> enable auto nosignal -> htt change because ADC reload -> auto no signal disable input source(HW) -> load PQ -> unmute
                    // it's not flash buffer because load PQ in disable input source
                    // so here is not enable auto nosignal when video mute
                    MDrv_XC_DisableInputSource(pInstance, DISABLE, eWindow, stPCMonitorInfo.eCurrentSrc);
                    if(gSrcInfo[eWindow].bAutoNoSignalEnabled)
                    {
                        //YPbPr have some garbage when enable the auto signal detect.
                        if((!IsSrcTypeYPbPr(stPCMonitorInfo.eCurrentSrc)) || (!MDrv_SC_CheckMuteStatusByRegister(pInstance,  eWindow)))
                        {
                            pXCResourcePrivate->stapiXC_PCMonitor._bEnableAutoNoSignalDetect[eWindow] = TRUE;
                            Hal_SC_ip_set_IPAutoNoSignal(pInstance, ENABLE,eWindow);
                        }
                    }
                    //_MApi_XC_PCMonitor_ModeParse(eWindow);

                    //Update HDMI 2.1 & HFR status
                    if(IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc))
                    {
                        _MApi_XC_PCMonitorCheckHfr(pInstance, stPCMonitorInfo, eWindow);
                    }
                }

                PCMSG(printf("*** Do Mode In Analog Path ***\n"));

                _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);
                return stPCMonitorInfo.eCurrentState;
            }
        }

        if(gSrcInfo[eWindow].bAutoNoSignalEnabled)
        {
            _XC_ENTRY(pInstance);
            if(( stPCMonitorInfo.eCurrentState == E_XC_PCMONITOR_STABLE_SYNC)
                &&(stPCMonitorInfo.ucInputTimingStableCounter
                    >=pXCResourcePrivate->stapiXC_PCMonitor._u16TimingStableCounter[eWindow])
                &&(!Hal_SC_ip_get_IPAutoNoSignal(pInstance, eWindow))&&(!MDrv_XC_IsInputSourceDisabled(pInstance, eWindow, stPCMonitorInfo.eCurrentSrc)))
            {
                // error flow: setwindow ->MDrv_XC_ADC_Reload -> enable auto nosignal -> htt change because ADC reload -> auto no signal disable input source(HW) -> load PQ -> unmute
                // it's not flash buffer because load PQ in disable input source
                // so here is not enable auto nosignal when video mute
                if((!IsSrcTypeYPbPr(stPCMonitorInfo.eCurrentSrc)) || (!MDrv_SC_CheckMuteStatusByRegister(pInstance,  eWindow)))
                {
                    //when signal stable, enable the auto signal detect.
                    pXCResourcePrivate->stapiXC_PCMonitor._bEnableAutoNoSignalDetect[eWindow] = TRUE;
                    Hal_SC_ip_set_IPAutoNoSignal(pInstance, ENABLE,eWindow);
                }
            }
			_XC_RETURN(pInstance);
        }

    }

    //Mantis issue of 0270665. Set the DE HV Mode when pre monitor state is E_XC_PCMONITOR_UNSTABLE .
    if((IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc) || IsSrcTypeDVI(stPCMonitorInfo.eCurrentSrc) )
        && ((stPCMonitorInfo.ePreMonitorState == E_XC_PCMONITOR_UNSTABLE)
            || (stPCMonitorInfo.ePreMonitorState == E_XC_PCMONITOR_STABLE_NOSYNC)))
    {
        MDrv_XC_Switch_DE_HV_Mode_By_Timing(pInstance, eWindow);
    }

    if (IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc) || IsSrcTypeDVI(stPCMonitorInfo.eCurrentSrc))
    {
#if SUPPORT_IP_HDMI_FOR_HV_MODE
        MDrv_XC_Switch_DE_HV_Mode_By_Timing(pInstance, eWindow);
#else
        //MDrv_XC_Set_DE_Lock_Mode(pInstance, eWindow);
#endif
        MDrv_DVI_HF_adjust_internal();
    }

    _XC_ENTRY(pInstance);
    MDrv_XC_NewModeInterlacedDetect(pInstance, eWindow, stPCMonitorInfo.eCurrentSrc);
    _XC_RETURN(pInstance);

    stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, INPUT_SOURCE_NONE);
    stPCMonitorInfo.ePreMonitorState = stPCMonitorInfo.eCurrentState;
    MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);
    _XC_SEMAPHORE_RETURN(pInstance,E_XC_ID_VAR);

#ifdef MSOS_TYPE_LINUX_KERNEL
    if(pXCResourcePrivate->stdrvXC_MVideo.bTimingUnstableForStr == TRUE)
    {
        if(pXCResourcePrivate->stdrvXC_MVideo.u8DebounceForStr < TIMING_CHANGE_DEBOUNCE_FOR_STR)
        {
            stPCMonitorInfo = MDrv_XC_PCMonitor_GetStatus(pInstance, eWindow, INPUT_SOURCE_NONE);
            stPCMonitorInfo.eCurrentState = E_XC_PCMONITOR_UNSTABLE;
            stPCMonitorInfo.bInputTimingChange = TRUE;
            stPCMonitorInfo.ePreMonitorState = stPCMonitorInfo.eCurrentState;
            MDrv_XC_PCMonitor_SetStatus(pInstance, stPCMonitorInfo, eWindow, INPUT_SOURCE_NONE);
            ++(pXCResourcePrivate->stdrvXC_MVideo.u8DebounceForStr);
        }
        else
        {
            pXCResourcePrivate->stdrvXC_MVideo.bTimingUnstableForStr = FALSE;
            pXCResourcePrivate->stdrvXC_MVideo.u8DebounceForStr = 0;
        }
    }
#endif
    if(IsSrcTypeHDMI(stPCMonitorInfo.eCurrentSrc))
    {
        _MApi_XC_PCMonitorCheckHfr(pInstance, stPCMonitorInfo, eWindow);
    }

    if(_MApi_XC_PCMonitor_IsEndOfStablizationPeriod(pInstance, eWindow, stPCMonitorInfo.eCurrentState) == TRUE)
    {
        PC_GET_SYSTEM_TIME(_gs64PcStableSyncTimeEnd);
        gSrcInfo[eWindow].s64SrcChgTime = _gs64PcStableSyncTimeEnd - _gs64PcStableSyncTimeStart;
        if(MDrv_XC_IsReasonableSrcChgTime(pInstance, eWindow, eCurrentSrc, gSrcInfo[eWindow].s64SrcChgTime) == TRUE)
        {
            gSrcInfo[eWindow].bIsSrcChgTimeReasonable = TRUE;
        }
        else
        {
            gSrcInfo[eWindow].bIsSrcChgTimeReasonable = FALSE;
        }
    }

    return stPCMonitorInfo.eCurrentState;
}

#ifndef UTOPIAXP_REMOVE_WRAPPER
XC_PCMONITOR_STATUS MApi_XC_PCMonitor(INPUT_SOURCE_TYPE_t eCurrentSrc, SCALER_WIN eWindow)
{
    if (pu32XCInst == NULL)
    {
        printf("[%s,%5d]No instance existed, please get an instance by calling MApi_XC_Init() first\n",__FUNCTION__,__LINE__);
        return E_XC_PCMONITOR_STABLE_NOSYNC;
    }

    stXC_PCMONITOR XCArgs;
    XCArgs.eCurrentSrc = eCurrentSrc;
    XCArgs.eWindow = eWindow;
    XCArgs.eReturnValue = E_XC_PCMONITOR_STABLE_NOSYNC;

    if(UtopiaIoctl(pu32XCInst, E_XC_PCMONITOR_CMD, (void*)&XCArgs) != 0)
    {
        printf("Obtain XC engine fail\n");
        return E_XC_PCMONITOR_STABLE_NOSYNC;
    }
    else
    {
        return XCArgs.eReturnValue;
    }
}
#endif
#undef _API_XC_PC_MONITOR_C_
#endif  // _API_XC_PC_MONITOR_C_
#endif
