//<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) 2008-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.
//
////////////////////////////////////////////////////////////////////////////////
//==============================================================================
// [mhal_frc.c]
// Date: 20081203
// Descriptions: Add a new layer for HW setting
//==============================================================================
#define  MHAL_FRC_C

//-------------------------------------------------------------------------------------------------
//  Include files
//-------------------------------------------------------------------------------------------------
#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

// Common Definition
#include "MsCommon.h"
#include "MsIRQ.h"
#include "MsOS.h"

#include "mhal_xc_chip_config.h"
#include "utopia_dapi.h"
// Registers
#include "drvXC_IOPort.h"
#include "xc_hwreg_utility2.h"
#include "hwreg_adc_atop.h"
#include "hwreg_adc_dtop.h"
//#include "hwreg_chiptop.h"
#include "hwreg_hdmi.h"
#include "hwreg_pm_sleep.h"//alex_tung
#include "hwreg_ipmux.h"

#include "apiXC.h"

#include "xc_Analog_Reg.h"

#include "mhal_mux.h"
#include "drv_sc_display.h"
#include "drv_sc_isr.h"
#include "apiXC_Adc.h"
#include "apiXC_Auto.h"
#include "apiXC_PCMonitor.h"
#include "apiXC_ModeParse.h"
#include "drvXC_ADC_Internal.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 "mvideo_context.h"
#include "drv_sc_ip.h"
#include "mhal_adc.h"
#include "drvXC_HDMI_if.h"
#include "drvXC_HDMI_Internal.h"
#include "mhal_sc.h"
#include "mhal_hdmi.h"

#include "mdrv_frc.h"
#include "mhal_frc.h"
#include "drvMBX.h"
#include "apiMBX.h"
//#include "MHal_FRC_4K2K_QualityMap.h"

#include "XC_private.h"
#include "halCHIP.h"
#include "mdrv_sc_dynamicscaling.h"
#include "mhal_dynamicscaling.h"
#include "drvMIU.h"

#ifdef STELLAR
#include "apiPNL.h"
MS_BOOL MApi_PNL_GetStatusEx(PNL_ApiExtStatus *pPnlExtStatus);
#endif
//--------------------------------------------------------------------------------------------------
//  Macro definition
//--------------------------------------------------------------------------------------------------

#ifdef STELLAR
#define FRC_MIU_diversion_patch 1
#endif

#if (TGEN_VTT_LOCK_MODE_VER > 0)
#define  V_FREQ_UPPER_50HZ  (505)
#define  V_FREQ_LOWER_50HZ  (495)
#define  VTT_4K_UPPER_50HZ  (2739)
#define  VTT_4K_LOWER_50HZ  (2659)
#define  VTT_4K_UPPER_60HZ  (2286)
#define  VTT_4K_LOWER_60HZ  (2238)
#define  VTT_FHD_UPPER_50HZ  (1368)
#define  VTT_FHD_LOWER_50HZ  (1337)
#define  VTT_FHD_UPPER_60HZ  (1136)
#define  VTT_FHD_LOWER_60HZ  (1114)
#define  VTT_DELTA  (2)
#define VTT_BOUNDARY_RATIO  (10)  // 1 means +-0.1% // 1%
#define VTT_LOWER_PROTECT_THRESHOLD (1)

#define  POSDIFF(a,b)           (((a) > (b)) ? ((a)-(b)):0)
#endif

#define PHASE_DIFF_STABLE_CRITERIA (10)
#define VTT_VARIATION_LOCK_DEBOUNCE (3)

//-------------------------------------------------------------------------------------------------
//  Local Variables
//-------------------------------------------------------------------------------------------------

////#define CONFIG_FPGA

MS_U16 g_u16LastOffsetH = 0;
MS_U16 g_u16LastOffsetV = 0;
#if (ENABLE_FIX_PP_DLY == TRUE)
static MS_U16 u16FSC_1X_HFDEOffset = 0;
#endif

#if (TGEN_VTT_LOCK_MODE_VER > 0)
static MS_U16 _u16TGEN_CentralVTT = 0;
#endif

//-------------------------------------------------------------------------------------------------
//  Debug Functions
//-------------------------------------------------------------------------------------------------
#define _u16FRCDbgSwitch 1

#define FRC_DBG_MSG(fmt,...)                                                                 \
    MS_DEBUG_MSG(do{                                                                                      \
        if(_u16FRCDbgSwitch){                                                                   \
           printf( "[FRC_DBG_MSG]: %s: %d \n"  fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
          }                                                                                  \
      } while(0))

#define FRC_PRINT_VAR(var)                                                                   \
    do{                                                                                      \
        if(_u16FRCDbgSwitch){                                                                   \
          FRC_DBG_MSG("%30s: %d\n", #var, (var));                                            \
          }                                                                                  \
      }while(0)

//-------------------------------------------------------------------------------------------------
//  Local Functions
//-------------------------------------------------------------------------------------------------
//static MS_FRC_RGBGAINOFFSET_INFO stGainOffsetSetting;
#ifdef PATCH_TCON_BRING_UP
        const char* MDrv_PNL_GetName(void);
#endif

//-------------------------------------------------------------------------------------------------
//for internal function
//-------------------------------------------------------------------------------------------------

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

//------------------------------------------------------------------------------
//  Exernal
//------------------------------------------------------------------------------


//======================================================================
// FRC TGEN
//======================================================================

void MHal_FRC_TGEN_Init(void *pInstance)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);

    #if 1 // for mantis 0915469: MM zoom display window position wrong, need wait for DS ready
    MHal_FRC_TGEN_Enable_Lock_Source(pInstance, ENABLE, E_FRC_TGEN_LOCK_SOURCE_MODE_FROM_TGEN, FALSE);
    #endif

    //bk68_20[0]: reg_tg_lock_en: 0: free run, 1: lock mode
    //             [1]: reg_tg_lock_src_sel_usr_en
    //             [2]: reg_tg_lock_src_sel_usr: 1: from origin TGEN
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_20_L, (BIT(0)|BIT(1)|BIT(2)), (BIT(0)|BIT(1)|BIT(2)));

    //mload setting for op2 domain, set 0 from HW RD.
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_60_L, 0, 0x1FFF);

    //MHal_FRC_TGEN_Enable_LockMode(pInstance, ENABLE);
    //MHal_FRC_TGEN_Enable_Source_Select_Mode(pInstance, ENABLE);
    //MHal_FRC_TGEN_Set_Lock_Source(pInstance, E_FRC_TGEN_LOCK_SOURCE_MODE_FROM_TGEN);
}

