/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/

/*-----------------------------------------------------------------------------
 *
 * $Author$
 * $Date$
 * $RCSfile: drv_tcon.c,v $
 * $Revision$
 *
 *---------------------------------------------------------------------------*/
#ifdef CC_UP8032_ATV
#include "general_mt82.h"
#endif

#ifdef CC_COPLAT_MT82
#include "util.h"
#endif

#include "general.h"

#include "x_pinmux.h"
#include "x_bim.h"
#include "x_assert.h"

#include "hw_ckgen.h"
#include "hw_tcon.h"
#include "hw_lvds.h"
#include "hw_mlvds.h"
#include "hw_tg.h"
#include "hw_vbyone.h"

#include "drv_tcon.h"
#include "drv_vdoclk.h"
#include "drv_lvds.h"
#include "drv_pwm.h"
#include "drv_vbyone.h"

#include "sif_if.h"
#include "panel.h"
#include "drv_display.h"

#include "nptv_debug.h"
#include "pe_if.h"

#ifdef CC_SUPPORT_FLASH_TCON
#include "nor_if.h"
#ifdef CC_NAND_ENABLE
#include "nand_if.h"
#endif
#endif

#include "drvcust_if.h"

#ifdef SUPPORT_LOCK_FROM_SRVAD
#include "x_pdwnc.h"
#define SERVOADC_TCON_LOCK 1
#endif

//-----------------------------------------------------------------------------
// Static variables
//-----------------------------------------------------------------------------
#define TCON_ADDR_BASE 0xf0000000

static UINT8 _u1GammaReady=0;
static BOOL _fgTconCustSel=FALSE;
static VIDEO_TCON_TABLE_T _u1TconCustSel = EPIV13FHD60_32;
static BOOL _fgIsTCONIsrReg = FALSE;
UINT8 bbypass_isr=0;

extern UINT8 _Lvds7To4FifoReset;


//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------

extern PANEL_FLASH_DATA_ATTRIBUTE_T rFlashPanelTable;

//-----------------------------------------------------------------------------
// Static functions
//----------------------------------------------------------------------------- 
// DPM power control
static void vTconDPMCtrl(UINT8 u1Val)
{
  u1TconCustDPMCtrlEN1(u1Val);
  u1TconCustDPMCtrlEN2(u1Val);  	
}

//TCON Register Write
void vTconRegWrite(UINT32 u4addr, UINT32 val)
{
    #ifndef CC_MTK_LOADER
    UINT32 u4tmp;
    #endif

	if ((u4addr == 0xffffffff) || ((u4addr&TCON_ADDR_BASE) != TCON_ADDR_BASE))
	{
		LOG(1,"Write addr Err!!! w 0x%x 0x%x\n", u4addr, val);
	}
    else
    {
	    vIO32Write4B(u4addr, val);
        #ifndef CC_MTK_LOADER
   	    u4tmp = u4IO32Read4B(u4addr);
        LOG(1,"0x%8x, 0x%8x, 0xffffffff,\n", u4addr, u4tmp);
        #endif
    }
}

//TCON Register Read
UINT32 u4TconRegRead(UINT32 u4addr)
{
    UINT32 u4tmp;
	
	if ((u4addr == 0xffffffff) || ((u4addr&TCON_ADDR_BASE) != TCON_ADDR_BASE))
	{
		LOG(1,"Read addr Err!!! w 0x%x\n", u4addr);
		return (0);
	}
    else
    {
   	    u4tmp = u4IO32Read4B(u4addr);
        LOG(1,"0x%8x, 0x%8x, 0xffffffff,\n", u4addr, u4tmp);		
		return (u4tmp);
    }
}

BOOL fgTXPath2CHMode(void)
{
	if (PANEL_Is4K2K60())
	{
	    return (TRUE);
	}
	else
	{
	    return (FALSE);
	}
}

BOOL fgTXPath4CHMode(void)
{
	if (PANEL_Is4K2K120()||PANEL_Is8K4K30())
	{
		return (TRUE);
	}
	else
	{
		return (FALSE);
	}
}

// Panel  Interface Pattern
void vDrvMLVDSPatternGen(UINT8 u1OnOff)
{
	UINT8 u1DIV_2CH=0;

	 if(fgTXPath2CHMode())
	 {
		 u1DIV_2CH = 1;
	 }
	 else if (fgTXPath4CHMode())
	 {
		u1DIV_2CH = 2;
	 }

	 vIO32WriteFldAlign(VINTF_B6, 0, VINTF_PTGEN_MIRROR);
	 vIO32WriteFldAlign(VINTF_B6, 0, VINTF_PTGEN_TYPE_BD_DIS);	 
	 
	 vIO32WriteFldAlign(VINTF_B12, 0, VINTF_PTGEN_V_RUN);
	 vIO32WriteFldAlign(VINTF_B12, 0, VINTF_PTGEN_H_RUN);			
			
    if (IS_PANEL_L12R12)
    {
     vIO32WriteFldAlign(VINTF_B6, 3, VINTF_PTGEN_TYPE);    
     vIO32WriteFldAlign(VINTF_B12, 3, VINTF_PTGEN_OSD_TYPE); 	 	 
     vIO32WriteFldAlign(VINTF_B6, 0, VINTF_PTGEN_SEQ);       
    }
	else
	{
     vIO32WriteFldAlign(VINTF_B6, 2, VINTF_PTGEN_TYPE);    	
     vIO32WriteFldAlign(VINTF_B12, 2, VINTF_PTGEN_OSD_TYPE); 	 
	 vIO32WriteFldAlign(VINTF_B6, 1, VINTF_PTGEN_SEQ);	
	}
    
    vIO32WriteFldAlign(VINTF_B1, PANEL_GetPanelWidth() >> u1DIV_2CH, VINTF_PTGEN_H_ACTIVE);
#if 0  // [Husky] no bypass path, need to review later[JW]
	if (PANEL_IsSupport4K2KDD() && (GetPANEL4K2K_TYPE() != PANEL_TYPE_4K2K_60_BYP))
#else
	if (PANEL_IsSupport4K2KDD())
#endif
	{
    	vIO32WriteFldAlign(VINTF_B1, wDrvGetPnlHTotal() >> u1DIV_2CH, VINTF_PTGEN_H_TOTAL); 
		vIO32WriteFldAlign(VINTF_B4, IO32ReadFldAlign(EH_0C, EH_DE_HS_WIDTH) >> u1DIV_2CH, VINTF_PTGEN_H_WIDTH);
		vIO32WriteFldAlign(VINTF_B3, (wDrvGetHsyncBp()+wDrvGetHsyncWidth()) >> u1DIV_2CH, VINTF_PTGEN_H_START);
	}
	else
	{
    	vIO32WriteFldAlign(VINTF_B1, wDrvGetPnlHTotal(), VINTF_PTGEN_H_TOTAL); 
		vIO32WriteFldAlign(VINTF_B4, IO32ReadFldAlign(EH_0C, EH_DE_HS_WIDTH), VINTF_PTGEN_H_WIDTH);
		vIO32WriteFldAlign(VINTF_B3, (wDrvGetHsyncBp()+wDrvGetHsyncWidth()), VINTF_PTGEN_H_START);
	}
    vIO32WriteFldAlign(VINTF_B2, PANEL_GetPanelHeight(), VINTF_PTGEN_V_ACTIVE);
    vIO32WriteFldAlign(VINTF_B11, PANEL_GetPanelHeight(), VINTF_PTGEN_V_OSD_ACTIVE);	
    vIO32WriteFldAlign(VINTF_B2, wDrvGetPnlVTotal(), VINTF_PTGEN_V_TOTAL);

    vIO32WriteFldAlign(VINTF_B6, (PANEL_GetPanelHeight()/4), VINTF_PTGEN_COLOR_BAR_TH);
	
	 if (IS_SEPARATE_OSD_AND_DATA)
	 {
	 	vIO32WriteFldAlign(VINTF_B11, 6, VINTF_PTGEN_V_OSD_START);
	 }	
	 vIO32WriteFldAlign(VINTF_B4, IO32ReadFldAlign(EH_0D, EH_DE_VS_WIDTH)+1, VINTF_PTGEN_V_WIDTH);
	 vIO32WriteFldAlign(VINTF_B3, (wDrvGetVsyncBp()+wDrvGetVsyncWidth()), VINTF_PTGEN_V_START);

	if (u1OnOff)
    {
        vIO32WriteFldAlign(VINTF_B6, 1, VINTF_PTGEN_EN);
        vIO32WriteFldAlign(EH_01, 0, EH_USE_SC_TIMING_EN);		
    }
    else
    {
        vIO32WriteFldAlign(VINTF_B6, 0, VINTF_PTGEN_EN);
        vIO32WriteFldAlign(EH_01, 1, EH_USE_SC_TIMING_EN);				
    }

	if(PANEL_GetDisplayType()== PANEL_DISPLAY_TYPE_VB1)
	{
		if(fgTXPath2CHMode()||fgTXPath4CHMode())
		{
			vVByOneWriteFldAlign(VB1SYS6, u1OnOff, VB1SYS6_TSET_VB1_4567);
		}

		//vIO32WriteFldAlign(VB1OSDSYS6,u1OnOff,VB1OSDSYS6_TEST);

		if(IS_VB1_2SEC_ENABLE)
		{
			vIO32WriteFldAlign(VINTF_B6, 0xA, VINTF_PTGEN_TYPE);
			vVByOneWriteFldAlign(VB1SYS6, 0x0, VB1SYS6_TSET_VB1_4567);
		}
		else if (IS_VB1_4SEC_ENABLE)
		{
			vIO32WriteFldAlign(VINTF_B6, 0xB, VINTF_PTGEN_TYPE);
			vVByOneWriteFldAlign(VB1SYS6, 0x0, VB1SYS6_TSET_VB1_4567);
		}
		else if (IS_VB1_8SEC_ENABLE)
		{
			vIO32WriteFldAlign(VINTF_B6, 0xC, VINTF_PTGEN_TYPE);
			vVByOneWriteFldAlign(VB1SYS6, 0x0, VB1SYS6_TSET_VB1_4567);
		}		
	}
}


/**
 * @brief u1DrvTconTestPattern

 * TCON test pattern

 * @param  void
 * @retval 0: fail, 1: success
 */

// Panel Interface Pattern
UINT8 u1DrvTconTP(UINT8 val)
{
    UINT8 u1Ret = 0;

	vDrvMLVDSPatternGen(1);

	switch(val)
	{
	    case TCON_TP_OFF:
			vDrvMLVDSPatternGen(0);
			break;
			
		case TCON_TP_R:
			vIO32WriteFldAlign(VINTF_B6, 1, VINTF_PTGEN_TYPE_BD_DIS);	 
			vIO32WriteFldAlign(VINTF_B6, 1, VINTF_PTGEN_TYPE);	 
			vIO32WriteFldAlign(VINTF_B5, 0x3FF, VINTF_PTGEN_R);	 
			vIO32WriteFldAlign(VINTF_B5, 0, VINTF_PTGEN_G);	 
			vIO32WriteFldAlign(VINTF_B5, 0, VINTF_PTGEN_B);	 			
			break;
			
		case TCON_TP_G:
			vIO32WriteFldAlign(VINTF_B6, 1, VINTF_PTGEN_TYPE_BD_DIS);	 			
			vIO32WriteFldAlign(VINTF_B6, 1, VINTF_PTGEN_TYPE);	 
			vIO32WriteFldAlign(VINTF_B5, 0, VINTF_PTGEN_R);	 
			vIO32WriteFldAlign(VINTF_B5, 0x3FF, VINTF_PTGEN_G);	 
			vIO32WriteFldAlign(VINTF_B5, 0, VINTF_PTGEN_B);	 			
			break;
			
		case TCON_TP_B:
			vIO32WriteFldAlign(VINTF_B6, 1, VINTF_PTGEN_TYPE_BD_DIS);	 			
			vIO32WriteFldAlign(VINTF_B6, 1, VINTF_PTGEN_TYPE);	 
			vIO32WriteFldAlign(VINTF_B5, 0, VINTF_PTGEN_R);	 
			vIO32WriteFldAlign(VINTF_B5, 0, VINTF_PTGEN_G);	 
			vIO32WriteFldAlign(VINTF_B5, 0x3FF, VINTF_PTGEN_B);	 			
			break;
			
		case TCON_TP_BLACK:
			vIO32WriteFldAlign(VINTF_B6, 1, VINTF_PTGEN_TYPE_BD_DIS);	 
			vIO32WriteFldAlign(VINTF_B6, 1, VINTF_PTGEN_TYPE);	 
			vIO32WriteFldAlign(VINTF_B5, 0, VINTF_PTGEN_R);	 
			vIO32WriteFldAlign(VINTF_B5, 0, VINTF_PTGEN_G);	 
			vIO32WriteFldAlign(VINTF_B5, 0, VINTF_PTGEN_B);			
			break;
			
		case TCON_TP_WHITE:
			vIO32WriteFldAlign(VINTF_B6, 1, VINTF_PTGEN_TYPE_BD_DIS);	 			
			vIO32WriteFldAlign(VINTF_B6, 1, VINTF_PTGEN_TYPE);	 
			vIO32WriteFldAlign(VINTF_B5, 0x3FF, VINTF_PTGEN_R);	 
			vIO32WriteFldAlign(VINTF_B5, 0x3FF, VINTF_PTGEN_G);	 
			vIO32WriteFldAlign(VINTF_B5, 0x3FF, VINTF_PTGEN_B);
			break;
			
		case TCON_TP_COLORRAMP:
			vIO32WriteFldAlign(VINTF_B6, 2, VINTF_PTGEN_TYPE);	 
			vIO32WriteFldAlign(VINTF_B5, 0, VINTF_PTGEN_R);	 
			vIO32WriteFldAlign(VINTF_B5, 0, VINTF_PTGEN_G);	 
			vIO32WriteFldAlign(VINTF_B5, 0, VINTF_PTGEN_B);
			break;
			
		case TCON_TP_MOVING:
			vIO32WriteFldAlign(VINTF_B6, 1, VINTF_PTGEN_TYPE_BD_DIS);	 			
			vIO32WriteFldAlign(VINTF_B12, 1, VINTF_PTGEN_V_RUN);
			vIO32WriteFldAlign(VINTF_B12, 1, VINTF_PTGEN_H_RUN);			
			vIO32WriteFldAlign(VINTF_B6, 2, VINTF_PTGEN_TYPE);	 
			vIO32WriteFldAlign(VINTF_B5, 0, VINTF_PTGEN_R);	 
			vIO32WriteFldAlign(VINTF_B5, 0, VINTF_PTGEN_G);	 
			vIO32WriteFldAlign(VINTF_B5, 0, VINTF_PTGEN_B);
			break;
			
		case TCON_TP_AUTO:

			break;

		case TCON_TP_2SEC:
			vIO32WriteFldAlign(VINTF_B6, 0xA, VINTF_PTGEN_TYPE);
			vVByOneWriteFldAlign(VB1SYS6, 0x0, VB1SYS6_TSET_VB1_4567);
			break;

		case TCON_TP_4SEC:
			vIO32WriteFldAlign(VINTF_B6, 0xB, VINTF_PTGEN_TYPE);
			vVByOneWriteFldAlign(VB1SYS6, 0x0, VB1SYS6_TSET_VB1_4567);
			break;

		case TCON_TP_8SEC:
			vIO32WriteFldAlign(VINTF_B6, 0xC, VINTF_PTGEN_TYPE);
			vVByOneWriteFldAlign(VB1SYS6, 0x0, VB1SYS6_TSET_VB1_4567);
			break;
			
		default:
			break;

	}

	return(u1Ret);	
}

