/* 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: wanli.zhang $
 * $Date: 2015/08/17 $
 * $RCSfile: panel_table.c,v $
 * $Revision: #14 $
 *
 *---------------------------------------------------------------------------*/

/** @file panel_tablc.c
 *  This file includes panel timing configuration.
 */

//-----------------------------------------------------------------------------
// Include files
//-----------------------------------------------------------------------------

#ifndef CC_MTK_PRELOADER

#include "panel.h"
#include "eeprom_if.h"
#include "drvcust_if.h"
#include "drv_od.h"
#include "nand_if.h"
#include "x_lint.h"
LINT_EXT_HEADER_BEGIN
#include "x_typedef.h"
#include "x_printf.h"
#include "x_pinmux.h"
#include "x_hal_5381.h"
#include "x_assert.h"
#include "x_os.h"
LINT_EXT_HEADER_END


#ifdef CUSTOM_CFG_FILE
#include CUSTOM_CFG_FILE
#endif /* CUSTOM_CFG_FILE */

#include "drv_default.h"
//#ifdef SUPPORT_PANEL_CUSTOMER_SPEC
#include"panel_cust.h"
//#endif

#ifdef CUSTOM_EEPROM_FILE
#include CUSTOM_EEPROM_FILE
#endif

#ifdef CC_ENABLE_MTK_MODEL_INDEX
#include "modelIndex.h"
#endif

#include "nptv_debug.h"

//---------------------------------------------------------------------------
// Type definitions
//---------------------------------------------------------------------------

typedef struct
{
    UINT16 u2PanelWidth;
    UINT16 u2PanelHeight;

    // Clk60Hz = htotal*vtotal*60/1.001
    // Clk50Hz = htotal*vtotal*50
    UINT32 u4PixelClkMax;
    UINT32 u4PixelClk60Hz;
    UINT32 u4PixelClk50Hz;
    UINT32 u4PixelClkMin;

    // HTotal = spec value
    UINT16 u2HTotalMax;
    UINT16 u2HTotal60Hz;
    UINT16 u2HTotal50Hz;
    UINT16 u2HTotalMin;

    // VTotal = spec value
    UINT16 u2VTotalMax;
    UINT16 u2VTotal60Hz;
    UINT16 u2VTotal50Hz;
    UINT16 u2VTotalMin;
    UINT8 u1VClkMax;
    UINT8 u1VClkMin;

    UINT8 u1HSyncWidth;
    UINT8 u1VSyncWidth;
    UINT16 u2HPosition;
    UINT16 u2VPosition;
    UINT32 u4ControlWord;

    // backlight ragne
    UINT8 u1BacklightHigh;
    UINT8 u1BacklightMiddle;
    UINT8 u1BacklightLow;
    UINT8 u1Reserved;

    UINT16 u2DimmingFrequency60Hz;
    UINT16 u2DimmingFrequency50Hz;

    // delay unit: 10ms
    UINT8 u1LvdsOnDalay;
    UINT8 u1BacklightOnDelay;
    UINT8 u1BacklightOffDelay;
    UINT8 u1LvdsOffDalay;

    UINT16 u2MaxOverscan;
    UINT32 u4ControlWord2;
}__attribute__ ((packed))PANEL_ATTRIBUTE_T;



typedef struct
{
    UINT16 u2PanelWidth;
    UINT16 u2PanelHeight;

    UINT32 u4PixelClkMax;
    UINT32 u4PixelClk60Hz;
    UINT32 u4PixelClk50Hz;
    UINT32 u4PixelClkMin;

    UINT32 u4Reserved1;

    UINT16 u2HTotalMax;
    UINT16 u2HTotal60Hz;
    UINT16 u2HTotal50Hz;
    UINT16 u2HTotalMin;

    UINT16 u2Reserved2;
    UINT16 u2VTotalMax;
    UINT16 u2VTotal60Hz;
    UINT16 u2VTotal50Hz;
    UINT16 u2VTotalMin;
    UINT16 u2Reserved3;

    UINT32 u4Reserved4;

    UINT16 u2Reserved5;
    UINT8 u1VClkMax;
    UINT8 u1VClkMin;

    UINT16 u2Reserved6;
    UINT8 u1HSyncWidth;
    UINT8 u1VSyncWidth;

    UINT8 u2HPosition;
    UINT8 u2VPosition;
    UINT16 u2Reserved7;

    UINT16 u4Reserved8;
    UINT8 u1LvdsMapping;
    UINT8 u1MaxOverscan1;

    UINT8 u1MaxOverscan2;
    UINT8 u1ControlWord1;
    UINT8 u1ControlWord2;
    UINT8 u1PanelOnTime1;

    UINT8 u1LvdsOnDalay;

    UINT8 u1BacklightOnDelay;
    UINT8 u1PanelOnTime4;
    UINT8 u1Reserved8;

    UINT8 u1PanelOffTime1;
    UINT8 u1BacklightOffDelay;
    UINT8 u1LvdsOffDalay;
    UINT8 u1PanelOffTime4;
} PANEL_FLASH_ATTRIBUTE_T;

//-----------------------------------------------------------------------------
// Macro definitions
//-----------------------------------------------------------------------------

/*lint -save -e960 */
#define PANEL_ATTRIBUTE_SET_TMPL(NAME, FIELD) \
    void PANEL_Set##NAME(UINT32 u4Value) \
    { \
        _prPanelAttribute->FIELD = u4Value; \
    } \

#define PANEL_ATTRIBUTE_GET_TMPL(NAME, FIELD) \
    UINT32 PANEL_Get##NAME(void) \
    { \
        return _prPanelAttribute->FIELD; \
    } \

#define PANEL_ATTRIBUTE_SETGET_TMPL(NAME, FIELD) \
    PANEL_ATTRIBUTE_SET_TMPL(NAME, FIELD) \
    PANEL_ATTRIBUTE_GET_TMPL(NAME, FIELD) \

/* above line is intendedly left blank */
/*lint -restore */

#define IS_PANEL_INDEX_INVALID(X) ((X) >= u4TotalNumber)
#define CHECK_ZERO(X) \
    { \
        if ((X) == 0) \
        { \
            LOG(0,"Line %d: is zero\r\n", __LINE__ ); \
            return FALSE; \
        } \
    }


#define EXT_PANEL_INDEX_INVALID 0xffff

#define SCALER_PSCAN_DISPMODE_MIN_VTOTAL_OFFSET (10)

//-----------------------------------------------------------------------------
// Static variables
//-----------------------------------------------------------------------------

#ifndef CC_MULTI_PANEL
// we build all panel timing in default
#define CC_MULTI_PANEL 1
#endif

#ifdef CC_NAND_LOADER
#define NAND_PAGE_SIZE  (2048)
#endif

// this is the panel_table_cust.c in each customer's directory
#include PANEL_TABLE_CUST_FILE

#if CC_MULTI_PANEL
static PANEL_ATTRIBUTE_T* _prPanelAttribute =
                          &_arPanelAttribute[DEFAULT_PANEL_SELECT];
static UINT32 _u4PanelIndex = DEFAULT_PANEL_SELECT;
static UINT32 _u4EepromPanelIndex = DEFAULT_PANEL_SELECT;

#if defined(SUPPORT_PANEL_CUSTOMER_SPEC) || defined(SUPPORT_PANEL_SS) || defined(SUPPORT_PANEL_DITHER) || defined(SUPPORT_PANEL_DRIVING)|| defined(SUPPORT_PANEL_ERRORLIMIT_TABLE)|| defined(SUPPORT_PANEL_3D_PIXEL_SIZE) || defined(SUPPORT_PANEL_SCAN_PWM)|| defined(SUPPORT_PANEL_PRE_EMPHASIS) || defined(SUPPORT_PANEL_SIZE_CM)
static PANEL_ATTRIBUTE_EXT_T* _prPanelAttributeExt = & _arPanelAttributeExt[0];
#endif

#else
static PANEL_ATTRIBUTE_T* _prPanelAttribute = &_arPanelAttribute[0];
static UINT32 _u4PanelIndex = 0;
static UINT32 _u4EepromPanelIndex = 0;
#endif
static UINT32 u4TotalNumber = PANEL_TOTAL_NUMBER;
static INT32 _i4HPixelShift = 0;
static INT32 _i4VPixelShift = 0;
static BOOL _fgPixelShiftEnable = FALSE;
static UINT32 _fgPanelIdInEeprom = FALSE;

UINT32 u4PanelTypeDefinition[PANEL_TYPE_MAX] =
{
    PANEL_TYPE_WIDTH_2K | PANEL_TYPE_HEIGHT_1K | PANEL_TYPE_60HZ,
    PANEL_TYPE_WIDTH_2K | PANEL_TYPE_HEIGHT_1K | PANEL_TYPE_120HZ,
    PANEL_TYPE_WIDTH_4K | PANEL_TYPE_HEIGHT_1K | PANEL_TYPE_60HZ,
    PANEL_TYPE_WIDTH_4K | PANEL_TYPE_HEIGHT_2K | PANEL_TYPE_30HZ,
    PANEL_TYPE_WIDTH_4K | PANEL_TYPE_HEIGHT_2K | PANEL_TYPE_60HZ
};

#if defined(SUPPORT_PANEL_CUSTOMER_SPEC) || defined(SUPPORT_PANEL_SS) || defined(SUPPORT_PANEL_DITHER) || defined(SUPPORT_PANEL_DRIVING)|| defined(SUPPORT_PANEL_ERRORLIMIT_TABLE)|| defined(SUPPORT_PANEL_3D_PIXEL_SIZE) || defined(SUPPORT_PANEL_SCAN_PWM)|| defined(SUPPORT_PANEL_PRE_EMPHASIS) || defined(SUPPORT_PANEL_SIZE_CM)
static UINT32 PANEL_GetExtAttributeIndex(void);
#endif

#ifdef CC_S_PLATFORM
#if defined(SUPPORT_PANEL_GRAPH_MODE)
static GRAPHMODE_ATTRIBUTE_T * _prGraphModeAttribute = &_arGraphModeAttribute[0];
//static UINT32 u4GraphModeIndex = PANEL_4K_BACKEND;
static UINT32 u4PanelType = PANEL_TYPE_MAX;
#endif
#endif
static BOOL _fgPanelPower1On = FALSE;
static BOOL _fgPanelPower2On = FALSE;
static BOOL _fgBackLightMuteOff = FALSE;
//-----------------------------------------------------------------------------
// Static functions
//-----------------------------------------------------------------------------

#ifndef LOAD_PANEL_FROM_FLASH_CUSTOM
static BOOL _PanelLoadTableFromFlash(UINT32 u4Offset)
{
    PANEL_FLASH_ATTRIBUTE_T rFlashTable;
#ifndef CC_NAND_LOADER
    LOG(0, "Load panel table from flash, address=0x%lx\n", u4Offset);
    // FIXME!!
    // Need to replace with new interface of NOR flash access

    x_memcpy(&rFlashTable, &u4Offset, sizeof(PANEL_FLASH_ATTRIBUTE_T));
#else
    // FIXME!!
    // Need to replace with new interface of NAND flash access

    UINT64  u8Offset = (UINT64)u4Offset;
    UINT8   aui1_buf[sizeof(PANEL_FLASH_ATTRIBUTE_T)+NAND_PAGE_SIZE*2];

    /* must be aligned */
    UINT64  u8_algin_bytes;
    UINT32  ui4_read_size;  /* should be aligned */
    UINT8*  pui1_buf = NULL;
    UINT8   ui1_idx = 0;


    u8_algin_bytes = u8Offset % NAND_PAGE_SIZE;

    ui4_read_size = sizeof(PANEL_FLASH_ATTRIBUTE_T)+(UINT32)u8_algin_bytes;
    ui4_read_size += NAND_PAGE_SIZE - (ui4_read_size % NAND_PAGE_SIZE);

    pui1_buf  = (UINT8 *)&aui1_buf;
    //if (u8_algin_bytes != 0)
    {
        while (ui4_read_size > 0)
        {
            NAND_Read(u8Offset-u8_algin_bytes+ui1_idx*NAND_PAGE_SIZE, 
                     (UINT32)pui1_buf+ui1_idx*NAND_PAGE_SIZE, 
                      NAND_PAGE_SIZE);
            ui1_idx++;
            ui4_read_size -= NAND_PAGE_SIZE;
        }
        x_memcpy(&rFlashTable, pui1_buf+(UINT32)u8_algin_bytes, sizeof(PANEL_FLASH_ATTRIBUTE_T));
    }
#endif
    _arPanelAttribute[0].u2PanelWidth = rFlashTable.u2PanelWidth;
    CHECK_ZERO(_arPanelAttribute[0].u2PanelWidth);
    _arPanelAttribute[0].u2PanelHeight = rFlashTable.u2PanelHeight;
    CHECK_ZERO(_arPanelAttribute[0].u2PanelHeight);
    _arPanelAttribute[0].u4PixelClkMax = rFlashTable.u4PixelClkMax;
    CHECK_ZERO(_arPanelAttribute[0].u4PixelClkMax);
    _arPanelAttribute[0].u4PixelClk60Hz = rFlashTable.u4PixelClk60Hz;
    CHECK_ZERO(_arPanelAttribute[0].u4PixelClk60Hz);
    _arPanelAttribute[0].u4PixelClk50Hz = rFlashTable.u4PixelClk50Hz;
    CHECK_ZERO(_arPanelAttribute[0].u4PixelClk50Hz);
    _arPanelAttribute[0].u4PixelClkMin = rFlashTable.u4PixelClkMin;
    CHECK_ZERO(_arPanelAttribute[0].u4PixelClkMin);

    _arPanelAttribute[0].u2HTotalMax = rFlashTable.u2HTotalMax;
    CHECK_ZERO(_arPanelAttribute[0].u2HTotalMax);
    _arPanelAttribute[0].u2HTotal60Hz = rFlashTable.u2HTotal60Hz;
    CHECK_ZERO(_arPanelAttribute[0].u2HTotal60Hz);
    _arPanelAttribute[0].u2HTotal50Hz = rFlashTable.u2HTotal50Hz;
    CHECK_ZERO(_arPanelAttribute[0].u2HTotal50Hz);
    _arPanelAttribute[0].u2HTotalMin = rFlashTable.u2HTotalMin;
    CHECK_ZERO(_arPanelAttribute[0].u2HTotalMin);

    _arPanelAttribute[0].u2VTotalMax = rFlashTable.u2VTotalMax;
    CHECK_ZERO(_arPanelAttribute[0].u2VTotalMax);
    _arPanelAttribute[0].u2VTotal60Hz = rFlashTable.u2VTotal60Hz;
    CHECK_ZERO(_arPanelAttribute[0].u2VTotal60Hz);
    _arPanelAttribute[0].u2VTotal50Hz = rFlashTable.u2VTotal50Hz;
    CHECK_ZERO(_arPanelAttribute[0].u2VTotal50Hz);
    _arPanelAttribute[0].u2VTotalMin = rFlashTable.u2VTotalMin;
    CHECK_ZERO(_arPanelAttribute[0].u2VTotalMin);

    _arPanelAttribute[0].u1VClkMax = rFlashTable.u1VClkMax;
    CHECK_ZERO(_arPanelAttribute[0].u1VClkMax);
    _arPanelAttribute[0].u1VClkMin = rFlashTable.u1VClkMin;
    CHECK_ZERO(_arPanelAttribute[0].u1VClkMin);

    _arPanelAttribute[0].u1HSyncWidth = rFlashTable.u1HSyncWidth;
    CHECK_ZERO(_arPanelAttribute[0].u1HSyncWidth);
    _arPanelAttribute[0].u1VSyncWidth = rFlashTable.u1VSyncWidth;
    CHECK_ZERO(_arPanelAttribute[0].u1VSyncWidth);
    _arPanelAttribute[0].u2HPosition = rFlashTable.u2HPosition << 4;
    CHECK_ZERO(_arPanelAttribute[0].u2HPosition);
    _arPanelAttribute[0].u2VPosition = rFlashTable.u2VPosition << 3;
    CHECK_ZERO(_arPanelAttribute[0].u2VPosition);
    _arPanelAttribute[0].u2MaxOverscan = (UINT16)rFlashTable.u1MaxOverscan1;
    _arPanelAttribute[0].u2MaxOverscan |= (UINT16)rFlashTable.u1MaxOverscan2 << 8;
    _arPanelAttribute[0].u4ControlWord = (UINT32)rFlashTable.u1ControlWord1;
    _arPanelAttribute[0].u4ControlWord |= (UINT32)rFlashTable.u1ControlWord2 << 8;
    _arPanelAttribute[0].u4ControlWord |= (UINT32)rFlashTable.u4Reserved8 << 16;	

    _arPanelAttribute[0].u1LvdsOnDalay = rFlashTable.u1LvdsOnDalay;
    _arPanelAttribute[0].u1BacklightOnDelay = rFlashTable.u1BacklightOnDelay;
    _arPanelAttribute[0].u1BacklightOffDelay = rFlashTable.u1BacklightOffDelay;
    _arPanelAttribute[0].u1LvdsOffDalay = rFlashTable.u1LvdsOffDalay;

    SelectPanel(0);

#ifdef CC_EXTERNAL_LVDS_CHIP
    {
        PanelDataStructType rPanel;
        UINT8 bOutType;
        UINT8 bHSYNCP;
        UINT8 bVSYNCP;
        UINT8 bDataClk;
        UINT8 bDataEn;
        UINT8 bMSBOnOff;

        if (rFlashTable.u2PanelHeight == 768)
        {
            rPanel.PanelType_R = 0; // WXGA/768p = 0
        }
        else
        {
            rPanel.PanelType_R = 1; // WUXGA/1080p = 1
        }
        if (LVDS_OUTPUT_PORT == SINGLE_PORT)
        {
            rPanel.PanelPixPerClk_R = 0; // single
        }
        else
        {
            rPanel.PanelPixPerClk_R = 1; // dule
        }
        switch (DISP_BIT)
        {
            case DISP_30BIT:
                rPanel.PanelDepth_R = 10; // 10 bit
                break;

            case DISP_24BIT:
                rPanel.PanelDepth_R = 8; // 8 bit
                break;

            default:
                rPanel.PanelDepth_R = 6; // 6 bit
                break;
        }
        rPanel.PanelWidth_R = rFlashTable.u2PanelWidth;
        rPanel.PanelHeight_R = rFlashTable.u2PanelHeight;
        rPanel.PanelMinHTotal_R = rFlashTable.u2HTotalMin;
        rPanel.PanelMinHSyncWidth_R = rFlashTable.u1HSyncWidth;
        rPanel.PanelMinHSyncBackPorch_R = HSYNCLEN_TYPI - rFlashTable.u1HSyncWidth - rFlashTable.u2HPosition;
        rPanel.PanelTypVTotal_R = rFlashTable.u2VTotal60Hz;
        rPanel.PanelMinVSyncWidth_R = rFlashTable.u1VSyncWidth;
        rPanel.PanelMinVSyncBackPorch_R = rFlashTable.u1VSyncWidth + rFlashTable.u2VPosition + 1;

        #if (HSYNC_POLARITY == HSYNC_LOW)
        {
            bHSYNCP = 1;
        }
        #else
        {
            bHSYNCP = 0;
        }
        #endif

        #if (VSYNC_POLARITY == VSYNC_LOW)
        {
            bVSYNCP = 1;
        }
        #else
        {
            bVSYNCP = 0;
        }
        #endif

        bDataClk = 0;
        bDataEn = 0;

        if (LVDS_DISP_FORMAT == LVDS_MSB_SW_ON) // NS
        {
            bMSBOnOff = 1;
        }
        else // JEIDA
        {
            bMSBOnOff = 0;
        }
        rPanel.PanelOutputType_R = (bVSYNCP << 7) | (bHSYNCP << 6) | (bDataClk << 5) | (bDataEn << 4) | (bMSBOnOff << 3);

        IMpac3P_SetPanelParam(&rPanel, sizeof(rPanel));
        IMpac3P_SetPower(1);
    }
#endif /* CC_EXTERNAL_LVDS_CHIP */
    return TRUE;
}
#endif

//-----------------------------------------------------------------------------
// Public functions
//-----------------------------------------------------------------------------

PANEL_ATTRIBUTE_SET_TMPL(PanelWidth, u2PanelWidth)
PANEL_ATTRIBUTE_SET_TMPL(PanelHeight, u2PanelHeight)
PANEL_ATTRIBUTE_SETGET_TMPL(PixelClkMax, u4PixelClkMax)
#if !SCALER_PSCAN_DISPMODE_MIN_VTOTAL_OFFSET 
PANEL_ATTRIBUTE_SETGET_TMPL(PixelClk60Hz, u4PixelClk60Hz)
PANEL_ATTRIBUTE_SETGET_TMPL(PixelClk50Hz, u4PixelClk50Hz)
#else
PANEL_ATTRIBUTE_SET_TMPL(PixelClk60Hz, u4PixelClk60Hz)
PANEL_ATTRIBUTE_SET_TMPL(PixelClk50Hz, u4PixelClk50Hz)
#endif
PANEL_ATTRIBUTE_SETGET_TMPL(PixelClkMin, u4PixelClkMin)
PANEL_ATTRIBUTE_SETGET_TMPL(HTotalMax, u2HTotalMax)
PANEL_ATTRIBUTE_SETGET_TMPL(HTotal60Hz, u2HTotal60Hz)
PANEL_ATTRIBUTE_SETGET_TMPL(HTotal50Hz, u2HTotal50Hz)
PANEL_ATTRIBUTE_SETGET_TMPL(HTotalMin, u2HTotalMin)
PANEL_ATTRIBUTE_SETGET_TMPL(VTotalMax, u2VTotalMax)
#if !SCALER_PSCAN_DISPMODE_MIN_VTOTAL_OFFSET 
PANEL_ATTRIBUTE_SETGET_TMPL(VTotal60Hz, u2VTotal60Hz)
PANEL_ATTRIBUTE_SETGET_TMPL(VTotal50Hz, u2VTotal50Hz)
#else
PANEL_ATTRIBUTE_SET_TMPL(VTotal60Hz, u2VTotal60Hz)
PANEL_ATTRIBUTE_SET_TMPL(VTotal50Hz, u2VTotal50Hz)
#endif
PANEL_ATTRIBUTE_SETGET_TMPL(VTotalMin, u2VTotalMin)
PANEL_ATTRIBUTE_SETGET_TMPL(VClkMax, u1VClkMax)
PANEL_ATTRIBUTE_SETGET_TMPL(VClkMin, u1VClkMin)
//#ifndef SUPPORT_PANEL_CUSTOMER_SPEC
PANEL_ATTRIBUTE_SETGET_TMPL(HSyncWidth, u1HSyncWidth)
PANEL_ATTRIBUTE_SETGET_TMPL(VSyncWidth, u1VSyncWidth)
//#else
//    PANEL_ATTRIBUTE_SET_TMPL(HSyncWidth, u1HSyncWidth)
//    PANEL_ATTRIBUTE_SET_TMPL(VSyncWidth, u1VSyncWidth)
//#endif
PANEL_ATTRIBUTE_SET_TMPL(HPosition60Hz, u2HPosition)
PANEL_ATTRIBUTE_SET_TMPL(VPosition, u2VPosition)
PANEL_ATTRIBUTE_SETGET_TMPL(ControlWord, u4ControlWord)
PANEL_ATTRIBUTE_SETGET_TMPL(DimmingFrequency60Hz, u2DimmingFrequency60Hz)
PANEL_ATTRIBUTE_SETGET_TMPL(DimmingFrequency50Hz, u2DimmingFrequency50Hz)
PANEL_ATTRIBUTE_SETGET_TMPL(LvdsOnDalay, u1LvdsOnDalay)
PANEL_ATTRIBUTE_SETGET_TMPL(BacklightOnDelay, u1BacklightOnDelay)
PANEL_ATTRIBUTE_SETGET_TMPL(BacklightOffDelay, u1BacklightOffDelay)
PANEL_ATTRIBUTE_SETGET_TMPL(LvdsOffDalay, u1LvdsOffDalay)
PANEL_ATTRIBUTE_SETGET_TMPL(MaxOverscan, u2MaxOverscan)
PANEL_ATTRIBUTE_SETGET_TMPL(ControlWord2, u4ControlWord2)