#if (TGEN_VTT_LOCK_MODE_VER > 0)
void MHal_FRC_TGEN_VTT_StoreCentralVTT(void *pInstance, MS_U16 u16CentralVTT)
{
    _u16TGEN_CentralVTT = u16CentralVTT;
}

void MHal_FRC_TGEN_VttLockModeEnable(void *pInstance, MS_BOOL bEn)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_31_L, bEn?BIT(0):0x00, BIT(0));
    XC_LOG_TRACE(XC_DBGLEVEL_SETTIMING, "bEn = %d\n", bEn);
}

void MHal_FRC_TGEN_VTT_LOCK_PROTECT_ENABLE(void *pInstance, MS_BOOL bEn)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    //BK68_31[13]: describe at reg_lock_vtt_ud_sw_en
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_31_L, bEn?BIT(8):0x00, BIT(8));
    XC_LOG_TRACE(XC_DBGLEVEL_SETTIMING, "bEn = %d\n", bEn);
}

void MHal_FRC_TGEN_VTT_UD_SW_ENABLE(void *pInstance, MS_BOOL bEn)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    //BK68_31[13]: describe at reg_lock_vtt_ud_sw_en
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_31_L, bEn?BIT(13):0x00, BIT(13));
    XC_LOG_TRACE(XC_DBGLEVEL_SETTIMING, "bEn = %d\n", bEn);
}

void MHal_FRC_TGEN_VTT_LOCK_VTT_DIFF_LIMIT(void *pInstance, MS_BOOL bEn, MS_U16 u16DiffLimit)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_30_L, bEn?BIT(15):0x00, BIT(15));
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_30_L, u16DiffLimit, 0x3FFF);
    XC_LOG_TRACE(XC_DBGLEVEL_SETTIMING, "bEn = %d, u16DiffLimit = 0x%x\n", bEn,u16DiffLimit);
}

void MHal_FRC_TGEN_VTT_CENTAL_VTT_CHANGE(void *pInstance, MS_BOOL bEn, MS_U8 u8FrameCount, MS_U8 u8threshold)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    SC_EXT_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_EXT_BK2F_20_L, bEn?BIT(15):0x00, BIT(15));
    SC_EXT_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_EXT_BK2F_20_L, u8FrameCount<<8, 0x7F00);
    SC_EXT_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_EXT_BK2F_20_L, u8threshold, 0xFF);
    XC_LOG_TRACE(XC_DBGLEVEL_SETTIMING, "bEn = %d, u8FrameCount = 0x%x, u8threshold = 0x%x\n", bEn,u8FrameCount,u8threshold);
}

void MHal_FRC_TGEN_VTT_VAR_MODE_DATA_PATH(void *pInstance, MS_BOOL bEn)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    //BK68_2F[3]:vtt variation mode data path
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_2F_L, bEn?BIT(3):0x00, BIT(3));
    XC_LOG_TRACE(XC_DBGLEVEL_SETTIMING, "bEn = %d\n", bEn);
}

void MHal_FRC_TGEN_SetLockCentralVTotal(void* pInstance, MS_BOOL bEn, MS_U8 u8VframeCnt, MS_U8 u8threshold)
{
    MS_U16 u16Value = (u8VframeCnt << 8) | u8threshold;
    u16Value = (u16Value & 0x7FFF) | (bEn ? BIT(15) : 0);
    XC_LOG_TRACE(XC_DBGLEVEL_SETTIMING, "bEn = %d\n", bEn);
}

void MHal_FRC_TGEN_SetVTotalRange(void* pInstance, MS_U16 u16VFreq)
{
    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_U32 u32VttUpper =0, u32VttLower = 0;

    u32VttUpper = pXCResourcePrivate->stdrvXC_MVideo_Context.g_XC_InitData.stPanelInfo.u16VTotal * (1000 + VTT_BOUNDARY_RATIO)/1000;
    u32VttLower = pXCResourcePrivate->stdrvXC_MVideo_Context.g_XC_InitData.stPanelInfo.u16VTotal * (1000 - VTT_BOUNDARY_RATIO)/1000;

    //error handling if VTT < VDE end
    if(SC_R2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK10_07_L, 0x1FFF) >= u32VttLower)
    {
        u32VttLower = SC_R2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK10_07_L, 0x1FFF)+VTT_LOWER_PROTECT_THRESHOLD;
    }

    //BK68_36: upper vtt, BK68_37: lower vtt
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_36_L, (MS_U16)u32VttUpper , 0xFFFF);
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_37_L, (MS_U16)u32VttLower , 0xFFFF);
    XC_LOG_TRACE(XC_DBGLEVEL_SETTIMING, "u16VFreq = %u, u32VttUpper = %lu, u32VttLower = %lu\n", u16VFreq, u32VttUpper, u32VttLower);
}

void MHal_FRC_TGEN_ClearState(void *pInstance)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    //BK68_33[14]: clear ivs mask count
    //BK68_33[3]: state of trace reset
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_33_L, BIT(14)|BIT(3), BIT(14)|BIT(3));
    MsOS_DelayTask(1);
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_33_L, 0, BIT(14)|BIT(3));
    XC_LOG_TRACE(XC_DBGLEVEL_SETTIMING, "toggle, REG_SC_BK68_33_L[14][3]\n");
}