//Error Handle Initialize
void vErrorHandleSetByPanel(void)
{
	UINT32 H_LOW_TH,H_HIGH_TH;
	UINT32 V_LOW_TH,V_HIGH_TH; 
	UINT32 DE_LOW_TH,DE_HIGH_TH; 
	UINT32 VDE_LOW_TH,VDE_HIGH_TH;	   
	UINT32 EH_CLK_HIGH_TH=0, EH_CLK_LOW_TH=0;
	UINT8 u1DIV_2CH=0;

#ifndef NDEBUG
	LOG(3, "[NPTV][EH] PANEL_GetPanelWidth=0x%x, PANEL_GetPanelHeight=0x%x , wDrvGetOutputHTotal=0x%x , wDrvGetOutputVTotal=0x%x\n",
		  PANEL_GetPanelWidth(),PANEL_GetPanelHeight(),wDrvGetOutputHTotal(),wDrvGetOutputVTotal());		
#endif     


#ifndef NDEBUG
	LOG(3, "[NPTV][EH] PANEL_GetHTotalMax=0x%x, PANEL_GetHTotalMin=0x%x, PANEL_GetVTotalMax=0x%x, PANEL_GetVTotalMin=0x%x \n",
		  PANEL_GetHTotalMax(),PANEL_GetHTotalMin(),PANEL_GetVTotalMax(),PANEL_GetVTotalMin()); 	   
	LOG(3, "[NPTV][EH] PANEL_GetPixelClkMax=%d, PANEL_GetPixelClkMin=%d \n",
		  PANEL_GetPixelClkMax(),PANEL_GetPixelClkMin());					   
#endif    
	if(fgTXPath2CHMode())
	{
		u1DIV_2CH = 1;
	}
	else if (fgTXPath4CHMode())
	{
		u1DIV_2CH = 2;
	}

	H_HIGH_TH = PANEL_GetHTotalMax() >> u1DIV_2CH;
	if (PANEL_IsSupport4K2KDD())
	H_LOW_TH = PANEL_GetHTotalMin() >> u1DIV_2CH;
	else
	H_LOW_TH = PANEL_GetHTotalMin();

	V_HIGH_TH = PANEL_GetVTotalMax();
	V_LOW_TH = PANEL_GetVTotalMin();

	DE_HIGH_TH = (PANEL_GetPanelWidth() >> u1DIV_2CH)+7;
	DE_LOW_TH = (PANEL_GetPanelWidth() >> u1DIV_2CH)-8;

	VDE_HIGH_TH = PANEL_GetPanelHeight();
	VDE_LOW_TH = PANEL_GetPanelHeight();

	// fix error for mt8283
	if (IS_XTAL_24MHZ())
	{
		ASSERT(PANEL_GetPixelClkMin()!=0);
		EH_CLK_HIGH_TH = (2048*24000/ ((PANEL_GetPixelClkMin())/ 1000));
		ASSERT(PANEL_GetPixelClkMax()!=0);
		EH_CLK_LOW_TH = (2048*24000/ ((PANEL_GetPixelClkMax())/ 1000));	
	}
	else if (IS_XTAL_27MHZ())
	{
		ASSERT(PANEL_GetPixelClkMin()!=0);
		EH_CLK_HIGH_TH = (2048*27000/ ((PANEL_GetPixelClkMin())/ 1000));
		ASSERT(PANEL_GetPixelClkMax()!=0);
		EH_CLK_LOW_TH = (2048*27000/ ((PANEL_GetPixelClkMax())/ 1000));
	}

	if (PANEL_IsSupport4K2KDD())
	{
		EH_CLK_HIGH_TH = EH_CLK_HIGH_TH << 1;
		EH_CLK_LOW_TH = EH_CLK_LOW_TH << 1;			
	}	
		
	vIO32WriteFldAlign(EH_02,H_HIGH_TH,EH_FAST_MUTE_H_TOTAL_HIGH_TH);
	vIO32WriteFldAlign(EH_02,H_LOW_TH,EH_FAST_MUTE_H_TOTAL_LOW_TH);		  

	vIO32WriteFldAlign(EH_03,V_HIGH_TH,EH_FAST_MUTE_V_TOTAL_HIGH_TH);
	vIO32WriteFldAlign(EH_03,V_LOW_TH,EH_FAST_MUTE_V_TOTAL_LOW_TH);				  
		 
	vIO32WriteFldAlign(EH_04,DE_HIGH_TH,EH_FAST_MUTE_DE_TOTAL_HIGH_TH);
	vIO32WriteFldAlign(EH_04,DE_LOW_TH,EH_FAST_MUTE_DE_TOTAL_LOW_TH);	   

	vIO32WriteFldAlign(EH_05,VDE_HIGH_TH,EH_FAST_MUTE_VDE_TOTAL_HIGH_TH);		
	vIO32WriteFldAlign(EH_05,VDE_LOW_TH,EH_FAST_MUTE_VDE_TOTAL_LOW_TH);					   

	vIO32WriteFldAlign(EH_06,EH_CLK_HIGH_TH,EH_FAST_MUTE_CLK_TOTAL_HIGH_TH);
	vIO32WriteFldAlign(EH_06,EH_CLK_LOW_TH,EH_FAST_MUTE_CLK_TOTAL_LOW_TH);			

	vIO32WriteFldAlign(EH_0B,(PANEL_GetPanelHeight()-1),EH_CALI_RANGE_H);						
		 
	vErrorHandleSetByTiming();  

	vIO32WriteFldAlign(EH_10,(PANEL_GetPanelWidth() >> u1DIV_2CH),EH_PTGEN_H_ACTIVE);			
#if 0  // [Husky] no bypass path, need to review later[JW]
	if (PANEL_IsSupport4K2KDD() && (GetPANEL4K2K_TYPE() != PANEL_TYPE_4K2K_60_BYP))
#else
	if (PANEL_IsSupport4K2KDD())
#endif
		vIO32WriteFldAlign(EH_10,(wDrvGetOutputHTotal() >> u1DIV_2CH),EH_PTGEN_H_TOTAL);
	else
		vIO32WriteFldAlign(EH_10,wDrvGetOutputHTotal(),EH_PTGEN_H_TOTAL);

	vIO32WriteFldAlign(EH_12,PANEL_GetPanelHeight(),EH_PTGEN_V_ACTIVE);			 
	vIO32WriteFldAlign(EH_12,wDrvGetOutputVTotal(),EH_PTGEN_V_TOTAL);	

	vIO32WriteFldAlign(EH_18,wDrvGetOutputVTotal(),EH_DE_VS_TOTAL_SW);			
	if (PANEL_IsSupport4K2KDD() && (GetPANEL4K2K_TYPE() != PANEL_TYPE_4K2K_60_BYP))
		vIO32WriteFldAlign(EH_18,(wDrvGetOutputHTotal() >> u1DIV_2CH),EH_DE_HS_TOTAL_SW); 
	else
		vIO32WriteFldAlign(EH_18,wDrvGetOutputHTotal(),EH_DE_HS_TOTAL_SW); 
		   
	vIO32WriteFldAlign(EH_1A,(PANEL_GetPanelWidth() >> u1DIV_2CH)-20,EH_FIX_VDE_TH);			
	 
	//WXGA Panel , Error Handling FIXED_DE_TOATL+2=1368
	vIO32WriteFldAlign(EH_1A,(PANEL_GetPanelWidth() >> u1DIV_2CH),EH_FIXED_DE_TOATL); 

#ifndef NDEBUG	
	LOG(3, "---------- [NPTV][EH] vErrorHandleSetByPanel end----------\n"); 
#endif

}


void vErrorHandleSetByTiming(void)
{
	UINT16 u2HSyncWidth,u2VSyncWidth,u2HSyncStart,u2VSyncStart;
	UINT8 u1DIV_2CH=0;

	if(fgTXPath2CHMode())
	{
		u1DIV_2CH = 1;
	}
	else if (fgTXPath4CHMode())
	{
		u1DIV_2CH = 2;
	}
	
#ifndef NDEBUG	
	LOG(3, "---------- [NPTV][EH] vErrorHandleSetByTiming ----------\n"); 
#endif
	u2HSyncWidth = wDrvGetOutputHTotal() - wDrvGetOutputHActive() - wDrvGetHsyncBp() - wDrvGetHsyncFp();
	u2HSyncStart = wDrvGetOutputHActive() + wDrvGetHsyncFp();
	u2VSyncWidth = wDrvGetOutputVTotal() - wDrvGetOutputVActive() - wDrvGetVsyncBp() - wDrvGetVsyncFp();
	u2VSyncStart = wDrvGetOutputVActive() + wDrvGetVsyncFp();

#ifndef NDEBUG
	LOG(3, "[NPTV][EH] u2HSyncWidth=%d, u2HSyncStart=%d, u2VSyncWidth=%d, u2VSyncStart=%d\n", u2HSyncWidth, u2HSyncStart,u2VSyncWidth,u2VSyncStart);
#endif

	vIO32WriteFldAlign(EH_0C, u2HSyncWidth ,EH_DE_HS_WIDTH);
	// [Note] minus 4 --> Dealy 4T in DE fix mode .
	// 2 ch minus 8, 1 ch minus 4
	vIO32WriteFldAlign(EH_0C, u2HSyncStart - 4 ,EH_DE_HS_START);
	if (u2VSyncWidth >= 2)
	{
	 vIO32WriteFldAlign(EH_0D, u2VSyncWidth - 1 ,EH_DE_VS_WIDTH); 
	} 
	else
	{
		 vIO32WriteFldAlign(EH_0D, 1 ,EH_DE_VS_WIDTH); 
	}
	// [Note] minus OS_75_VSYNC_DELSEL 
	// [Note] minus 2 --> Dealy 1 Line in DE fix mode and 1 Line in HSYNC & VSYNC align.
	// [Note] 6line=1, HV_BYPASS=0, HV_hold=1, VBack porch delay 1 line
	// Need jimmy check
	if((IO32ReadFldAlign(VINTF_B0,VINTF_HV_HOLD) == 1)
	   &&(IO32ReadFldAlign(VINTF_B0, VINTF_HV_BYPASS) == 0)
	   && (IO32ReadFldAlign(VINTF_B0, VINTF_LINE_BUFFER_BYPASS) == 0))
	{
	 vIO32WriteFldAlign(EH_0D, u2VSyncStart - 2 ,EH_DE_VS_START);
	}
	else
	{
	 vIO32WriteFldAlign(EH_0D, u2VSyncStart - 1 ,EH_DE_VS_START);
	}

	 // For Set Data Function
	 if (PANEL_IsSupport4K2KDD())
	 {
		 vIO32WriteFldAlign(EH_19,(wDrvGetOutputHActive()>>u1DIV_2CH) + 80,EH_FIX_HTOTAL_VALUE);
		 vIO32WriteFldAlign(EH_19,(wDrvGetOutputHActive()>>u1DIV_2CH) + 80,EH_FIX_HTOTAL_TH);
	 }
	 else
	 {
		 vIO32WriteFldAlign(EH_19,wDrvGetOutputHActive() + 80,EH_FIX_HTOTAL_VALUE);
		 vIO32WriteFldAlign(EH_19,wDrvGetOutputHActive() + 80,EH_FIX_HTOTAL_TH);
	 }
#ifndef NDEBUG		 
	 LOG(3, "---------- [NPTV][EH] vErrorHandleSetByTiming end----------\n"); 
#endif
}

static void vErrorHandleOSDInit(void)
{
#if defined(SUPPORT_PANEL_GRAPH_MODE)
	#ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
	if (FlashPanel_GetControlWord2_GraphModeEn())
	#else
	if (IS_SUPPORT_VB1_GRAPH_MODE)
	#endif
	{
		vIO32WriteFldAlign(EH_00, 1 ,EH_FRAME_METER_EN_OSD);
		
		vIO32WriteFldMulti(EH_0F, P_Fld(0x0, EH_OSD_B_SWAP)
								| P_Fld(0x0, EH_OSD_G_SWAP)
								| P_Fld(0x0, EH_OSD_R_SWAP)								
								| P_Fld(0x0, EH_OSD_A_SWAP));
	}
#endif
}