static UINT8 fgLVDSPCBSwap = 0;
#ifdef CC_COMBINE_4K_2K	
UINT32 DRVCUST_Get_2K_Model(void);
UINT32 DRVCUST_Get_BE_Type(void);
UINT32 DRVCUST_Get_FRC_Type(void);
UINT32 DRVCUST_Get_PQ_Type(void);
BOOL DRVCUST_Is_All_in_One_Series(void);
#endif
UINT32 DRVCUST_Get_Illumination_LED_Type(void);
UINT32 DRVCUST_Get_FP_Key_Type(void);
UINT32 DRVCUST_Get_InterMemc_type(void);
UINT8 DRVCUST_Get_TrialLv(void);
UINT8 DRVCUST_Get_Series(void);
extern UINT32 DRVCUST_Get_MVI_Val_Byte(UINT32 u4Addr);

//----------------------------------------------------------------------------
/** DRVCUST_PanelQuery() return customization paramter.
 */
//----------------------------------------------------------------------------
INT32 DRVCUST_PanelQuery(QUERY_TYPE_T eQryType, UINT32 *pu4Data)
{
#ifdef CC_BACKLIGHT_PWM_BY_MODEL
#ifdef PANEL_BACKLIGHT_PWM_PORT
    static INT32 i4ModelIdx = -1;
#endif // PANEL_BACKLIGHT_PWM_PORT
#endif

    ASSERT(pu4Data!=NULL);

    switch(eQryType)
    {
    // Panel
    case eDefaultPanelSelect:
        *pu4Data = DEFAULT_PANEL_SELECT;
        return 0;
    case eLvdsACtrlEven:
		if(fgLVDSPCBSwap)
        *pu4Data = LVDS_A_CTRL_ODD;
		else
        *pu4Data = LVDS_A_CTRL_EVEN;
        return 0;
    case eLvdsACtrlOdd:
		if(fgLVDSPCBSwap)		
        *pu4Data = LVDS_A_CTRL_EVEN;
		else
        *pu4Data = LVDS_A_CTRL_ODD;
        return 0;
    case eLvdsBCtrlEven:
		if(fgLVDSPCBSwap)				
        *pu4Data = LVDS_B_CTRL_ODD;
		else
        *pu4Data = LVDS_B_CTRL_EVEN;
        return 0;
    case eLvdsBCtrlOdd:
		if(fgLVDSPCBSwap)				
        *pu4Data = LVDS_B_CTRL_EVEN;
		else
        *pu4Data = LVDS_B_CTRL_ODD;
        return 0;
    case eBackLightGpio:
#ifdef BACKLIGHT_GPIO
        *pu4Data = BACKLIGHT_GPIO;
        return 0;
#else
        return -1;
#endif
    case eBackLightOnVal:
#ifdef BACKLIGHT_ON_VAL
        *pu4Data = BACKLIGHT_ON_VAL;
        return 0;
#else
        return -1;
#endif
    case ePanelPowerGpio:
#ifdef CC_COMBINE_4K_2K
        if ((DRVCUST_Get_2K_Model()&0x03)==0x00)
        {
#ifdef PANELPOWER_GPIO_2K
            *pu4Data = PANELPOWER_GPIO_2K;
            return 0;
#else
            return -1;
#endif
        }
        else
        {
            if (DRVCUST_Get_BE_Type() != 0x0)
            {
#ifdef PANELPOWER_GPIO_4K
                *pu4Data = PANELPOWER_GPIO_4K;
                return 0;
#else
                return -1;
#endif
            }
            else
            {
#ifdef PANELPOWER_GPIO_4K_NO_BE
                *pu4Data = PANELPOWER_GPIO_4K_NO_BE;
                return 0;
#else
                return -1;
#endif
            }
        }
#else//
#ifdef PANELPOWER_GPIO		  
        *pu4Data = PANELPOWER_GPIO;
        return 0;
#else
        return -1;
#endif
#endif//CC_COMBINE_4K_2K
    case ePanelPowerOnVal:
#ifdef PANELPOWER_ON_VAL
        *pu4Data = PANELPOWER_ON_VAL;
        return 0;
#else
        return -1;
#endif
    case ePanelDCRGpio:
#ifdef PANEL_DCR_GPIO
        *pu4Data = PANEL_DCR_GPIO;
        return 0;
#else
        return -1;
#endif /* PANEL_DCR_GPIO */

    case ePanelDCROnVal:
#ifdef PANEL_DCR_ON_VAL
        *pu4Data = PANEL_DCR_ON_VAL;
        return 0;
#else
        return -1;
#endif /* PANEL_DCR_ON_VAL */

    case ePanelPdpVsGpio:
#ifdef PANEL_PDP_VS_GPIO
        *pu4Data = PANEL_PDP_VS_GPIO;
        return 0;
#else
        return -1;
#endif /* PANEL_PDP_VS_GPIO */

    case ePanelPdpVsOnVal:
#ifdef PANEL_PDP_VS_ON_VAL
        *pu4Data = PANEL_PDP_VS_ON_VAL;
        return 0;
#else
        return -1;
#endif /* PANEL_PDP_VS_ON_VAL */

    case eLvdsMsbSw:
#ifdef LVDS_MSB_SW
        *pu4Data = LVDS_MSB_SW;
        return 0;
#else
        return -1;
#endif /* LVDS_MSB_SW */

    case ePanelPwmPrescalar:
#ifdef PWM_PRESCALAR
        *pu4Data = PWM_PRESCALAR;
        return 0;
#else
        return -1;
#endif /* PWM_PRESCALAR */

    case ePanelDisableDimming:
#ifdef PANEL_DISABLE_DIMMING
        *pu4Data = PANEL_DISABLE_DIMMING;
        return 0;
#else
        return -1;
#endif /* PANEL_DISABLE_DIMMING */

    case ePanelChannelSwap:
        *pu4Data = PANEL_CHANNEL_SWAP;
        return 0;

    case ePanelPwmPolarity:
#ifdef PWM_POLARITY
        *pu4Data = PWM_POLARITY;
        return 0;
#else
        return -1;
#endif /* PWM_POLARITY */
    case ePanelIndexFromEeprom:
#ifdef PANEL_INDEX_FROM_EEPROM
        *pu4Data = PANEL_INDEX_FROM_EEPROM;
        return 0;
#else
        return -1;
#endif /* PANEL_INDEX_FROM_EEPROM */

    case ePanelIndexOffset1:
#ifdef PANEL_INDEX_OFFSET1
        *pu4Data = PANEL_INDEX_OFFSET1;
        return 0;
#else
        return -1;
#endif /* PANEL_INDEX_OFFSET1 */

    case ePanelIndexOffset2:
#ifdef PANEL_INDEX_OFFSET2
        *pu4Data = PANEL_INDEX_OFFSET2;
        return 0;
#else
        return -1;
#endif /* PANEL_INDEX_OFFSET2 */

    case ePanelIndexOffset3:
#ifdef PANEL_INDEX_OFFSET3
        *pu4Data = PANEL_INDEX_OFFSET3;
        return 0;
#else
        return -1;
#endif /* PANEL_INDEX_OFFSET3 */

    case ePanelIndexFromGpioNum:
        *pu4Data = PANEL_INDEX_FROM_GPIO_NUM;
        return 0;

    case eBacklightHigh:
#ifdef BACKLIGHT_HIGH_PWM
        *pu4Data = BACKLIGHT_HIGH_PWM;
        return 0;
#else
        return -1;
#endif /* BACKLIGHT_HIGH_PWM */

    case eBacklightMiddle:
#ifdef BACKLIGHT_MIDDLE_PWM
        *pu4Data = BACKLIGHT_MIDDLE_PWM;
        return 0;
#else
        return -1;
#endif /* BACKLIGHT_MIDDLE_PWM */

    case eBacklightLow:
#ifdef BACKLIGHT_LOW_PWM
        *pu4Data = BACKLIGHT_LOW_PWM;
        return 0;
#else
        return -1;
#endif /* BACKLIGHT_LOW_PWM */

    case eBackLightGpio2:
#ifdef BACKLIGHT_GPIO2
        *pu4Data = BACKLIGHT_GPIO2;
        return 0;
#else
        return -1;
#endif /* BACKLIGHT_GPIO2 */

    case eSpreadSpectrumPermillage:
#ifdef SPREAD_SPECTRUM_PERMILLAGE
        *pu4Data = SPREAD_SPECTRUM_PERMILLAGE;
        return 0;
#else
        return -1;
#endif /* SPREAD_SPECTRUM_PERMILLAGE */

    case eTimerDimmingFreq:
#ifdef TIMER_DIMMING_FREQ
        *pu4Data = TIMER_DIMMING_FREQ;
        return 0;
#else
        return -1;
#endif /* TIMER_DIMMING_FREQ */

    case eDimmingFreq60:
        *pu4Data = DIMMING_FREQ_60;
        return 0;

    case eDimmingFreq50:
        *pu4Data = DIMMING_FREQ_50;
        return 0;

    case ePanelTTLOutput:
        *pu4Data = PANEL_TTL_OUTPUT;
        return 0;

    case ePanelFlashTableSize:
        *pu4Data = PANEL_FLASH_TABLE_SIZE;
        return 0;

    case ePanelFlashTableAddress:
        *pu4Data = PANEL_FLASH_TABLE_ADDRESS;
        return 0;

    case eLvdsDrivingCurrent:
#ifdef LVDS_DRIVING_CURRENT
        *pu4Data = LVDS_DRIVING_CURRENT;
        return 0;
#else
        return -1;
#endif /* LVDS_DRIVING_CURRENT */

    case ePanelBacklightPwmPort:
#ifdef PANEL_BACKLIGHT_PWM_PORT
#ifdef CC_BACKLIGHT_PWM_BY_MODEL
        if (i4ModelIdx == -1)
        {
            i4ModelIdx = GetModelIndexFromEEPROM ();
        }
        *pu4Data = GetModelIndexBacklightPwmPort (i4ModelIdx);
#else
        *pu4Data = PANEL_BACKLIGHT_PWM_PORT;
#endif        
#else
		*pu4Data = 2; // Default using PWM2 as backlight control.
#endif /* PANEL_BACKLIGHT_PWM_PORT */
		return 0;

    case ePanelBacklightGPIO:
#ifdef PANEL_BACKLIGHT_PWM_GPIO
		*pu4Data = PANEL_BACKLIGHT_PWM_GPIO;
#else
		*pu4Data = 0; // Default using PWM output
#endif /* PANEL_BACKLIGHT_PWM_GPIO */
    return 0;

	case eFlagBacklightBoostCtrl:
#ifdef SUPPORT_BACKLIGHT_BOOST_CTRL
		*pu4Data = (UINT32)SUPPORT_BACKLIGHT_BOOST_CTRL;
#else
		*pu4Data = (UINT32)0;
#endif // #ifdef SUPPORT_BACKLIGHT_BOOST_CTRL
		return 0;
	case eFlagBacklightBoostPort:
#ifdef PANEL_BACKLIGHT_BOOST_PORT
		*pu4Data = (UINT32)PANEL_BACKLIGHT_BOOST_PORT;
#else
		*pu4Data = (UINT32)1;
#endif // #ifdef PANEL_BACKLIGHT_BOOST_PORT
		return 0;
	case eFlagBacklightBoostInvert:
#ifdef SUPPORT_BACKLIGHT_BOOST_INVERT
		*pu4Data = (UINT32)SUPPORT_BACKLIGHT_BOOST_INVERT;
#else
		*pu4Data = (UINT32)0;
#endif // #ifdef SUPPORT_BACKLIGHT_BOOST_INVERT
		return 0;
	case eFlagBacklightDimmingLock:
#ifdef SUPPORT_BACKLIGHT_DIMMING_LOCK
		*pu4Data = (UINT32)SUPPORT_BACKLIGHT_DIMMING_LOCK;
#else
        // default set pwm lock OFF
		*pu4Data = (UINT32)0;
#endif // #ifdef SUPPORT_BACKLIGHT_DIMMING_LOCK
		return 0;
	case eFlagBacklightDimmingInvert:
#ifdef SUPPORT_BACKLIGHT_DIMMING_INVERT
        *pu4Data = (UINT32)SUPPORT_BACKLIGHT_DIMMING_INVERT;
#else
        *pu4Data = (UINT32)0;
#endif // #ifdef SUPPORT_BACKLIGHT_DIMMING_INVERT
        return 0;

    case ePanelPixelShiftHMax:
        *pu4Data = PANEL_PIXEL_SHIFT_H_MAX;
        return 0;
    case ePanelPixelShiftVMax:
        *pu4Data = PANEL_PIXEL_SHIFT_V_MAX;
        return 0;

    case ePanelBitSelectCtrlGpio:
#ifdef PANEL_BIT_SELECT_CTRL_GPIO
        *pu4Data = PANEL_BIT_SELECT_CTRL_GPIO;
        return 0;
#else
        *pu4Data = (UINT32)-1;
        return -1;
#endif

        case ePanelLvdsSelectCtrlGpio:
#ifdef PANEL_LVDS_SELECT_CTRL_GPIO
            *pu4Data = PANEL_LVDS_SELECT_CTRL_GPIO;
            return 0;
#else
            *pu4Data = (UINT32)-1;
            return -1;
#endif

        case ePanel242530pOutput:
            #ifdef PANEL_SUPPORT_24_25_30_OUTPUT           
            *pu4Data = (UINT32)PANEL_SUPPORT_24_25_30_OUTPUT;
            #else
            *pu4Data = (UINT32)0;
            #endif
            return 0;


        case eDDDSErrorLimit:
            #ifdef DDDS_ERROR_LIMIT
            *pu4Data = DDDS_ERROR_LIMIT;
            return 0;
            #else
            *pu4Data = (UINT32)-1;
            return -1;
            #endif

        case eDDDSLockOnOthers:
            #ifdef DDDS_LOCK_OTHERS
            *pu4Data = DDDS_LOCK_OTHERS;
            #else
            *pu4Data = (UINT32)1;
            #endif
            return 0;

		case eDISP_RLVDSEncodeLink:
		#ifdef DISP_RLVDSENCODE_PORT
			*pu4Data = DISP_RLVDSENCODE_LINK;
			return 0;
		#else
			*pu4Data = (UINT32)-1;
			return -1;
		#endif
        
#ifdef CC_ENABLE_MTK_MODEL_INDEX
        case eModelIndexOffset1:
#ifdef MODEL_INDEX_OFFSET1
            *pu4Data = MODEL_INDEX_OFFSET1;
            return 0;
#else
            return -1;
#endif /* MODEL_INDEX_OFFSET1 */
        
        case eModelIndexOffset2:
#ifdef MODEL_INDEX_OFFSET2
            *pu4Data = MODEL_INDEX_OFFSET2;
            return 0;
#else
            return -1;
#endif /* MODEL_INDEX_OFFSET2 */
    
        case eModelIndexOffset3:
#ifdef MODEL_INDEX_OFFSET3
            *pu4Data = MODEL_INDEX_OFFSET3;
            return 0;
#else
            return -1;
#endif /* MODEL_INDEX_OFFSET3 */
#endif /* #ifdef CC_ENABLE_MTK_MODEL_INDEX */
		case eBackLightMuteGpio:
#ifdef BACKLIGHT_GPIO
		    *pu4Data = BACKLIGHT_GPIO;
			return 0;
#else
			return -1;
#endif
		 case eBackLightMuteOnVal:
#ifdef BACKLIGHT_ON_VAL
			*pu4Data = !BACKLIGHT_ON_VAL;
			return 0;
#else
			return -1;
#endif
		 case ePanelPower1Gpio:
#ifdef PANELPOWER_1_GPIO
			*pu4Data = PANELPOWER_1_GPIO;
			return 0;
#else
			return -1;
#endif
		 case ePanelPower1OnVal:
#ifdef PANELPOWER_1_ON_VAL
			*pu4Data = PANELPOWER_1_ON_VAL;
			return 0;
#else
			return -1;
#endif
		 case ePanelPower2Gpio:
#ifdef PANELPOWER_2_GPIO
			*pu4Data = PANELPOWER_2_GPIO;
			return 0;
#else
			return -1;
#endif
		 case ePanelPower2OnVal:
#ifdef PANELPOWER_2_ON_VAL
			*pu4Data = PANELPOWER_2_ON_VAL;
			return 0;
#else
			return -1;
#endif
    default:
        return -1;
    }
}

INT32 DRVCUST_PanelQueryUptr(QUERY_TYPE_T eQryType, UPTR *pu4Data)
{
    ASSERT(pu4Data!=NULL);

    switch(eQryType)
    {
    // used in panel_table.c
    case ePanelIndexFromGpioIdx:
        *pu4Data = (UPTR)PANEL_INDEX_FROM_GPIO_IDX;
        return 0;

    // used in panel_table.c
    case (QUERY_UPTR_T)(ePanelIndexFromGpioMap):
        *pu4Data = (UPTR)PANEL_INDEX_FROM_GPIO_MAP;
        return 0;

    // 5891 not used...
    case (QUERY_UPTR_T)(ePanelLvds8bitPinMap):
        *pu4Data = (UPTR)PANEL_LVDS_8BIT_PIN_MAP;
        return 0;

    // used in drv_lvds.c
    case (QUERY_UPTR_T)(ePanelLvds10bitPinMap):
        *pu4Data = (UPTR)PANEL_LVDS_10BIT_PIN_MAP;
        return 0;

    // used in drv_lvds.c
    case (QUERY_UPTR_T)(ePanelLvds10bitPNSwap):
        *pu4Data = (UPTR)PANEL_LVDS_10BIT_PN_SWAP;
        return 0;

    // used in drv_vbyone.c
    case ePanelVB1LaneSwap:
        *pu4Data = (UPTR)PANEL_VB1_LANE_SWAP;
        return 0;

    // used in drv_vbyone.c
    case ePanelVB1LanePNSwap:
        *pu4Data = (UPTR)PANEL_VB1_LANE_PN_SWAP;
        return 0;

    // used in drv_lvds.c
	case ePanelLVDSToGPO:
		*pu4Data = (UPTR)PANEL_LVDS_PORTB_TO_GPO_MAP;
		return 0;

    // used in drv_lvds.c
	case ePanelLVDSToGPI:
		*pu4Data = (UPTR)PANEL_LVDS_PORTB_TO_GPI_MAP;
		return 0;

    // used in panel_table.c
    case ePanelEepromToFlashIndexMap:
        *pu4Data = (UPTR)PANEL_EEPROM_TO_FLASH_INDEX_MAP;
        return 0;

	// used in drv_vbyone.c
	case ePanelVB1OsdLocknPin:
#ifdef PANEL_VB1_OSD_LOCKN_PIN
		*pu4Data = (UPTR)PANEL_VB1_OSD_LOCKN_PIN;
		return 0;
#else
		return -1;
#endif

    // used in drv_vbyone.c
	case ePanelVB1OsdLocknPinFunc:
#ifdef PANEL_VB1_OSD_LOCKN_PIN_FUNC
		*pu4Data = (UPTR)PANEL_VB1_OSD_LOCKN_PIN_FUNC;
		return 0;
#else
		return -1;
#endif

    // used in drv_vbyone.c
	case ePanelVB1OsdHtpdnPin:
#ifdef PANEL_VB1_OSD_HTPDN_PIN
		*pu4Data = (UPTR)PANEL_VB1_OSD_HTPDN_PIN;
		return 0;
#else
		return -1;
#endif

    // used in drv_vbyone.c
	case ePanelVB1OsdHtpdnPinFunc:
#ifdef PANEL_VB1_OSD_HTPDN_PIN_FUNC
		*pu4Data = (UPTR)PANEL_VB1_OSD_HTPDN_PIN_FUNC;
		return 0;
#else
		return -1;
#endif

    // used in drv_vbyone.c
	case ePanelVB1LocknPin:
#ifdef PANEL_VB1_LOCKN_PIN
		*pu4Data = (UPTR)PANEL_VB1_LOCKN_PIN;
		return 0;
#else
		return -1;
#endif

    // used in drv_vbyone.c
	case ePanelVB1LocknPinFunc:
#ifdef PANEL_VB1_LOCKN_PIN_FUNC
		*pu4Data = (UPTR)PANEL_VB1_LOCKN_PIN_FUNC;
		return 0;
#else
		return -1;
#endif

    // used in drv_vbyone.c
	case ePanelVB1HtpdnPin:
#ifdef PANEL_VB1_HTPDN_PIN
		*pu4Data = (UPTR)PANEL_VB1_HTPDN_PIN;
		return 0;
#else
		return -1;
#endif

    // used in drv_vbyone.c
	case ePanelVB1HtpdnPinFunc:
#ifdef PANEL_VB1_HTPDN_PIN_FUNC
		*pu4Data = (UPTR)PANEL_VB1_HTPDN_PIN_FUNC;
		return 0;
#else
		return -1;
#endif

    default:
        return -1;
    }
}

UINT32 DRVCUST_PanelGet(QUERY_TYPE_T eQryType)
{
    UINT32 u4Ret = 0xffffffff;

    UNUSED(DRVCUST_PanelQuery(eQryType, &u4Ret));
    return u4Ret;
}

UPTR DRVCUST_PanelGetUptr(QUERY_TYPE_T eQryType)
{
    UPTR u4Ret = ~((UPTR)0);

    UNUSED(DRVCUST_PanelQueryUptr(eQryType, &u4Ret));
    return u4Ret;
}

static BOOL _bIsGetTrialLv = FALSE;
static UINT8 _u1MVITrialLv = 0;

UINT8 DRVCUST_Get_TrialLv(void)
{
    if (!_bIsGetTrialLv)
    {
        UNUSED(EEPROM_Read(0x10012, (UPTR)&_u1MVITrialLv, 1));
        _bIsGetTrialLv = TRUE;
    }
    return _u1MVITrialLv;
}

static BOOL _bIsGetSeries = FALSE;
static UINT8 _u1MVISeries = 0;
UINT8 DRVCUST_Get_Series(void)
{
    if (!_bIsGetSeries)
    {
        UNUSED(EEPROM_Read(0x10000, (UPTR)&_u1MVISeries, 1));
        _bIsGetSeries = TRUE;
    }
    return _u1MVISeries;
}
//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------

UINT32 IsLvdsMsbSwOn(void)
{
    UINT32 u4Value;
    if (DRVCUST_PanelQuery(eLvdsMsbSw, &u4Value) == 0)
    {
        return u4Value;
    }
    if (IS_COMPANION_CHIP_ON())
    {
        return LVDS_JEIDA;
    }
   return (PANEL_GetControlWord() & (LVDS_MSB_SW_ON | LVDS_SPECIAL_NS));
}


/**
* @brief Check if support 120Hz Panel
* @retval SV_TURE/SV_FALSE
*/
UINT8 fgIsSupport120HzPanel(void)
{
    if (PANEL_GetVClkMax() > 100)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}


//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------