void MHal_FRC_TGEN_SetIvsOvs(void* pInstance, MS_U16 u16FrcIn, MS_U16 u16FrcOut)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    //BK68_32 ovs:ivs
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_32_L, u16FrcOut<<8 , 0xFF00);
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_32_L, u16FrcIn , 0x00FF);
    XC_LOG_TRACE(XC_DBGLEVEL_SETTIMING, "u16FrcIn = %d, u16FrcOut  = %d\n", u16FrcIn, u16FrcOut);
}

MS_BOOL MHal_FRC_TGEN_GetFPLLDoneStatus(void* pInstance)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    static MS_U8 _u8StableCnt = 0;
    static MS_U16 _u16PrePhaseDiff = 0;

    if( abs(SC_R2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_3C_L, 0x3FFF) - _u16PrePhaseDiff) <= PHASE_DIFF_STABLE_CRITERIA)
    {
        _u8StableCnt++;

        if ( _u8StableCnt > VTT_VARIATION_LOCK_DEBOUNCE)
        {
            _u8StableCnt = VTT_VARIATION_LOCK_DEBOUNCE;
        }
    }
    else
    {
        _u8StableCnt = 0 ;
    }

    _u16PrePhaseDiff = SC_R2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_3C_L, 0x3FFF);

    if (_u8StableCnt >= VTT_VARIATION_LOCK_DEBOUNCE )
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

void MHal_FRC_TGEN_CalculateVtt(void* pInstance)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
    static MS_U16 u16TGEN_CentralVTTPre = 0;
    static MS_U16 _u16VTotalResult = 0;
    static MS_U16 _u16NewCentral = 0;

    if(_u16TGEN_CentralVTT != u16TGEN_CentralVTTPre)
    {
        _u16NewCentral = _u16TGEN_CentralVTT;
    }

    _u16VTotalResult = SC_R2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK10_0D_L, 0x3FFF)+1;

    u16TGEN_CentralVTTPre = _u16TGEN_CentralVTT;

    MS_U16 u16PWMHTotal = SC_R2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK10_0C_L, 0x3FFF);


    MS_U8 u8Delta = VTT_DELTA;   // SW Define
    MS_U16 u16MaxOutputVTotal = SC_R2BYTE(psXCInstPri->u32DeviceID, REG_SC_BK68_36_L);
    MS_U16 u16MinOutputVTotal = SC_R2BYTE(psXCInstPri->u32DeviceID, REG_SC_BK68_37_L);
    MS_S8 s8TraceDirection0 = 0;   // consider increase, decrease, hold
    MS_S8 s8TraceDirection1 = 0;   // consider in/out difference
    MS_S8 s8TraceDirection2 = 0;   // consider speed, distance, over run
    MS_S16 s16FinalDeltaResult = 0;
    MS_S16 s16Increase = 0;
    MS_S16 s16Hold = 0;
    MS_S8 s8OverSpeed;
    MS_S8 s8OverDistance;
    MS_S8 s8OverRun = 0;
    MS_S16 s16InOutDifference = 0;
    static MS_S16 _s16OutputCentralDiffVTotal = 0;
    static MS_S16 _s16OutputCentralDiffVTotalPre = 0;
    MS_S16 s16DistIO = 0;
    MS_S16 s16DistDec = 0;
    MS_S16 s16DistDecPos = 0;
    MS_S16 s16T = 0;
    MS_S16 s16Target = 0;
    MS_S16 s16Decrease = 0;
    MS_S16 s16ExpectedVTotal = 0; // original expected vtotal
    MS_S16 s16ExpectedVTotal1 = 0; // consider min/max vtotal
    MS_S16 s16ExpectedVTotal2 = 0; // consider delta
    MS_U8 u8Direction = 0;
    static MS_U8 _u8DebugIdx = 0;

    u8Direction = SC_R2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_3D_L, BIT(8)) >> 8;
    if ( u8Direction > 0 )
    {
        s16InOutDifference = 0 - (SC_R2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_3C_L, BMASK(13:0)));
    }
    else
    {
        s16InOutDifference = SC_R2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_3C_L, BMASK(13:0));
    }

    _s16OutputCentralDiffVTotalPre = _s16OutputCentralDiffVTotal;
    _s16OutputCentralDiffVTotal = abs(_u16VTotalResult - _u16NewCentral);

    s16DistIO = abs( s16InOutDifference ) - _s16OutputCentralDiffVTotal;

    s16DistDec = _s16OutputCentralDiffVTotal*_s16OutputCentralDiffVTotal/u8Delta/2 - _s16OutputCentralDiffVTotal/2;

    if ( s16DistDec < 0)
    {
        s16DistDecPos = 0;
    }
    else
    {
        s16DistDecPos = s16DistDec;
    }

    s16Increase = s16DistIO - s16DistDecPos - 2 * _s16OutputCentralDiffVTotal;
    s16Hold = s16DistIO - _s16OutputCentralDiffVTotal - s16DistDecPos;
    s16T = ( _s16OutputCentralDiffVTotal +  POSDIFF(u8Delta, 1 ) ) / u8Delta + 1;
    s16Target = s16DistIO * 2 / s16T;
    s16Decrease = _s16OutputCentralDiffVTotal - s16Target;

    if ( _u16VTotalResult == _u16NewCentral )
    {
        s8OverSpeed = 0;
    }
    else if ( _u16VTotalResult > _u16NewCentral )
    {
        s8OverSpeed = 1;
    }
    else
    {
        s8OverSpeed = -1;
    }

    if ( s16InOutDifference > 0 )
    {
        s8OverDistance = -1;
    }
    else if ( s16InOutDifference == 0 )
    {
        s8OverDistance = 0;
    }
    else
    {
        s8OverDistance = 1;
    }

    if ( ( s8OverSpeed + s8OverDistance ) > 0)
    {
        s8OverRun = -1;
    }
    else if ( ( s8OverSpeed + s8OverDistance ) < 0 )
    {
        s8OverRun = 1;
    }
    else
    {
        s8OverRun = 0;
    }

    if ( s16Increase > 0 )
    {
        s8TraceDirection0 = 1;
    }
    else if (_u8DebugIdx == 0 && s16Hold >= 0)
    {
        s8TraceDirection0 = 0;
    }
    else if ( s16Decrease > 0 )
    {
        s8TraceDirection0 = -1;
    }
    else
    {
        s8TraceDirection0 = s8TraceDirection0;
    }

    if ( s16InOutDifference == 0)
    {
        s8TraceDirection1 = s8TraceDirection0;
    }
    else if ( s16InOutDifference > 0)
    {
        s8TraceDirection1 = s8TraceDirection0;
    }
    else
    {
        s8TraceDirection1 = (0 - s8TraceDirection0);
    }

    if ( s8OverRun == 0)
    {
        s8TraceDirection2 = s8TraceDirection1;
    }
    else
    {
        s8TraceDirection2 = s8OverRun;
    }

    if ( s16Increase > 0)
    {
        s16FinalDeltaResult = s16Increase;
    }
    else if ( s16Hold >= 0)
    {
        s16FinalDeltaResult = 0;
    }
    else
    {
        s16FinalDeltaResult = s16Decrease;
    }

    s16ExpectedVTotal = _u16VTotalResult + s8TraceDirection2 * s16FinalDeltaResult;
    s16ExpectedVTotal1 = MAX( MIN( u16MaxOutputVTotal, s16ExpectedVTotal ), u16MinOutputVTotal );
    s16ExpectedVTotal2 = MAX( MIN( _u16VTotalResult + u8Delta, s16ExpectedVTotal1 ), _u16VTotalResult - u8Delta );
    _u16VTotalResult = s16ExpectedVTotal2;

    // Update vTotal
    //MDrv_XC_MLoad_WriteCmd(pInstance, REG_SC_BK10_0D_L, POSDIFF(_u16VTotalResult, 1), VOP_VTT_MASK);
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK10_0D_L, POSDIFF(_u16VTotalResult, 1), VOP_VTT_MASK);

    W2BYTEMSK(REG_SC_BKF0_31_L, u16PWMHTotal, BMASK(13:0)); // [13:0] : 1, PWM SW mode vTotal
    //MDrv_XC_MLoad_WriteCmd(pInstance, REG_SC_BKF0_32_L, POSDIFF(_u16VTotalResult, 1), BMASK(12:0));
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BKF0_32_L, POSDIFF(_u16VTotalResult, 1), BMASK(12:0));
}