#define ErrorHandling_DEMODE 0
void vErrorHandleInit(void)
{
#ifndef NDEBUG	
	LOG(0,"---------- [NPTV][EH] vErrorHandleInit ----------\n"); 
#endif
	vIO32WriteFldMulti(EH_00, P_Fld(1, EH_DISPR_DETECT_EN)|P_Fld(0, EH_INPUT_SEL)|P_Fld(1, EH_FRAME_METER_EN)|P_Fld(1, EH_INV_OUT_VS_EN)|P_Fld(1, EH_INV_OUT_HS_EN)|P_Fld(0, EH_DUAL_CHAN_PROCESS)|
	              			P_Fld(1, EH_H_CALI_WO_FILTER)|P_Fld(1, EH_REAL_TIME_CALI_EN)|P_Fld(1, EH_MUTE_MLVDS_EN)|P_Fld(0, EH_SET_DATA_TIME_SEL)|
	              			P_Fld(0, EH_XTAL_CLK_RST)|P_Fld(0, EH_OCLK_RST)|P_Fld(0, EH_REG_RST));

	vIO32WriteFldMulti(EH_01, P_Fld(1, EH_CLK_MISS_CHECK_EN)|P_Fld(0, EH_VDE_GEN_SEL)|P_Fld(0, EH_MUTE_DDDS_EN)|P_Fld(1, EH_DE_MISS_MUTE_EN)|
	              			P_Fld(1, EH_USE_SC_TIMING_EN)|P_Fld(1, EH_INV_VS_EN)|P_Fld(1, IEH_NV_HS_EN)|P_Fld(1, EH_CLK_STABLE_CHECK_EN)|
	              			P_Fld(1, EH_VDE_STABLE_CHECK_EN)|P_Fld(1, EH_DE_STABLE_CHECK_EN)|P_Fld(1, EH_V_STABLE_CHECK_EN)|P_Fld(1, EH_H_STABLE_CHECK_EN)|
	              			P_Fld(1, EH_STABLE_CHECK_EN)|P_Fld(1, EH_CONFIG_RDY_WO_FM)|P_Fld(1, EH_CONFIG_RDY_WO_STABLE)|P_Fld(0, EH_DISP_MLVDS_WO_DDDS_LOCK)|
	              			P_Fld(0, EH_DISP_MLVDS_WO_OD_RDY)|P_Fld(0, EH_SW_MUTE)|P_Fld(0, EH_SW_MUTE_EN)|P_Fld(0, EH_SCALER_MUTE_LVDS_RX_EN)|
	              			P_Fld(1, EH_H_MISS_MUTE_EN)|P_Fld(1, EH_CLK_MUTE_EN)|P_Fld(0, EH_VDE_MUTE_EN)|P_Fld(0, EH_DE_MUTE_EN)|
	              			P_Fld(1, EH_V_MUTE_EN)|P_Fld(1, EH_H_MUTE_EN)|P_Fld(1, EH_FAST_MUTE_EN));

	vIO32WriteFldMulti(EH_07, P_Fld(0, EH_CLK_MUTE_TEST_PERIOD)|P_Fld(2, EH_CLK_MISS_PERIOD_SEL)|P_Fld(5, EH_FAST_MUTE_CLK_CNT_TH)|P_Fld(0, EH_FAST_MUTE_V_CNT_TH)|
	              			P_Fld(2, EH_FAST_MUTE_H_CNT_TH));                
	vIO32WriteFldMulti(EH_08, P_Fld(2, EH_V_STB_CNT_TH)|P_Fld(2, EH_V_STB_DIFF_TH)|P_Fld(5, EH_H_STB_CNT_TH)|P_Fld(0x0A, EH_H_STB_DIFF_TH));
	vIO32WriteFldMulti(EH_09, P_Fld(2, EH_VDE_STB_CNT_TH)|P_Fld(2, EH_VDE_STB_DIFF_TH)|P_Fld(5, EH_DE_STB_CNT_TH)|P_Fld(0x0A, EH_DE_STB_DIFF_TH));
	vIO32WriteFldMulti(EH_0A, P_Fld(0x80, EH_CLK_STB_CNT_TH)|P_Fld(2, EH_CLK_STB_DIFF_TH));
	// MT8283 Fail --> EH_FIXED_VDE_EN
#if ErrorHandling_DEMODE
	vIO32WriteFldMulti(EH_0E, P_Fld(1, EH_FIXED_DE_EN)|P_Fld(0, EH_FIXED_VDE_EN)|P_Fld(1, EH_SET_LOW_HTOTAL_EN)|P_Fld(0, EH_WXGA_DATA_DELAY_SEL)|
	              			P_Fld(0, EH_CALI_MONI_SEL)|P_Fld(0, EH_DE_COUNTER_RESET_SEL)|P_Fld(0, EH_DE_DEGLITCH_EN)|P_Fld(0, EH_HTOTAL_CALI_MEDAIN_EN)|
	              			P_Fld(0, EH_HTOTAL_CALI_LOW_PASS_EN)|P_Fld(1, EH_MUTE_MLVDS_OFF_WHEN_PTGEN)|P_Fld(0, EH_MUTE_MLVDS_PERIOD)|P_Fld(0, EH_EH_MONI_SEL));        
#else
	vIO32WriteFldMulti(EH_0E, P_Fld(0, EH_FIXED_DE_EN)|P_Fld(0, EH_FIXED_VDE_EN)|P_Fld(1, EH_SET_LOW_HTOTAL_EN)|P_Fld(0, EH_WXGA_DATA_DELAY_SEL)|
	              			P_Fld(0, EH_CALI_MONI_SEL)|P_Fld(0, EH_DE_COUNTER_RESET_SEL)|P_Fld(0, EH_DE_DEGLITCH_EN)|P_Fld(0, EH_HTOTAL_CALI_MEDAIN_EN)|
	              			P_Fld(0, EH_HTOTAL_CALI_LOW_PASS_EN)|P_Fld(1, EH_MUTE_MLVDS_OFF_WHEN_PTGEN)|P_Fld(0, EH_MUTE_MLVDS_PERIOD)|P_Fld(0, EH_EH_MONI_SEL));        
#endif
	vIO32WriteFldMulti(EH_11, P_Fld(0x18, EH_PTGEN_H_WIDTH)|P_Fld(0x32, EH_PTGEN_H_START));
	vIO32WriteFldMulti(EH_13, P_Fld(0x10, EH_PTGEN_V_WIDTH)|P_Fld(0x13, EH_PTGEN_V_START));
	vIO32WriteFldMulti(EH_14, P_Fld(0, EH_PTGEN_TYPE_EN)|P_Fld(0, EH_PTGEN_B)|P_Fld(0, EH_PTGEN_G)|P_Fld(0, EH_PTGEN_R));
	vIO32WriteFldMulti(EH_15, P_Fld(0xFF, EH_AUTO_PTGEN_TIME_TH)|P_Fld(0, EH_PTGEN_H_RUN)|P_Fld(0, EH_PTGEN_V_RUN)|P_Fld(0, EH_AUTO_CHG_PTGEN_EN)|
	              			P_Fld(2, EH_PTGEN_TYPE));
	vIO32WriteFldMulti(EH_16, P_Fld(0, EH_INTR_CLR)|P_Fld(0xFF, EH_INTR_MASK));
	vIO32WriteFldAlign(EH_17, 0x70, EH_FAST_MUTE_DE_MISS_TH);
	vIO32WriteFldAlign(EH_STATUS_05,0,EH_LVDS_RX_INTR);

	if (LVDS_OUTPUT_PORT == SINGLE_PORT) // WXGA/60
	{
		vIO32WriteFldMulti(EH_02, P_Fld(0xAAC, EH_FAST_MUTE_H_TOTAL_HIGH_TH)|P_Fld(0x578, EH_FAST_MUTE_H_TOTAL_LOW_TH));
		vIO32WriteFldMulti(EH_03, P_Fld(0x600, EH_FAST_MUTE_V_TOTAL_HIGH_TH)|P_Fld(0x310, EH_FAST_MUTE_V_TOTAL_LOW_TH));
		vIO32WriteFldMulti(EH_04, P_Fld(0x560, EH_FAST_MUTE_DE_TOTAL_HIGH_TH)|P_Fld(0x551, EH_FAST_MUTE_DE_TOTAL_LOW_TH));
		vIO32WriteFldMulti(EH_05, P_Fld(0x310, EH_FAST_MUTE_VDE_TOTAL_HIGH_TH)|P_Fld(0x2F0, EH_FAST_MUTE_VDE_TOTAL_LOW_TH));
		vIO32WriteFldMulti(EH_06, P_Fld(0x228, EH_FAST_MUTE_CLK_TOTAL_HIGH_TH)|P_Fld(0x113, EH_FAST_MUTE_CLK_TOTAL_LOW_TH));            
		vIO32WriteFldMulti(EH_0B, P_Fld(1, EH_CALI_RANGE_SEL)|P_Fld(0, EH_CALI_WO_STABLE)|P_Fld(0x2, EH_CALI_RANGE_L)|P_Fld(0x2FF, EH_CALI_RANGE_H));
	#if ErrorHandling_DEMODE	  
		vIO32WriteFldMulti(EH_0C, P_Fld(1, EH_DE_MODE_EN)|P_Fld(0x10, EH_DE_HS_WIDTH)|P_Fld(0x568, EH_DE_HS_START));
	#else
		vIO32WriteFldMulti(EH_0C, P_Fld(0, EH_DE_MODE_EN)|P_Fld(0x10, EH_DE_HS_WIDTH)|P_Fld(0x568, EH_DE_HS_START));
	#endif
		vIO32WriteFldMulti(EH_0D, P_Fld(1, EH_DE_VS_WIDTH)|P_Fld(0x310, EH_DE_VS_START));
		vIO32WriteFldMulti(EH_10, P_Fld(0x558, EH_PTGEN_H_ACTIVE)|P_Fld(0x647, EH_PTGEN_H_TOTAL));
		vIO32WriteFldMulti(EH_12, P_Fld(0x300,EH_PTGEN_V_ACTIVE)|P_Fld(0x329, EH_PTGEN_V_TOTAL));  
		vIO32WriteFldMulti(EH_18, P_Fld(0, EH_CALI_HS_USE_SW_EN)|P_Fld(0, EH_CALI_VS_USE_SW_EN)|P_Fld(0, EH_CALI_DE_USE_SW_EN)|P_Fld(0, EH_CALI_VDE_USE_SW_EN)|
		                		P_Fld(0x329, EH_DE_VS_TOTAL_SW)|P_Fld(0x647, EH_DE_HS_TOTAL_SW));     
		vIO32WriteFldMulti(EH_19, P_Fld(0x5A6, EH_FIX_HTOTAL_VALUE)|P_Fld(0x5A7, EH_FIX_HTOTAL_TH));
		vIO32WriteFldMulti(EH_1A, P_Fld(0x540, EH_FIX_VDE_TH)|P_Fld(0x558, EH_FIXED_DE_TOATL));    
	}
	else  if ((LVDS_OUTPUT_PORT == DUAL_PORT)||(LVDS_OUTPUT_PORT == FOUR_PORT)) // 1080P/60
	{
		vIO32WriteFldMulti(EH_02, P_Fld(0xFFF, EH_FAST_MUTE_H_TOTAL_HIGH_TH)|P_Fld(0x7D0, EH_FAST_MUTE_H_TOTAL_LOW_TH));
		vIO32WriteFldMulti(EH_03, P_Fld(0xFFF, EH_FAST_MUTE_V_TOTAL_HIGH_TH)|P_Fld(0x456, EH_FAST_MUTE_V_TOTAL_LOW_TH));
		vIO32WriteFldMulti(EH_04, P_Fld(0x788, EH_FAST_MUTE_DE_TOTAL_HIGH_TH)|P_Fld(0x779, EH_FAST_MUTE_DE_TOTAL_LOW_TH));
		vIO32WriteFldMulti(EH_05, P_Fld(0x442, EH_FAST_MUTE_VDE_TOTAL_HIGH_TH)|P_Fld(0x42E, EH_FAST_MUTE_VDE_TOTAL_LOW_TH));
		vIO32WriteFldMulti(EH_06, P_Fld(0x114, EH_FAST_MUTE_CLK_TOTAL_HIGH_TH)|P_Fld(0x99, EH_FAST_MUTE_CLK_TOTAL_LOW_TH));        
		if (LVDS_OUTPUT_PORT == FOUR_PORT)
		{
			vIO32WriteFldMulti(EH_06, P_Fld(0x8A, EH_FAST_MUTE_CLK_TOTAL_HIGH_TH)|P_Fld(0x4C, EH_FAST_MUTE_CLK_TOTAL_LOW_TH));		
		}

		vIO32WriteFldMulti(EH_0B, P_Fld(1, EH_CALI_RANGE_SEL)|P_Fld(0, EH_CALI_WO_STABLE)|P_Fld(0x2, EH_CALI_RANGE_L)|P_Fld(0x438, EH_CALI_RANGE_H));
	#if ErrorHandling_DEMODE
		vIO32WriteFldMulti(EH_0C, P_Fld(1, EH_DE_MODE_EN)|P_Fld(0x10, EH_DE_HS_WIDTH)|P_Fld(0x7C4, EH_DE_HS_START));
	#else
		vIO32WriteFldMulti(EH_0C, P_Fld(0, EH_DE_MODE_EN)|P_Fld(0x10, EH_DE_HS_WIDTH)|P_Fld(0x7C4, EH_DE_HS_START));
	#endif
		vIO32WriteFldMulti(EH_0D, P_Fld(1, EH_DE_VS_WIDTH)|P_Fld(0x44A, EH_DE_VS_START));
		vIO32WriteFldMulti(EH_10, P_Fld(0x780, EH_PTGEN_H_ACTIVE)|P_Fld(0x898, EH_PTGEN_H_TOTAL));
		vIO32WriteFldMulti(EH_12, P_Fld(0x348,EH_PTGEN_V_ACTIVE)|P_Fld(0x464, EH_PTGEN_V_TOTAL));
		vIO32WriteFldMulti(EH_18, P_Fld(0, EH_CALI_HS_USE_SW_EN)|P_Fld(0, EH_CALI_VS_USE_SW_EN)|P_Fld(0, EH_CALI_DE_USE_SW_EN)|P_Fld(0, EH_CALI_VDE_USE_SW_EN)|
		                		P_Fld(0x465, EH_DE_VS_TOTAL_SW)|P_Fld(0x898, EH_DE_HS_TOTAL_SW));     
		vIO32WriteFldMulti(EH_19, P_Fld(0x7D0, EH_FIX_HTOTAL_VALUE)|P_Fld(0x7D0, EH_FIX_HTOTAL_TH));
		vIO32WriteFldMulti(EH_1A, P_Fld(0x76C, EH_FIX_VDE_TH)|P_Fld(0x780, EH_FIXED_DE_TOATL));
	}
	else if (LVDS_OUTPUT_PORT == OCTA_PORT)  // 4k2k@60: 2k2k@60
	{
		vIO32WriteFldMulti(EH_02, P_Fld(0xB40, EH_FAST_MUTE_H_TOTAL_HIGH_TH)|P_Fld(0x848, EH_FAST_MUTE_H_TOTAL_LOW_TH));
		vIO32WriteFldMulti(EH_03, P_Fld(0x992, EH_FAST_MUTE_V_TOTAL_HIGH_TH)|P_Fld(0x886, EH_FAST_MUTE_V_TOTAL_LOW_TH));
		vIO32WriteFldMulti(EH_04, P_Fld(0x787, EH_FAST_MUTE_DE_TOTAL_HIGH_TH)|P_Fld(0x778, EH_FAST_MUTE_DE_TOTAL_LOW_TH));
		vIO32WriteFldMulti(EH_05, P_Fld(0x870, EH_FAST_MUTE_VDE_TOTAL_HIGH_TH)|P_Fld(0x870, EH_FAST_MUTE_VDE_TOTAL_LOW_TH));
		vIO32WriteFldMulti(EH_06, P_Fld(0xCE, EH_FAST_MUTE_CLK_TOTAL_HIGH_TH)|P_Fld(0x9E, EH_FAST_MUTE_CLK_TOTAL_LOW_TH));  
		vIO32WriteFldMulti(EH_0B, P_Fld(1, EH_CALI_RANGE_SEL)|P_Fld(0, EH_CALI_WO_STABLE)|P_Fld(0x2, EH_CALI_RANGE_L)|P_Fld(0x86F, EH_CALI_RANGE_H));
	#if ErrorHandling_DEMODE
		vIO32WriteFldMulti(EH_0C, P_Fld(1, EH_DE_MODE_EN)|P_Fld(0x2C, EH_DE_HS_WIDTH)|P_Fld(0x984, EH_DE_HS_START));
	#else
		vIO32WriteFldMulti(EH_0C, P_Fld(0, EH_DE_MODE_EN)|P_Fld(0x2C, EH_DE_HS_WIDTH)|P_Fld(0x984, EH_DE_HS_START));
	#endif
		vIO32WriteFldMulti(EH_0D, P_Fld(5, EH_DE_VS_WIDTH)|P_Fld(0x8BD, EH_DE_VS_START));
		vIO32WriteFldMulti(EH_10, P_Fld(0x780, EH_PTGEN_H_ACTIVE)|P_Fld(0xA50, EH_PTGEN_H_TOTAL));
		vIO32WriteFldMulti(EH_12, P_Fld(0x870,EH_PTGEN_V_ACTIVE)|P_Fld(0x8CA, EH_PTGEN_V_TOTAL));
		vIO32WriteFldMulti(EH_18, P_Fld(0, EH_CALI_HS_USE_SW_EN)|P_Fld(0, EH_CALI_VS_USE_SW_EN)|P_Fld(0, EH_CALI_DE_USE_SW_EN)|P_Fld(0, EH_CALI_VDE_USE_SW_EN)|
		                		P_Fld(0x8CA, EH_DE_VS_TOTAL_SW)|P_Fld(0xA50, EH_DE_HS_TOTAL_SW));     
		vIO32WriteFldMulti(EH_19, P_Fld(0xAA0, EH_FIX_HTOTAL_VALUE)|P_Fld(0xAA0, EH_FIX_HTOTAL_TH));
		vIO32WriteFldMulti(EH_1A, P_Fld(0x7D0, EH_FIX_VDE_TH)|P_Fld(0x7D0, EH_FIXED_DE_TOATL));
	}
	else if (LVDS_OUTPUT_PORT == HEXA_PORT)
	{
		if (PANEL_Is4K2K120())  // 4k2k@120: 1k2k@120
		{
			vIO32WriteFldMulti(EH_02, P_Fld(0x5A0, EH_FAST_MUTE_H_TOTAL_HIGH_TH)|P_Fld(0x424, EH_FAST_MUTE_H_TOTAL_LOW_TH));
			vIO32WriteFldMulti(EH_03, P_Fld(0x992, EH_FAST_MUTE_V_TOTAL_HIGH_TH)|P_Fld(0x886, EH_FAST_MUTE_V_TOTAL_LOW_TH));
			vIO32WriteFldMulti(EH_04, P_Fld(0x3C7, EH_FAST_MUTE_DE_TOTAL_HIGH_TH)|P_Fld(0x3B8, EH_FAST_MUTE_DE_TOTAL_LOW_TH));
			vIO32WriteFldMulti(EH_05, P_Fld(0x870, EH_FAST_MUTE_VDE_TOTAL_HIGH_TH)|P_Fld(0x870, EH_FAST_MUTE_VDE_TOTAL_LOW_TH));
			vIO32WriteFldMulti(EH_06, P_Fld(0xCE, EH_FAST_MUTE_CLK_TOTAL_HIGH_TH)|P_Fld(0x9E, EH_FAST_MUTE_CLK_TOTAL_LOW_TH));  
			vIO32WriteFldMulti(EH_0B, P_Fld(1, EH_CALI_RANGE_SEL)|P_Fld(0, EH_CALI_WO_STABLE)|P_Fld(0x2, EH_CALI_RANGE_L)|P_Fld(0x86F, EH_CALI_RANGE_H));
		#if ErrorHandling_DEMODE
			vIO32WriteFldMulti(EH_0C, P_Fld(1, EH_DE_MODE_EN)|P_Fld(0x16, EH_DE_HS_WIDTH)|P_Fld(0x4C2, EH_DE_HS_START));
		#else
			vIO32WriteFldMulti(EH_0C, P_Fld(0, EH_DE_MODE_EN)|P_Fld(0x16, EH_DE_HS_WIDTH)|P_Fld(0x4C2, EH_DE_HS_START));
		#endif
			vIO32WriteFldMulti(EH_0D, P_Fld(5, EH_DE_VS_WIDTH)|P_Fld(0x8BD, EH_DE_VS_START));
			vIO32WriteFldMulti(EH_10, P_Fld(0x3C0, EH_PTGEN_H_ACTIVE)|P_Fld(0x528, EH_PTGEN_H_TOTAL));
			vIO32WriteFldMulti(EH_12, P_Fld(0x870,EH_PTGEN_V_ACTIVE)|P_Fld(0x8CA, EH_PTGEN_V_TOTAL));
			vIO32WriteFldMulti(EH_18, P_Fld(0, EH_CALI_HS_USE_SW_EN)|P_Fld(0, EH_CALI_VS_USE_SW_EN)|P_Fld(0, EH_CALI_DE_USE_SW_EN)|P_Fld(0, EH_CALI_VDE_USE_SW_EN)|
			                		P_Fld(0x8CA, EH_DE_VS_TOTAL_SW)|P_Fld(0x528, EH_DE_HS_TOTAL_SW));     
			vIO32WriteFldMulti(EH_19, P_Fld(0x578, EH_FIX_HTOTAL_VALUE)|P_Fld(0x578, EH_FIX_HTOTAL_TH));
			vIO32WriteFldMulti(EH_1A, P_Fld(0x7D0, EH_FIX_VDE_TH)|P_Fld(0x7D0, EH_FIXED_DE_TOATL));
		}
		else if (PANEL_Is8K4K30())  // 8k4k@30: 2k4k@30
		{
			vIO32WriteFldMulti(EH_02, P_Fld(0xB40, EH_FAST_MUTE_H_TOTAL_HIGH_TH)|P_Fld(0x848, EH_FAST_MUTE_H_TOTAL_LOW_TH));
			vIO32WriteFldMulti(EH_03, P_Fld(0x1324, EH_FAST_MUTE_V_TOTAL_HIGH_TH)|P_Fld(0x110C, EH_FAST_MUTE_V_TOTAL_LOW_TH));
			vIO32WriteFldMulti(EH_04, P_Fld(0x787, EH_FAST_MUTE_DE_TOTAL_HIGH_TH)|P_Fld(0x778, EH_FAST_MUTE_DE_TOTAL_LOW_TH));
			vIO32WriteFldMulti(EH_05, P_Fld(0x10E0, EH_FAST_MUTE_VDE_TOTAL_HIGH_TH)|P_Fld(0x10E0, EH_FAST_MUTE_VDE_TOTAL_LOW_TH));
			vIO32WriteFldMulti(EH_06, P_Fld(0xCE, EH_FAST_MUTE_CLK_TOTAL_HIGH_TH)|P_Fld(0x9E, EH_FAST_MUTE_CLK_TOTAL_LOW_TH));  
			vIO32WriteFldMulti(EH_0B, P_Fld(1, EH_CALI_RANGE_SEL)|P_Fld(0, EH_CALI_WO_STABLE)|P_Fld(0x2, EH_CALI_RANGE_L)|P_Fld(0x86F, EH_CALI_RANGE_H));
		#if ErrorHandling_DEMODE
			vIO32WriteFldMulti(EH_0C, P_Fld(1, EH_DE_MODE_EN)|P_Fld(0x2C, EH_DE_HS_WIDTH)|P_Fld(0x984, EH_DE_HS_START));
		#else
			vIO32WriteFldMulti(EH_0C, P_Fld(0, EH_DE_MODE_EN)|P_Fld(0x2C, EH_DE_HS_WIDTH)|P_Fld(0x984, EH_DE_HS_START));
		#endif
			vIO32WriteFldMulti(EH_0D, P_Fld(11, EH_DE_VS_WIDTH)|P_Fld(0x90C, EH_DE_VS_START));
			vIO32WriteFldMulti(EH_10, P_Fld(0x780, EH_PTGEN_H_ACTIVE)|P_Fld(0xA50, EH_PTGEN_H_TOTAL));
			vIO32WriteFldMulti(EH_12, P_Fld(0x10E0,EH_PTGEN_V_ACTIVE)|P_Fld(0x1194, EH_PTGEN_V_TOTAL));
			vIO32WriteFldMulti(EH_18, P_Fld(0, EH_CALI_HS_USE_SW_EN)|P_Fld(0, EH_CALI_VS_USE_SW_EN)|P_Fld(0, EH_CALI_DE_USE_SW_EN)|P_Fld(0, EH_CALI_VDE_USE_SW_EN)|
			                		P_Fld(0x1194, EH_DE_VS_TOTAL_SW)|P_Fld(0xA50, EH_DE_HS_TOTAL_SW));     
			vIO32WriteFldMulti(EH_19, P_Fld(0xAA0, EH_FIX_HTOTAL_VALUE)|P_Fld(0xAA0, EH_FIX_HTOTAL_TH));
			vIO32WriteFldMulti(EH_1A, P_Fld(0x7D0, EH_FIX_VDE_TH)|P_Fld(0x7D0, EH_FIXED_DE_TOATL));
		}
	}

	vErrorHandleOSDInit();

	vErrorHandleSetByPanel();
}