UINT32 IsPwmLowPanelBright(void)
{
    UINT32 u4Value;
    if (DRVCUST_PanelQuery(ePanelPwmPolarity, &u4Value) == 0)
    {
        return u4Value;
    }
    return PANEL_GetControlWord() & PWM_LOW_PANEL_BRIGHT;
}


//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------
#if defined(SUPPORT_PANEL_GRAPH_MODE)
static UINT32 u4GraphModeIndex = PANEL_4K_BACKEND;
#endif
void SelectPanel(UINT32 u4Index)
{
	#ifdef SUPPORT_PANEL_CUSTOMER_SPEC
	UINT32 u4ExtIdx = EXT_PANEL_INDEX_INVALID;
	#endif
    // read panel index from customer define
    if (u4Index == PANEL_INVALID)
    {
        u4Index = DRVCUST_PanelGet(eDefaultPanelSelect);
    }
    if (u4Index != PANEL_INVALID)
    {
        _u4PanelIndex = u4Index;

#ifndef CC_MULTI_PANEL
        _u4PanelIndex = 0;
#endif

        _prPanelAttribute = &_arPanelAttribute[_u4PanelIndex];
    }
	#ifdef SUPPORT_PANEL_CUSTOMER_SPEC
	u4ExtIdx = PANEL_GetExtAttributeIndex();
    if ((u4ExtIdx != EXT_PANEL_INDEX_INVALID))
    {
		_prPanelAttributeExt =	& _arPanelAttributeExt[u4ExtIdx];
    }
	#endif

#if defined(SUPPORT_PANEL_GRAPH_MODE)
	#ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
	if (FlashPanel_GetControlWord2_GraphModeEn())
	#else
	if (IS_SUPPORT_VB1_GRAPH_MODE)
	#endif
	{
		u4GraphModeIndex  = _u4PanelIndex; 
		LOG(0, "[VB1][GFX]u4GraphModeIndex=%ld\n", u4GraphModeIndex);
	#ifdef CC_S_PLATFORM
        GraphMode_SetPanelType(PANEL_TYPE_4K1K_60);
    #else
		if(GetCurrentPanelIndex() == PANEL_4K_BACKEND)	
		{
			GraphMode_SetPanelType(PANEL_TYPE_4K1K_60); // force gfx output 4k1k@60
		}
		else if (GetCurrentPanelIndex() == PANEL_VB1_4K2KDD_GRAPH)
		{
			GraphMode_SetPanelType(PANEL_TYPE_2K1K_120); // force gfx output 2k1k@120 
			//GraphMode_SetPanelType(PANEL_TYPE_2K1K_60);
		}
		else
		{
			GraphMode_SetPanelType(PANEL_TYPE_4K2K_30); // force gfx output 4k2k@30 	
		}
	#endif
	}      
#endif
}


//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------

CHAR* GetCurrentPanelName(void)
{
    if (DRVCUST_PanelGet(ePanelFlashTableSize) > 0)
    {
        return GetPanelName(PANEL_GetEepromPanelIndex());
    }
    else
    {
        return GetPanelName(GetCurrentPanelIndex());
    }
}


//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------

UINT32 GetCurrentPanelIndex(void)
{
    if (DRVCUST_PanelGet(ePanelFlashTableSize) > 0)
    {
        return PANEL_GetEepromPanelIndex();
    }
    else
    {
	    return _u4PanelIndex;
    }
}

UINT32 GetFlagPanelIdInEeprom(void)
{
    return _fgPanelIdInEeprom;
}

//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------

void DumpPanelAttribute(UINT32 u4Flag)
{
    UINT32 u4Size = sizeof(_arPanelAttribute) / sizeof(PANEL_ATTRIBUTE_T);
    UINT32 i = 0;
    PANEL_ATTRIBUTE_T* prTbl;

#ifdef DUMP_PANEL_LIST_FROM_FLASH_CUSTOM
    if ((u4Flag & PANEL_DUMP_TITLE) && (u4Flag & PANEL_DUMP_ALL))
    {
        DUMP_PANEL_LIST_FROM_FLASH_CUSTOM();
        return;
    }
#endif

    if ((u4Flag & PANEL_DUMP_ALL) == 0)
    {
        i = _u4PanelIndex;
        u4Size = _u4PanelIndex + 1;
    }
    for (; i < u4Size; i++)
    {
        prTbl = &_arPanelAttribute[i];
        if ((DRVCUST_PanelGet(ePanelFlashTableSize) > 0) && (i == 0))
        {
        #ifdef CC_S_PLATFORM
                        #ifdef LOAD_PANEL_FROM_FLASH_CUSTOM			
			LOG(0,"---------- FlashPanel[%3ld] %s %dx%d ----------\n",
			       PANEL_GetEepromPanelIndex(), FlashPanel_GetIDString(), prTbl->u2PanelWidth, prTbl->u2PanelHeight);
                        #endif
		#else
            LOG(0,"---------- FlashPanel[%3ld] %s %dx%d ----------\n",
                   PANEL_GetEepromPanelIndex(), GetPanelName(PANEL_GetEepromPanelIndex()), prTbl->u2PanelWidth, prTbl->u2PanelHeight);
		#endif
		}
        else
        {
            LOG(0,"---------- Panel[%3ld] %s %dx%d ----------\n",
                   i, GetPanelName(i), prTbl->u2PanelWidth, prTbl->u2PanelHeight);
        }
        if ((u4Flag & PANEL_DUMP_TITLE) == PANEL_DUMP_TITLE)
        {
            continue;
        }
        LOG(0,"PixelClk[Max=%ld, 60Hz=%ld, 50Hz=%ld, Min=%ld]\n",
               prTbl->u4PixelClkMax, prTbl->u4PixelClk60Hz,
               prTbl->u4PixelClk50Hz, prTbl->u4PixelClkMin);
        LOG(0,"HTotal[Max=%d, 60Hz=%d, 50Hz=%d, Min=%d] HSyncLen[60Hz=%ld, 50Hz=%ld]\n",
               prTbl->u2HTotalMax, prTbl->u2HTotal60Hz,
               prTbl->u2HTotal50Hz, prTbl->u2HTotalMin,
               PANEL_GetHSyncLen60Hz(), PANEL_GetHSyncLen50Hz());
        LOG(0,"VTotal[Max=%d, 60Hz=%d, 50Hz=%d, Min=%d] VClk[Max=%d, Min=%d]\n",
               prTbl->u2VTotalMax, prTbl->u2VTotal60Hz,
               prTbl->u2VTotal50Hz, prTbl->u2VTotalMin,
               prTbl->u1VClkMax, prTbl->u1VClkMin);
        #ifdef SUPPORT_PANEL_CUSTOMER_SPEC
        LOG(0,"HSyncWidth60Hz=%ld, ", PANEL_GetHSyncWidthByTiming(SV_DCLK_60HZ));
        LOG(0,"HSyncWidth50Hz=%ld, ", PANEL_GetHSyncWidthByTiming(SV_DCLK_50HZ));
        LOG(0,"VSyncWidth60Hz=%ld, ", PANEL_GetVSyncWidthByTiming(SV_DCLK_60HZ));
        LOG(0,"VSyncWidth50Hz=%ld\n", PANEL_GetVSyncWidthByTiming(SV_DCLK_50HZ));
        #else
        LOG(0,"HSyncWidth=%d, ", prTbl->u1HSyncWidth);
        LOG(0,"VSyncWidth=%d, ", prTbl->u1VSyncWidth);
        #endif
        LOG(0,"HPosition60Hz=0x%lX, ", H_POS_60HZ);
        LOG(0,"HPosition50Hz=0x%lX, ", H_POS_50HZ);
        #ifdef SUPPORT_PANEL_CUSTOMER_SPEC
        LOG(0,"VPosition60Hz=%ld, ", PANEL_GetVPositionByTiming(SV_DCLK_60HZ));
        LOG(0,"VPosition50Hz=%ld\n", PANEL_GetVPositionByTiming(SV_DCLK_50HZ));
        #else
        LOG(0,"VPosition=%d\n", prTbl->u2VPosition);
        #endif        

        if (SUPPORT_PANEL_48HZ)
        {
        LOG(0,"-SUPPORT_48HZ ExtId[%ld]- Pclk=%ld, HTot48Hz=%ld, VTot48Hz=%ld\n"
               "HsWid48Hz=%ld, VsWid48Hz=%ld, HPos48Hz=0x%lX, VPos48Hz=0x%lX\n",
                PANEL_GetExtAttributeIndex(),
                PANEL_GetPixelClk48Hz(), PANEL_GetHTotal48Hz(), PANEL_GetVTotal48Hz(),
        #ifdef SUPPORT_PANEL_CUSTOMER_SPEC
                PANEL_GetHSyncWidthByTiming(SV_DCLK_48HZ), 
                PANEL_GetVSyncWidthByTiming(SV_DCLK_48HZ),
                PANEL_GetHPositionByTiming(SV_DCLK_48HZ),
                PANEL_GetVPositionByTiming(SV_DCLK_48HZ) 
        #else
                prTbl->u1HSyncWidth, prTbl->u1VSyncWidth,
                H_POS_60HZ, prTbl->u2VPosition
        #endif
                );
        } 

	#if defined(SUPPORT_PANEL_SIZE_CM)
		LOG(0,"Panel_Physical_Width=%ld(CM)\n, ", PANEL_GetCurrentPanelWidthCM());
        LOG(0,"Panel_Physical_Height=%ld(CM)\n", PANEL_GetCurrentPanelHeightCM());
	#endif
	
        if (prTbl->u4ControlWord & LVDS_MSB_SW_ON)
        {
            LOG(0,"LVDS_NS, ");
        }
        else
        {
            LOG(0,"LVDS_JEIDA, ");
        }
        if (prTbl->u4ControlWord & LVDS_ODD_SW_ON)
        {
            LOG(0,"LVDS_ODD_SW_ON, ");
        }
        else
        {
            LOG(0,"LVDS_ODD_SW_OFF, ");
        }

        if ((prTbl->u4ControlWord & LVDS_PORT_MASK) == DUAL_PORT)
        {
            LOG(0,"DUAL_PORT, ");
        }
        else if ((prTbl->u4ControlWord & LVDS_PORT_MASK) == FOUR_PORT)
        {
            LOG(0,"FOUR_PORT, ");
        }
        else if ((prTbl->u4ControlWord & LVDS_PORT_MASK) == OCTA_PORT)
        {
            LOG(0,"OCTA_PORT, ");
        }
		else if ((prTbl->u4ControlWord & LVDS_PORT_MASK) == HEXA_PORT)
        {
            LOG(0,"HEXA_PORT, ");
        }
        else
        {
            LOG(0,"SINGLE_PORT, ");
        }

        if ((prTbl->u4ControlWord & DISP_BIT_MSK) == DISP_30BIT)
        {
            LOG(0,"DISP_30BIT, ");
        }
        else if ((prTbl->u4ControlWord & DISP_BIT_MSK) == DISP_24BIT)
        {
            LOG(0,"DISP_24BIT\n");
        }
        else
        {
            LOG(0,"DISP_18BIT\n");
        }
        if (prTbl->u4ControlWord & WFB_PANEL_RESET_ON)
        {
            LOG(0,"WFB_PANEL_RESET_ON, ");
        }
        else
        {
            LOG(0,"WFB_PANEL_RESET_OFF, ");
        }
        if (prTbl->u4ControlWord & PWM_LOW_PANEL_BRIGHT)
        {
            LOG(0,"PWM_LOW_PANEL_BRIGHT\n");
        }
        else
        {
            LOG(0,"PWM_HIGH_PANEL_BRIGHT\n");
        }

        if(prTbl->u4ControlWord & LVDS_USE_INDEPENDENT_SETTING)
        {
		if (LVDS_A_INDEPENDENT_SETTING == 3)
        {
            LOG(0,"LVDS_A_FROM_BO,");
        }
		else if (LVDS_A_INDEPENDENT_SETTING == 2)
        {
            LOG(0,"LVDS_A_FROM_BE,");
        }
        else if (LVDS_A_INDEPENDENT_SETTING == 1)
        {
            LOG(0,"LVDS_A_FROM_AO,");
        }
		else if (LVDS_A_INDEPENDENT_SETTING == 0)
		{
			LOG(0,"LVDS_A_FROM_AE,");
		}

		if (LVDS_B_INDEPENDENT_SETTING == 3)
        {
            LOG(0,"LVDS_B_FROM_BO,");
        }
        else if (LVDS_B_INDEPENDENT_SETTING == 2)
        {
            LOG(0,"LVDS_B_FROM_BE,");
        }
        else if (LVDS_B_INDEPENDENT_SETTING == 1)
        {
            LOG(0,"LVDS_B_FROM_AO,");
        }
		else if (LVDS_B_INDEPENDENT_SETTING == 0)
		{
			LOG(0,"LVDS_B_FROM_AE,");
		}

		if (LVDS_C_INDEPENDENT_SETTING == 3)
        {
            LOG(0,"LVDS_C_FROM_BO,");
        }
        else if (LVDS_C_INDEPENDENT_SETTING == 2)
        {
            LOG(0,"LVDS_C_FROM_BE,");
        }
        else if (LVDS_C_INDEPENDENT_SETTING == 1)
        {
            LOG(0,"LVDS_C_FROM_AO,");
        }
		else if (LVDS_C_INDEPENDENT_SETTING == 0)
		{
			LOG(0,"LVDS_C_FROM_AE,");
		}

		if (LVDS_D_INDEPENDENT_SETTING == 3)
        {
            LOG(0,"LVDS_D_FROM_BO,\n");
        }
        else if (LVDS_D_INDEPENDENT_SETTING == 2)
        {
            LOG(0,"LVDS_D_FROM_BE,\n");
        }
        else if (LVDS_D_INDEPENDENT_SETTING == 1)
        {
            LOG(0,"LVDS_D_FROM_AO,\n");
        }
		else if (LVDS_D_INDEPENDENT_SETTING == 0)
		{
			LOG(0,"LVDS_D_FROM_AE,\n");
		}		
        }
		
        if(LVDS_DISP_3D==LVDS_DISP_3D_POLARIZED_LRLR)
        {
            LOG(0,"3D_POLARIZED_LRLR, ");
        }
        else if(LVDS_DISP_3D==LVDS_DISP_3D_POLARIZED_RLRL)
        {
            LOG(0,"3D_POLARIZED_RLRL, ");
        }
        else if(LVDS_DISP_3D==LVDS_DISP_3D_SHUTTER)
        {
            LOG(0,"3D_SHUTTER, ");
        }
        else
        {
            LOG(0,"3D_NA, ");
        }

        if(LVDS_DISP_SPLIT)
        {
            LOG(0,"SPLIT_ON, ");
        }
        else
        {
            LOG(0,"SPLIT_OFF, ");
        }

        if(IS_VBYONE)
        {
            LOG(0,"VB1");
        }
        if(IS_MLVDS)
        {
            LOG(0,"MLVDS");
        }
        if(IS_EPI)
        {
            LOG(0,"EPI");
        }
        LOG(0,"\n");

        if(IS_LVDS_HIGHSPEED)
        {
            LOG(0,"LVDS_HIGHSPEED,");
        }

        if(IS_PANEL_L12R12)
        {
            LOG(0,"PANEL_L12R12,");
        }		

        if(IS_PANEL_ASPECT_RATIO_21_9)
        {
            LOG(0,"PANEL_ASPECT_RATIO_21_9,");
        }	

        if(IS_OD_ENABLE)
        {
            LOG(0,"OD_ENABLE,");
        }	

        if(IS_FB_ENABLE)
        {
            LOG(0,"FB_ENABLE,");
        }	

	#ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
		if (FlashPanel_GetControlWord_2SecEn())
	#else
		if(IS_VB1_2SEC_ENABLE)
	#endif
		{
			LOG(0,"VB1_2SEC_ENABLE,");
		}
	#ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
		if (FlashPanel_GetControlWord_4SecEn())
	#else
		if(IS_VB1_4SEC_ENABLE)
	#endif
		{
			LOG(0,"VB1_4SEC_ENABLE,");
		}
	#ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
		if (FlashPanel_GetControlWord_8SecEn())
	#else
		if(IS_VB1_8SEC_ENABLE)
	#endif
		{
			LOG(0,"VB1_8SEC_ENABLE,");
		}

		LOG(0,"\n");

		// Panel Table Control Word 2 START
		LOG(0,"==CW2==\n");
		if (IS_DISPR_ENCODEL4)
            LOG(0,"DISPR_ENCODEL4,");
		
		if (IS_DISABLE_PANEL_HVSYNC)
					LOG(0,"DISABLE_PANEL_HVSYNC,");			
		#ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
		if (FlashPanel_GetControlWord2_GraphModeEn())
		#else
		if (IS_SUPPORT_VB1_GRAPH_MODE)
		#endif
		{
					LOG(0,"SUPPORT_VB1_GRAPH_MODE,");	
		}

		if (IS_FORCE_LVDS_ANA_2CH_ON)
					LOG(0,"FORCE_LVDS_ANA_2CH_ON,");

		if (IS_FORCE_LVDS_ANA_4CH_ON)
					LOG(0,"FORCE_LVDS_ANA_4CH_ON,");		

		if (IS_SEPARATE_OSD_AND_DATA)
					LOG(0,"SEPARATE_OSD_AND_DATA,");	

		if (IS_DISPLAY_FREERUN)
					LOG(0,"DISPLAY_FREERUN,");			

		if (IS_FORCE_LVDS_DIG_4CH_ON)
					LOG(0,"FORCE_LVDS_DIG_4CH_ON,");		

		if (IS_PANEL_2D_N_3D_L12R12)
					LOG(0,"PANEL_2D_N_3D_L12R12,");	

		if (IS_DISABLE_LVDS_LINEBUFFER)
					LOG(0,"DISABLE_LVDS_LINEBUFFER,");		

		if (IS_DISP_4K2K_TYPE1)
					LOG(0,"DISP_4K2K_TYPE_1,");	

		if (IS_DISP_4K2K_TYPE2)
					LOG(0,"DISP_4K2K_TYPE_2,");

		if (IS_DISP_4K2K_TYPE3)
					LOG(0,"DISP_4K2K_TYPE_3,");
		
		if (IS_DISP_4K2K_TYPE4)
					LOG(0,"DISP_4K2K_TYPE_4,");		

		if (IS_DISP_4K2K_TYPE5)
					LOG(0,"DISP_4K2K_TYPE_5,");	

		if (IS_SUPPORT_OSD_INDEX)
					LOG(0,"SUPPORT_OSD_INDEX,");	

		if (IS_EPI_4LANE)
					LOG(0,"EPI_4LANE,");			

		if (IS_EPI_8LANE)
					LOG(0,"EPI_8LANE,");			

		if (IS_STEP_CLOCK_CHG)
		   			LOG(0,"STEP_CLOCK_CHG,"); 

		if (IS_DISPR_INVERSE)
		   			LOG(0,"DISPR_INVERSE,"); 			

		if (IS_VB1_ALL_LANE_ON)
		   			LOG(0,"VB1_ALL_LANE_ON,"); 			

		if (IS_DISP_4K2K_FORMAT_ARGB)
		   			LOG(0,"DISP_4K2K_FORMAT_ARGB,"); 

		if (IS_DISP_4K2K_FORMAT_YUV444)
		   			LOG(0,"DISP_4K2K_FORMAT_YUV444,"); 			

		if (IS_DISP_4K2K_FORMAT_YUV422)
		   			LOG(0,"DISP_4K2K_FORMAT_YUV422,"); 
		
		if (IS_DISP_2K_TYPE1)
		   			LOG(0,"DISP_2K_TYPE1,"); 

		if (IS_DISP_2K_TYPE2)
		   			LOG(0,"DISP_2K_TYPE2,"); 			

		if (IS_DISP_2K_TYPE3)
		   			LOG(0,"DISP_2K_TYPE3,");
		
		if (IS_ENGINEER_DISPLAY_MODE)
		   			LOG(0,"ENGINEER_DISPLAY_MODE,"); 			

		if (IS_DISP_48HZ_TO_48HZ)
					LOG(0,"DISP_48HZ_TO_48HZ,");	

		if (IS_DISP_48HZ_TO_50HZ)
					LOG(0,"DISP_48HZ_TO_50HZ,");

		if (IS_DISP_48HZ_TO_60HZ)
					LOG(0,"DISP_48HZ_TO_60HZ,");

		if (IS_SUPPORT_UHD_OSD_SEPARATE)
					LOG(0,"SUPPORT_UHD_OSD_SEPARATE,");

		LOG(0,"\n");		
		// Panel Table Control Word 2 End

        LOG(0,"Backlight[High=0x%x, Middle=0x%x, Low=0x%x]\n",
               prTbl->u1BacklightHigh, prTbl->u1BacklightMiddle,
               prTbl->u1BacklightLow);
        LOG(0,"DimFreq60Hz=%d, DimFreq50Hz=%d"
               "\n",
               prTbl->u2DimmingFrequency60Hz, prTbl->u2DimmingFrequency50Hz
               );
		if (SUPPORT_PANEL_48HZ)
		{
			LOG(0,"DimFreq48Hz=%ld\n", PANEL_GetDimmingFrequency48Hz());
		}
        LOG(0,"Delay[LvdsOn=%d0, BacklightOn=%d0, BacklightOff=%d0, LvdsOff=%d0]\n",
               prTbl->u1LvdsOnDalay, prTbl->u1BacklightOnDelay,
               prTbl->u1BacklightOffDelay, prTbl->u1LvdsOffDalay);
        LOG(0,"MaxOverscan=%d\n", prTbl->u2MaxOverscan);
    }
#ifdef CC_S_PLATFORM
	if (DRVCUST_PanelGet(ePanelFlashTableSize) > 0)
	{
                #ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
		LOG(0,"\nCurrent flash panel setting is %s\n", FlashPanel_GetIDString());
                #endif
	}
	else
#else
	{
    	LOG(0,"\nCurrent panel setting is %s\n", GetCurrentPanelName());
	}
#endif
    LOG(0,"Backlight gpio=%ld, turn on value=%ld, ",
           DRVCUST_PanelGet(eBackLightGpio), DRVCUST_PanelGet(eBackLightOnVal));
    LOG(0,"LVDS gpio=%ld, turn on value=%ld\n",
           DRVCUST_PanelGet(ePanelPowerGpio), DRVCUST_PanelGet(ePanelPowerOnVal));
    LOG(0,"Pixel Shift=%d (%ld x %ld)\n", _fgPixelShiftEnable,
           PANEL_GetPanelWidth(), PANEL_GetPanelHeight());
#ifdef SUPPORT_PANEL_ERRORLIMIT_TABLE
	if (PANEL_GetErrorLimit() == 0xFFFFFFFF)
	{
		LOG(0,"No Error Limit in the ExtPnlTbl!\n");
	}
	else
	{
		LOG(0,"Error Limit in the ExtPnlTbl: 0x%lx\n", PANEL_GetErrorLimit());
	}
#endif

	if (!PANEL_GetPreEmphasisEn())
	{
		LOG(0,"VB1 pre-emphasis is turned off!\n");
	}
	else
	{
		LOG(0,"VB1 pre-emphasis ON: value=%d\n", PANEL_GetPreEmphasisVal());
	}

#ifdef SUPPORT_PANEL_STEP_LIMIT
	if (PANEL_GetStepLimitLevel() == 0xFF)
	{
		LOG(0,"No Step_Limit_level in the ExtPnlTbl!\n");
	}
	else
	{
		LOG(0,"Step_Limit_level in the ExtPnlTbl: 0x%lx\n", PANEL_GetStepLimitLevel());
	}
#endif

#ifdef CC_S_PLATFORM
#if defined(CC_PANEL_FROM_FLASH)
    {
	    LOG(0,"Dolby data from panel : \n");
	    LOG(0,"Min Target PQ V2 = %d, Max Target PQ V2 = %d\n",
		       FlashPanel_GetDVTargetMinPQv2(),FlashPanel_GetDVTargetMaxPQv2());
		LOG(0,"Rx/Ry = %d/%d, Gx/Gy = %d/%d, Bx/By = %d/%d\n",
			   FlashPanel_GetDVRx(),FlashPanel_GetDVRy(),
			   FlashPanel_GetDVGx(),FlashPanel_GetDVGy(),
			   FlashPanel_GetDVBx(),FlashPanel_GetDVBy());
	}
#endif
#endif

}