void MHal_FRC_TGEN_IVSShiftModeEnable(void *pInstance, MS_BOOL bEn)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);

    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_31_L, bEn?BIT(9):0x00, BIT(9));
    XC_LOG_TRACE(XC_DBGLEVEL_SETTIMING, "%s bEn = %d\n",__FUNCTION__, bEn);
}
#endif

void MHal_FRC_TGEN_SetVTotal(void *pInstance, MS_U16 u16VTotal)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);

    //BK68_0F [12:0]:reg_v_total
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_0F_L, (u16VTotal -1), 0x1FFF);
}

void MHal_FRC_TGEN_SetHTotal(void *pInstance, MS_U16 u16HTotal)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);

    //BK68_07 [13:0]:reg_h_total
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_07_L, (u16HTotal -1), 0x3FFF);
}

void MHal_FRC_TGEN_SetVSyncStartEndY(void *pInstance, MS_U16 u16Start, MS_U16 u16End, MS_U16 u16VTT)
{
    UNUSED(u16VTT);
    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));

#ifdef STELLAR
    //Retrieve TCON setting.
    PNL_ApiExtStatus sPnlExtStatus;
    memset(&sPnlExtStatus, 0, sizeof(PNL_ApiExtStatus));
    sPnlExtStatus.u32ApiStatusEx_Version = API_PNLSTATUS_EX_VERSION;
    sPnlExtStatus.u16ApiStatusEX_Length = sizeof(PNL_ApiExtStatus);
    MApi_PNL_GetStatusEx(&sPnlExtStatus);
#endif

    u16Start += VSYNCSTART_OFFSET;
    u16End += VSYNCSTART_OFFSET;

    if((pXCResourcePrivate->stdrvXC_MVideo_Context.g_XC_Init_Misc.u32MISC_B & E_XC_INIT_MISC_B_HDMITX_ENABLE)
        &&(!MHal_FRC_IsFHDToFSC(pInstance,MAIN_WINDOW))
        &&(pXCResourcePrivate->stdrvXC_MVideo.gu16HPixelShiftRange == 0)
        &&(pXCResourcePrivate->stdrvXC_MVideo.gu16VPixelShiftRange == 0)) //Check if PIXEL FEATURE is ENABLE or NOT.
    {
        u16Start += (FRC_PIPE_DELAY_VCNT_FSC_FHD_HDMITX - FRC_PIPE_DELAY_VCNT_FSC_4K);
        u16End += (FRC_PIPE_DELAY_VCNT_FSC_FHD_HDMITX - FRC_PIPE_DELAY_VCNT_FSC_4K);
    }

    // Erorr handling: there is line garbage at video bottom side, ex. VGA 800x600 case
    // (Vsync position - V FDE end)  should be > 10
    MS_U16 u16VFDE_Start = SC_R2BYTE(psXCInstPri->u32DeviceID, REG_SC_BK68_0B_L);
    MS_U16 u16VFDE_End = SC_R2BYTE(psXCInstPri->u32DeviceID, REG_SC_BK68_0C_L);
    MS_U16 u16VTotal = SC_R2BYTE(psXCInstPri->u32DeviceID, REG_SC_BK68_0F_L);
    MS_U16 u16VsyncSize = u16End - u16Start;

    if (((u16Start > u16VFDE_End) && ((u16Start - u16VFDE_End) < VSYNC_FRONT_PORCH))
        ||(u16Start <= u16VFDE_End)
       )
    {
        #ifdef STELLAR
        if(sPnlExtStatus.bUsingTCON)
        {
            u16Start = u16VFDE_End + VSYNC_FRONT_PORCH_EPI;
        }
        else //E_FRC_TGEN_LOCK_SOURCE_MODE_FROM_TGEN
        #endif
        {
            u16Start = u16VFDE_End + VSYNC_FRONT_PORCH;
        }
        u16End = u16Start + u16VsyncSize;
    }

    // Error handling : Vsync start/end is out of Vtotal
    if(u16Start > u16VTotal)
    {
        u16Start -= u16VTotal;
        u16End -= u16VTotal;
    }
    else if((u16Start < u16VTotal)&&(u16End > u16VTotal))
    {
        u16End = u16VFDE_Start - 1;
        u16Start = u16End - u16VsyncSize;
    }