void vErrorHandleStatus(void)
{
	UINT32 u2MUTE_STATUS; 
	UINT32 u2Temp;
	UINT32 u2Temp_num,u2Temp_point;
	UNUSED(u2Temp_point);
	u2MUTE_STATUS = IO32ReadFldAlign(EH_STATUS_02,EH_FLD_ALL);
	
	LOG(0,"---------- Error Handling Status ----------\n"); 
	
	LOG(0,"[Panel Interface Information]\n");
	if (IO32ReadFldAlign(VINTF_P0,VINTF_PANEL_IN_SEL)==0)
	LOG(0,"(0)From TCON-Error handling\n");
	else if (IO32ReadFldAlign(VINTF_P0,VINTF_PANEL_IN_SEL)==1)
	LOG(0,"(1)From OD\n");
	else if (IO32ReadFldAlign(VINTF_P0,VINTF_PANEL_IN_SEL)==2)
	LOG(0,"(2)From From SCPOS\n");

	LOG(0,"[Error handling input]\n");    
	if (IO32ReadFldAlign(EH_00, EH_INPUT_SEL) == 1)
	LOG(0,"[0] From OD (Test)\n");
	else if (IO32ReadFldAlign(EH_00, EH_INPUT_SEL) == 0)
	LOG(0,"[1] From SCPOS (default) \n");
	
	LOG(0,"[Clock Information]\n");
	if (IS_XTAL_24MHZ())
	{
		LOG(0,"(Input)Clock=%ld MHz\n",(((2048*24)/(IO32ReadFldAlign(EH_STATUS_04,EH_CLK_TOTAL_MON)))));
	}
	else if (IS_XTAL_27MHZ())
	{
		LOG(0,"(Input)Clock=%ld MHz\n",(((2048*27)/(IO32ReadFldAlign(EH_STATUS_04,EH_CLK_TOTAL_MON)))));
	}

	LOG(0,"[Frame Rate]\n"); 
	u2Temp = IO32ReadFldAlign(EH_STATUS_0D,EH_XCLK_IN_FRAME);	
	if (!u2Temp)
	{
		u2Temp = 1;
	}
	if (IS_XTAL_24MHZ())
	{
		u2Temp_num = 24000000/u2Temp;
	  	u2Temp_point = (24000000 - u2Temp_num * u2Temp)*100/u2Temp;
		LOG(0,"(Input) frame rate = %ld.%2ld Hz\n", u2Temp_num, u2Temp_point);
	}
	else
	{
		u2Temp_num = 27000000/u2Temp;
	  	u2Temp_point = (27000000 - u2Temp_num * u2Temp)*100/u2Temp;	
		LOG(0,"(Input)frame rate = %ld.%2ld Hz\n", u2Temp_num, u2Temp_point);

	}
	
	LOG(0,"[DISP_R status]\n"); 
	if(IO32ReadFldAlign(EH_STATUS_0D,EH_DISP_R_STATUS)==0)	
	{
		LOG(0,"LRLR Mode\n");
	}
	else if(IO32ReadFldAlign(EH_STATUS_0D,EH_DISP_R_STATUS)==1)	
	{
		LOG(0,"LLRR Mode\n");
	}
	else if(IO32ReadFldAlign(EH_STATUS_0D,EH_DISP_R_STATUS)==2)	
	{
		LOG(0,"MUTE Mode\n");
	}
	else if(IO32ReadFldAlign(EH_STATUS_0D,EH_DISP_R_STATUS)==3)	
	{
		LOG(0,"IDLE Mode\n");
	}
		
	LOG(0,"[V,F Information]\n");
	LOG(0,"(Input)DE_TOTAL_MON=%ld, H_TOTAL_MON=%ld, VDE_TOTAL_MON=%ld, V_TOTAL_MON=%ld\n",
			(IO32ReadFldAlign(EH_STATUS_00,EH_DE_TOTAL_MON)),((IO32ReadFldAlign(EH_STATUS_00,EH_H_TOTAL_MON)) + 1),
			IO32ReadFldAlign(EH_STATUS_01,EH_VDE_TOTAL_MON), (IO32ReadFldAlign(EH_STATUS_01,EH_V_TOTAL_MON)+1));		  
    if(IO32ReadFldAlign(EH_01,EH_USE_SC_TIMING_EN)==1)	
    {
		LOG(0,"Ouput Status from Scaler \n");	
    }
	else
	{
		LOG(0,"Ouput Status from Error Handling \n");	
	}
	u2Temp = IO32ReadFldAlign(EH_01,EH_USE_SC_TIMING_EN);
	vIO32WriteFldAlign(EH_01,1,EH_USE_SC_TIMING_EN);
	LOG(0,"(Ouput#1 from scaler )DE_TOTAL_MON=%ld, H_TOTAL_MON=%ld, VDE_TOTAL_MON=%ld, V_TOTAL_MON=%ld\n",
			IO32ReadFldAlign(EH_STATUS_08,EH_DE_TOTAL_CALI),IO32ReadFldAlign(EH_STATUS_08,EH_H_TOTAL_CALI),
			IO32ReadFldAlign(EH_STATUS_09,EH_VDE_TOTAL_CALI), IO32ReadFldAlign(EH_STATUS_09,EH_V_TOTAL_CALI));
	vIO32WriteFldAlign(EH_01,0,EH_USE_SC_TIMING_EN);
	LOG(0,"(Ouput#2 EH calculate)DE_TOTAL_MON=%ld, H_TOTAL_MON=%ld, VDE_TOTAL_MON=%ld, V_TOTAL_MON=%ld\n",
			IO32ReadFldAlign(EH_STATUS_08,EH_DE_TOTAL_CALI),IO32ReadFldAlign(EH_STATUS_08,EH_H_TOTAL_CALI),
			IO32ReadFldAlign(EH_STATUS_09,EH_VDE_TOTAL_CALI), IO32ReadFldAlign(EH_STATUS_09,EH_V_TOTAL_CALI));
	vIO32WriteFldAlign(EH_01,u2Temp,EH_USE_SC_TIMING_EN);
	LOG(0,"(Ouput)H_WIDTH=%ld, H_START=%ld, V_WIDTH=%ld, V_START=%ld\n",
			IO32ReadFldAlign(EH_STATUS_0A,EH_H_WIDTH_CALI),IO32ReadFldAlign(EH_STATUS_0B,EH_H_START_CALI),
			IO32ReadFldAlign(EH_STATUS_0A,EH_V_WIDTH_CALI), IO32ReadFldAlign(EH_STATUS_0B,EH_V_START_CALI));	
	
	LOG(0,"[UNREADY Status]\n"); 
	// if (((u2MUTE_STATUS >> EHS_OD_READY)& 0x01) == 0)
	// LOG(0,"| OD_UNREADY");
	if (((u2MUTE_STATUS >> EHS_OD_OK)& 0x01) == 0)
	LOG(0,"| OD_UNOK");
	if (((u2MUTE_STATUS >> EHS_DISP_OK)& 0x01) == 0)
	LOG(0,"| DISP_UNOK");
	if (((u2MUTE_STATUS >> EHS_FAST_MUTE_READY)& 0x01) == 0)
	LOG(0,"FAST_MUTE_UNREADY");
	LOG(0,"\n");
	
	LOG(0,"[MUTE Condition]\n");
	LOG(0,"HOTAL[High = %4ld,Low = %4ld]\n",
			IO32ReadFldAlign(EH_02,EH_FAST_MUTE_H_TOTAL_HIGH_TH),
			IO32ReadFldAlign(EH_02,EH_FAST_MUTE_H_TOTAL_LOW_TH));
	LOG(0,"VOTAL[High = %4ld,Low = %4ld]\n",
			IO32ReadFldAlign(EH_03,EH_FAST_MUTE_V_TOTAL_HIGH_TH),
			IO32ReadFldAlign(EH_03,EH_FAST_MUTE_V_TOTAL_LOW_TH));
	LOG(0,"DE   [High = %4ld,Low = %4ld]\n",
			IO32ReadFldAlign(EH_04,EH_FAST_MUTE_DE_TOTAL_HIGH_TH),
			IO32ReadFldAlign(EH_04,EH_FAST_MUTE_DE_TOTAL_LOW_TH)); 		 
	LOG(0,"VDE  [High = %4ld,Low = %4ld]\n",
			IO32ReadFldAlign(EH_05,EH_FAST_MUTE_VDE_TOTAL_HIGH_TH),
			IO32ReadFldAlign(EH_05,EH_FAST_MUTE_VDE_TOTAL_LOW_TH)); 		 
	if (IS_XTAL_24MHZ())
	{
		LOG(0,"Clock[High = %ld MHz,Low = %ld MHz]\n",
			(((1024*24)/(IO32ReadFldAlign(EH_06,EH_FAST_MUTE_CLK_TOTAL_LOW_TH)))),
			(((1024*24)/(IO32ReadFldAlign(EH_06,EH_FAST_MUTE_CLK_TOTAL_HIGH_TH)))));
		}
	else if (IS_XTAL_27MHZ())
	{
		LOG(0,"Clock[High = %ld MHz,Low = %ld MHz]\n",
			(((1024*27)/(IO32ReadFldAlign(EH_06,EH_FAST_MUTE_CLK_TOTAL_LOW_TH)))),
			(((1024*27)/(IO32ReadFldAlign(EH_06,EH_FAST_MUTE_CLK_TOTAL_HIGH_TH)))));
	}
	
	LOG(0,"[Mute Status]\n");	  
	if (((u2MUTE_STATUS >> EHS_OD_INTF_ERROR)& 0x01) == 1)
	LOG(0,"OD_INTF_ERROR");
	if (((u2MUTE_STATUS >> EHS_MUTE_LVDS)& 0x01) == 1)
	LOG(0,"| MUTE_MLVDS");
	if (((u2MUTE_STATUS >> EHS_DE_MISS_MUTE)& 0x01) == 1)
	LOG(0,"| DE_MISS_MUTE");
	if (((u2MUTE_STATUS >> EHS_INPUT_OK)& 0x01) == 1)
	LOG(0,"| INPUT_OK");
	// if (((u2MUTE_STATUS >> EHS_OD_BYPASS)& 0x01) == 1)
	// LOG(0,"| OD_BYPASS");
	if (((u2MUTE_STATUS >> EHS_OD_MUTE_DDDS)& 0x01) == 1)
	LOG(0,"| OD_MUTE_DDDS");
	LOG(0,"\n");	 
	
	if (((u2MUTE_STATUS >> EHS_H_MISS_MUTE)& 0x01) == 1)
	LOG(0,"| H_MISS_MUTE");
	if (((u2MUTE_STATUS >> EHS_CLOCK_MUTE)& 0x01) == 1)
	LOG(0,"| CLOCK MUTE");
	if (((u2MUTE_STATUS >> EHS_VDE_MUTE)& 0x01) == 1)
	LOG(0,"| VDE_MUTE");
	if (((u2MUTE_STATUS >> EHS_V_MUTE)& 0x01) == 1)
	LOG(0,"| V_MUTE");
	if (((u2MUTE_STATUS >> EHS_DE_MUTE)& 0x01) == 1)
	LOG(0,"| DE_MUTE");
	if (((u2MUTE_STATUS >> EHS_H_MUTE)& 0x01) == 1)
	LOG(0,"| H_MUTE");
	if (((u2MUTE_STATUS >> EHS_MUTE)& 0x01) == 1)
	LOG(0,"| MUTE");  
	LOG(0,"\n");	 
	
	LOG(0,"[UNSTABLE Status]\n");	  
	
	if (((u2MUTE_STATUS >> EHS_CONFIG_READY)& 0x01) == 0)
	LOG(0,"Configuration_UNREADY");
	//if (((u2MUTE_STATUS >> EHS_DDDS_LOCK)& 0x01) == 0)
	//LOG(0,"| DDDS_UNLOCK");
	if (((u2MUTE_STATUS >> EHS_CLOCK_STABLE)& 0x01) == 0)
	LOG(0,"| CLOCK_UNSTABLE");
	if (((u2MUTE_STATUS >> EHS_VDE_STABLE)& 0x01) == 0)
	LOG(0,"| VDE_UNSTABLE");
	if (((u2MUTE_STATUS >> EHS_V_STABLE)& 0x01) == 0)
	LOG(0,"| V_UNSTABLE");
	if (((u2MUTE_STATUS >> EHS_DE_STABLE)& 0x01) == 0)
	LOG(0,"| DE_UNSTABLE");
	if (((u2MUTE_STATUS >> EHS_H_STABLE)& 0x01) == 0)
	LOG(0,"| H_UNSTABLE");
	if (((u2MUTE_STATUS >> EHS_STABLE)& 0x01) == 0)
	LOG(0,"| UNSTABLE");  
	LOG(0,"\n");	 

	#if defined(SUPPORT_PANEL_GRAPH_MODE)
	#ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
	if (FlashPanel_GetControlWord2_GraphModeEn())
	#else
	if (IS_SUPPORT_VB1_GRAPH_MODE)
	#endif
	{
		LOG(0,"[Ouput Status from OSD]\n");			
		LOG(0,"(Ouput)DE_TOTAL_MON=%ld, H_TOTAL_MON=%ld, VDE_TOTAL_MON=%ld, V_TOTAL_MON=%ld\n",
				IO32ReadFldAlign(EH_STATUS_12,EH_HACTIVE_STATUS),IO32ReadFldAlign(EH_STATUS_10,EH_HTOTAL_STATUS),
				IO32ReadFldAlign(EH_STATUS_12,EH_VACTIVE_STATUS), IO32ReadFldAlign(EH_STATUS_10,EH_VTOTAL_STATUS));	
		LOG(0,"(Ouput)H_START=%ld, V_START=%ld\n",
				IO32ReadFldAlign(EH_STATUS_11,EH_HSTART_STATUS),IO32ReadFldAlign(EH_STATUS_11,EH_VSTART_STATUS));

		LOG(0,"[Frame Rate]\n"); 
		u2Temp = IO32ReadFldAlign(EH_STATUS_13,EH_OSD_FRATE_STATUS);	
		if (!u2Temp)
		{
			u2Temp = 1;
		}
		if (IS_XTAL_24MHZ())
		{
			u2Temp_num = 24000000/u2Temp;
			u2Temp_point = (24000000 - u2Temp_num * u2Temp)*100/u2Temp;
			LOG(0,"(Input) frame rate = %ld.%2ld Hz\n", u2Temp_num, u2Temp_point);
		}
		else
		{
			u2Temp_num = 27000000/u2Temp;
			u2Temp_point = (27000000 - u2Temp_num * u2Temp)*100/u2Temp; 
			LOG(0,"(Input)frame rate = %ld.%2ld Hz\n", u2Temp_num, u2Temp_point);
		}
	}
	#endif

}