UINT32 PANEL_TranslateEepromToFlashIndex(UINT32 u4EepromIndex)
{
    UINT32 u4Size, u4FlashIndex;
    UINT32* pu4Array;

    u4Size = DRVCUST_PanelGet(ePanelFlashTableSize);
    if ((pu4Array = (UINT32*)(UPTR)DRVCUST_PanelGetUptr(ePanelEepromToFlashIndexMap)) !=  NULL)
    {
        for (u4FlashIndex = 0; u4FlashIndex < u4Size; u4FlashIndex++)
        {
            if (pu4Array[u4FlashIndex] == u4EepromIndex)
            {
                return u4FlashIndex;
            }
        }
        if (u4FlashIndex == u4Size)
        {
            return 0;
        }
    }
    return u4EepromIndex;
}

UINT32 PANEL_GetEepromPanelIndex(void)
{
    return _u4EepromPanelIndex;
}

#ifdef CC_ENABLE_MTK_MODEL_INDEX
// static variables 
static UINT32 _u4PanelIdFromModelIndex=0xFFFFFFFF;
static UINT16 _u4AQ_tableIndex=0;
static UINT16 _u4PQ_tableIndex=0;
static BOOL bIsmodelindex_init = FALSE;

void WriteModelIndex(UINT32 u4ModelIndex)
{
    UINT32 u4Value, i;
    QUERY_TYPE_T arKey[] = {eModelIndexOffset1, eModelIndexOffset2,
                            eModelIndexOffset3};
    UINT32 u4Size = sizeof(arKey) / sizeof(QUERY_TYPE_T);

    for (i = 0; i < u4Size; i++)
    {
        if (DRVCUST_PanelQuery(arKey[i], &u4Value) == 0)
        {
            if (EEPROM_Write((UINT64)u4Value, (UPTR)&u4ModelIndex, 1) != 0)
            {
                LOG(0, "WriteModelIndexToEeprom fail, eeprom addr=0x%x\n", u4Value);
            }
        }
    }

    bIsmodelindex_init = FALSE;
}

#define IS_MODEL_INDEX_VALID(x) ((x) != 0xFF)
#define MODEL_INVALID (0xFF)
static UINT32 u4FinalIndex = MODEL_INVALID;

UINT32 GetModelIndexFromEEPROM(void)
{
    UINT8 au1Index[] = {MODEL_INVALID, MODEL_INVALID, MODEL_INVALID};
    QUERY_TYPE_T arKey[] = {eModelIndexOffset1, eModelIndexOffset2,
                            eModelIndexOffset3};
    UINT32 u4Size = sizeof(arKey) / sizeof(QUERY_TYPE_T);
    UINT32 u4Value, u4ValidCounter = 0, i, j;
    INT32 i4Ret;

    if (!bIsmodelindex_init)
    {
        // read configuration from eeprom
        for (i = 0; i < u4Size; i++)
        {
            if (DRVCUST_PanelQuery(arKey[i], &u4Value) == 0)
            {
                LOG(3, "GetModelIndexFromEEPROM(): i=%d, EEPROM read offset 0x%x\n", i, u4Value);
                i4Ret = EEPROM_Read((UINT64)u4Value, (UPTR)&au1Index[i], 1);
                if ((i4Ret != 0) || IS_MODEL_INDEX_VALID(au1Index[i]))
                {
                    u4ValidCounter++;
                    LOG(3, "GetModelIndexFromEEPROM(): Got value 0x%x\n", au1Index[i]);
                }
                else
                {
                    au1Index[i] = MODEL_INVALID;            
                }
            }
        }

        // decide valid model index
        if (u4ValidCounter == 1)
        {
            for (i = 0; i < u4Size; i++)
            {
                if (au1Index[i] != MODEL_INVALID)
                {
                    u4FinalIndex = au1Index[i];
                    break;
                }
            }
        }
        else if (u4ValidCounter >= 2)
        {
            for (i = 0; i < u4Size; i++)
            {
                if (au1Index[i] == MODEL_INVALID)
                {
                    continue;
                }
                for (j = 0; j < u4Size; j++)
                {
                    if ((i != j) && (au1Index[i] == au1Index[j]))
                    {
                        u4FinalIndex = au1Index[i];
                        break;
                    }
                }
                if (u4FinalIndex != MODEL_INVALID)
                {
                    break;
                }
            }
        }
        else if (u4ValidCounter == 0)
        {
            u4FinalIndex = 0;
            WriteModelIndex (u4FinalIndex);
        }

        // Here, u4FinalIndex is the EEPROM panel id value.
        if (u4FinalIndex == MODEL_INVALID)
        {
            LOG(0, "Here, Model index is invalid, change to default 0\n");
            u4FinalIndex = 0;
        }    

        LOG(0, "GetModelIndexFromEEPROM(): return final index %d\n", u4FinalIndex);
        bIsmodelindex_init = TRUE;
        return u4FinalIndex;
    }
    else  // init ok , return modelindex directly
    {
        return u4FinalIndex;
    }
}

extern void SRMFBM_SetConf(UINT32 conf);
#ifdef CC_SET_TUNER_TYPE_BY_MODEL_INDEX
extern void TunerSelectType(UINT8 TunerType);
#endif
extern void vSetSuperFlipMirrorConfig(UINT8 u1SuperCfgOnOff, UINT8 u1SuperFlip, UINT8 u1SuperMirror);

void GetModelIndexSetDriverTypes(void)
{
    UINT32 u4ModelIndex;

    // Set driver types before they are initialized
    u4ModelIndex = GetModelIndexFromEEPROM();
    
#if !defined(CC_UBOOT) && !defined(CC_MTK_LOADER) && !defined(CC_MTK_PRELOADER)
    // Set FBM config
    LOG(3, "Set FBM config 0x%x\n", GetModelIndexFbmId(u4ModelIndex));
    SRMFBM_SetConf(GetModelIndexFbmId(u4ModelIndex));

    // Set Tuner type
    LOG(0,"Set tuner type 0x%x\n", GetModelIndexTunerId(u4ModelIndex));
    #ifdef CC_SET_TUNER_TYPE_BY_MODEL_INDEX
    TunerSelectType((UINT8)GetModelIndexTunerId(u4ModelIndex));
    #endif
#endif // !defined(CC_UBOOT) && !defined(CC_MTK_LOADER) && !defined(CC_MTK_PRELOADER)

#if !defined(CC_UBOOT) && !defined(CC_MTK_PRELOADER)

    _u4AQ_tableIndex = GetModelIndexAQId(u4ModelIndex);
    _u4PQ_tableIndex = GetModelIndexPQId(u4ModelIndex);

    // Set Panel
    LOG(3, "Set panel id %d\n", GetModelIndexPanelId(u4ModelIndex));
    _u4PanelIdFromModelIndex = GetModelIndexPanelId(u4ModelIndex);

    // Set Mirror/Flip  
    LOG(3, "Set mirror/flip %d\n", GetModelIndexMirrorFlipOpt(u4ModelIndex));
    vSetSuperFlipMirrorConfig(1, GetModelIndexMirrorFlipOpt(u4ModelIndex) & 0x1, 
                              (GetModelIndexMirrorFlipOpt(u4ModelIndex) & 0x2) >> 1);
#endif // !defined(CC_UBOOT) && !defined(CC_MTK_PRELOADER)

    return ;
}

UINT32 GetCurrentAQIndex(void)
{
    return _u4AQ_tableIndex;
}

UINT32 GetCurrentPQIndex(void)
{
    return _u4PQ_tableIndex;
}
#else // CC_ENABLE_MTK_MODEL_INDEX not defined

void GetModelIndexSetDriverTypes(void)
{
}
#endif // CC_ENABLE_MTK_MODEL_INDEX

//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------
 
void LoadPanelIndex(void)
{
    UINT8 au1Index[] = {PANEL_INVALID, PANEL_INVALID, PANEL_INVALID};
    QUERY_TYPE_T arKey[] = {ePanelIndexOffset1, ePanelIndexOffset2,
                            ePanelIndexOffset3};
    UINT32 u4Size = sizeof(arKey) / sizeof(QUERY_TYPE_T);
    UINT32 u4Value, u4ValidCounter = 0, i, j;
    UINT32 u4FinalIndex = PANEL_INVALID, i4Ret;
    UINT32 u4WriteIdxToEeprom = 0;
    static UINT8 _fgInit = 0 ;

    if (_fgInit)
    {
        //  LOG(0,"skip LoadPanelIndex\n");
        return  ;
    }
    _fgInit = 1 ;
    
#ifdef CC_ENABLE_MTK_MODEL_INDEX
    GetModelIndexSetDriverTypes();  // Get table for model index from EEPROM before selecting Panel
#endif
    if ((DRVCUST_PanelQuery(ePanelIndexFromEeprom, &u4Value) == 0) &&
        (u4Value == 1))
    {
        _fgPanelIdInEeprom = TRUE;

        // hack u4TotalNumber to pass IS_PANEL_INDEX_INVALID
        if (DRVCUST_PanelGet(ePanelFlashTableSize) > 0)
        {
            u4TotalNumber = 0xff;
        }

#ifdef CC_ENABLE_MTK_MODEL_INDEX
        // check whether panel id is set by model index
        if (_u4PanelIdFromModelIndex != 0xFFFFFFFF)
        {
            u4ValidCounter = u4Size;
            for (i = 0; i < u4Size; i++)
            {
                au1Index[i] = _u4PanelIdFromModelIndex;
            }
        }
        else
        {
#endif
            // read configuration from eeprom
            for (i = 0; i < u4Size; i++)
            {
                if (DRVCUST_PanelQuery(arKey[i], &u4Value) == 0)
                {
                    i4Ret = EEPROM_Read((UINT64)u4Value, (UPTR)&au1Index[i], 1);
                    if ((i4Ret != 0) || IS_PANEL_INDEX_INVALID(au1Index[i]))
                    {
                        au1Index[i] = PANEL_INVALID;
                    }
                    else
                    {
                        u4ValidCounter++;
                    }
                }
            }
#ifdef CC_ENABLE_MTK_MODEL_INDEX
        }
#endif // CC_ENABLE_MTK_MODEL_INDEX

        // decide valid panel index
        if (u4ValidCounter == 1)
        {
            for (i = 0; i < u4Size; i++)
            {
                if (au1Index[i] != PANEL_INVALID)
                {
                    u4FinalIndex = au1Index[i];
                    break;
                }
            }
        }
        else if (u4ValidCounter >= 2)
        {
            for (i = 0; i < u4Size; i++)
            {
                if (au1Index[i] == PANEL_INVALID)
                {
                    continue;
                }
                for (j = 0; j < u4Size; j++)
                {
                    if ((i != j) && (au1Index[i] == au1Index[j]))
                    {
                        u4FinalIndex = au1Index[i];
                        break;
                    }
                }
                if (u4FinalIndex != PANEL_INVALID)
                {
                    break;
                }
            }
        }

        // Here, u4FinalIndex is the EEPROM panel id value.
        // Check this is use gpio number.
#ifdef PANEL_INDEX_FLAG_OFFSET
        u4Value = 0;
        i4Ret = EEPROM_Read((UINT64)PANEL_INDEX_MAGIC, (UPTR)&u4Value, 1);
        if (i4Ret == 0)
        {
            if ((u4Value & 0xff) != 0x5a)
            {
                u4Value = 0;
                EEPROM_Write((UINT64)PANEL_INDEX_FLAG_OFFSET, (UPTR)&u4Value, 1);
                u4Value = 0x5a;
                EEPROM_Write((UINT64)PANEL_INDEX_MAGIC, (UPTR)&u4Value, 1);
            }
        }

        u4Value = 0;    // default flag is not in eeprom (gpio).
        i4Ret = EEPROM_Read((UINT64)PANEL_INDEX_FLAG_OFFSET, (UPTR)&u4Value, 1);
        if (i4Ret != 0) { u4FinalIndex = 0; } // if eeprom failed, force gpio directly.
        if (u4Value != 1) { u4FinalIndex = 0; } // if eeprom flag is not 1, force gpio directly.
#endif /* PANEL_INDEX_FLAG_OFFSET */
        {
            _u4EepromPanelIndex = u4FinalIndex;
            if (u4FinalIndex != PANEL_INVALID)
            {
                LOG(0, "Find panel index %ld from EEPROM\n", u4FinalIndex);

                // check if we need to write panel idx back to EEPROM
                for (i = 0; i < u4Size; i++)
                {
                    if (DRVCUST_PanelQuery(arKey[i], &u4Value) == 0)
                    {
                        if (au1Index[i] != (UINT8)u4FinalIndex)
                        {
                            u4WriteIdxToEeprom = 1;
                            LOG(0, "Recover panel index in EEPROM\n");
                        }
                    }
                }

                // 1. check if we need to load panel table from flash 
                // 2. check if we need to map EEPROM index to flash index
                // 3. Load panel table from flash
                LOG(0, "Panel Flash Table Size=%ld , >0 means using flash table\n",DRVCUST_PanelGet(ePanelFlashTableSize));
                if (DRVCUST_PanelGet(ePanelFlashTableSize) > 0)
                {
                    // if there is no mapping table, return the same index
                    // if can't find flash index from mapping table, return 0
                    u4FinalIndex = PANEL_TranslateEepromToFlashIndex(u4FinalIndex);
                    LOG(0, "Translate panel index to %ld\n", u4FinalIndex);

                    #ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
                    if (!LOAD_PANEL_FROM_FLASH_CUSTOM(LOAD_PANEL_FROM_FLASH_BY_ID, &u4FinalIndex))
                    {
                            LOG(0, "[CUSTOM]Load panel table from EEPROM failed\n");

                            // FIXME!
                            // FIXME!
                            // start self-diag.
                            SelectPanel(0);    

                    }
                    #else  // turnkey load panel table from flash
                    {
                        UINT32 offset = DRVCUST_PanelGet(ePanelFlashTableAddress)+
                        (u4FinalIndex * DRVCUST_PanelGet(ePanelFlashTableSize));
                        if (!_PanelLoadTableFromFlash(offset))
                        {
                            LOG(0, "Load panel table from EEPROM failed\n");
                            SelectPanel(PANEL_INVALID);
                        }
                    }
                    #endif
                }
                else
                {
                    if (u4FinalIndex >= PANEL_TOTAL_NUMBER)
                    {
                        LOG(0, "Panel index loaded from EEPROM is out of panel table size\n");
                        u4FinalIndex = PANEL_INVALID;
                    }
                    SelectPanel(u4FinalIndex);
                }
            }
            else
            {
                LOG(0, "No valid index found from EEPROM\n");
                SelectPanel(PANEL_INVALID);
            }
            if (u4WriteIdxToEeprom)
            {
                WritePanelIndexToEeprom(_u4EepromPanelIndex);
            }
            _fgPanelIdInEeprom = TRUE;
        }
    }
    else if ((u4Value = DRVCUST_PanelGet(ePanelIndexFromGpioNum)) > 0)
    {
        UINT32* pu4Array = (UINT32*)(UPTR)DRVCUST_PanelGetUptr(ePanelIndexFromGpioIdx);
        u4FinalIndex = 0;
        for (i = 0; i < u4Value; i++)
        {
            u4FinalIndex <<= 1;
            u4FinalIndex |= GPIO_Input(pu4Array[i]);
            //LOG(0,"gpio[%d]=%d, u4FinalIndex=%d\n", i, pu4Array[i], u4FinalIndex);
        }
        pu4Array = (UINT32*)(UPTR)DRVCUST_PanelGetUptr(ePanelIndexFromGpioMap);
        u4FinalIndex = pu4Array[u4FinalIndex];
        if (IS_PANEL_INDEX_INVALID(u4FinalIndex))
        {
            LOG(0, "No valid index found from GPIO\n");
            SelectPanel(PANEL_INVALID);
        }
        else
        {
            SelectPanel(u4FinalIndex);
            LOG(0, "Find panel index %ld(%s) from GPIO\n",
                   u4FinalIndex, GetCurrentPanelName());
        }
        _fgPanelIdInEeprom = FALSE;
    }
    else
    {
        // use compile time defined panel index
        SelectPanel(PANEL_INVALID);
        _fgPanelIdInEeprom = FALSE;
    }
}


//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------

void WritePanelIndexToEeprom(UINT32 u4PanelIndex)
{
    UINT32 u4Value, i;
    QUERY_TYPE_T arKey[] = {ePanelIndexOffset1, ePanelIndexOffset2,
                            ePanelIndexOffset3};
    UINT32 u4Size = sizeof(arKey) / sizeof(QUERY_TYPE_T);

    if ((DRVCUST_PanelQuery(ePanelIndexFromEeprom, &u4Value) == 0) &&
        (u4Value == 1))
    {
        for (i = 0; i < u4Size; i++)
        {
            if (DRVCUST_PanelQuery(arKey[i], &u4Value) == 0)
            {
                if (EEPROM_Write((UINT64)u4Value, (unsigned long)&u4PanelIndex, 1) != 0)
                {
                    LOG(3, "WritePanelIndexToEeprom fail, eeprom addr=0x%lx\n",
                           u4Value);
                }
            }
        }
    }
}


//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------

UINT32 PANEL_GetBacklightHigh(void)
{
    UINT32 value;
    if (DRVCUST_PanelQuery(eBacklightHigh, &value) == 0)
    {
        return value;
    }

    return _prPanelAttribute->u1BacklightHigh;
}


//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------

UINT32 PANEL_GetBacklightMiddle(void)
{
    UINT32 value;
    if (DRVCUST_PanelQuery(eBacklightMiddle, &value) == 0)
    {
        return value;
    }
    return _prPanelAttribute->u1BacklightMiddle;
}


//-----------------------------------------------------------------------------
/** Brief
 *  @param
 *  @return
 */
//-----------------------------------------------------------------------------

UINT32 PANEL_GetBacklightLow(void)
{
    UINT32 value;
    if (DRVCUST_PanelQuery(eBacklightLow, &value) == 0)
    {
        return value;
    }
    return _prPanelAttribute->u1BacklightLow;
}

#if SCALER_PSCAN_DISPMODE_MIN_VTOTAL_OFFSET 
UINT32 PANEL_GetVTotal60Hz(void)
{
    if(_prPanelAttribute->u2VTotal60Hz 
        < (PANEL_GetPanelHeight() + SCALER_PSCAN_DISPMODE_MIN_VTOTAL_OFFSET))
    {
        return (PANEL_GetPanelHeight() + SCALER_PSCAN_DISPMODE_MIN_VTOTAL_OFFSET);
    }
    else
    {
        return _prPanelAttribute->u2VTotal60Hz;        
    }
}

UINT32 PANEL_GetPixelClk60Hz(void)
{
    UINT32 u4Clk;
    UINT32 u4VTotal;
    UINT32 u4HTotal;
    
    u4VTotal = PANEL_GetVTotal60Hz();
    u4HTotal = PANEL_GetHTotal60Hz();
    
    if((_prPanelAttribute->u2VTotal60Hz) < u4VTotal)
    {
        u4Clk = u4HTotal * u4VTotal * 60;
        if (fgIsSupport120HzPanel())
        {
            u4Clk <<= 1;
        }
    }
    else
    {
        u4Clk = _prPanelAttribute->u4PixelClk60Hz;
    }
    
    return u4Clk;
}

UINT32 PANEL_GetVTotal50Hz(void)
{
    if(_prPanelAttribute->u2VTotal50Hz 
        < (PANEL_GetPanelHeight() + SCALER_PSCAN_DISPMODE_MIN_VTOTAL_OFFSET))
    {
        return (PANEL_GetPanelHeight() + SCALER_PSCAN_DISPMODE_MIN_VTOTAL_OFFSET);
    }
    else
    {
        return _prPanelAttribute->u2VTotal50Hz;        
    }
}

UINT32 PANEL_GetPixelClk50Hz(void)
{
    UINT32 u4Clk;
    UINT32 u4VTotal;
    UINT32 u4HTotal;
    
    u4VTotal = PANEL_GetVTotal50Hz();
    u4HTotal = PANEL_GetHTotal50Hz();
    
    if((_prPanelAttribute->u2VTotal50Hz) < u4VTotal)
    {
        u4Clk = u4HTotal * u4VTotal * 50;
        if (fgIsSupport120HzPanel())
        {
            u4Clk <<= 1;
        }
    }
    else
    {
        u4Clk = _prPanelAttribute->u4PixelClk50Hz;
    }
    
    return u4Clk;
}
#endif

UINT32 PANEL_GetHSyncLen60Hz(void)
{
    UINT32 u4Len = 0;

#if 0
    if (_fgPixelShiftEnable)
    {
        // leave right mask as (PIXEL_SHIFT_H_MAX + 1) - _i4HPixelShift
        u4Len = (PANEL_GetHTotal60Hz() - PANEL_GetPanelWidth()) -
                ((PIXEL_SHIFT_H_MAX + 1) - _i4HPixelShift);
    }
    else
    {
        // leave right mask as PIXEL_SHIFT_H_MAX*2 + 1
        u4Len = (PANEL_GetHTotal60Hz() - PANEL_GetPanelWidth()) -
                (PIXEL_SHIFT_H_MAX * 2 + 1);
    }
#else
//    u4Len = (PANEL_GetHTotal60Hz() - _prPanelAttribute->u2PanelWidth) - (PIXEL_SHIFT_H_MAX * 2 + RIGHT_MASK_TYPI);
    u4Len = (PANEL_GetHTotal60Hz() - _prPanelAttribute->u2PanelWidth) - (PIXEL_SHIFT_H_MAX * 2);
#endif

    // protect overflow
    return (u4Len > 2047)?2047:u4Len; // 5360B is 511.
//    return (u4Len > 511)?511:u4Len;
}

UINT32 PANEL_GetHSyncLen50Hz(void)
{
    UINT32 u4Len = 0;

#if 0
    if (_fgPixelShiftEnable)
    {
        // leave right mask as (PIXEL_SHIFT_H_MAX + 1) - _i4HPixelShift
        u4Len = (PANEL_GetHTotal50Hz() - PANEL_GetPanelWidth()) -
                ((PIXEL_SHIFT_H_MAX + 1) - _i4HPixelShift);
    }
    else
    {
        // leave right mask as PIXEL_SHIFT_H_MAX*2 + 1
        u4Len = (PANEL_GetHTotal50Hz() - PANEL_GetPanelWidth()) -
                (PIXEL_SHIFT_H_MAX * 2 + 1);
    }
#else
//    u4Len = (PANEL_GetHTotal50Hz() - _prPanelAttribute->u2PanelWidth) - (PIXEL_SHIFT_H_MAX * 2 + RIGHT_MASK_50HZ);
    u4Len = (PANEL_GetHTotal50Hz() - _prPanelAttribute->u2PanelWidth) - (PIXEL_SHIFT_H_MAX * 2);
#endif

    // protect overflow
//    return (u4Len > 2047)?2047:u4Len; // 5360B is 511.
    //return (u4Len > 511)?511:u4Len;
    return (u4Len > 2047)?2047:u4Len; //5387 is 11 bits
}