#ifdef PATCH_TCON_BRING_UP
        if((((MS_U8)pXCResourcePrivate->stdrvXC_MVideo_Context.g_XC_InitData.stPanelInfo.eLPLL_Type) == E_XC_PNL_LPLL_EPI28_12P)
          && !(strcmp(panelName_UD_VB1_8LANE_DRDEPI,MDrv_PNL_GetName())))
        {
            u16Start = FRC_TGEN_VSYNC_START_FOR_UD_VB1_8LANE_DRDEPI;
            u16End = FRC_TGEN_VSYNC_END_FOR_UD_VB1_8LANE_DRDEPI;
        }
#endif

    //BK68_09 [12:0]:reg_vs_yst
    //Bk68_0A [12:0]:reg_vs_yend
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_09_L, u16Start, 0x1FFF);
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_0A_L, u16End, 0x1FFF);
}

void MHal_FRC_TGEN_SetHSyncStartEndX(void *pInstance, MS_U16 u16Start, MS_U16 u16End)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);

    //BK68_01 [13:0]:reg_hs_xst
    //BK68_02 [13:0]:reg_hs_xend
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_01_L, u16Start, 0x3FFF);
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_02_L, u16End, 0x3FFF);
}

void MHal_FRC_TGEN_SetFdeStartEndY(void *pInstance, MS_U16 u16Start, MS_U16 u16End)
{
    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));

#ifdef STELLAR
    //Retrieve TCON setting.
    PNL_ApiExtStatus sPnlExtStatus;
    memset(&sPnlExtStatus, 0, sizeof(PNL_ApiExtStatus));
    sPnlExtStatus.u32ApiStatusEx_Version = API_PNLSTATUS_EX_VERSION;
    sPnlExtStatus.u16ApiStatusEX_Length = sizeof(PNL_ApiExtStatus);
    MApi_PNL_GetStatusEx(&sPnlExtStatus);

    if(!sPnlExtStatus.bUsingTCON)
#endif
    {
        u16Start += VSTART_OFFSET;
        u16End += VSTART_OFFSET;
    }


    if((pXCResourcePrivate->stdrvXC_MVideo_Context.g_XC_Init_Misc.u32MISC_B & E_XC_INIT_MISC_B_HDMITX_ENABLE)
        &&(!MHal_FRC_IsFHDToFSC(pInstance,MAIN_WINDOW))
        &&(pXCResourcePrivate->stdrvXC_MVideo.gu16HPixelShiftRange == 0)
        &&(pXCResourcePrivate->stdrvXC_MVideo.gu16VPixelShiftRange == 0)) //Check if PIXEL FEATURE is ENABLE or NOT.
    {
        u16Start += (FRC_PIPE_DELAY_VCNT_FSC_FHD_HDMITX - FRC_PIPE_DELAY_VCNT_FSC_4K);
        u16End += (FRC_PIPE_DELAY_VCNT_FSC_FHD_HDMITX - FRC_PIPE_DELAY_VCNT_FSC_4K);
    }

#ifdef STELLAR
    if( (MHal_FRC_IsFHDToFSC(pInstance,MAIN_WINDOW))
        &&(pXCResourcePrivate->stdrvXC_MVideo.gu16HPixelShiftRange == 0)
        &&(pXCResourcePrivate->stdrvXC_MVideo.gu16VPixelShiftRange == 0)) //Check if PIXEL FEATURE is ENABLE or NOT.
    {
        if(sPnlExtStatus.bUsingTCON)
        {
            if(u16Start < VSTART_OFFSET )
                u16Start = 0;
            else
                u16Start -= VSTART_OFFSET;

            if(u16End < VSTART_OFFSET )
                u16End = 0;
            else
                u16End -= VSTART_OFFSET;
        }
        else
        {
            u16Start += VSTART_OFFSET_FHD;
            u16End += VSTART_OFFSET_FHD;
        }

        if (pXCResourcePrivate->stdrvXC_MVideo_Context.g_bFRCEnabled == TRUE)
        {
            if (u16Start > FRC_Y_TRIGGER_DE_START)
            {
                pXCResourcePrivate->stdrvXC_MVideo_Context.g_u16DE_VStartdelta = u16Start - FRC_Y_TRIGGER_DE_START;
            }
            else
            {
                pXCResourcePrivate->stdrvXC_MVideo_Context.g_u16DE_VStartdelta = 0;
            }
            u16Start = u16Start - pXCResourcePrivate->stdrvXC_MVideo_Context.g_u16DE_VStartdelta;
            u16End = u16End - pXCResourcePrivate->stdrvXC_MVideo_Context.g_u16DE_VStartdelta;
        }
    }
#endif

    #ifdef STELLAR
    gSrcInfo[MAIN_WINDOW].u16FdeStartY = u16Start;
    gSrcInfo[MAIN_WINDOW].u16FdeEndY = u16End;
    #endif

    //BK68_0B [12:0]:reg_f_de_yst
    //BK68_0C [12:0]:reg_f_de_yend
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_0B_L, u16Start, 0x1FFF);
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_0C_L, u16End, 0x1FFF);
}

void MHal_FRC_TGEN_SetMdeStartEndY(void *pInstance, MS_U16 u16Start, MS_U16 u16End)
{
    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));