void vScEhSta(void)
{
	UINT32 u2Temp;
	u2Temp = IO32ReadFldAlign(EH_01,EH_USE_SC_TIMING_EN);
	vIO32WriteFldAlign(EH_01,1,EH_USE_SC_TIMING_EN);
	LOG(0,"(Ouput#1 from scaler )DE_TOTAL_MON=%ld, H_TOTAL_MON=%ld, VDE_TOTAL_MON=%ld, V_TOTAL_MON=%ld\n",
			IO32ReadFldAlign(EH_STATUS_08,EH_DE_TOTAL_CALI),IO32ReadFldAlign(EH_STATUS_08,EH_H_TOTAL_CALI),
			IO32ReadFldAlign(EH_STATUS_09,EH_VDE_TOTAL_CALI), IO32ReadFldAlign(EH_STATUS_09,EH_V_TOTAL_CALI));
	vIO32WriteFldAlign(EH_01,0,EH_USE_SC_TIMING_EN);
	LOG(0,"(Ouput#2 EH calculate)DE_TOTAL_MON=%ld, H_TOTAL_MON=%ld, VDE_TOTAL_MON=%ld, V_TOTAL_MON=%ld\n",
			IO32ReadFldAlign(EH_STATUS_08,EH_DE_TOTAL_CALI),IO32ReadFldAlign(EH_STATUS_08,EH_H_TOTAL_CALI),
			IO32ReadFldAlign(EH_STATUS_09,EH_VDE_TOTAL_CALI), IO32ReadFldAlign(EH_STATUS_09,EH_V_TOTAL_CALI));
	vIO32WriteFldAlign(EH_01,u2Temp,EH_USE_SC_TIMING_EN);
}