//#ifndef SUPPORT_PANEL_CUSTOMER_SPEC
UINT32 PANEL_GetHPosition60Hz(void)
{
    if (_fgPixelShiftEnable)
    {
        return (UINT32)((INT32)(_prPanelAttribute->u2HPosition + PIXEL_SHIFT_H_MAX) + (_i4HPixelShift));
    }
    else
    {
        return _prPanelAttribute->u2HPosition;
    }
}

UINT32 PANEL_GetHPosition50Hz(void)
{
    return ((PANEL_GetHPosition60Hz() + PANEL_GetHTotal50Hz()) - PANEL_GetHTotal60Hz());
}

UINT32 PANEL_GetVPosition(void)
{
    if (_fgPixelShiftEnable)
    {
        return (UINT32)((INT32)(_prPanelAttribute->u2VPosition + PIXEL_SHIFT_V_MAX) + _i4VPixelShift);
    }
    else
    {
        return _prPanelAttribute->u2VPosition;
    }
}
//#endif  //SUPPORT_PANEL_CUSTOMER_SPEC

UINT32 PANEL_GetPanelWidth(void)
{
#if 1 // customers' spec
    return _prPanelAttribute->u2PanelWidth + (PIXEL_SHIFT_H_MAX * 2);
#else
    if (_fgPixelShiftEnable)
    {
        return _prPanelAttribute->u2PanelWidth + (PIXEL_SHIFT_H_MAX * 2);
    }
    else
    {
        return _prPanelAttribute->u2PanelWidth;
    }
#endif
}

UINT32 PANEL_GetPanelHeight(void)
{
#if 1 // customers' spec
    return _prPanelAttribute->u2PanelHeight + (PIXEL_SHIFT_V_MAX * 2);
#else
    if (_fgPixelShiftEnable)
    {
        return _prPanelAttribute->u2PanelHeight + (PIXEL_SHIFT_V_MAX * 2);
    }
    else
    {
        return _prPanelAttribute->u2PanelHeight;
    }
#endif
}

UINT32 PANEL_GetCurrentPanelWidthCM(void)
{
    UINT32 u2Value;
#ifndef CC_PANEL_FROM_FLASH
	UINT32 u4ExtIdx;
#endif

	u2Value = 0;

#ifdef SUPPORT_PANEL_SIZE_CM
#ifdef CC_PANEL_FROM_FLASH
	#ifdef CC_S_PLATFORM	
	u2Value = _arPanelAttributeExt[0].u2PanleWidth;
	#else
	// u2Value should be get from the flash panel table.
	#endif
#else
    u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx < EXT_PANEL_INDEX_INVALID)
    {   
        u2Value = (UINT32)_arPanelAttributeExt[u4ExtIdx].u2PanleWidth;
    }
    else
    {
		u2Value = 100;
	}	
#endif
#endif 

	return u2Value;
}

UINT32 PANEL_GetCurrentPanelHeightCM(void)
{
    UINT32 u2Value;
#ifndef CC_PANEL_FROM_FLASH
	UINT32 u4ExtIdx;
#endif

	u2Value = 0;
	
#ifdef SUPPORT_PANEL_SIZE_CM
#ifdef CC_PANEL_FROM_FLASH
	#ifdef CC_S_PLATFORM
	u2Value = _arPanelAttributeExt[0].u2PanleHeight;
	#else
	// u2Value should be get from the flash panel table.
	#endif
#else
  u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx < EXT_PANEL_INDEX_INVALID)
    {   
        u2Value = (UINT32)_arPanelAttributeExt[u4ExtIdx].u2PanleHeight;
    }
    else
	{
		u2Value = 100;
	}
#endif
#endif    

	return u2Value;
}

UINT8 PANEL_Get4kbeRstPanelOnWait(void)
{
    UINT8 u1Value;
    u1Value = 0;    // default value.

#ifdef SUPPORT_PANEL_4KBERST_PANELON_WAIT
#ifdef CC_PANEL_FROM_FLASH
    u1Value = _arPanelAttributeExt[0].u14kbeRstPanelOnWait;
#else
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx < EXT_PANEL_INDEX_INVALID)
    {
        u1Value = _arPanelAttributeExt[u4ExtIdx].u14kbeRstPanelOnWait;
    }
#endif
#endif
    return u1Value;
}

UINT8 PANEL_GetTconOnCellWait(void)
{
    UINT8 u1Value;
    u1Value = 0;    // default value.
#ifdef SUPPORT_PANEL_TCONON_CELL_WAIT
#ifdef CC_PANEL_FROM_FLASH
    u1Value = _arPanelAttributeExt[0].u1TconOnCellWait;
#else
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx < EXT_PANEL_INDEX_INVALID)
    {
        u1Value = _arPanelAttributeExt[u4ExtIdx].u1TconOnCellWait;
    }
#endif
#endif
    return u1Value;
}

UINT32 PANEL_GetPanelPhysicalWidth(void)
{
    return PANEL_GetCurrentPanelWidthCM();
}

UINT32 PANEL_GetPanelPhysicalHeight(void)
{
    return PANEL_GetCurrentPanelHeightCM();
}

UINT32 PANEL_GetPixelShiftHMax(void)
{
    UINT32 u4Value;
    if (DRVCUST_PanelQuery(ePanelPixelShiftHMax, &u4Value) != 0)
    {
        u4Value = 0;
    }
    return u4Value;
}

UINT32 PANEL_GetPixelShiftVMax(void)
{
    UINT32 u4Value;
    if (DRVCUST_PanelQuery(ePanelPixelShiftVMax, &u4Value) != 0)
    {
        u4Value = 0;
    }
    return u4Value;
}

void PANEL_SetPixelShift(BOOL fgEnable, INT32 i4HPixelShift, INT32 i4VPixelShift)
{
    _fgPixelShiftEnable = fgEnable;
    _i4HPixelShift = i4HPixelShift;
    _i4VPixelShift = i4VPixelShift;
}

BOOL PANEL_IsPixelShift(void)
{
    return _fgPixelShiftEnable;
}

INT32 PANEL_GetPixelShift_H(void)
{
    return _i4HPixelShift;
}

INT32 PANEL_GetPixelShift_V(void)
{
    return _i4VPixelShift;
}

CHAR * PANEL_GetVersion(void)
{
    #ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
    return FlashPanel_GetVersion();
    #else
    return "Unknow";
    #endif
}

UINT32 PANEL_GetSpreadSpectrum(UINT32 *pu4Freq, UINT32 *pu4Permillage)
{
    if ((pu4Freq == NULL) || (pu4Permillage == NULL))
    {
        return 1;
    }
    #ifdef SUPPORT_PANEL_SS
    {
        UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
        if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
        {           
            *pu4Freq = 30000;
            *pu4Permillage = 0; 
            return 1;
        }
        *pu4Freq = _arPanelAttributeExt[u4ExtIdx].u4SSFreq;
        *pu4Permillage = (UINT32)_arPanelAttributeExt[u4ExtIdx].u1SSPermillage;
    }
    #else
    *pu4Freq = 30000;
    #ifdef CC_MTK_LOADER
    *pu4Permillage = 0;
    #else
    *pu4Permillage = DRVCUST_OptGet(eSpreadSpectrumPermillage);
    #endif
    #endif
    return 0;
}

UINT32 PANEL_GetDither(void)
{
    #ifdef SUPPORT_PANEL_DITHER
    {
        UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
        if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
        {   
            return 0xffffffff;
        }
        return (UINT32)_arPanelAttributeExt[u4ExtIdx].u4Dither;
    }
    #else
    return 0xffffffff;
    #endif
}

UINT32 PANEL_GetDrivingCurrent(void)
{
    UINT32 u4Value;
    #ifdef SUPPORT_PANEL_DRIVING
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx < EXT_PANEL_INDEX_INVALID)
    {   
        u4Value = (UINT32)_arPanelAttributeExt[u4ExtIdx].u1DrivingCurrent;
    }
    else
    #endif
    if (DRVCUST_PanelQuery(eLvdsDrivingCurrent, &u4Value) == -1)
    {
        u4Value = 0xffffffff;
    }
    return u4Value;
}

UINT16 PANEL_Get3DPixelSize(void)
{
    UINT32 u4Value;
    #ifdef SUPPORT_PANEL_3D_PIXEL_SIZE
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx < EXT_PANEL_INDEX_INVALID)
    {   
        u4Value = (UINT32)_arPanelAttributeExt[u4ExtIdx].u2PixelSize;
    }
    else
    #endif
    {
        u4Value = 320; // Pixel Size = 0.320 mm = 320 um
    }
    return u4Value;
}

UINT32 Panel_GetAQIndex(UINT32 u4Idx)
{
    #ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
    return FlashPanel_GetAQIndex(u4Idx);
    #else
    return 0;
    #endif
}

UINT32 Panel_GetPQIndex(UINT32 u4Idx)
{
    #ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
    return FlashPanel_GetPQIndex(u4Idx);
    #else
    return 0;
    #endif
}


// ------------------------------------------------------------------
//  Optional function
// ------------------------------------------------------------------
#if defined(SUPPORT_PANEL_CUSTOMER_SPEC) || defined(SUPPORT_PANEL_SS) || defined(SUPPORT_PANEL_DITHER) || defined(SUPPORT_PANEL_DRIVING)|| defined(SUPPORT_PANEL_ERRORLIMIT_TABLE)|| defined(SUPPORT_PANEL_3D_PIXEL_SIZE) || defined(SUPPORT_PANEL_SCAN_PWM)|| defined(SUPPORT_PANEL_PRE_EMPHASIS) || defined(SUPPORT_PANEL_SIZE_CM)
static UINT32 PANEL_GetExtAttributeIndex(void)
{
    UINT32 u4ExtIdx = 0;
	UINT32 i ;

    if (DRVCUST_PanelGet(ePanelFlashTableSize) > 0)
    {   // load panel table from flash
        u4ExtIdx = 0;
    }
    else
    {
        u4ExtIdx = EXT_PANEL_INDEX_INVALID;
        for(i=0 ; i < sizeof(_arPanelAttributeExt)/sizeof(PANEL_ATTRIBUTE_EXT_T); i++)
        {
            if(GetCurrentPanelIndex() == _arPanelAttributeExt[i].u4PanelIndex)
            {
                u4ExtIdx = i;
                break;
            }
        }
    }
    return u4ExtIdx;
}


UINT32 PANEL_IsSupportExtAttribute(void)
{
    if(PANEL_GetExtAttributeIndex() >= EXT_PANEL_INDEX_INVALID)
    {
        return 0; 
    }
    return 1;
}

#endif

UINT32 PANEL_GetPixelClk48Hz(void)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    UINT32 u4Clk;
#if SCALER_PSCAN_DISPMODE_MIN_VTOTAL_OFFSET 
    UINT32 u4VTotal;
#endif    
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return PANEL_GetPixelClk60Hz();
    }

#if SCALER_PSCAN_DISPMODE_MIN_VTOTAL_OFFSET 
    u4VTotal = PANEL_GetVTotal48Hz();
    
    if(_arPanelAttributeExt[u4ExtIdx].u2VTotal48Hz < u4VTotal)
    {
        u4Clk = PANEL_GetHTotal48Hz() * u4VTotal * 48;
        if (fgIsSupport120HzPanel())
        {
            u4Clk <<= 1;
        }
    }
    else
#endif
    {
        u4Clk = _arPanelAttributeExt[u4ExtIdx].u4PixelClk48Hz;
    }
    
    return u4Clk;
}

UINT32 PANEL_GetHTotal48Hz(void)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return PANEL_GetHTotal60Hz();
    }
    return _arPanelAttributeExt[u4ExtIdx].u2HTotal48Hz;
}

UINT32 PANEL_GetVTotal48Hz(void)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return PANEL_GetVTotal60Hz();
    }
#if SCALER_PSCAN_DISPMODE_MIN_VTOTAL_OFFSET 
    if(_arPanelAttributeExt[u4ExtIdx].u2VTotal48Hz 
        < (PANEL_GetPanelHeight() + SCALER_PSCAN_DISPMODE_MIN_VTOTAL_OFFSET))
    {
        return (PANEL_GetPanelHeight() + SCALER_PSCAN_DISPMODE_MIN_VTOTAL_OFFSET);
    }
    else
#endif
    {
        return _arPanelAttributeExt[u4ExtIdx].u2VTotal48Hz;
    }
}

UINT32 PANEL_GetHSyncLen48Hz(void)
{
    UINT32 u4Len;
    u4Len = (PANEL_GetHTotal48Hz() - PANEL_GetPanelWidth());

    // protect overflow
    return (u4Len > 2047)?2047:u4Len;
}

UINT32 PANEL_GetDimmingFrequency48Hz(void)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return PANEL_GetDimmingFrequency60Hz();
    }
    return (UINT32)_arPanelAttributeExt[u4ExtIdx].u2DimmingFrequency48Hz;
}

void PANEL_SetPixelClk48Hz(UINT32 u4Value)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return ;
    }
    _arPanelAttributeExt[u4ExtIdx].u4PixelClk48Hz = u4Value;
    return;
}

void PANEL_SetHTotal48Hz(UINT32 u4Value)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return;
    }
    _arPanelAttributeExt[u4ExtIdx].u2HTotal48Hz = (UINT16)u4Value;
    return;
}

void PANEL_SetVTotal48Hz(UINT32 u4Value)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return;
    }
    _arPanelAttributeExt[u4ExtIdx].u2VTotal48Hz = (UINT16)u4Value;
    return;
}
UINT32 PANEL_GetHPosition48Hz(void)
{
    return ((PANEL_GetHPosition60Hz() + PANEL_GetHTotal48Hz()) - PANEL_GetHTotal60Hz());
}

#ifdef SUPPORT_PANEL_CUSTOMER_SPEC
INT32 PANEL_GetHPositionByTiming(UINT8 bDclkType)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if ((u4ExtIdx >= EXT_PANEL_INDEX_INVALID) || (bDclkType >= 3))
    {
    	if (bDclkType==0 && SUPPORT_PANEL_48HZ)
		return PANEL_GetHPosition48Hz();
    	else if (bDclkType==1)
		return PANEL_GetHPosition50Hz();
		else	
        return PANEL_GetHPosition60Hz();
    }
    return (_arPanelAttributeExt[u4ExtIdx].u2HFrontPorch[bDclkType]+0x800);
}

INT32 PANEL_GetVPositionByTiming(UINT8 bDclkType)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    UINT16 u2VSyncWidth;
    UINT16 u2VBackPorch;
    UINT16 u2VSyncDelSel;

    if ((u4ExtIdx >= EXT_PANEL_INDEX_INVALID) || (bDclkType >= 3))
    {
        return PANEL_GetVPosition();
    }
    
    u2VSyncWidth = _arPanelAttributeExt[u4ExtIdx].u1VSyncWidth[bDclkType];
    u2VBackPorch = _arPanelAttributeExt[u4ExtIdx].u2VbackPorch[bDclkType];
    u2VSyncDelSel =5;

#if 0//CC_SCPOS_BOTTOM_MASK_BIT_WA
    #ifndef CC_5391_LOADER
    return (INT32)(0x400 -u2VSyncWidth -u2VBackPorch + u2BottomMaskToTop +u2VSyncDelSel);
    #else
    return (INT32)(0x400 -u2VSyncWidth -u2VBackPorch +u2VSyncDelSel);
    #endif
#else
    return (INT32)(0x400 -u2VSyncWidth -u2VBackPorch +u2VSyncDelSel);
#endif
}

UINT32 PANEL_GetHSyncWidthByTiming(UINT8 bDclkType)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return PANEL_GetHSyncWidth();
    }
	else if (bDclkType >= 3)
	{
		return _arPanelAttributeExt[u4ExtIdx].u1HSyncWidth[SV_DCLK_60HZ];
	}
    return _arPanelAttributeExt[u4ExtIdx].u1HSyncWidth[bDclkType];
}

UINT32 PANEL_GetVSyncWidthByTiming(UINT8 bDclkType)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return PANEL_GetVSyncWidth();
    }
	else if (bDclkType >= 3)
	{
		return _arPanelAttributeExt[u4ExtIdx].u1VSyncWidth[SV_DCLK_60HZ];
	}
    return _arPanelAttributeExt[u4ExtIdx].u1VSyncWidth[bDclkType];
}

void PANEL_SetVSyncWidthByTiming(UINT8 bDclkType, UINT16 u2VSyncWd)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if ((u4ExtIdx >= EXT_PANEL_INDEX_INVALID) || (bDclkType >= 3))
    {
        return;
    }
    _arPanelAttributeExt[u4ExtIdx].u1VSyncWidth[bDclkType]=u2VSyncWd;
}

void PANEL_SetHSyncWidthByTiming(UINT8 bDclkType, UINT8 u1HSyncWd)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if ((u4ExtIdx >= EXT_PANEL_INDEX_INVALID) || (bDclkType >= 3))
    {
        return;
    }
    _arPanelAttributeExt[u4ExtIdx].u1HSyncWidth[bDclkType]=u1HSyncWd;
}

UINT32 PANEL_GetVSyncBpByTiming(UINT8 bDclkType)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return (V_POS < (0x400 - VS_WIDTH + 6))?((0x400 - V_POS - VS_WIDTH + 6)):(0);
    }
	else if (bDclkType >= 3)
	{
		return _arPanelAttributeExt[u4ExtIdx].u2VbackPorch[SV_DCLK_60HZ];
	}
    return _arPanelAttributeExt[u4ExtIdx].u2VbackPorch[bDclkType];
}

void PANEL_SetVSyncBpByTiming(UINT8 bDclkType, UINT16 u2VSyncFP)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if ((u4ExtIdx >= EXT_PANEL_INDEX_INVALID) || (bDclkType >= 3))
    {
        return;
    }
    _arPanelAttributeExt[u4ExtIdx].u2VbackPorch[bDclkType]=u2VSyncFP;
}

UINT32 PANEL_GetHSyncFpByTiming(UINT8 bDclkType)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
		return (H_POS_60HZ > 0x800)?(H_POS_60HZ-0x800):(0);
    }
	else if (bDclkType >= 3)
	{
		return _arPanelAttributeExt[u4ExtIdx].u2HFrontPorch[SV_DCLK_60HZ];
	}
    return _arPanelAttributeExt[u4ExtIdx].u2HFrontPorch[bDclkType];
}

void PANEL_SetHSyncFpByTiming(UINT8 bDclkType, UINT16 u2HSyncFP)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if ((u4ExtIdx >= EXT_PANEL_INDEX_INVALID) || (bDclkType >= 3))
    {
        return;
    }
    _arPanelAttributeExt[u4ExtIdx].u2HFrontPorch[bDclkType]=u2HSyncFP;
}

UINT32 PANEL_GetHSyncPolarity(void)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return HSYNC_LOW;
    }
    return _arPanelAttributeExt[u4ExtIdx].u1HSyncPolarity;
}

UINT32 PANEL_GetVSyncPolarity(void)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return VSYNC_LOW;
    }
    return _arPanelAttributeExt[u4ExtIdx].u1VSyncPolarity;
}

void PANEL_SetHSyncPolarity(UINT8 u1HsyncPol)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return;
    }
    _arPanelAttributeExt[u4ExtIdx].u1HSyncPolarity=u1HsyncPol;
}

void PANEL_SetVSyncPolarity(UINT8 u1VsyncPol)
{
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return;
    }
    _arPanelAttributeExt[u4ExtIdx].u1VSyncPolarity=u1VsyncPol;
}

/*
//return num*10; for 120Hz panel
UINT32 PANEL_GetFrameDelay(void)
{    
    return 0;
}*/
#endif //#SUPPORT_PANEL_CUSTOMER_SPEC

#ifdef SUPPORT_PANEL_ERRORLIMIT_TABLE
UINT32 PANEL_GetErrorLimit(void)
{
#ifdef CC_PANEL_FROM_FLASH
		return (UINT32)_arPanelAttributeExt[0].u4ErrorLimit;
#else
    UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();

    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return 0xFFFFFFFF;        
    }    
    return (UINT32)_arPanelAttributeExt[u4ExtIdx].u4ErrorLimit;
#endif
}
#endif

#ifdef SUPPORT_PANEL_SCAN_PWM
UINT32 PANEL_GetScanPWMStart(void)
{
	UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return (DEFAULT_SCAN_PWM_START);
    }
    return _arPanelAttributeExt[u4ExtIdx].u4ScanPWMStart;
}

UINT32 PANEL_GetScanPWMDuty(void)
{
	UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
    if (u4ExtIdx >= EXT_PANEL_INDEX_INVALID)
    {
        return (DEFAULT_SCAN_PWM_DUTY);
    }
    return _arPanelAttributeExt[u4ExtIdx].u4ScanPWMDuty;
}
#endif

UINT8 PANEL_GetPreEmphasisEn(void)
{
#ifdef SUPPORT_PANEL_PRE_EMPHASIS
	#ifdef CC_PANEL_FROM_FLASH
		#ifdef CC_S_PLATFORM
		return FlashPanel_GetPreEmphasisEn();
		#else
		// u1Val should be from the flash panel data.
		UINT8 u1Val;
		u1Val = 1;
		return (u1Val);
		#endif
	#else
		UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
	    if (u4ExtIdx < EXT_PANEL_INDEX_INVALID)
	    {
	    	return _arPanelAttributeExt[u4ExtIdx].u1PreEmpEn;
	    }
	    else

		{
			return (PANEL_PRE_EMPHASIS_EN);
		}
	#endif
#else
	return (PANEL_PRE_EMPHASIS_EN);
#endif
}

UINT8 PANEL_GetPreEmphasisVal(void)
{

#ifdef SUPPORT_PANEL_PRE_EMPHASIS
	#ifdef CC_PANEL_FROM_FLASH
		#ifdef CC_S_PLATFORM
		return FlashPanel_GetPreEmphasisVal();
		#else
		// u1Val should be from the flash panel data.
		UINT8 u1Val;
		u1Val = 1;
		return (u1Val);
		#endif
	#else
		UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
		if (u4ExtIdx < EXT_PANEL_INDEX_INVALID)
		{
			return _arPanelAttributeExt[u4ExtIdx].u1PreEmpVal;
		}
		else
		{
			return (PANEL_PRE_EMPHASIS_VAL);
		}
	#endif
#else
	return (PANEL_PRE_EMPHASIS_VAL);
#endif
}

#ifdef SUPPORT_PANEL_STEP_LIMIT
UINT8 PANEL_GetStepLimitLevel(void)
{
	#ifdef CC_PANEL_FROM_FLASH
	UINT8 u1Val;
	u1Val = DEFAULT_PANEL_STEP_LIMIT_LEVEL;
	return (u1Val);
	#else
	UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
	if (u4ExtIdx < EXT_PANEL_INDEX_INVALID)
	{
		return _arPanelAttributeExt[u4ExtIdx].u1StepLevel;
	}
	else
	{
		return (0xFF);
	}
	#endif
}

UINT8 PANEL_GetStepLimitEn(void)
{
	#ifdef CC_PANEL_FROM_FLASH
	UINT8 u1Val;
	u1Val = DEFAULT_ENABLE_STEP_LIMIT;
	return (u1Val);
	#else
	UINT32 u4ExtIdx = PANEL_GetExtAttributeIndex();
	if (u4ExtIdx < EXT_PANEL_INDEX_INVALID)
	{
		return _arPanelAttributeExt[u4ExtIdx].u1StepEn;
	}
	else
	{
		return (0xFF);
	}
	#endif
}
#endif