#ifdef STELLAR
    //Retrieve TCON setting.
    PNL_ApiExtStatus sPnlExtStatus;
    memset(&sPnlExtStatus, 0, sizeof(PNL_ApiExtStatus));
    sPnlExtStatus.u32ApiStatusEx_Version = API_PNLSTATUS_EX_VERSION;
    sPnlExtStatus.u16ApiStatusEX_Length = sizeof(PNL_ApiExtStatus);
    MApi_PNL_GetStatusEx(&sPnlExtStatus);

    if(!sPnlExtStatus.bUsingTCON)
#endif
    {
        u16Start += VSTART_OFFSET;
        u16End += VSTART_OFFSET;
    }

    if((pXCResourcePrivate->stdrvXC_MVideo_Context.g_XC_Init_Misc.u32MISC_B & E_XC_INIT_MISC_B_HDMITX_ENABLE)
        &&(!MHal_FRC_IsFHDToFSC(pInstance,MAIN_WINDOW))
        &&(pXCResourcePrivate->stdrvXC_MVideo.gu16HPixelShiftRange == 0)
        &&(pXCResourcePrivate->stdrvXC_MVideo.gu16VPixelShiftRange == 0)) //Check if PIXEL FEATURE is ENABLE or NOT.
    {
        u16Start += (FRC_PIPE_DELAY_VCNT_FSC_FHD_HDMITX - FRC_PIPE_DELAY_VCNT_FSC_4K);
        u16End += (FRC_PIPE_DELAY_VCNT_FSC_FHD_HDMITX - FRC_PIPE_DELAY_VCNT_FSC_4K);
    }

#ifdef STELLAR
    if( (MHal_FRC_IsFHDToFSC(pInstance,MAIN_WINDOW))
        &&(pXCResourcePrivate->stdrvXC_MVideo.gu16HPixelShiftRange == 0)
        &&(pXCResourcePrivate->stdrvXC_MVideo.gu16VPixelShiftRange == 0)) //Check if PIXEL FEATURE is ENABLE or NOT.
    {
        if(sPnlExtStatus.bUsingTCON)
        {
            if(u16Start < VSTART_OFFSET )
                u16Start = 0;
            else
                u16Start -= VSTART_OFFSET;

            if(u16End < VSTART_OFFSET )
                u16End = 0;
            else
                u16End -= VSTART_OFFSET;
        }
        else
        {
            u16Start += VSTART_OFFSET_FHD;
            u16End += VSTART_OFFSET_FHD;
        }
    }
#endif

    //BK68_0D [12:0]:reg_m_de_yst
    //BK68_0E [12:0]:reg_m_de_yend
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_0D_L, u16Start, 0x1FFF);
    if (Hal_SC_NeedXCV8Align(pInstance))
    {
        u16End = u16Start + XC8ALIGN(u16End - u16Start + 1) - 1;
    }
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_0E_L, u16End, 0x1FFF);
}

void MHal_FRC_TGEN_SetMdeStartEndX(void *pInstance, MS_U16 u16Start, MS_U16 u16End)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);

    //BK68_05 [13:0]:reg_m_de_xst
    //BK68_06 [13:0]:reg_m_de_xend
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_05_L, u16Start, 0x3FFF);
    if (Hal_SC_NeedXCH8Align(pInstance))
    {
        //w need be 8 align
        u16End = u16Start + XC8ALIGN(u16End - u16Start + 1) - 1;
    }
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_06_L, u16End, 0x3FFF);
}

void MHal_FRC_TGEN_SetFdeStartEndX(void *pInstance, MS_U16 u16Start, MS_U16 u16End)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);

    //BK68_03 [13:0]:reg_f_de_xst
    //BK68_04 [13:0]:reg_f_de_xend
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_03_L, u16Start, 0x3FFF);
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_04_L, u16End, 0x3FFF);
}

void MHal_FRC_TGEN_SetSubMdeStartEndY(void *pInstance, MS_U16 u16Start, MS_U16 u16End)
{
    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));

    u16Start += VSTART_OFFSET;
    u16End += VSTART_OFFSET;

    if((pXCResourcePrivate->stdrvXC_MVideo_Context.g_XC_Init_Misc.u32MISC_B & E_XC_INIT_MISC_B_HDMITX_ENABLE)
        &&(!MHal_FRC_IsFHDToFSC(pInstance,MAIN_WINDOW))
        &&(pXCResourcePrivate->stdrvXC_MVideo.gu16HPixelShiftRange == 0)
        &&(pXCResourcePrivate->stdrvXC_MVideo.gu16VPixelShiftRange == 0)) //Check if PIXEL FEATURE is ENABLE or NOT.
    {
        u16Start += (FRC_PIPE_DELAY_VCNT_FSC_FHD_HDMITX - FRC_PIPE_DELAY_VCNT_FSC_4K);
        u16End += (FRC_PIPE_DELAY_VCNT_FSC_FHD_HDMITX - FRC_PIPE_DELAY_VCNT_FSC_4K);
    }

    //BK68_0D [12:0]:reg_m_de_yst
    //BK68_0E [12:0]:reg_m_de_yend
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_12_L, u16Start, 0x1FFF);
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_13_L, u16End, 0x1FFF);
}

void MHal_FRC_TGEN_SetSubMdeStartEndX(void *pInstance, MS_U16 u16Start, MS_U16 u16End)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);

    //BK68_05 [13:0]:reg_m_de_xst
    //BK68_06 [13:0]:reg_m_de_xend
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_10_L, u16Start, 0x3FFF);
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_11_L, u16End, 0x3FFF);
}