void u1ErrorHandleFixEnable(UINT8 val)
{
  vIO32WriteFldMulti(EH_0E, P_Fld(val, EH_FIXED_DE_EN)
                                       |P_Fld(val, EH_FIXED_VDE_EN)|P_Fld(val, EH_DE_DEGLITCH_EN));

}

void u1ErrorHandleMuteEnable(UINT8 val)
{
   vIO32WriteFldAlign(EH_00, val, EH_MUTE_MLVDS_EN);   
}


void u1ErrorHandlingSourceSet(UINT8 val)
{
  if (val<=1)
  {
   vIO32WriteFldAlign(EH_00, val, EH_INPUT_SEL);   
  } 
}

UINT8 u1ErrorHandlingSourceGet(void)
{
  return (IO32ReadFldAlign(EH_00, EH_INPUT_SEL));
}

void vVByOneOsdARGBMap_SM0ToInhouse(void)
{
	// A7->A0; A6->A3; A5->A2; A4->A5; A3->A4; A2->A7; A1->A6; A0->A1
	vIO32WriteFldMulti(EH_1B, P_Fld(0x1, EH_OSD_A7_SEL)
							| P_Fld(0x5, EH_OSD_A6_SEL)
							| P_Fld(0x5, EH_OSD_A5_SEL)
							| P_Fld(0x1, EH_OSD_A4_SEL)
							| P_Fld(0x1, EH_OSD_A3_SEL)
							| P_Fld(0x5, EH_OSD_A2_SEL)							
							| P_Fld(0x5, EH_OSD_A1_SEL)									
							| P_Fld(0x1, EH_OSD_A0_SEL));
	
	vIO32WriteFldMulti(EH_1C, P_Fld(0x0, EH_OSD_R7_SEL)
							| P_Fld(0x0, EH_OSD_R6_SEL)
							| P_Fld(0x0, EH_OSD_R5_SEL)
							| P_Fld(0x0, EH_OSD_R4_SEL)
							| P_Fld(0x0, EH_OSD_R3_SEL)
							| P_Fld(0x0, EH_OSD_R2_SEL)							
							| P_Fld(0x0, EH_OSD_R1_SEL)									
							| P_Fld(0x0, EH_OSD_R0_SEL));	

	vIO32WriteFldMulti(EH_1E, P_Fld(0x0, EH_OSD_G7_SEL)
							| P_Fld(0x0, EH_OSD_G6_SEL)
							| P_Fld(0x0, EH_OSD_G5_SEL)
							| P_Fld(0x0, EH_OSD_G4_SEL)
							| P_Fld(0x0, EH_OSD_G3_SEL)
							| P_Fld(0x0, EH_OSD_G2_SEL)							
							| P_Fld(0x0, EH_OSD_G1_SEL)									
							| P_Fld(0x0, EH_OSD_G0_SEL));	

	vIO32WriteFldMulti(EH_1F, P_Fld(0x0, EH_OSD_B7_SEL)
							| P_Fld(0x0, EH_OSD_B6_SEL)
							| P_Fld(0x0, EH_OSD_B5_SEL)
							| P_Fld(0x0, EH_OSD_B4_SEL)
							| P_Fld(0x0, EH_OSD_B3_SEL)
							| P_Fld(0x0, EH_OSD_B2_SEL)							
							| P_Fld(0x0, EH_OSD_B1_SEL)									
							| P_Fld(0x0, EH_OSD_B0_SEL));
	
}


/**
 * @brief vDrvErrorHandleEN

 * Error handle enable control

 * @param  bEn
 * @retval void
 */
/*
static void vDrvErrorHandleEN(UINT8 bEn) 
{
    vIO32WriteFldAlign(EH_00,bEn,EH_MUTE_MLVDS_EN);
    vIO32WriteFldMulti(EH_01,P_Fld(bEn,EH_FAST_MUTE_EN)|P_Fld(bEn,EH_DE_MISS_MUTE_EN));

}
*/

//Gamma Initialize	
static void vDrvTconGammaInit(void)
{   
	#if  HISENSE_IPS_2010_PANEL 
	   x_thread_delay(15);
	#endif

    if (u1TconCustGammaInit() == 1)
    {
        _u1GammaReady = 1;
    }
    else
    {
        _u1GammaReady = 0;
    }
    
	LOG(1,"Tcon Gamma init\n");
}

//Tg Initialize
static void vDrvTgPreInit(void)
{
	LOG(0, "[TCON] vDrvTgPreInit \n");
	
	vIO32WriteFldMulti(GR0, P_Fld(1, GR0_TC_EN)|P_Fld(0x002, GR0_TCTG_FCR)|P_Fld(0, GR0_TCTG_OEN));
	vIO32WriteFldMulti(GR1, P_Fld(1, GR1_TCTG_HSINV)|P_Fld(1, GR1_TCTG_VSINV));
	vIO32WriteFldMulti(GR7, P_Fld(0, GR7_TCO_MUTE)|P_Fld(0, GR7_TCO_DEFAULT));
	vIO32WriteFldMulti(GR8, P_Fld(0, GR8_TCGPO)|P_Fld(0, GR8_TCGPOEN));
}

#ifdef CONFIG_OPM
    BOOL _fgTCONInit = FALSE;
#else
    static BOOL _fgTCONInit = FALSE;
#endif
void vDrvTgInit(void)
{
    if (IO32ReadFldAlign(DDDS_08, FLAG_TCON_INITIAL) == 1)
    {
        _fgTCONInit = TRUE;
    }

	if (!_fgTCONInit)
	{
		LOG(3, "[TCON] vDrvTgInit(START) \n");
		vDrvTgPreInit();
	
    	if(_fgTconCustSel == FALSE)
    	{
    		u1TconCustTgInit();
    	}
    	else
    	{
        	vDrvTCONCustSel(_u1TconCustSel);
    	}

		_fgTCONInit = TRUE;
		vIO32WriteFldAlign(DDDS_08, 1, FLAG_TCON_INITIAL);
    }
	
}

UINT16 wApiFlashPqGetPanelId(void)
{
    UINT16 wFashPanelid=PANEL_TOTAL_NUMBER;

	switch (GetCurrentPanelIndex())
    {                 
    	#ifdef PANEL_MLVDS_LGDV4FHD60
        case PANEL_MLVDS_LGDV4FHD60: 
            wFashPanelid = 0;
        break;
		#endif

		#ifdef PANEL_MLVDS_LGDV4FHD120
		case PANEL_MLVDS_LGDV4FHD120:             
            wFashPanelid = 1;
        break;
		#endif

		#ifdef PANEL_MLVDS_PANASONIC32WXGA1P6P
		case PANEL_MLVDS_PANASONIC32WXGA1P6P:             
            wFashPanelid = 2;
        break;
		#endif

		#ifdef PANEL_MLVDS_PANASONIC32WXGA2P3P
		case PANEL_MLVDS_PANASONIC32WXGA2P3P:             
            wFashPanelid = 3;
        break;
		#endif

		#ifdef PANEL_MLVDS_PANASONIC42FHD120
        case PANEL_MLVDS_PANASONIC42FHD120:             
            wFashPanelid = 4;
        break;
		#endif

		#ifdef PANEL_MLVDS_CMO2011FHD60
        case PANEL_MLVDS_CMO2011FHD60:             
            wFashPanelid = 5;
        break;
		#endif
		
		#ifdef PANEL_MLVDS_CMO2011FHD120
		case PANEL_MLVDS_CMO2011FHD120:             
            wFashPanelid = 6;
        break;
		#endif

		#ifdef PANEL_MLVDS_SS_MB7
        case PANEL_MLVDS_SS_MB7:             
            wFashPanelid = 7;
        break;
		#endif

		#ifdef PANEL_EPI_LGDV12GIPFHD60
        case PANEL_EPI_LGDV12GIPFHD60:             
            wFashPanelid = 8;
        break;
		#endif

		#ifdef PANEL_EPI_LGDV12GIPFHD120
        case PANEL_EPI_LGDV12GIPFHD120:             
            wFashPanelid = 9;
        break;
		#endif

		#ifdef PANEL_MLVDS_LGD32WXGAV9
		case PANEL_MLVDS_LGD32WXGAV9:
            wFashPanelid = 10;
		break;	
		#endif

        default:
          break;
    }    
	return wFashPanelid;
}

#ifndef CC_UBOOT
void vDrvFlashPanelUpdateParam(void)
{
    UINT32 u4TvoVal;
    //TCON
    //GR0
   vIO32WriteFldAlign(GR0, rFlashPanelTable.u2FPGr0TctgFcr, GR0_TCTG_FCR);

    //GR4
    vIO32WriteFldMulti(GR4, P_Fld(rFlashPanelTable.u1FPGr4TgMuxselB15, GR4_TG_MUXSEL_B15)|
        P_Fld(rFlashPanelTable.u1FPGr4TgMuxselB14, GR4_TG_MUXSEL_B14)|P_Fld(rFlashPanelTable.u1FPGr4TgMuxselB13, GR4_TG_MUXSEL_B13)|
        P_Fld(rFlashPanelTable.u1FPGr4TgMuxselB12, GR4_TG_MUXSEL_B12)|P_Fld(rFlashPanelTable.u1FPGr4TgMuxselB11, GR4_TG_MUXSEL_B11)|
        P_Fld(rFlashPanelTable.u1FPGr4TgMuxselB10, GR4_TG_MUXSEL_B10)|P_Fld(rFlashPanelTable.u1FPGr4TgMuxselB9, GR4_TG_MUXSEL_B9)|
        P_Fld(rFlashPanelTable.u1FPGr4TgMuxselB8, GR4_TG_MUXSEL_B8));

    //GR5
    vIO32WriteFldMulti(GR5, P_Fld(rFlashPanelTable.u1FPGr5TgMuxselB7, GR5_TG_MUXSEL_B7)|
        P_Fld(rFlashPanelTable.u1FPGr5TgMuxselB6, GR5_TG_MUXSEL_B6)|P_Fld(rFlashPanelTable.u1FPGr5TgMuxselB5, GR5_TG_MUXSEL_B5)|
        P_Fld(rFlashPanelTable.u1FPGr5TgMuxselB4, GR5_TG_MUXSEL_B4)|P_Fld(rFlashPanelTable.u1FPGr5TgMuxselB3, GR5_TG_MUXSEL_B3)|
        P_Fld(rFlashPanelTable.u1FPGr5TgMuxselB2, GR5_TG_MUXSEL_B2)|P_Fld(rFlashPanelTable.u1FPGr5TgMuxselB1, GR5_TG_MUXSEL_B1)|
        P_Fld(rFlashPanelTable.u1FPGr5TgMuxselB0, GR5_TG_MUXSEL_B0));

    //GR6
    vIO32WriteFldMulti(GR6, P_Fld(rFlashPanelTable.u1FPGr6TgMode15, GR6_TG_MODE15)|
        P_Fld(rFlashPanelTable.u1FPGr6TgMode14, GR6_TG_MODE14)|P_Fld(rFlashPanelTable.u1FPGr6TgMode13, GR6_TG_MODE13)|
        P_Fld(rFlashPanelTable.u1FPGr6TgMode12, GR6_TG_MODE12)|P_Fld(rFlashPanelTable.u1FPGr6TgMode11, GR6_TG_MODE11)|
        P_Fld(rFlashPanelTable.u1FPGr6TgMode10, GR6_TG_MODE10)|P_Fld(rFlashPanelTable.u1FPGr6TgMode9, GR6_TG_MODE9)|
        P_Fld(rFlashPanelTable.u1FPGr6TgMode8, GR6_TG_MODE8)|P_Fld(rFlashPanelTable.u1FPGr6TgMode7, GR6_TG_MODE7)|
        P_Fld(rFlashPanelTable.u1FPGr6TgMode6, GR6_TG_MODE6)|P_Fld(rFlashPanelTable.u1FPGr6TgMode5, GR6_TG_MODE5)|
        P_Fld(rFlashPanelTable.u1FPGr6TgMode4, GR6_TG_MODE4)|P_Fld(rFlashPanelTable.u1FPGr6TgMode3, GR6_TG_MODE3)|
        P_Fld(rFlashPanelTable.u1FPGr6TgMode2, GR6_TG_MODE2)|P_Fld(rFlashPanelTable.u1FPGr6TgMode1, GR6_TG_MODE1)|
        P_Fld(rFlashPanelTable.u1FPGr6TgMode0, GR6_TG_MODE0));

    //TCSEL0
    vIO32WriteFldMulti(TCSEL0, P_Fld(rFlashPanelTable.u1FPTcsel0TgOutsel15, TCSEL0_TG_OUTSEL15)|
        P_Fld(rFlashPanelTable.u1FPTcsel0TgOutsel14, TCSEL0_TG_OUTSEL14)|P_Fld(rFlashPanelTable.u1FPTcsel0TgOutsel13, TCSEL0_TG_OUTSEL13)|
        P_Fld(rFlashPanelTable.u1FPTcsel0TgOutsel12, TCSEL0_TG_OUTSEL12)|P_Fld(rFlashPanelTable.u1FPTcsel0TgOutsel11, TCSEL0_TG_OUTSEL11)|
        P_Fld(rFlashPanelTable.u1FPTcsel0TgOutsel10, TCSEL0_TG_OUTSEL10)|P_Fld(rFlashPanelTable.u1FPTcsel0TgOutsel9, TCSEL0_TG_OUTSEL9)|
        P_Fld(rFlashPanelTable.u1FPTcsel0TgOutsel8, TCSEL0_TG_OUTSEL8));

    //TCSEL1
    vIO32WriteFldMulti(TCSEL1, P_Fld(rFlashPanelTable.u1FPTcsel1TgOutsel7, TCSEL1_TG_OUTSEL7)|
        P_Fld(rFlashPanelTable.u1FPTcsel1TgOutsel6, TCSEL1_TG_OUTSEL6)|P_Fld(rFlashPanelTable.u1FPTcsel1TgOutsel5, TCSEL1_TG_OUTSEL5)|
        P_Fld(rFlashPanelTable.u1FPTcsel1TgOutsel4, TCSEL1_TG_OUTSEL4)|P_Fld(rFlashPanelTable.u1FPTcsel1TgOutsel3, TCSEL1_TG_OUTSEL3)|
        P_Fld(rFlashPanelTable.u1FPTcsel1TgOutsel2, TCSEL1_TG_OUTSEL2)|P_Fld(rFlashPanelTable.u1FPTcsel1TgOutsel1, TCSEL1_TG_OUTSEL1)|
        P_Fld(rFlashPanelTable.u1FPTcsel1TgOutsel0, TCSEL1_TG_OUTSEL0));

    //Swing and Skew
    //LVDS
    if (IS_IC_5895())
    {
        u4TvoVal = vDrvLVDSsettingDrivingCurrent(rFlashPanelTable.u1FPRgLVDSATvo);
        vIO32WriteFldAlign(REG_LVDS_TX_CFG31, u4TvoVal, RG_LVDSA_TVO_0);
        vIO32WriteFldAlign(REG_LVDS_TX_CFG32, u4TvoVal, RG_LVDSA_TVO_1);
        vIO32WriteFldAlign(REG_LVDS_TX_CFG33, u4TvoVal, RG_LVDSA_TVO_2);
        vIO32WriteFldAlign(REG_LVDS_TX_CFG34, u4TvoVal, RG_LVDSA_TVO_3);
        vIO32WriteFldAlign(REG_LVDS_TX_CFG12, rFlashPanelTable.u1FPRgLVDSATvcm, RG_LVDSA_TVCM);
    }
    else
    {
        vIO32WriteFldMulti(REG_LVDS_TX_CFG3, P_Fld(rFlashPanelTable.u1FPRgLVDSBTvo, RG_LVDSB_TVO_ODD_D11)|
            P_Fld(rFlashPanelTable.u1FPRgLVDSBTvo, RG_LVDSB_TVO_EVEN_D11));
        vIO32WriteFldAlign(REG_LVDS_TX_CFG0, rFlashPanelTable.u1FPRgLVDSBTvcm, RG_LVDSB_TVCM_D11);
    }

    //vIO32WriteFldAlign(REG_LVDSTX_PLL_CFG2, rFlashPanelTable.u1FPRgVpllDlyData, REG_LVDSTX_PLL_CFG2_VPLL_DLY_DATA);  // Capy remove
}
#endif