// ====== Local Dimming ============================

UINT32 PANEL_IsSupportLocalDimming(void)
{
    UINT32 u4PanelIdx;
    UINT32 i;

    u4PanelIdx = GetCurrentPanelIndex();

    for (i = 0; i < sizeof(_arPanelLDAttribute)/sizeof(PANEL_LOCAL_DIMMING_ATTRIBUTE_T); i++)
    {
        if (_arPanelLDAttribute[i].u4PanelIndex == u4PanelIdx)
        {
            return SV_TRUE;
        }
    }
    return SV_FALSE;
}


UINT32 PANEL_GetLocalDimmingParam(PANEL_LOCAL_DIMMING_ATTRIBUTE_T **pParam)
{
    UINT32 u4PanelIdx;
    UINT32 i;

    u4PanelIdx = GetCurrentPanelIndex();

    for (i = 0; i < sizeof(_arPanelLDAttribute)/sizeof(PANEL_LOCAL_DIMMING_ATTRIBUTE_T); i++)
    {
        if (_arPanelLDAttribute[i].u4PanelIndex == u4PanelIdx)
        {
            *pParam = &_arPanelLDAttribute[i];
            return SV_TRUE;
        }
    }
    *pParam = NULL;
    return SV_FALSE;
}

// ====== miniLVDS ============================
UINT32 PANEL_IsSupportMlvds(void)
{
    return ((PANEL_GetControlWord() & DISP_TYPE_MASK) == DISP_TYPE_MLVDS);
}


UINT32 PANEL_GetMlvdsParam(PANEL_MINILVDS_ATTRIBUTE_T **pParam)
{
    UINT32 u4PanelIdx;
    UINT32 i;

    if (DRVCUST_PanelGet(ePanelFlashTableSize) > 0)
    {   
        if(PANEL_IsSupportMlvds()) //Adam check
//        if((PANEL_GetControlWord() & DISP_TYPE_VB1) != 0) //Adam check
        {
            *pParam = &_arPanelMiniLVDSAttribute[0];
            return  SV_TRUE;
        }

    }
    else
    {
    u4PanelIdx = GetCurrentPanelIndex();

    for (i = 0; i < sizeof(_arPanelMiniLVDSAttribute)/sizeof(PANEL_MINILVDS_ATTRIBUTE_T); i++)
    {
        if (_arPanelMiniLVDSAttribute[i].u4PanelIndex == u4PanelIdx)
        {
            *pParam = &_arPanelMiniLVDSAttribute[i];
            return SV_TRUE;
        }
    }
    }
    *pParam = NULL;
    return SV_FALSE;
}

static UINT32 _u4ProtDisplayTypeMsk = 
#ifdef PANEL_DISPLAY_TYPE_ALLOWED_MASK
    PANEL_DISPLAY_TYPE_ALLOWED_MASK;
#else
    // defaultly set to lvds only mode
    (1<<PANEL_DISPLAY_TYPE_LVDS);
#endif

UINT32 PANEL_SetProtDisplayTypeMsk(UINT32 *u4ProtDisplayTypeMsk)
{
    if(u4ProtDisplayTypeMsk != NULL)
    {
        _u4ProtDisplayTypeMsk = *u4ProtDisplayTypeMsk; 
    }
    return _u4ProtDisplayTypeMsk;
}

// -- for multiple panel interface configuration --
UINT8 PANEL_IsSupportVb1(void)
{
    return ((PANEL_GetControlWord() & DISP_TYPE_MASK) == DISP_TYPE_VB1); 
}
UINT8 PANEL_IsSupportEpi(void)
{
    return ((PANEL_GetControlWord() & DISP_TYPE_MASK) == DISP_TYPE_EPI); 
}