void MHal_SWDS_AddTGENMdeStartEndY(void *pInstance, MS_U16 u16Start, MS_U16 u16End, SCALER_WIN eWindow)
{
    u16Start += VSTART_OFFSET;
    u16End += VSTART_OFFSET;

    if (SUPPORT_3D_DS && (g_bSWDSGenScenario == TRUE))
    {
        if (eWindow == MAIN_WINDOW)
        {
            Hal_SC_WriteSWDSCommand(pInstance, MAIN_WINDOW, REG_SC_BK68_0D_L, u16Start, DS_OP,DS_XC,&PSTXC_DS_CMDCNT);
            if (Hal_SC_NeedXCV8Align(pInstance))
            {
                u16End = u16Start + XC8ALIGN(u16End - u16Start + 1) - 1;
            }
            Hal_SC_WriteSWDSCommand(pInstance, MAIN_WINDOW, REG_SC_BK68_0E_L, u16End, DS_OP,DS_XC,&PSTXC_DS_CMDCNT);
        }
        else
        {
            Hal_SC_WriteSWDSCommand(pInstance, MAIN_WINDOW, REG_SC_BK68_12_L, u16Start, DS_OP,DS_XC,&PSTXC_DS_CMDCNT);
            Hal_SC_WriteSWDSCommand(pInstance, MAIN_WINDOW, REG_SC_BK68_13_L, u16End, DS_OP,DS_XC,&PSTXC_DS_CMDCNT);
        }
    }
}

void MHal_SWDS_AddTGENMdeStartEndX(void *pInstance, MS_U16 u16Start, MS_U16 u16End, SCALER_WIN eWindow)
{
    if (SUPPORT_3D_DS && (g_bSWDSGenScenario == TRUE))
    {
        if (eWindow == MAIN_WINDOW)
        {
            Hal_SC_WriteSWDSCommand(pInstance, MAIN_WINDOW, REG_SC_BK68_05_L, u16Start, DS_OP,DS_XC,&PSTXC_DS_CMDCNT);
            if (Hal_SC_NeedXCH8Align(pInstance))
            {
                //w need be 8 align
                u16End = u16Start + XC8ALIGN(u16End - u16Start + 1) - 1;
            }
            Hal_SC_WriteSWDSCommand(pInstance, MAIN_WINDOW, REG_SC_BK68_06_L, u16End, DS_OP,DS_XC,&PSTXC_DS_CMDCNT);
        }
        else
        {
            Hal_SC_WriteSWDSCommand(pInstance, MAIN_WINDOW, REG_SC_BK68_10_L, u16Start, DS_OP,DS_XC,&PSTXC_DS_CMDCNT);
            Hal_SC_WriteSWDSCommand(pInstance, MAIN_WINDOW, REG_SC_BK68_11_L, u16End, DS_OP,DS_XC,&PSTXC_DS_CMDCNT);
        }
    }
}

void MHal_FRC_TGEN_Enable_LockMode(void *pInstance, MS_BOOL bEn)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);

    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_20_L, bEn?BIT(0):0x00, BIT(0));
}

void MHal_FRC_TGEN_Enable_Source_Select_Mode(void *pInstance, MS_BOOL bEn)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);

    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_20_L, bEn?BIT(1):0x00, BIT(1));
}

void MHal_FRC_TGEN_Enable_Lock_Source(void *pInstance, MS_BOOL bEn, E_FRC_TGEN_LOCK_SOURCE_MODE eMode, MS_BOOL bMenuload)
{
#ifdef CONFIG_FPGA
    eMode = E_FRC_TGEN_LOCK_SOURCE_MODE_FROM_IP;
#endif
    if (ENABLE == bMenuload)
    {
        MS_U16 u16STGEN_Setting = 0x00;
        if (E_FRC_TGEN_LOCK_SOURCE_MODE_FROM_TGEN == eMode)
        {
            u16STGEN_Setting |= BIT(2);
        }
        MDrv_XC_MLoad_WriteCmd(pInstance, REG_SC_BK68_20_L, BIT(0) | u16STGEN_Setting , (BIT(0)|BIT(2))); // reg_stgen_en: use simple tgen to trigger op/vip
    }
    else
    {
        XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
        UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);
        SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_20_L, BIT(0) | (eMode<<2), (BIT(0)|BIT(2)));
    }

}

MS_BOOL _MHal_FRC_IsOutput48HZ(void *pInstance)
{
    MS_BOOL bResult = FALSE;

    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((gSrcInfo[MAIN_WINDOW].u16InputVFreq > 235 && gSrcInfo[MAIN_WINDOW].u16InputVFreq <245)
        && (gSrcInfo[MAIN_WINDOW].Status2.u16OutputVFreqAfterFRC > 475 && gSrcInfo[MAIN_WINDOW].Status2.u16OutputVFreqAfterFRC < 485) )
    {
        bResult = TRUE;
    }

    return bResult;
}

void MHal_FRC_SetYTrig(void *pInstance, MS_U16 u16Trig1, MS_U16 u16Trig2)
{
    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_U8 u8LPLL_Type = (MS_U8)pXCResourcePrivate->stdrvXC_MVideo_Context.g_XC_InitData.stPanelInfo.eLPLL_Type;
    //MS_U16 u16Pipedelay = 0;
    //MS_U16 u16VDEend = 0;
    MS_U16 u16YtrigStage = 0;
    MS_U16 u16VMDEstart = 0;
    MS_U32 u32Time = 0;
    // FO setting
    if (IsVBY1_16LANE(u8LPLL_Type))
    {
        //Maxim not support 120Hz output (16 lane case)
    }
    else
    {
        MS_U16 u16VttLower = 0;
        u16VttLower = pXCResourcePrivate->stdrvXC_MVideo_Context.g_XC_InitData.stPanelInfo.u16DefaultVTotal * (1000 - VTT_BOUNDARY_RATIO)/1000;


        // |u16Trig1|u16Trig2|u16Ytrig_Stage|
        //|_|__|__________|
        //according to M7632 sequence
        //Tgen vmde_Start
        u16VMDEstart = SC_R2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK10_0A_L, VOP_VTT_MASK);
        //need conside the case:if(u16VMDEstart < 64)
        u16YtrigStage = u16VttLower + u16VMDEstart -64;

        //according to M7622
        u16Trig2 = u16YtrigStage - FRC_YTRIG_OFFSET;
        u16Trig1 = u16Trig2 -1;

        if(u16VttLower != 0)
        {
            u16Trig1 %= u16VttLower;
            u16Trig2 %= u16VttLower;
            u16YtrigStage %= u16VttLower;
        }
    }

    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_65_L, u16Trig1, 0x1FFF); //trig1
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_66_L, u16YtrigStage, 0x1FFF); //trig2
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_67_L, u16Trig2, 0x1FFF); //second ytrig setting.  //trig3
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_6B_L, u16Trig2, 0x1FFF);   //frc'ds trig
}