//-----------------------------------------------------------------------------
// Public functions
//-----------------------------------------------------------------------------
/**
 * @brief u1DrvTconInit

 * Init TCON

 * @param  void
 * @retval 0: fail, 1: success
 */
UINT8 u1DrvTconInit(void)
{
    UINT8 u1Ret = 0;

	_u1GammaReady = 0;

	// Error Handling
    vErrorHandleInit();        

	// Tg Init
	vDrvTgInit();

    // Set TCON Pinmux and EPI LOCKN    
    _vDrvTconSetPinMux();

    // Flash TCON Init
    #ifdef CC_SUPPORT_FLASH_TCON
        vFlashTconInit();
    #endif

	#ifndef CC_UBOOT
    if (bApiFlashPqUpdatePanelTable() == SV_FALSE)
    {
        LOG(0, "Restore FlashPanel fail\n");
    }
    else	
    {
        LOG(0, "Restore FlashPanel success");
        vDrvFlashPanelUpdateParam();
    }         
	#endif
	
	// Enable TCON PMIC
    if(PANEL_GetDisplayType()!= PANEL_DISPLAY_TYPE_EPI)
    {
    #ifndef __MLVDS_slt__
	    vTconDPMCtrl(1);
    #else
        vTconDPMCtrl(0); //disable TCON power for SLT
    #endif
    }

	// Set Gamma Voltage
    if (_u1GammaReady == 0)
        vDrvTconGammaInit();

    #if !defined(CC_FPGA) && !defined(CC_UBOOT)
        // tcon on
        vDrvTconOn();
    #endif

	u1Ret=1;	
	return(u1Ret);
}

/**
 * @brief u1DrvTcon_Enable

 * Enable TCON

 * @param  void
 * @retval 0: fail, 1: success
 */
void u1DrvTcon_Enable(BOOL fgOnOff)
{
	if (fgOnOff)
		vIO32WriteFldAlign(GR0, 0xFFFF, GR0_TCTG_OEN);
	else
		vIO32WriteFldAlign(GR0, 0, GR0_TCTG_OEN);
}

/**
 * @brief u1DrvTconIsReady

 * TCON Ready or not

 * @param  void
 * @retval 0: not ready, 1: ready
 */
UINT8 u1DrvTconIsReady(void)
{
	UINT8 u1Ret = 0;
	u1Ret = IO32ReadFldAlign(DDDS_08, FLAG_TCON_INITIAL) && (IO32ReadFldAlign(DDDS_08, FLAG_MLVDS_INITIAL)||IO32ReadFldAlign(DDDS_08, FLAG_EPI_INITIAL));
    return (u1Ret);
}

/**
 * @brief vDrvTconDump

 * TCON Dump

 * @param  void
 * @retval 0: fail, 1: success
 */
/*
UINT8 u1DrvTconRegDump(void)
{
    UINT8 u1Ret = 1;
	UINT8 i = 0;
	UINT8 u1count;
	UINT32 u4tmp;
	  
    // CKGEN

	// error handling

	// post

	// minilvds
  	LOG(1,"minilvds reg dump\n");
	u1count = (sizeof(sRegMini) / sizeof(struct sTCONREGTABLE));
    for ( i = 0 ; i < u1count ; i++)
    {
        u4tmp = sRegMini[i].u4Addr;
		u4TconRegRead(u4tmp);
    }
    LOG(1,"Tcon reg dump %d counts, %d / %d\n", i, sizeof(sRegMini),sizeof(struct sTCONREGTABLE));
	


	// tg
  	LOG(1,"tg reg dump\n");
	u1count = (sizeof(sRegTg) / sizeof(struct sTCONREGTABLE));
    for ( i = 0 ; i < u1count ; i++)
    {
        u4tmp = sRegTg[i].u4Addr;
		u4TconRegRead(u4tmp);
    }
    LOG(1,"Tcon reg dump %d counts, %d / %d\n", i, sizeof(sRegTg),sizeof(struct sTCONREGTABLE));

	return(u1Ret);
}
*/
/**
 * @brief u1DrvTconRegDiff

 * TCON register diff

 * @param  void
 * @retval 0: fail, 1: success
 */
/*
UINT8 u1DrvTconRegDiff(void)
{
    UINT8 u1Ret = 1;
	UINT8 i = 0;
	UINT8 u1count;
	UINT32 u4tmp, u4tmp1;
	
	// minilvds
  	LOG(1,"minilvds reg diff\n");
	u1count = (sizeof(sRegMini) / sizeof(struct sTCONREGTABLE));
    for ( i = 0 ; i < u1count ; i++)
    {
        u4tmp = sRegMini[i].u4Addr;
		u4tmp1 = u4TconRegRead(u4tmp);
		if (u4tmp1 != sRegMini[i].u4Val)
		{
            LOG(1,"!!! diff addr 0x%8x, 0x%8x --> 0x%8x\n", u4tmp, u4tmp1, sRegMini[i].u4Val);			
		}
    }
    LOG(1,"Tcon reg diff %d counts, %d / %d\n", i, sizeof(sRegMini),sizeof(struct sTCONREGTABLE));

	// tg
  	LOG(1,"tg reg diff\n");
	u1count = (sizeof(sRegTg) / sizeof(struct sTCONREGTABLE));
    for ( i = 0 ; i < u1count ; i++)
    {
        u4tmp = sRegTg[i].u4Addr;
		u4tmp1 = u4TconRegRead(u4tmp);
		if (u4tmp1 != sRegTg[i].u4Val)
		{
            LOG(1,"!!! diff addr 0x%8x, 0x%8x --> 0x%8x\n", u4tmp, u4tmp1, sRegTg[i].u4Val);			
		}
    }
    LOG(1,"Tcon reg diff %d counts, %d / %d\n", i, sizeof(sRegTg),sizeof(struct sTCONREGTABLE));

    return (u1Ret);
}
*/

 
#ifdef CC_SUPPORT_FLASH_TCON
INT32 i4FlashTconRead(UINT16 u2Offset, UINT8 *u1Data, UINT32 u4Length)
{
    UINT8 u1AQPartition;
    UINT32 u2AQSize;    
    INT32 i4Ret = 0;
    UINT64 u8Offset;
    
    UNUSED(u2AQSize);
    u1Data[0] = '\0';        
    u1AQPartition = (UINT8)DRVCUST_InitGet(eTconFlashTconPartition);
    if (u1AQPartition == 0xFF)
    {
        LOG(3,"AudioFlashAQPartition is not defined !!\n");
        return -1;
    }

#if 0    
    // check boundary 
    //u2AQSize = (UINT32)DRVCUST_OptGet(eAudioFlashAQSize);
    if (u2Offset > u2AQSize)
    {
        LOG(0,"Fail! AQ test read length larger than 0x%x\n", u2AQSize);
        return;
    }
#endif

#ifndef CC_NOR_DISABLE
     //   return ((INT32)NORSTG_Read(DRVCUST_OptGet(eTconFlashTconPartition), u2Offset, u1Data, u4Length));
            u8Offset = 0;
	     i4Ret = (INT32)DRVCUST_InitGet(eTconFlashTconPartition);
	    if (i4Ret > 1)
	    {
	        LOG(3, "eTconFlashTconPartition %d", i4Ret);
	        u8Offset |= (((UINT64)(UINT32)i4Ret) << 32);	
	        i4Ret = NORPART_Read(u8Offset, (UINT32)u1Data, u4Length);
	        return i4Ret;
	    }   
#endif  //CC_NOR_DISABLE

    return (i4Ret);

}


void vFlashTconWrite(UINT16 u2Offset, UINT8 *u1Data, UINT32 u4size)
{
    UINT8 u1AQPartition;
    UINT32 u2AQSize;
    INT32 i4Ret;
    UINT64 u8Offset;
//    UINT32 u4Offset;
    
    UNUSED(u2AQSize);
    u1AQPartition = (UINT8)DRVCUST_InitGet(eTconFlashTconPartition);
    if (u1AQPartition == 0xFF)
    {
        LOG(3,"eTconFlashTconPartition is not defined !!\n");
        return;
    }    

#if 1
    // check boundary.
    //u2AQSize = (UINT32)DRVCUST_OptGet(eAudioFlashAQSize)
    if ((u2Offset + u4size) > FLASH_TCON_SIZE)
    {
        LOG(0,"TCON test write length larger than 0x%x\n", FLASH_TCON_SIZE);
        return;
    }
#endif    
//    u4Offset = ((UINT64)u1AQPartition << 32) | ((UINT64)u2Offset);
//    NANDPART_Write(u8Offset, (UINT32)u1Data, u4size);

#ifndef CC_NOR_DISABLE
      //  NORSTG_Write(DRVCUST_OptGet(eTconFlashTconPartition), u2Offset, u1Data, u4size);
            u8Offset = 0;
	    i4Ret = (INT32)DRVCUST_InitGet(eTconFlashTconPartition);
	    if (i4Ret > 1)
	    {
	        u8Offset |= (((UINT64)(UINT32)i4Ret) << 32);
			
		 i4Ret = NORPART_Erase(u8Offset, 1);
 	        i4Ret |= NORPART_Write(u8Offset, (UINT32)u1Data, u4size);
	    }      
#endif  //CC_NOR_DISABLE

}

void vFlashTconInit(void)
{
    UINT8 pau1Buf[FLASH_TCON_BUF_SIZE];
    UINT32 i;
    struct sTCONREGTABLE *pArray;    

    // check for header
    pau1Buf[0] = '\0';
    
    i4FlashTconRead(0, (UINT8*)&pau1Buf[0], FLASH_TCON_BUF_SIZE);
    
    if (x_strncmp((CHAR*)pau1Buf, "TCON", 4) !=0)
    {
        LOG(0, "Flash TCON header is not correct, using default value\n");
        return;
    }

  
    LOG(3, "\nFlash Tcon init reading...\n");
        
    for (i=0; i<FLASH_TCON_BUF_SIZE; i++)
    {
        if (i % 12 == 0) 
        {
        //    LOG(0,"\n");
        }
        //LOG(0,"0x%x ", pau1Buf[i]);
    }

   // LOG(0,"\n");

    pArray = (struct sTCONREGTABLE *) &pau1Buf[0];

    if (pArray[0].u4Msk != GetCurrentPanelIndex())
    {
        LOG(0, "Flash TCON panel ID is not matching, using default value\n");
        return;
    }

    for (i=0 ; i < 255 && i < pArray[0].u4Val ; i++)
    {
    //    LOG(0,"tcon reg write %x %x %x \n", pArray[i].u4Addr, pArray[i].u4Val, pArray[i].u4Msk);
        vTconRegWrite(pArray[i].u4Addr,pArray[i].u4Val);
    }

     LOG(3, "Flash Tcon init done...PID: %d, %d cmds\n", pArray[0].u4Msk, pArray[0].u4Val);
    
}