UINT8 PANEL_IsSupport48Hz(void)
{
	if (PANEL_IsSupportExtAttribute() && IS_DISP_48HZ_TO_48HZ)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

#ifdef CC_PHP_SUPPORT
UINT32 GetPanel3DType(void)
{
	UINT32 ui4_id=0;
	switch (GetCurrentPanelIndex())
	{
	}
	return ui4_id;
}
#endif

UINT32 PANEL_IsUseScanPwm(void)
{
#ifdef CC_PHP_SUPPORT
    static BOOL isPanelIndexLoad = FALSE; 
    if(!isPanelIndexLoad)
    {
        LoadPanelIndex();
        isPanelIndexLoad = TRUE;
    }

    if(GetPanel3DType() == 1)
    {
        #ifndef CC_MTK_LOADER
        extern BOOL DRVCUST_IsScanPwmOn(void);
        if(DRVCUST_IsScanPwmOn())
        {
	        return 1;
	    }
	    else
        {
            return 0;
        }
        #else
            return 0;
        #endif
    }
#endif
#ifdef SUPPORT_PANEL_SCAN_PWM
	return 1;
#endif

    return 0;
}

UINT32 PANEL_GetDisplayType(void)
{
    UINT32 u4PanelDisplayType = PANEL_DISPLAY_TYPE_LVDS;

    if( PANEL_IsSupportVb1() )
    {
        // check if multiple panel interface is defined
        ASSERT(u4PanelDisplayType == PANEL_DISPLAY_TYPE_LVDS);

        u4PanelDisplayType = PANEL_DISPLAY_TYPE_VB1;
    }

    // set to allowed mode only if confirmed 
    if(0 == (_u4ProtDisplayTypeMsk & (1<<u4PanelDisplayType)))
    {
        return PANEL_DISPLAY_TYPE_MAX;
    } 

    return u4PanelDisplayType;
}

void PANEL_SetColorDepth(UINT8 u1BitRes)
{
    UINT32 u4ControlWord = PANEL_GetControlWord();

    /* clear the bits we used */
    u4ControlWord = u4ControlWord & (~DISP_BIT_MSK);

    if (u1BitRes == 0) // 8bit
    {
        u4ControlWord |= DISP_24BIT;   
    }
    else
    {
        u4ControlWord |= DISP_30BIT;   
    }
    PANEL_SetControlWord(u4ControlWord);
}

void PANEL_SetLvdsSelect(UINT8 u1Format)
{
    UINT32 u4ControlWord = PANEL_GetControlWord();

    if (u1Format == 0) // ns
    {
        u4ControlWord = (u4ControlWord & 0xFFFFFFFC) | LVDS_NS;
    }
    else if (u1Format == 1) // jeida
    {
        u4ControlWord = (u4ControlWord & 0xFFFFFFFC) | LVDS_JEIDA;
    }
	else
	{
        u4ControlWord = (u4ControlWord & 0xFFFFFFFC) | LVDS_SPECIAL_NS;
	}
	
    PANEL_SetControlWord(u4ControlWord);
//    vDrvLVDSConfig();
}

void PANEL_SetLvdsSwap(UINT8 u1Inverse)
{

    UINT32 u4ControlWord = PANEL_GetControlWord();

    u4ControlWord = u4ControlWord & (~LVDS_ODD_SW_ON);

    if (u1Inverse == 0)
    {
        u4ControlWord |= LVDS_ODD_SW_OFF;
    }
    else
    {
        u4ControlWord |= LVDS_ODD_SW_ON;
    }

    PANEL_SetControlWord(u4ControlWord);
	
}

void PANEL_SetLvdsPCBSwap(UINT8 u1Inverse)
{
	if(u1Inverse)
	fgLVDSPCBSwap = 1;	
	else
	fgLVDSPCBSwap = 0;			
}

void PANEL_SetLvdsPixel(UINT8 u1Mode)
{
    UINT32 u4ControlWord = PANEL_GetControlWord();
    
    /* clear the bits we used */
    u4ControlWord = u4ControlWord & (~(DUAL_PORT|FOUR_PORT));

    if (u1Mode == 0) // single
    {
        u4ControlWord = u4ControlWord | SINGLE_PORT;
        PANEL_SetVClkMax(78);
        PANEL_SetVClkMin(46);
    }
    else if(u1Mode == 1)// dual
    {
        u4ControlWord= u4ControlWord | DUAL_PORT;
		if (IS_PANEL_L12R12)
		{
        	PANEL_SetVClkMax(123);
        	PANEL_SetVClkMin(46);		
		}
		else
		{
			PANEL_SetVClkMax(78);
			PANEL_SetVClkMin(46);
		}
    }
    else
    {
        u4ControlWord= u4ControlWord | FOUR_PORT;
        PANEL_SetVClkMax(123);
        PANEL_SetVClkMin(46);
    }

    PANEL_SetControlWord(u4ControlWord);
}

void PANEL_SetResolution(UINT16 u2Width, UINT16 u2Height)
{
    PANEL_SetPanelWidth(u2Width);
    PANEL_SetPanelHeight(u2Height);
#ifndef CC_MT5893
#ifndef CC_MTK_LOADER  
	if (IS_PANEL_L12R12)
	{             
    	vDrvODInit();
	}
#endif
#endif
}

void PANEL_SetHTotalTyp(UINT16 u2HTotal)
{
	PANEL_SetHTotal60Hz(u2HTotal);
	PANEL_SetHTotal50Hz(u2HTotal);
	if (SUPPORT_PANEL_48HZ)
	{
		PANEL_SetHTotal48Hz(u2HTotal);
	}
	PANEL_SetHTotalMax(u2HTotal/10*12);
	PANEL_SetHTotalMin(u2HTotal/10*8);
}

void PANEL_SetVTotal(UINT16 u2VTotal48Hz, UINT16 u2VTotal50Hz, UINT16 u2VTotal60Hz)
{
    UINT8 u1MultiFrameRate;

	if (SUPPORT_PANEL_48HZ)
	{
		_prPanelAttributeExt->u2VTotal48Hz = u2VTotal48Hz;
	}
	PANEL_SetVTotal60Hz(u2VTotal60Hz);
	PANEL_SetVTotal50Hz(u2VTotal50Hz);
	PANEL_SetVTotalMax(u2VTotal48Hz/20*21);
	PANEL_SetVTotalMin(u2VTotal60Hz/10*8);

	if (IS_PANEL_L12R12)
	{
	    u1MultiFrameRate = 1;
	}
	else
	{
		u1MultiFrameRate = ((PANEL_GetControlWord() & FOUR_PORT)!=0)?(2):(1); 
	}

	// update pixel clock
	PANEL_SetPixelClk50Hz(PANEL_GetHTotal60Hz() * u2VTotal50Hz * 50 *u1MultiFrameRate);
	PANEL_SetPixelClk60Hz(PANEL_GetHTotal60Hz() * u2VTotal60Hz * 60 *u1MultiFrameRate);
	if (SUPPORT_PANEL_48HZ)
	{
		PANEL_SetPixelClk48Hz(PANEL_GetHTotal60Hz() * u2VTotal48Hz * 48 *u1MultiFrameRate);
	}
	//PANEL_SetPixelClkMax(PANEL_GetHTotal60Hz() * PANEL_GetVTotalMax()*60*u1MultiFrameRate);
	PANEL_SetPixelClkMax(PANEL_GetHTotal60Hz() * PANEL_GetVTotalMax()*48*u1MultiFrameRate);
	PANEL_SetPixelClkMin(PANEL_GetHTotal60Hz() * PANEL_GetVTotalMin()*48*u1MultiFrameRate);
}

void PANEL_SetVertSyncWidth(UINT8 u1Vsync48Hz, UINT8 u1Vsync50Hz, UINT8 u1Vsync60Hz)
{
#ifdef SUPPORT_PANEL_CUSTOMER_SPEC
    _prPanelAttributeExt->u1VSyncWidth[0] = u1Vsync48Hz;
    _prPanelAttributeExt->u1VSyncWidth[1] = u1Vsync50Hz;
    _prPanelAttributeExt->u1VSyncWidth[2] = u1Vsync60Hz;
#endif
}

void PANEL_SetVertBackPorch(UINT16 u2VbackPorch48Hz, UINT16 u2VbackPorch50Hz, UINT16 u2VbackPorch60Hz)
{
#ifdef SUPPORT_PANEL_CUSTOMER_SPEC
    _prPanelAttributeExt->u2VbackPorch[0] = u2VbackPorch48Hz;
    _prPanelAttributeExt->u2VbackPorch[1] = u2VbackPorch50Hz;
    _prPanelAttributeExt->u2VbackPorch[2] = u2VbackPorch60Hz;
#endif
}

void PANEL_SetHorizSyncWidth(UINT8 u1Hsync48Hz, UINT8 u1Hsync50Hz, UINT8 u1Hsync60Hz)
{
#ifdef SUPPORT_PANEL_CUSTOMER_SPEC
    _prPanelAttributeExt->u1HSyncWidth[0] = u1Hsync48Hz;
    _prPanelAttributeExt->u1HSyncWidth[1] = u1Hsync50Hz;
    _prPanelAttributeExt->u1HSyncWidth[2] = u1Hsync60Hz;
#endif
}

void PANEL_SetHorizBackPorch(UINT16 u2HbackPorch48Hz, UINT16 u2HbackPorch50Hz, UINT16 u2HbackPorch60Hz)
{
#ifdef SUPPORT_PANEL_CUSTOMER_SPEC
	if (SUPPORT_PANEL_48HZ)
	{
		_prPanelAttributeExt->u2HFrontPorch[0] = (UINT16)(HLEN_TOTAL_48HZ- wDISPLAY_WIDTH - u2HbackPorch48Hz - _prPanelAttributeExt->u1HSyncWidth[0]);
	}
	_prPanelAttributeExt->u2HFrontPorch[1] = (UINT16)(HLEN_TOTAL_50HZ- wDISPLAY_WIDTH - u2HbackPorch50Hz - _prPanelAttributeExt->u1HSyncWidth[1]);
	_prPanelAttributeExt->u2HFrontPorch[2] = (UINT16)(HLEN_TOTAL_TYPI- wDISPLAY_WIDTH - u2HbackPorch60Hz - _prPanelAttributeExt->u1HSyncWidth[2]);
#endif
}

#define BL_CTRL_OLED            (0x06)
BOOL PANEL_IsSupport_OLED(void)
{
#ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
    if (FlashPanel_GetControlWord3_BLCtrlIf() == BL_CTRL_OLED)
    {
        return TRUE;
    }
#endif
    return FALSE;
}

BOOL PANEL_IsSupport_DISP_4K2K_TYPE2(void)
{
#ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
	if (FlashPanel_GetControlWord3_BEType() == BE_TYPE_FRC_120HZ)
#else
	if ((PANEL_GetControlWord2() & SUPPORT_4K2K_TYPE_MASK) == DISP_4K2K_TYPE_2)
#endif
		return TRUE;
	else
		return FALSE;
}

BOOL PANEL_IsSupport_DISP_4K2K_TYPE3(void)
{
#ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
	if ((FlashPanel_GetControlWord3_BEType() == BE_TYPE_4KBE_120_240HZ)
         || (FlashPanel_GetControlWord3_BEType() == BE_TYPE_4KBE_120_120HZ)
         || (FlashPanel_GetControlWord3_BEType() == BE_TYPE_4KBE_8KBE)
         || (FlashPanel_GetControlWord3_BEType() == BE_TYPE_4KBE_60HZ))
#else
	if ((PANEL_GetControlWord2() & SUPPORT_4K2K_TYPE_MASK) == DISP_4K2K_TYPE_3)
#endif
		return TRUE;
	else
		return FALSE;
}

UINT8 PANEL_IsOn(void)
{
    UINT32 gpio, value;
    UINT32 u4BLControlIf = 0;

    #ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
    u4BLControlIf = FlashPanel_GetControlWord3_BLCtrlIf() >> 8;
    #endif

    /* OLED model(6) don't have BL_MUTE */
    if((u4BLControlIf != BL_CTRL_OLED) && (!_fgBackLightMuteOff))
    {
        if(DRVCUST_PanelQuery(eBackLightMuteGpio, &gpio) == 0 &&
           DRVCUST_PanelQuery(eBackLightMuteOnVal, &value) == 0)
        {
            if((GPIO_Enable(gpio, NULL) == 1) && (GPIO_Output(gpio, NULL) != value))
            {
                LOG(3, "[PNL_ON]panel backlight power is already on!\n");
                return 1;
            }
        }
    }
    if(!_fgPanelPower1On)
    {
        if(DRVCUST_PanelQuery(ePanelPower1Gpio, &gpio) == 0 &&
           DRVCUST_PanelQuery(ePanelPower1OnVal, &value) == 0)
        {
            if((GPIO_Enable(gpio, NULL) == 1) && (GPIO_Output(gpio, NULL) == value))
            {
                LOG(3, "[PNL_ON]panel power is already on!\n");
                return 1;
            }
        }
    }
    /* OLED model(6) has Panel Power On 2 */
    if((u4BLControlIf == BL_CTRL_OLED) && (!_fgPanelPower2On))
    {
        if(DRVCUST_PanelQuery(ePanelPower2Gpio, &gpio) == 0 &&
           DRVCUST_PanelQuery(ePanelPower2OnVal, &value) == 0)
        {
            if((GPIO_Enable(gpio, NULL) == 1) && (GPIO_Output(gpio, NULL) == value))
            {
                LOG(3, "[PNL_ON]panel power 2 is already on!\n");
                return 1;
            }
        }
    }

    return 0;
}

void PANEL_SetPanelPower1On(void)
{
    _fgPanelPower1On = TRUE;
}

void PANEL_SetPanelPower1Off(void)
{
    _fgPanelPower1On = FALSE;
}

void PANEL_SetPanelPower2On(void)
{
    _fgPanelPower2On = TRUE;
}

void PANEL_SetPanelPower2Off(void)
{
    _fgPanelPower2On = FALSE;
}

void PANEL_SetBackLightMuteOn(void)
{
    _fgBackLightMuteOff = FALSE;
}

void PANEL_SetBackLightMuteOff(void)
{
    _fgBackLightMuteOff = TRUE;
}

GRAPHMODE_ATTRIBUTE_T * VideoMode_GetAttributeByType(UINT32 u4Type)
{
    GRAPHMODE_ATTRIBUTE_T * prAttribute = NULL;
    UINT32 u4Index;
	UINT32 u4ChgType = ((u4Type == PANEL_TYPE_4K2K_60_SRS) || (u4Type == PANEL_TYPE_MAX))? PANEL_TYPE_4K2K_60 : u4Type;
    UINT32 u4RefIndex = GetCurrentPanelIndex() | PANEL_SetType(u4ChgType);

	#ifdef CC_PANEL_FROM_FLASH
		UINT32 u4MaxIndex=4;
	#else
    	UINT32 u4MaxIndex = sizeof(_arVideoModeAttribute)/sizeof(GRAPHMODE_ATTRIBUTE_T);
	#endif
	
    for (u4Index = 0 ; u4Index < u4MaxIndex; u4Index++)
    {
       #ifdef CC_PANEL_FROM_FLASH       
		   if (u4RefIndex == rVideo[u4Index].u4PanelIndex)
		   {
				LOG(0, "[S][Dynamic PNL] Find VideoModeAttribute[%ld]: PNL_Index=0x%lx\n", u4Index, _arVideoModeAttribute[u4Index].u4PanelIndex);
				prAttribute = &rVideo[u4Index];
				break;
		   }
	   #else
		   if (u4RefIndex == _arVideoModeAttribute[u4Index].u4PanelIndex)
	       {
	    	    LOG(0, "[Dynamic PNL] Find VideoModeAttribute[%ld]: PNL_Index=0x%lx\n", u4Index, _arVideoModeAttribute[u4Index].u4PanelIndex);
	            prAttribute = &_arVideoModeAttribute[u4Index];
	            break;
	       }
	   #endif
    }
    return prAttribute;
}

#if defined(SUPPORT_PANEL_GRAPH_MODE)
#ifndef CC_S_PLATFORM
static GRAPHMODE_ATTRIBUTE_T * _prGraphModeAttribute = &_arGraphModeAttribute[0];
static UINT32 u4PanelType = PANEL_TYPE_MAX;
#endif
GRAPHMODE_ATTRIBUTE_T * GraphMode_GetAttributeByType(UINT32 u4Type)
{
    GRAPHMODE_ATTRIBUTE_T * prAttribute = NULL;
    UINT32 u4Index;
    #ifndef CC_S_PLATFORM
    UINT32 u4RefIndex = u4GraphModeIndex | PANEL_SetType(u4Type);
    #else
    UINT32 u4RefIndex = GetCurrentPanelIndex() | PANEL_SetType(u4Type);
    #endif
#ifdef CC_PANEL_FROM_FLASH
		UINT32 u4MaxIndex=2;
#else
    UINT32 u4MaxIndex = sizeof(_arGraphModeAttribute)/sizeof(GRAPHMODE_ATTRIBUTE_T);
#endif

    for (u4Index = 0 ; u4Index < u4MaxIndex; u4Index++)
    {
		#ifdef CC_PANEL_FROM_FLASH		 
			if (u4RefIndex == rGraphic[u4Index].u4PanelIndex)
			{
				 LOG(0, "[S][Dynamic PNL] Find _arGraphModeAttribute[%d]: PNL_Index=0x%x\n", u4Index, _arGraphModeAttribute[u4Index].u4PanelIndex);
				 prAttribute = &rGraphic[u4Index];
				 break;
			}
		#else
	        if (u4RefIndex == _arGraphModeAttribute[u4Index].u4PanelIndex)
	        {
	            prAttribute = &_arGraphModeAttribute[u4Index];
	            break;
	        }
		#endif
    }
    return prAttribute;
}

void GraphMode_SetAttributeByType(UINT32 u4DstType, UINT32 u4SrcType)
{
    GRAPHMODE_ATTRIBUTE_T * prSrcAttribute;
    GRAPHMODE_ATTRIBUTE_T * prDstAttribute;
    UINT32 u4SrcPanelTypeDefine;
    UINT32 u4DstPanelTypeDefine;

    u4SrcPanelTypeDefine = u4PanelTypeDefinition[u4SrcType];
    u4DstPanelTypeDefine = u4PanelTypeDefinition[u4DstType];

	#ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
	if (FlashPanel_GetControlWord2_GraphModeEn())
	#else
	if (IS_SUPPORT_VB1_GRAPH_MODE)
	#endif
	{
        prSrcAttribute = GraphMode_GetAttributeByType(u4SrcPanelTypeDefine);
        prDstAttribute = GraphMode_GetAttributeByType(u4DstPanelTypeDefine);
        if (prSrcAttribute == NULL || prDstAttribute == NULL)
        {
            return;
        }

        if (PANEL_GetPanelTypeWidth(u4DstPanelTypeDefine) >= PANEL_GetPanelTypeWidth(u4SrcPanelTypeDefine))
        {
            UINT8 u1Ratio = PANEL_GetPanelTypeWidth(u4DstPanelTypeDefine) / PANEL_GetPanelTypeWidth(u4SrcPanelTypeDefine);

            prDstAttribute->u2GraphModeWidth = prSrcAttribute->u2GraphModeWidth * u1Ratio;
            prDstAttribute->au2HTotal[SV_DCLK_48HZ] = prSrcAttribute->au2HTotal[SV_DCLK_48HZ] * u1Ratio;
            prDstAttribute->au2HTotal[SV_DCLK_50HZ] = prSrcAttribute->au2HTotal[SV_DCLK_50HZ] * u1Ratio;
            prDstAttribute->au2HTotal[SV_DCLK_60HZ] = prSrcAttribute->au2HTotal[SV_DCLK_60HZ] * u1Ratio;
            prDstAttribute->au2HFrontPorch[SV_DCLK_48HZ] = prSrcAttribute->au2HFrontPorch[SV_DCLK_48HZ] * u1Ratio;
            prDstAttribute->au2HFrontPorch[SV_DCLK_50HZ] = prSrcAttribute->au2HFrontPorch[SV_DCLK_50HZ] * u1Ratio;
            prDstAttribute->au2HFrontPorch[SV_DCLK_60HZ] = prSrcAttribute->au2HFrontPorch[SV_DCLK_60HZ] * u1Ratio;
            prDstAttribute->au2HBackPorch[SV_DCLK_48HZ] = prSrcAttribute->au2HBackPorch[SV_DCLK_48HZ] * u1Ratio;
            prDstAttribute->au2HBackPorch[SV_DCLK_50HZ] = prSrcAttribute->au2HBackPorch[SV_DCLK_50HZ] * u1Ratio;
            prDstAttribute->au2HBackPorch[SV_DCLK_60HZ] = prSrcAttribute->au2HBackPorch[SV_DCLK_60HZ] * u1Ratio;
            prDstAttribute->au1HSyncWidth[SV_DCLK_48HZ] = prDstAttribute->au1HSyncWidth[SV_DCLK_48HZ] * u1Ratio;
            prDstAttribute->au1HSyncWidth[SV_DCLK_50HZ] = prDstAttribute->au1HSyncWidth[SV_DCLK_50HZ] * u1Ratio;
            prDstAttribute->au1HSyncWidth[SV_DCLK_60HZ] = prDstAttribute->au1HSyncWidth[SV_DCLK_60HZ] * u1Ratio;
        }
        else
        {
            UINT8 u1Ratio = PANEL_GetPanelTypeWidth(u4SrcPanelTypeDefine) / PANEL_GetPanelTypeWidth(u4DstPanelTypeDefine);

            prDstAttribute->u2GraphModeWidth = prSrcAttribute->u2GraphModeWidth / u1Ratio;
            prDstAttribute->au2HTotal[SV_DCLK_48HZ] = prSrcAttribute->au2HTotal[SV_DCLK_48HZ] / u1Ratio;
            prDstAttribute->au2HTotal[SV_DCLK_50HZ] = prSrcAttribute->au2HTotal[SV_DCLK_50HZ] / u1Ratio;
            prDstAttribute->au2HTotal[SV_DCLK_60HZ] = prSrcAttribute->au2HTotal[SV_DCLK_60HZ] / u1Ratio;
            prDstAttribute->au2HFrontPorch[SV_DCLK_48HZ] = prSrcAttribute->au2HFrontPorch[SV_DCLK_48HZ] / u1Ratio;
            prDstAttribute->au2HFrontPorch[SV_DCLK_50HZ] = prSrcAttribute->au2HFrontPorch[SV_DCLK_50HZ] / u1Ratio;
            prDstAttribute->au2HFrontPorch[SV_DCLK_60HZ] = prSrcAttribute->au2HFrontPorch[SV_DCLK_60HZ] / u1Ratio;
            prDstAttribute->au2HBackPorch[SV_DCLK_48HZ] = prSrcAttribute->au2HBackPorch[SV_DCLK_48HZ] / u1Ratio;
            prDstAttribute->au2HBackPorch[SV_DCLK_50HZ] = prSrcAttribute->au2HBackPorch[SV_DCLK_50HZ] / u1Ratio;
            prDstAttribute->au2HBackPorch[SV_DCLK_60HZ] = prSrcAttribute->au2HBackPorch[SV_DCLK_60HZ] / u1Ratio;
            prDstAttribute->au1HSyncWidth[SV_DCLK_48HZ] = prDstAttribute->au1HSyncWidth[SV_DCLK_48HZ] / u1Ratio;
            prDstAttribute->au1HSyncWidth[SV_DCLK_50HZ] = prDstAttribute->au1HSyncWidth[SV_DCLK_50HZ] / u1Ratio;
            prDstAttribute->au1HSyncWidth[SV_DCLK_60HZ] = prDstAttribute->au1HSyncWidth[SV_DCLK_60HZ] / u1Ratio;
        }

        if (PANEL_GetPanelTypeHeight(u4DstPanelTypeDefine) >= PANEL_GetPanelTypeHeight(u4SrcPanelTypeDefine))
        {
            UINT8 u1Ratio = PANEL_GetPanelTypeHeight(u4DstPanelTypeDefine) / PANEL_GetPanelTypeHeight(u4SrcPanelTypeDefine);

            prDstAttribute->u2GraphModeHeight= prSrcAttribute->u2GraphModeHeight * u1Ratio;
            prDstAttribute->au2VTotal[SV_DCLK_48HZ] = prSrcAttribute->au2VTotal[SV_DCLK_48HZ] * u1Ratio;
            prDstAttribute->au2VTotal[SV_DCLK_50HZ] = prSrcAttribute->au2VTotal[SV_DCLK_50HZ] * u1Ratio;
            prDstAttribute->au2VTotal[SV_DCLK_60HZ] = prSrcAttribute->au2VTotal[SV_DCLK_60HZ] * u1Ratio;
            prDstAttribute->au2VFrontPorch[SV_DCLK_48HZ] = prSrcAttribute->au2VFrontPorch[SV_DCLK_48HZ] * u1Ratio;
            prDstAttribute->au2VFrontPorch[SV_DCLK_50HZ] = prSrcAttribute->au2VFrontPorch[SV_DCLK_50HZ] * u1Ratio;
            prDstAttribute->au2VFrontPorch[SV_DCLK_60HZ] = prSrcAttribute->au2VFrontPorch[SV_DCLK_60HZ] * u1Ratio;
            prDstAttribute->au2VBackPorch[SV_DCLK_48HZ] = prSrcAttribute->au2VBackPorch[SV_DCLK_48HZ] * u1Ratio;
            prDstAttribute->au2VBackPorch[SV_DCLK_50HZ] = prSrcAttribute->au2VBackPorch[SV_DCLK_50HZ] * u1Ratio;
            prDstAttribute->au2VBackPorch[SV_DCLK_60HZ] = prSrcAttribute->au2VBackPorch[SV_DCLK_60HZ] * u1Ratio;
            prDstAttribute->au1VSyncWidth[SV_DCLK_48HZ] = prDstAttribute->au1VSyncWidth[SV_DCLK_48HZ] * u1Ratio;
            prDstAttribute->au1VSyncWidth[SV_DCLK_50HZ] = prDstAttribute->au1VSyncWidth[SV_DCLK_50HZ] * u1Ratio;
            prDstAttribute->au1VSyncWidth[SV_DCLK_60HZ] = prDstAttribute->au1VSyncWidth[SV_DCLK_60HZ] * u1Ratio;
        }
        else
        {
            UINT8 u1Ratio = PANEL_GetPanelTypeHeight(u4SrcPanelTypeDefine) / PANEL_GetPanelTypeHeight(u4DstPanelTypeDefine);

            prDstAttribute->u2GraphModeHeight= prSrcAttribute->u2GraphModeHeight / u1Ratio;
            prDstAttribute->au2VTotal[SV_DCLK_48HZ] = prSrcAttribute->au2VTotal[SV_DCLK_48HZ] / u1Ratio;
            prDstAttribute->au2VTotal[SV_DCLK_50HZ] = prSrcAttribute->au2VTotal[SV_DCLK_50HZ] / u1Ratio;
            prDstAttribute->au2VTotal[SV_DCLK_60HZ] = prSrcAttribute->au2VTotal[SV_DCLK_60HZ] / u1Ratio;
            prDstAttribute->au2VFrontPorch[SV_DCLK_48HZ] = prSrcAttribute->au2VFrontPorch[SV_DCLK_48HZ] / u1Ratio;
            prDstAttribute->au2VFrontPorch[SV_DCLK_50HZ] = prSrcAttribute->au2VFrontPorch[SV_DCLK_50HZ] / u1Ratio;
            prDstAttribute->au2VFrontPorch[SV_DCLK_60HZ] = prSrcAttribute->au2VFrontPorch[SV_DCLK_60HZ] / u1Ratio;
            prDstAttribute->au2VBackPorch[SV_DCLK_48HZ] = prSrcAttribute->au2VBackPorch[SV_DCLK_48HZ] / u1Ratio;
            prDstAttribute->au2VBackPorch[SV_DCLK_50HZ] = prSrcAttribute->au2VBackPorch[SV_DCLK_50HZ] / u1Ratio;
            prDstAttribute->au2VBackPorch[SV_DCLK_60HZ] = prSrcAttribute->au2VBackPorch[SV_DCLK_60HZ] / u1Ratio;
            prDstAttribute->au1VSyncWidth[SV_DCLK_48HZ] = prDstAttribute->au1VSyncWidth[SV_DCLK_48HZ] / u1Ratio;
            prDstAttribute->au1VSyncWidth[SV_DCLK_50HZ] = prDstAttribute->au1VSyncWidth[SV_DCLK_50HZ] / u1Ratio;
            prDstAttribute->au1VSyncWidth[SV_DCLK_60HZ] = prDstAttribute->au1VSyncWidth[SV_DCLK_60HZ] / u1Ratio;
        }

        if (PANEL_GetPanelTypeWidth(u4DstPanelTypeDefine) * PANEL_GetPanelTypeHeight(u4DstPanelTypeDefine) * PANEL_GetPanelTypeFPS(u4DstPanelTypeDefine) >=
            PANEL_GetPanelTypeWidth(u4SrcPanelTypeDefine) * PANEL_GetPanelTypeHeight(u4SrcPanelTypeDefine) * PANEL_GetPanelTypeFPS(u4SrcPanelTypeDefine))
        {
            UINT8 u1Ratio = (PANEL_GetPanelTypeWidth(u4DstPanelTypeDefine) * PANEL_GetPanelTypeHeight(u4DstPanelTypeDefine) * PANEL_GetPanelTypeFPS(u4DstPanelTypeDefine)) / (PANEL_GetPanelTypeWidth(u4SrcPanelTypeDefine) * PANEL_GetPanelTypeHeight(u4SrcPanelTypeDefine) * PANEL_GetPanelTypeFPS(u4SrcPanelTypeDefine));

            prDstAttribute->au4PixelClk[SV_DCLK_48HZ] = prSrcAttribute->au4PixelClk[SV_DCLK_48HZ] * u1Ratio;
            prDstAttribute->au4PixelClk[SV_DCLK_50HZ] = prSrcAttribute->au4PixelClk[SV_DCLK_50HZ] * u1Ratio;
            prDstAttribute->au4PixelClk[SV_DCLK_60HZ] = prSrcAttribute->au4PixelClk[SV_DCLK_60HZ] * u1Ratio;
        }
        else
        {
            UINT8 u1Ratio = (PANEL_GetPanelTypeWidth(u4SrcPanelTypeDefine) * PANEL_GetPanelTypeHeight(u4SrcPanelTypeDefine) * PANEL_GetPanelTypeFPS(u4SrcPanelTypeDefine)) / (PANEL_GetPanelTypeWidth(u4DstPanelTypeDefine) * PANEL_GetPanelTypeHeight(u4DstPanelTypeDefine) * PANEL_GetPanelTypeFPS(u4DstPanelTypeDefine));

            prDstAttribute->au4PixelClk[SV_DCLK_48HZ] = prSrcAttribute->au4PixelClk[SV_DCLK_48HZ] / u1Ratio;
            prDstAttribute->au4PixelClk[SV_DCLK_50HZ] = prSrcAttribute->au4PixelClk[SV_DCLK_50HZ] / u1Ratio;
            prDstAttribute->au4PixelClk[SV_DCLK_60HZ] = prSrcAttribute->au4PixelClk[SV_DCLK_60HZ] / u1Ratio;
        }
	}
}

void GraphMode_DumpAttribute(void)
{
	#ifdef LOAD_PANEL_FROM_FLASH_CUSTOM
	if (FlashPanel_GetControlWord2_GraphModeEn())
	#else
    if (IS_SUPPORT_VB1_GRAPH_MODE)
	#endif
    {
        UINT8 u1PanelType;
        GRAPHMODE_ATTRIBUTE_T * prAttribute;
        for (u1PanelType = PANEL_TYPE_2K1K_60; u1PanelType < PANEL_TYPE_MAX; u1PanelType++)
        {
            prAttribute = GraphMode_GetAttributeByType(u4PanelTypeDefinition[u1PanelType]);
            if (prAttribute== NULL)
                continue;

            LOG(0,"---- Panel[%ld] %dx%d ----\n", GraphMode_GetPanelIndex(), prAttribute->u2GraphModeWidth, prAttribute->u2GraphModeHeight);
            LOG(0,"PixelClock ...: (%ld, %ld, %ld)\n",
                prAttribute->au4PixelClk[SV_DCLK_48HZ],
                prAttribute->au4PixelClk[SV_DCLK_50HZ],
                prAttribute->au4PixelClk[SV_DCLK_60HZ]);
            LOG(0,"HTotal .......: (%d, %d, %d)\n",
                prAttribute->au2HTotal[SV_DCLK_48HZ],
                prAttribute->au2HTotal[SV_DCLK_50HZ],
                prAttribute->au2HTotal[SV_DCLK_60HZ]);
            LOG(0,"HFrontPorch ..: (%d, %d, %d)\n",
                prAttribute->au2HFrontPorch[SV_DCLK_48HZ],
                prAttribute->au2HFrontPorch[SV_DCLK_50HZ],
                prAttribute->au2HFrontPorch[SV_DCLK_60HZ]);
            LOG(0,"HSyncWidth ...: (%d, %d, %d)\n",
                prAttribute->au1HSyncWidth[SV_DCLK_48HZ],
                prAttribute->au1HSyncWidth[SV_DCLK_50HZ],
                prAttribute->au1HSyncWidth[SV_DCLK_60HZ]);
            LOG(0,"HBackPorch ...: (%d, %d, %d)\n",
                prAttribute->au2HBackPorch[SV_DCLK_48HZ],
                prAttribute->au2HBackPorch[SV_DCLK_50HZ],
                prAttribute->au2HBackPorch[SV_DCLK_60HZ]);
            LOG(0,"VTotal .......: (%d, %d, %d)\n",
                prAttribute->au2VTotal[SV_DCLK_48HZ],
                prAttribute->au2VTotal[SV_DCLK_50HZ],
                prAttribute->au2VTotal[SV_DCLK_60HZ]);
            LOG(0,"VFrontPorch ..: (%d, %d, %d)\n",
                prAttribute->au2VFrontPorch[SV_DCLK_48HZ],
                prAttribute->au2VFrontPorch[SV_DCLK_50HZ],
                prAttribute->au2VFrontPorch[SV_DCLK_60HZ]);
            LOG(0,"VSyncWidth ...: (%d, %d, %d)\n",
                prAttribute->au1VSyncWidth[SV_DCLK_48HZ],
                prAttribute->au1VSyncWidth[SV_DCLK_50HZ],
                prAttribute->au1VSyncWidth[SV_DCLK_60HZ]);
            LOG(0,"VBackPorch ...: (%d, %d, %d)\n",
                prAttribute->au2VBackPorch[SV_DCLK_48HZ],
                prAttribute->au2VBackPorch[SV_DCLK_50HZ],
                prAttribute->au2VBackPorch[SV_DCLK_60HZ]);
            LOG(0,"ControlWord ..: 0x%8lx\n", prAttribute->u4GControlWord);
        }
	}
	else
	{
		LOG(0, "Not support graph mode\n");
	}
}

UINT32 GraphMode_GetPanelIndex(void)
{
    return u4GraphModeIndex;
}

#ifdef CC_S_PLATFORM
void GraphMode_SetPanelIndex(UINT32 u4Type)
{
    UINT32 u4Index;
    UINT32 u4RefIndex = GetCurrentPanelIndex() | PANEL_SetType(u4Type);
#ifdef CC_PANEL_FROM_FLASH
	UINT32 u4MaxIndex=2;
#else
    UINT32 u4MaxIndex = sizeof(_arGraphModeAttribute)/sizeof(GRAPHMODE_ATTRIBUTE_T);
#endif
    for (u4Index = 0 ; u4Index < u4MaxIndex; u4Index++)
    {
        #ifdef CC_PANEL_FROM_FLASH	
        if (u4RefIndex == rGraphic[u4Index].u4PanelIndex)
		#else
        if (u4RefIndex == _arGraphModeAttribute[u4Index].u4PanelIndex)
		#endif
        {
        #ifdef CC_PANEL_FROM_FLASH		 
			_prGraphModeAttribute = &rGraphic[u4Index];
		#else
            _prGraphModeAttribute = &_arGraphModeAttribute[u4Index];
		#endif
            u4GraphModeIndex = u4RefIndex;
            break;
        }
    }
}

void GraphMode_SetPanelType(UINT32 u4Type)
{
	LOG(3, "[GraphMode_SetPanelType] panel_type=%d\n", u4Type);
    u4PanelType = u4Type;

    GraphMode_SetPanelIndex(u4Type);
}
#else
void GraphMode_SetPanelIndex(UINT32 u4PanelIndex)
{
    UINT32 u4Index;
    UINT32 u4RefIndex = u4PanelIndex | PANEL_SetType(u4PanelType);
#ifdef CC_PANEL_FROM_FLASH
	UINT32 u4MaxIndex=2;
#else
    UINT32 u4MaxIndex = sizeof(_arGraphModeAttribute)/sizeof(GRAPHMODE_ATTRIBUTE_T);
#endif
    for (u4Index = 0 ; u4Index < u4MaxIndex; u4Index++)
    {
        if (u4RefIndex == _arGraphModeAttribute[u4Index].u4PanelIndex)
        {
        #ifdef CC_PANEL_FROM_FLASH		 
			_prGraphModeAttribute = &rGraphic[u4Index];
		#else
            _prGraphModeAttribute = &_arGraphModeAttribute[u4Index];
		#endif
            u4GraphModeIndex = u4PanelIndex;
            break;
        }
    }
}

void GraphMode_SetPanelType(UINT32 u4Type)
{
	LOG(3, "[GraphMode_SetPanelType] panel_type=%ld\n", u4Type);
    u4PanelType = u4Type;

    GraphMode_SetPanelIndex(u4GraphModeIndex);
}
#endif

UINT32 GraphMode_GetPanelType(void)
{
    return u4PanelType;
}

UINT32 GraphMode_GetFrameRateMax(void)
{
    return _prGraphModeAttribute->u1FrameRateMax;
}

UINT8 GraphMode_IsSupportAttribute(void)
{
    if (DRVCUST_PanelGet(ePanelFlashTableSize) > 0)
    {
        return FALSE;
    }

    return TRUE;
}

UINT32 GraphMode_GetControlWord(void)
{
    return _prGraphModeAttribute->u4GControlWord;
}

void GraphMode_SetControlWord(UINT32 u4ControlWord)
{
    _prGraphModeAttribute->u4GControlWord = u4ControlWord;
}

UINT32 GRAPHMODE_GetPixelClkByTiming(UINT8 bDclkType)
{
    return _prGraphModeAttribute->au4PixelClk[bDclkType];
}

void GRAPHMODE_SetPixelClkByTiming(UINT8 bDclkType, UINT32 u4PixelClk)
{
    _prGraphModeAttribute->au4PixelClk[bDclkType] = u4PixelClk;
}

void GRAPHMODE_SetPixelClk(UINT32 u4PixelClk48Hz, UINT16 u4PixelClk50Hz, UINT16 u4PixelClk60Hz)
{
    GRAPHMODE_SetPixelClkByTiming(0, u4PixelClk48Hz);
    GRAPHMODE_SetPixelClkByTiming(1, u4PixelClk50Hz);
    GRAPHMODE_SetPixelClkByTiming(2, u4PixelClk60Hz);	
}

UINT16 GRAPHMODE_GetHtotalByTiming(UINT8 bDclkType)
{
    return _prGraphModeAttribute->au2HTotal[bDclkType];
}

void GRAPHMODE_SetHtotalByTiming(UINT8 bDclkType, UINT16 u2Htotal)
{
    _prGraphModeAttribute->au2HTotal[bDclkType] = u2Htotal;
}

void GRAPHMODE_SetHtotal(UINT16 u2Htotal48Hz, UINT16 u2Htotal50Hz, UINT16 u2Htotal60Hz)
{
    GRAPHMODE_SetHtotalByTiming(0, u2Htotal48Hz);
    GRAPHMODE_SetHtotalByTiming(1, u2Htotal50Hz);
    GRAPHMODE_SetHtotalByTiming(2, u2Htotal60Hz);	
}

UINT32 GRAPHMODE_GetPanelWidth(void)
{
    return _prGraphModeAttribute->u2GraphModeWidth;
}

void GRAPHMODE_SetPanelWidth(UINT16 u2PanelWidth)
{
    _prGraphModeAttribute->u2GraphModeWidth = u2PanelWidth;
}

UINT16 GRAPHMODE_GetHSyncFpByTiming(UINT8 bDclkType)
{
    return _prGraphModeAttribute->au2HFrontPorch[bDclkType];
}

void GRAPHMODE_SetHSyncFpByTiming(UINT8 bDclkType, UINT16 u2HFp)
{
    _prGraphModeAttribute->au2HFrontPorch[bDclkType] = u2HFp;
}

void GRAPHMODE_SetHSyncFp(UINT16 u2HFp48Hz, UINT16 u2HFp50Hz, UINT16 u2HFp60Hz)
{
    GRAPHMODE_SetHSyncFpByTiming(0, u2HFp48Hz);
    GRAPHMODE_SetHSyncFpByTiming(1, u2HFp50Hz);
    GRAPHMODE_SetHSyncFpByTiming(2, u2HFp60Hz);
}

UINT8 GRAPHMODE_GetHSyncWidthByTiming(UINT8 bDclkType)
{
    return _prGraphModeAttribute->au1HSyncWidth[bDclkType];
}

void GRAPHMODE_SetHSyncWidthByTiming(UINT8 bDclkType, UINT8 u1HWidth)
{
    _prGraphModeAttribute->au1HSyncWidth[bDclkType] = u1HWidth;
}

void GRAPHMODE_SetHSyncWidth(UINT16 u2HWidth48Hz, UINT16 u2HWidth50Hz, UINT16 u2HWidth60Hz)
{
    GRAPHMODE_SetHSyncFpByTiming(0, u2HWidth48Hz);
    GRAPHMODE_SetHSyncFpByTiming(1, u2HWidth50Hz);
    GRAPHMODE_SetHSyncFpByTiming(2, u2HWidth60Hz);
}

UINT16 GRAPHMODE_GetHSyncBpByTiming(UINT8 bDclkType)
{
    return _prGraphModeAttribute->au2HBackPorch[bDclkType];
}

void GRAPHMODE_SetHSyncBpByTiming(UINT8 bDclkType, UINT16 u2HBp)
{
    _prGraphModeAttribute->au2HBackPorch[bDclkType] = u2HBp;
}

void GRAPHMODE_SetHSyncBp(UINT16 u2HBp48Hz, UINT16 u2HBp50Hz, UINT16 u2HBp60Hz)
{
    GRAPHMODE_SetHSyncFpByTiming(0, u2HBp48Hz);
    GRAPHMODE_SetHSyncFpByTiming(1, u2HBp50Hz);
    GRAPHMODE_SetHSyncFpByTiming(2, u2HBp60Hz);
}

UINT16 GRAPHMODE_GetVtotalByTiming(UINT8 bDclkType)
{
    return _prGraphModeAttribute->au2VTotal[bDclkType];
}

void GRAPHMODE_SetVtotalByTiming(UINT8 bDclkType, UINT16 u2Vtotal)
{
    _prGraphModeAttribute->au2VTotal[bDclkType] = u2Vtotal;
}

void GRAPHMODE_SetVtotal(UINT16 u2Vtotal48Hz, UINT16 u2Vtotal50Hz, UINT16 u2Vtotal60Hz)
{
    GRAPHMODE_SetVtotalByTiming(0, u2Vtotal48Hz);
    GRAPHMODE_SetVtotalByTiming(1, u2Vtotal50Hz);
    GRAPHMODE_SetVtotalByTiming(2, u2Vtotal60Hz);
}

UINT32 GRAPHMODE_GetPanelHeight(void)
{
    return _prGraphModeAttribute->u2GraphModeHeight;
}

void GRAPHMODE_SetPanelHeight(UINT16 u2PanelHeight)
{
    _prGraphModeAttribute->u2GraphModeHeight = u2PanelHeight;
}

UINT16 GRAPHMODE_GetVSyncFpByTiming(UINT8 bDclkType)
{
    return _prGraphModeAttribute->au2VFrontPorch[bDclkType];
}

void GRAPHMODE_SetVSyncFpByTiming(UINT8 bDclkType, UINT16 u2VFp)
{
    _prGraphModeAttribute->au2VFrontPorch[bDclkType] = u2VFp;
}

void GRAPHMODE_SetVSyncFp(UINT16 u2VFp48Hz, UINT16 u2VFp50Hz, UINT16 u2VFp60Hz)
{
    GRAPHMODE_SetVSyncFpByTiming(0, u2VFp48Hz);
    GRAPHMODE_SetVSyncFpByTiming(1, u2VFp50Hz);
    GRAPHMODE_SetVSyncFpByTiming(2, u2VFp60Hz);
}

UINT8 GRAPHMODE_GetVSyncWidthByTiming(UINT8 bDclkType)
{
    return _prGraphModeAttribute->au1VSyncWidth[bDclkType];
}

void GRAPHMODE_SetVSyncWidthByTiming(UINT8 bDclkType, UINT8 u1VWidth)
{
    _prGraphModeAttribute->au1VSyncWidth[bDclkType] = u1VWidth;
}

void GRAPHMODE_SetVSyncWidth(UINT8 u1VWidth48Hz, UINT8 u1VWidth50Hz, UINT8 u1VWidth60Hz)
{
    GRAPHMODE_SetVSyncWidthByTiming(0, u1VWidth48Hz);
    GRAPHMODE_SetVSyncWidthByTiming(1, u1VWidth50Hz);
    GRAPHMODE_SetVSyncWidthByTiming(2, u1VWidth60Hz);
}

UINT16 GRAPHMODE_GetVSyncBpByTiming(UINT8 bDclkType)
{
    return _prGraphModeAttribute->au2VBackPorch[bDclkType];
}

void GRAPHMODE_SetVSyncBpByTiming(UINT8 bDclkType, UINT16 u2VBp)
{
    _prGraphModeAttribute->au2VBackPorch[bDclkType] = u2VBp;
}

void GRAPHMODE_SetVSyncBp(UINT16 u2VBp48Hz, UINT16 u2VBp50Hz, UINT16 u2VBp60Hz)
{
    GRAPHMODE_SetVSyncBpByTiming(0, u2VBp48Hz);
    GRAPHMODE_SetVSyncBpByTiming(1, u2VBp50Hz);
    GRAPHMODE_SetVSyncBpByTiming(2, u2VBp60Hz);
}

UINT32 GRAPHMODE_GetHSyncPolarity(void)
{
	return _prGraphModeAttribute->u1HSyncPolarity;
}

UINT32 GRAPHMODE_GetVSyncPolarity(void)
{
	return _prGraphModeAttribute->u1VSyncPolarity;
}

void DumpGraphModeAttribute(void)
{
	UINT8 u1Cnt = 0;
	
	if(PANEL_GetDisplayType() == PANEL_DISPLAY_TYPE_VB1)
	{

		LOG(0,"Pixel Clock,HTotal, HActive, HFp, HWidth, HBp\n"); 
		for(u1Cnt=SV_DCLK_48HZ;u1Cnt<SV_DCLK_OTHERS;u1Cnt++)
		{
			if(u1Cnt==SV_DCLK_48HZ)
			LOG(0,"[48Hz]");	
			else if(u1Cnt==SV_DCLK_50HZ)
			LOG(0,"[50Hz]");	
			else // u1Cnt==SV_DCLK_60HZ
			LOG(0,"[60Hz], ");

			LOG(0," %9ld,%4d,%4ld,%4d,%4d,%4d\n",GRAPHMODE_GetPixelClkByTiming(u1Cnt),GRAPHMODE_GetHtotalByTiming(u1Cnt),GRAPHMODE_GetPanelWidth(),
						GRAPHMODE_GetHSyncFpByTiming(u1Cnt),GRAPHMODE_GetHSyncWidthByTiming(u1Cnt), GRAPHMODE_GetHSyncBpByTiming(u1Cnt));
		}

		LOG(0,"VTotal, VActive, VFp, VWidth, VBp\n"); 
		for(u1Cnt=SV_DCLK_48HZ;u1Cnt<SV_DCLK_OTHERS;u1Cnt++)
		{
			if(u1Cnt==SV_DCLK_48HZ)
			LOG(0,"[48Hz]");	
			else if(u1Cnt==SV_DCLK_50HZ)
			LOG(0,"[50Hz]");	
			else // u1Cnt==SV_DCLK_60HZ
			LOG(0,"[60Hz], ");

			LOG(0," %4d,%4ld,%4d,%4d,%4d\n",GRAPHMODE_GetVtotalByTiming(u1Cnt),GRAPHMODE_GetPanelHeight(),
						GRAPHMODE_GetVSyncFpByTiming(u1Cnt),GRAPHMODE_GetVSyncWidthByTiming(u1Cnt), GRAPHMODE_GetVSyncBpByTiming(u1Cnt));
		}
		
		if (GraphMode_FORMAT == GM_FORMAT_CASE0_SMODE1)
		LOG(0,"GM_FORMAT_CASE0_SMODE1,");
		else if (GraphMode_FORMAT == GM_FORMAT_CASE1_SMODE0)
		LOG(0,"GM_FORMAT_CASE1_SMODE0,");
		else if (GraphMode_FORMAT == GM_FORMAT_CASE2_MMODE0)
		LOG(0,"GM_FORMAT_CASE2_MMODE0,");	
		else if (GraphMode_FORMAT == GM_FORMAT_CASE3_INHOUSE)
		LOG(0,"GM_FORMAT_CASE3_INHOUSE,");	
		else
		LOG(0,"    ,");

		if (GM_LANE_NUM == GM_LANE_1)
		LOG(0,"GM_LANE_1,");	
		else if (GM_LANE_NUM == GM_LANE_2)
		LOG(0,"GM_LANE_2,");	
		else if (GM_LANE_NUM == GM_LANE_4)
		LOG(0,"GM_LANE_4,");
		else
		LOG(0,"    ,");

		LOG(0,"\n");		
	}
	else
	{
		LOG(0,"Not Support Graph Mode\n");
	}

}
#endif

#ifdef CC_COMBINE_4K_2K
static BOOL _bIsmodeltype_init   = FALSE;
static UINT32 _u42k4kInfo        = 1;
static UINT32 _u4BEType          = DRV_CUST_BE_TYPE_INVALID;
static BOOL _u4FRCType           = DRV_CUST_FRC_TYPE_INVALID;
static BOOL _u4FRCTypeDevice     = DRV_CUST_FRC_TYPE_DEVICE_INVALID;
static BOOL _u4PQType            = DRV_CUST_PQ_TYPE_INVALID;
static BOOL _fgAllInOneSeries    = FALSE;
static UINT32 _u4FEType          = DRV_CUST_FE_TYPE_NONE;

/*
 *  Sony MVI model information
 *  Addr: 0x10010
 *  Size: 1Byte
 *  Detail Info:
 *  bit0: Board type (Not used)
 *  bit1: 1=4K         0=2K
 *  bit2: 1=no BE      0=BE
 *  bit3: 1=Y16 BR     0=Y15 BE
 *  bit4: 1=no FRC     0=FRC
 *  bit5: 0=separated  0=All-in-One(FY15) => 0=Orinal FRC 1=New FRC (FY17)
 *  bit6: reserved(FY17) => 0=No extra model 1=has extra model (FY17)
 *  bit7: 1=force 2K   0:Normal
 **/
static VOID _DRVCUST_ModelInfo_Init_Old(VOID)
{
    UINT8 u1ModeInfo = 0;
    UINT8 u1ExtraDevice = 0;

    if (!_bIsmodeltype_init)
    {
        UNUSED(EEPROM_Read(0x10010, (UPTR)&u1ModeInfo, 1));

        if ((u1ModeInfo&0x02) != 0)
        {
            _u42k4kInfo = MVI_INFO_4K_MODULE;  //ModelType:bit1  0:2K 1:4K
        }
        else
        {
            _u42k4kInfo = 0x00;
        }

        if ((u1ModeInfo&0x80) != 0)
        {
            _u42k4kInfo |= MVI_INFO_FORCE_2K_DISPLAY;
        }

        if ((u1ModeInfo&0x2) != 0)
        {
            if ((u1ModeInfo&0x04) != 0)
            {
                _u4BEType = DRV_CUST_BE_TYPE_NONE;
            }
            else 
            {
                if ((u1ModeInfo&0x08) != 0x0)
                {
                    _u4BEType = DRV_CUST_BE_TYPE_S_Y16;
                }
                else
                {
                    _u4BEType = DRV_CUST_BE_TYPE_S_Y15;
                }
            }
        }
        else
        {
            _u4BEType = DRV_CUST_BE_TYPE_NONE;
        }
        ASSERT(_u4BEType!=DRV_CUST_BE_TYPE_INVALID);

#if 0 // remove old FRC Type spec
        if (_u4BEType == DRV_CUST_BE_TYPE_NONE)
        {
            if ((u1ModeInfo&0x10) != 0x0)
            {
                _u4FRCType = DRV_CUST_FRC_TYPE_NONE;
            }
            else 
            {
                if ((u1ModeInfo&0x20) != 0x0)
                {
                    _u4FRCType = DRV_CUST_FRC_TYPE_S_Y17;
                }
                else
                {
                    _u4FRCType = DRV_CUST_FRC_TYPE_S_Y15;
                }
            }
        }
        else
        {
            _u4FRCType = DRV_CUST_FRC_TYPE_NONE;
        }
        ASSERT(_u4FRCType!=DRV_CUST_FRC_TYPE_INVALID);
#endif

        if ((u1ModeInfo&0x40) != 0x0)
        {
            UNUSED(EEPROM_Read(0x10018, (UPTR)&u1ExtraDevice, 1));
            if ((u1ExtraDevice&0x1) != 0)
            {
                _u4PQType = DRV_CUST_PQ_TYPE_S_Y17;
            }
            else
            {
                _u4PQType = DRV_CUST_PQ_TYPE_NONE;
            }
        }
        else
        {
            _u4PQType = DRV_CUST_PQ_TYPE_NONE;
        }
        ASSERT(_u4PQType!=DRV_CUST_PQ_TYPE_INVALID);

        // For Y17, this byte being used for other function, set _fgAllInOneSeries=TRUE
#if 0
        if ((u1ModeInfo&0x20) != 0x0)
        {
            _fgAllInOneSeries = FALSE;
        }
        else
        {
            _fgAllInOneSeries = TRUE;
        }
#else
        _fgAllInOneSeries = TRUE;
#endif

        LOG(0,"ModelInfo(0x%X 0x%08X): 2k4k(0x%X) BE(0x%X) FRC(0x%X) PQ(0x%X)\n",
                u1ModeInfo, BSP_GetIcVersion(), _u42k4kInfo, _u4BEType, _u4FRCType, _u4PQType);

        _bIsmodeltype_init = TRUE;
    }

    return ;
}

/*
 *  Sony MVI model information
 *  Addr: 0x10010
 *  Size: 1Byte
 *  Detail Info:
 *  bit0/bit1  0:2k 1:4k: 2:8k,3:16k
 *  bit2: 0=no FE         1= FE refer to 0x10019
 *  bit3: 0=no BE         1=BE  refer to 0x1001A
 *  bit4: 0=no PQ         1=PQ refer to 0x1001B
 *  bit5: 0=no FRC        1=FRC refer to 0x1001C
 *  bit6: reserved
 *  bit7: reserved
 **/

static VOID _DRVCUST_ModelInfo_Init(VOID)
{
    UINT8 u1ModeInfo = 0;
    UINT8 u1ExtraDevice = 0;
    UINT8 u1FeTypeInfo = 0;
    UINT8 u1BeTypeInfo = 0;
    UINT8 u1FrcTypeInfo = 0;
    UINT8 u1FrcDeviceTypeInfo = 0;
    if (!_bIsmodeltype_init)
    {
        UNUSED(EEPROM_Read(0x10010, (UPTR)&u1ModeInfo, 1));
        //BE
        if ((u1ModeInfo&0x8) != 0)
        {
            UNUSED(EEPROM_Read(0x1001A, (UPTR)&u1BeTypeInfo, 1));
            if ((u1BeTypeInfo&0xf) == 0x0)
            {
                _u4BEType = DRV_CUST_BE_TYPE_NONE;
            }
            else if ((u1BeTypeInfo&0xf) == 0x1)
            {
                _u4BEType = DRV_CUST_BE_TYPE_S_Y15;
            }
            else if ((u1BeTypeInfo&0xf) == 0x2)
            {
                _u4BEType = DRV_CUST_BE_TYPE_S_Y16;
            }
            else if ((u1BeTypeInfo&0xf) == 0x3)
            {
                _u4BEType = DRV_CUST_BE_TYPE_S_4K_Y18;
            }
            else if ((u1BeTypeInfo&0xf) == 0x4)
            {
                _u4BEType = DRV_CUST_BE_TYPE_S_8K_Y18;
            }
            else
            {
            //
            }
        }
        else
        {
            _u4BEType = DRV_CUST_BE_TYPE_NONE;
        }
        ASSERT(_u4BEType!=DRV_CUST_BE_TYPE_INVALID);

        //resoltuion
        if ((u1ModeInfo&0x03) == 0)
        {
            _u42k4kInfo = 0x00;  //ModelType:bit0 bit1  0:2K 1:4K 2:8K 3:16k
        }
        else if((u1ModeInfo&0x03) == 1)
        {
            _u42k4kInfo = MVI_INFO_4K_MODULE;
        }
        else if(((u1ModeInfo&0x03) == 2) || ((u1ModeInfo&0x03) == 1 && (_u4BEType == DRV_CUST_BE_TYPE_S_8K_Y18)))
        {
            _u42k4kInfo = MVI_INFO_8K_MODULE;
        }
        else if((u1ModeInfo&0x03) == 3)
        {
            _u42k4kInfo = MVI_INFO_16K_MODULE;
        }
        else
        {
            //

        }

        if ((u1ModeInfo&0x80) != 0)
        {
            _u42k4kInfo |= MVI_INFO_FORCE_2K_DISPLAY;   //need to confirm this the same as with FY17?
        }
        //FE
        if ((u1ModeInfo&0x4) != 0)
        {
            UNUSED(EEPROM_Read(0x10019, (UPTR)&u1FeTypeInfo, 1));
            if ((u1FeTypeInfo&0xf) == 0x1)
            {
                _u4FEType = DRV_CUST_FE_TYPE_JP_SHV;
            }
            else if((u1FeTypeInfo&0xf) == 0x0)
            {
                _u4FEType = DRV_CUST_FE_TYPE_NONE;
            }
        }
        else
        {
            _u4FEType = DRV_CUST_FE_TYPE_NONE;
        }

        //FRC
        if ((u1ModeInfo&0x20) != 0x0)
        {
            UNUSED(EEPROM_Read(0x1001C, (UPTR)&u1FrcTypeInfo, 1));
            if ((u1FrcTypeInfo&0x0f) == 0x00)
            {
                _u4FRCType = DRV_CUST_FRC_TYPE_NONE;
            }
            else if ((u1FrcTypeInfo&0x0f) == 0x01)
            {
                _u4FRCType = DRV_CUST_FRC_TYPE_VENDOR_N;
            }
            else if ((u1FrcTypeInfo&0x0f) == 0x02)
            {
                _u4FRCType = DRV_CUST_FRC_TYPE_VENDOR_M;
            }
            else
            {
            //
            }
        }
        else
        {
            _u4FRCType = DRV_CUST_FRC_TYPE_NONE;
        }
        ASSERT(_u4FRCType!=DRV_CUST_FRC_TYPE_INVALID);
        //FRC Device
        if ((u1ModeInfo&0x20) != 0x0)
        {
            UNUSED(EEPROM_Read(0x1001C, (UPTR)&u1FrcDeviceTypeInfo, 1));
            if ((u1FrcDeviceTypeInfo&0xf0) == 0x00)
            {
                _u4FRCTypeDevice = DRV_CUST_FRC_TYPE_DEVICE_NONE;
            }
            else if ((u1FrcDeviceTypeInfo&0xf0) == 0x10)
            {
                _u4FRCTypeDevice = DRV_CUST_FRC_TYPE_DEVICE_1;
            }
            else if ((u1FrcDeviceTypeInfo&0xf0) == 0x20)
            {
                _u4FRCTypeDevice = DRV_CUST_FRC_TYPE_DEVICE_2;
            }
            else
            {
                //
            }
        }
        else
        {
            _u4FRCTypeDevice = DRV_CUST_FRC_TYPE_DEVICE_NONE;
        }
        ASSERT(_u4FRCTypeDevice!=DRV_CUST_FRC_TYPE_DEVICE_INVALID);
        //PQ
        if ((u1ModeInfo&0x10) != 0x0)
        {
            UNUSED(EEPROM_Read(0x1001B, (UPTR)&u1ExtraDevice, 1));
            if ((u1ExtraDevice&0x1) != 0)
            {
                _u4PQType = DRV_CUST_PQ_TYPE_S_Y17;
            }
            else
            {
                _u4PQType = DRV_CUST_PQ_TYPE_NONE;
            }
        }
        else
        {
            _u4PQType = DRV_CUST_PQ_TYPE_NONE;
        }
        ASSERT(_u4PQType!=DRV_CUST_PQ_TYPE_INVALID);

#if 0
        if ((u1ModeInfo&0x20) != 0x0)
        {
            _fgAllInOneSeries = FALSE;
        }
        else
        {
            _fgAllInOneSeries = TRUE;
        }
#else
        _fgAllInOneSeries = TRUE;
#endif

        Printf("ModelInfo(0x%X 0x%08X): 2k4k8k16k(0x%X) BE(0x%X) FRC(0x%X) PQ(0x%X) FE(0x%X)\n",
                u1ModeInfo, BSP_GetIcVersion(), _u42k4kInfo, _u4BEType, _u4FRCType, _u4PQType,_u4FEType);

        _bIsmodeltype_init = TRUE;
    }

    return ;
}


UINT32 DRVCUST_Get_2K_Model(void)
{
    if (!_bIsmodeltype_init)
    {
        UNUSED(_DRVCUST_ModelInfo_Init());
    }

    return _u42k4kInfo;
}

UINT32 DRVCUST_Get_BE_Type(void)
{
    if (!_bIsmodeltype_init)
    {
        UNUSED(_DRVCUST_ModelInfo_Init());
    }

    return _u4BEType;
}

UINT32 DRVCUST_Get_FRC_Type(void)
{
    if (!_bIsmodeltype_init)
    {
        UNUSED(_DRVCUST_ModelInfo_Init());
    }

    return _u4FRCType;
}

UINT32 DRVCUST_Get_PQ_Type(void)
{
    if (!_bIsmodeltype_init)
    {
        UNUSED(_DRVCUST_ModelInfo_Init());
    }

    return _u4PQType;
}

BOOL DRVCUST_Is_All_in_One_Series(void)
{
    if (!_bIsmodeltype_init)
    {
        UNUSED(_DRVCUST_ModelInfo_Init());
    }

    return _fgAllInOneSeries;
}

BOOL DRVCUST_IsExternalDecoderModel(void)
{
    if (!_bIsmodeltype_init)
    {
        UNUSED(_DRVCUST_ModelInfo_Init());
    }

    if (_u4FEType == DRV_CUST_FE_TYPE_NONE)
    {
        return FALSE;
    }
    else if (_u4FEType == DRV_CUST_FE_TYPE_JP_SHV)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}
#endif

static BOOL _bIsGetLEDtype = FALSE;
static UINT8 _u4MVILEDtype = DRV_CUST_ILLUMINATION_LED_INVALID;

UINT32 DRVCUST_Get_Illumination_LED_Type(void)
{
#ifdef CC_S_PLATFORM
#if (defined(CC_HK_CUST) || defined(CC_CP_CUST))
    if(!_bIsGetLEDtype)
    {
        UNUSED(EEPROM_Read(0x1010F, (UPTR)&_u4MVILEDtype, 1));
        /*
            MVI 0x1010F : Illumination LED type .
                                0x00 : WRGB
                                0x01 : RGB
                                0x02 : WR
          */
        if ((_u4MVILEDtype > DRV_CUST_ILLUMINATION_LED_INVALID) ||
            (_u4MVILEDtype == DRV_CUST_ILLUMINATION_LED_INVALID))
        {
            Printf("######## MVI Illumination_LED_Type error : %d ##########\n", _u4MVILEDtype);
            _u4MVILEDtype = DRV_CUST_ILLUMINATION_LED_INVALID;
            ASSERT(_u4MVILEDtype != DRV_CUST_ILLUMINATION_LED_INVALID);
        }
        _bIsGetLEDtype = TRUE;
    }
#endif
#endif
    return _u4MVILEDtype;
}

static BOOL _bIsGetFPKeytype = FALSE;
static UINT8 _u4MVIFPKey = DRV_CUST_FP_KEY_OTHER;

UINT32 DRVCUST_Get_FP_Key_Type(void)
{
#ifdef CC_S_PLATFORM
#if (defined(CC_HK_CUST) || defined(CC_CP_CUST))
    if(!_bIsGetFPKeytype)
    {
        UNUSED(EEPROM_Read(0x10110, (UPTR)&_u4MVIFPKey, 1));
        /*
            MVI 0x10110 : Main Key type .
                                0x00 : 3key
                                0x01 : 1key Position Center
                                0x02 : 1key Position Left
                                0x03 : 1key Position Right
          */
        if ((_u4MVIFPKey > DRV_CUST_FP_KEY_OTHER) ||
            (_u4MVIFPKey == DRV_CUST_FP_KEY_OTHER))
        {
            Printf("######## MVI FP KEY Type error : %d ##########\n", _u4MVIFPKey);
            _u4MVIFPKey = DRV_CUST_FP_KEY_OTHER;
        }
        _bIsGetFPKeytype = TRUE;
    }
#endif
#endif
    return _u4MVIFPKey;
}

UINT32 DRVCUST_Get_InterMemc_type(void)
{
    BOOL fgIsInterMemcSpt = FALSE;

    #ifdef CC_COMBINE_4K_2K
    if((DRVCUST_Get_BE_Type() == DRV_CUST_BE_TYPE_NONE) &&             \
        (DRVCUST_Get_FRC_Type() == DRV_CUST_FRC_TYPE_NONE))
    {
        fgIsInterMemcSpt = TRUE;
    }
    else
    {
        fgIsInterMemcSpt = FALSE;
    }
    #else
        fgIsInterMemcSpt = FALSE;
    #endif

    return (UINT32)fgIsInterMemcSpt;
}
#endif /* CC_MTK_PRELOADER */