void MHal_FRC_Init(void *pInstance, PMST_PANEL_INFO_t pPanelInfo, PFRC_INFO_t pFRCInfo)
{
    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 (PIP_PATCH_USING_SC1_MAIN_AS_SC0_SUB)
    if(psXCInstPri->u32DeviceID == 1)
    {
        // not support
        return;
    }
#endif

    MS_BOOL isYuv = FALSE;
    MS_U32 u32FrameYcout = 0;
    MS_U16 u16FB_YcountLinePitch, u16LineLimit;;
    MS_U8 u8FRC_PnlType = E_FRC_PNL_TYPE_2D; //E_FRC_PNL_TYPE_PASSIVE;
    MS_PHY u32ME2Addr = 0, u32ME2Size = 0;
    MS_PHY u32HRAddr = 0, u32HRSize = 0;

    //FRCTABLE_INFO FRCTableInfo;

    if(pFRCInfo->u8FRC3DPanelType == E_XC_3D_PANEL_SHUTTER)
    {
        u8FRC_PnlType = E_FRC_PNL_TYPE_ACTIVE;
    }
    else if(pFRCInfo->u8FRC3DPanelType == E_XC_3D_PANEL_PELLICLE)
    {
        u8FRC_PnlType = E_FRC_PNL_TYPE_PASSIVE;
    }
    else
    {
        u8FRC_PnlType = E_FRC_PNL_TYPE_2D;
    }

    pFRCInfo->u16PanelWidth = pPanelInfo->u16Width;
    pFRCInfo->u16PanelHeigh = pPanelInfo->u16Height;
    pFRCInfo->u83Dmode = 0;
    pFRCInfo->u8IpMode = FRC_IP_MEM_IP_YC_10_SPECIAL;
    pFRCInfo->u8MirrorMode = 0;

    printf("[%s]FRC 3D panel type=%x\n", __FUNCTION__, pFRCInfo->u8FRC3DPanelType);
    printf("[%s]R2 3D panel type=%x\n", __FUNCTION__, u8FRC_PnlType);
    printf("pFRCInfo->u32FRC_MEMC_MemAddr = %tu\n",(ptrdiff_t)pFRCInfo->u32FRC_MEMC_MemAddr);
    printf("pFRCInfo->u32FRC_MEMC_Memsize = %tu\n",(ptrdiff_t)pFRCInfo->u32FRC_MEMC_MemSize);

    // TGEN
    MHal_FRC_TGEN_Init(pInstance);
    MDrv_FRC_Tx_SetTgen(pInstance, pPanelInfo);
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_14_L , 1<<1, BIT(1));
}

void MHal_FRC_Composer_User_Mode_Enable(void *pInstance, MS_BOOL bEnable)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);

    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_48_L, bEnable?BIT(0):0x00, BIT(0));
}

void MHal_FRC_Set_Composer_User_Mode(void *pInstance, E_FRC_COMPOSER_SOURCE_MODE eMode, MS_BOOL bMenuload)
{
    MS_U16 u16Mode = 0;
    switch(eMode)
    {
        //M7332 only have VIP
        case E_FRC_COMPOSER_SOURCE_MODE_VIP:
        {
            u16Mode = FRC_COMPOSER_SOURCE_MODE_VIP;
        }
        break;
        default:
            return;
    }
    if (ENABLE == bMenuload)
    {
        MDrv_XC_MLoad_WriteCmd(pInstance, REG_SC_BK68_40_L, u16Mode, FRC_COMPOSER_SOURCE_MODE_MASK);
    }
    else
    {
        XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
        UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);

        SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_40_L, u16Mode, FRC_COMPOSER_SOURCE_MODE_MASK);
    }

}

void MHal_FRC_Set_FSC_DE_Selection(void *pInstance, E_FRC_FSC_SOURCE_MODE eMode)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);

    //register excel:0:fde 1:mde, RD suggest to "mde"
    //composer2dest
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_40_L, eMode<<4, BIT(4)|BIT(5)|BIT(6));

    if (Hal_SC_NeedXCV8Align(pInstance) || Hal_SC_NeedXCH8Align(pInstance))
    {
        //register excel:0:fde 1:mde, RD suggest to "mde"
        //composer2dest
        eMode = E_FRC_FSC_SOURCE_MODE_FDE;
        SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_40_L, eMode<<4, BIT(4)|BIT(5)|BIT(6));

        //from HWRD:patch: set "0",fde; NonPatch:set "1",mde
        eMode = E_FRC_FSC_SOURCE_MODE_MDE;
    }
    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_40_L, eMode<<2, BIT(2)|BIT(3));
}

 MS_BOOL MHal_FRC_IsSupportFRC_byEfuse(void *UNUSED_PARA(pInstance))
{
    //Because m7332 need tgen-lite
    return FALSE;
}

MS_BOOL MHal_FRC_Check_Condition(void *UNUSED_PARA(pInstance), ST_XC_FRCFSCCTRLPOLICY *UNUSED_PARA(pstXCFrcFscCtrlPolicy))
{
    return FALSE; // for m7332 not support FRC
}

void MHal_FRC_Set_Mload_Trig_Mode(void *pInstance, E_FRC_MLOAD_TRIG_MODE eMode)
{
    XC_INSTANCE_PRIVATE *psXCInstPri = NULL;
    UtopiaInstanceGetPrivate(pInstance, (void**)&psXCInstPri);

    SC_W2BYTEMSK(psXCInstPri->u32DeviceID, REG_SC_BK68_5F_L, eMode << 15, BIT(15));
}

MS_BOOL Hal_XC_Get_Stgen_Lock_Ip_status(void *UNUSED_PARA(pInstance))
{
    return FALSE;
}