#define FLASH_TCON_HEADER_SZIE
void vFlashTconSave(void)
{
    UINT8 pau1Data[FLASH_TCON_BUF_SIZE] = {0};
    UINT32 i;
    struct sTCONREGTABLE *pArray;
    struct sTCONREGTABLE *pBufArray = NULL;
    UINT32 u4tmp = 0;
    UINT32 u4Length = 0;
    UINT32 u4TotalBytes = 0;    
    UINT32 u4CmdCnt = 0;
    UINT32 u4TotalCmdCnt = 0;    
    
    u4TotalBytes = 0;
    u4TotalCmdCnt = 0;
    // check for header
    pau1Data[0] = '\0';
    
    i4FlashTconRead(0, (UINT8*) &pau1Data[0], 12);
    
    if (x_strncmp((CHAR*)pau1Data, "TCON", 4) !=0)
    {
        LOG(0, "Flash TCON header is not correct, using default value\n");
        return;
    }

    // tg setting
    pArray = pTconCustTgGet(&u4CmdCnt);
    u4Length = sizeof(struct sTCONREGTABLE ) * u4CmdCnt;
    
    if (pArray == NULL)
    {
        LOG(0, "Flash TCON array not existed\n");
        return;
    }    
    
    if (u4CmdCnt ==0)
    {
        LOG(0, "Flash TCON data length is zero\n");
        return;
    }
   
    if (u4TotalCmdCnt + u4Length > FLASH_TCON_BUF_SIZE)
    {
        LOG(0, "Flash TCON data length over FLASH_TCON_BUF_SIZE %d\n", FLASH_TCON_BUF_SIZE);
        return;
    }
    
    pBufArray = (struct sTCONREGTABLE *) &pau1Data[0];
    
    for ( i = 0 ; i < u4CmdCnt ; i++)
    {
        u4tmp = pArray[i].u4Addr;
        pBufArray[i+1].u4Addr = u4tmp;
        pBufArray[i+1].u4Val = u4TconRegRead(u4tmp);
        pBufArray[i+1].u4Msk = pArray[i].u4Msk;
        LOG(0, "Get reg %x %8x %x \n", pBufArray[i+1].u4Addr, pBufArray[i+1].u4Val, pBufArray[i+1].u4Msk);
    }
    
    u4TotalBytes += u4Length;
    u4TotalCmdCnt += u4CmdCnt;

    pBufArray[0].u4Val = 0x78796784;
    pBufArray[0].u4Val = u4TotalCmdCnt;
    pBufArray[0].u4Msk = GetCurrentPanelIndex();
    LOG(0, "Set buf %x %8x %x \n", pBufArray[0].u4Addr, pBufArray[0].u4Val, pBufArray[0].u4Msk);

    LOG(0, "save to flash\n");

    vFlashTconWrite(0, &pau1Data[0], u4TotalBytes);
    
    LOG(0,"Tcon reg save %d bytes\n", u4TotalBytes);
    
}

static UINT8 tcondata[12] = {0};
void vFlashTconWriteDefault(void)
{
    vFlashTconWrite(0, tcondata, sizeof(tcondata));
}
#endif  /*#ifdef CC_SUPPORT_FLASH_TCON*/

/**
 * @brief vDrvTCONSel

 * TCON power control

 * @param  void
 * @retval 0: fail, 1: success
 */
void vDrvTCONSel(VIDEO_TCON_TABLE_T eTconTableSel)
{
    _fgTconCustSel = TRUE;
    _u1TconCustSel = eTconTableSel;
    vDrvTCONCustSel(eTconTableSel);
}

void vDrvTCONTimingGenEn(UINT8 u1OnOff)
{
    if (!u1OnOff)
    {
	    vIO32WriteFldAlign(GR0, 0x0, GR0_TC_EN);
    }
    else
    {
	    vIO32WriteFldAlign(GR0, 0x1, GR0_TC_EN);
    }
}

void vDrvTCONTimingGenFrameCounter(UINT16 u2Frame)
{
	vIO32WriteFldAlign(GR0, u2Frame, GR0_TCTG_FCR);
}

void vDrvTCONTimingGenFrameCounterRst(void)
{	
	vIO32WriteFldAlign(GR1, 1, GR1_FCNT_RESET);
	HAL_Delay_us(10);
	vIO32WriteFldAlign(GR1, 0, GR1_FCNT_RESET);
}

void vDrvTCONTimingGenHsyncInvert(UINT8 u1OnOff)
{
	vIO32WriteFldAlign(GR1, u1OnOff, GR1_TCTG_HSINV);
}

void vDrvTCONTimingGenVsyncInvert(UINT8 u1OnOff)
{
	vIO32WriteFldAlign(GR1, u1OnOff, GR1_TCTG_VSINV);
}


void vDrvTCONISRSetLineCounter(UINT32 u4VFp, UINT32 u4VActive, UINT32 u4VBp)
{
	
    if (IS_PANEL_L12R12)
	{
	    vIO32WriteFldAlign(GR12, (((u4VActive/2)+u4VBp)+1), GR12_TCTG_VCNT_INT);
	}
	else
	{
		//vIO32WriteFldAlign(GR12, (u4VBp +2), GR12_TCTG_VCNT_INT);
		vIO32WriteFldAlign(GR12, (u4VBp +10), GR12_TCTG_VCNT_INT); //execute after DE
	}

}
void vDrvTCONISRSetFrameCounter(UINT16 u2INTRFrame)
{
    vIO32WriteFldAlign(GR12, u2INTRFrame, GR12_TCTG_FCNT_INT); 
}

void vDrvTCONIntrEn(void)
{
    vIO32WriteFldAlign(GR1, 0x30, GR1_TCON_INT_EN);  // [5:4]=2'b11
}

void vDrvTCONIntrDisable(void)
{
    vIO32WriteFldAlign(GR1, 0x0, GR1_TCON_INT_EN);  // [5:4]=2'b11
}

void vDrvTCONIntrClr(void)
{
    vIO32WriteFldAlign(GR1, 0x30, GR1_TCON_INT_CLR);  // [5:4]=2'b11
    vIO32WriteFldAlign(GR1, 0x00, GR1_TCON_INT_CLR);  // [5:4]=2'b00    
}

BOOL fgIsTCONIntrEn(void)
{
	if (IO32ReadFldAlign(GR1, GR1_TCON_INT_EN)==0x30)
		return TRUE;
	else 
		return FALSE;
}

void vDrvTCONDisableBIMInt(void)
{
    UNUSED(BIM_DisableIrq(VECTOR_TCON_TCH));
}

void vDrvTCONEnableBIMInt(void)
{
	BIM_EnableIrq(VECTOR_TCON_TCH);
}

BOOL fgIsTCONIntrInit(void)
{
	if (IO32ReadFldAlign(DDDS_08, FLAG_TCON_TCH_INT_INITIAL) == 1)
        return TRUE;
	else
		return FALSE;
}

extern UINT8 fgApplyScanPWMSetData;
extern UINT8 u1ScanPwmCrossFlg;
extern UINT8 fgApplyPWMModeChange;
extern UINT8 fgScanPWMSetpControl;
extern void vResetPWMFreq(void);
//extern UINT32 u4Support_ScanPWM;
extern UINT16 u2PscGetPanelVCNTStatus(void);

void vDrvTCONISR(UINT16 u2Vector)
{	
	static UINT16 u2Cnt = 0;
	static UINT8 u1PrevFcnt = 4;
	UINT8 u1ScanPWMApply = 2, u1CurrentFcnt = 0;
		
    if(u2Vector == VECTOR_TCON_TCH)  
    {
    	u1CurrentFcnt = u1DrvGetVsyncISRFCNTStatus();
	    vDrvTCONIntrClr();
		if(u1CurrentFcnt == u1PrevFcnt)
		{
			u1ScanPWMApply = 0;
		}
		else
		{
            #ifndef CC_MTK_LOADER
            vApiApplyVideoEvent(PEQTY_APPLY_TIME_OUTPUT_VSYNC_TECH_ISR);
            #endif
			if ((fgApplyScanPWMSetData) && (u1ScanPwmCrossFlg == 0))
			{
				u2Cnt = u2PscGetPanelVCNTStatus();
				if (u2Cnt >= u2DrvGetCrozzUpLimit())
				{
					u1ScanPWMApply = 0;			
				}
				else
				{
					u1ScanPWMApply = 1;			
					//vDrvSetScanPWMSW_SETDATA();
				   // vDrvSetScanPWMLatchMode(SCAN_PWM_LATCH_MODE_SETDATA_OFF,SCAN_PWM_LATCH_MODE_OFF,SCAN_PWM_ALIGN_MODE_VSYNC);  // Aligned Vsync
        			//vDrvScanPWMDataFire();
				}
			}
		}

		if (u1ScanPWMApply == 1)
		{
			if (fgScanPWMSetpControl)
			{		
				if(u1DrvGetScanPWMStruct_Ready())
				{
			  		fgApplyScanPWMSetData = 0;								 //clear scanpwm setting flag
				}
				else
				{
			  	//vDrvSetScanPWMSW_StepControl();		
				} 
			}
			else
			{
					fgApplyScanPWMSetData = 0;								   //clear scanpwm setting flag
			}
		}
		u1PrevFcnt = u1CurrentFcnt;
    }
#ifndef CC_NO_BIM_INTR
    VERIFY(BIM_ClearIrq(VECTOR_TCON_TCH));
#endif
}

/** Brief
 * TCON ISR initial
 * @return void
 */
void vDrvTCONInitISR(void)
{
    if (!fgIsTCONIntrInit())
    {
        LOG(0, "[TCON_INT]HW init!\n");
        if(PANEL_GetDisplayType()!= PANEL_DISPLAY_TYPE_EPI)
        {
            if(PANEL_GetDisplayType()== PANEL_DISPLAY_TYPE_VB1)
            {
                vIO32WriteFldAlign(CKGEN_TCLK_TEST, 0, FLD_TCLK_SEL); // xtal to tclk for tco isr.
            }

            if(!IO32ReadFldAlign(TMGR0,CKEN_CFG_TCON))
            {
                vIO32WriteFldAlign(TMGR0, 1, CKEN_CFG_TCON);
            }
            vDrvTCONTimingGenEn(SV_ON);
            vDrvTCONTimingGenFrameCounter(0x02);
            vDrvTCONISRSetFrameCounter(0x01);
        #ifdef SUPPORT_PANEL_CUSTOMER_SPEC
            if (HSYNC_POLARITY == HSYNC_HIGH)
                vDrvTCONTimingGenHsyncInvert(SV_OFF);
            else
                vDrvTCONTimingGenHsyncInvert(SV_ON);

            if (VSYNC_POLARITY == VSYNC_HIGH)
                vDrvTCONTimingGenVsyncInvert(SV_OFF);
            else
                vDrvTCONTimingGenVsyncInvert(SV_ON);
        #else
            vDrvTCONTimingGenHsyncInvert(SV_ON);
            vDrvTCONTimingGenVsyncInvert(SV_ON);
        #endif
            LOG(6, "[TCON_INT]TCLK_SEL=%d CKEN_TCON=%d\n", IO32ReadFldAlign(CKGEN_TCLK_TEST,FLD_TCLK_SEL), IO32ReadFldAlign(TMGR0,CKEN_CFG_TCON));
            LOG(6, "[TCON_INT]INT_STA#1=0x%x\n", IO32ReadFldAlign(GR1,GR1_TCON_INT));
            vIO32WriteFldAlign(GR1, 0x30, GR1_TCON_INT_CLR);
            LOG(6, "[TCON_INT]INT_STA#2=0x%x\n", IO32ReadFldAlign(GR1,GR1_TCON_INT));
            vDrvTCONIntrEn();
            vIO32WriteFldAlign(GR1, 0x00, GR1_TCON_INT_CLR);
            LOG(6, "[TCON_INT]INT_STA#3=0x%x\n", IO32ReadFldAlign(GR1,GR1_TCON_INT));		

            vIO32WriteFldAlign(DDDS_08, 1, FLAG_TCON_TCH_INT_INITIAL);
        }
    }
}

#ifndef CC_MTK_LOADER
void vDrvTCONRegisterISR(void)
{
    x_os_isr_fct pfnOldIsr=NULL;
    
    if (fgIsTCONIntrInit() && (!_fgIsTCONIsrReg))
    {
        if (x_reg_isr(VECTOR_TCON_TCH, vDrvTCONISR, &pfnOldIsr) != OSR_OK)
        {
            LOG(0, "[TCON_INT] Error: Fail to register TCON ISR!\n");
        }
        else
        {
            LOG(0, "[TCON_INT] Success to register TCON ISR!\n");
            _fgIsTCONIsrReg = TRUE;
        }
    }

    if (_fgIsTCONIsrReg)
    {
        vDrvTCONEnableBIMInt();
        LOG(0, "[TCON_INT] BIM enable IRQ\n");
    }
}
#endif

void vDrvTCLKPLLRst(void)
{
	vIO32WriteFldAlign(TMGR2, 0, TMGR2_TCLK_PLLRST);
	HAL_Delay_us(200);
	vIO32WriteFldAlign(TMGR2, 1, TMGR2_TCLK_PLLRST);
	HAL_Delay_us(200);
	vIO32WriteFldAlign(TMGR2, 0, TMGR2_TCLK_PLLRST);
}
