/* 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.
 *
 *****************************************************************************/


/*****************************************************************************
 *
 * Filename:
 * ---------
 *   $Workfile: mtk_edid.h
 *
 * Project:
 * --------
 *   MT5365
 *
 * Description:
 * ------------
 *   Edid customization
 *
 * Author:
 * -------
 *
 *
 * Unauthorized use, practice, perform, copy, distribution, reproduction,
 * or disclosure of this information in whole or in part is prohibited.
 *-----------------------------------------------------------------------------
 *
 * $Author: zhenyu.shi $
 * $Date: 2016/01/13 $
 * $RCSfile: mtk_vga.h,v $
 * $Revision: #6 $
 *
 *---------------------------------------------------------------------------*/
#ifndef _EDID_CUSTOMIZATION_H_
#define _EDID_CUSTOMIZATION_H_
#include "eeprom_if.h"
#include "panel_cust.h"
#include "drv_edid.h"

#include "x_os.h"
#include "x_stl_lib.h"
#include "x_drv_cli.h"

#ifdef __MW_CLI_DEF__
#include "x_mid_cli.h"
#else
#include "x_drv_cli.h"
#endif

#include "hdmi_debug.h"
#if defined(CC_HDMI_EARC_SUPPORT)&&!defined(CC_UBOOT)&&!defined(CC_MTK_LOADER)
#include "hdmi_earc_if.h"
#endif

#if defined(__KERNEL__)&&!defined(CC_UBOOT)
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/err.h>
#include <linux/version.h>
#include <linux/platform_device.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)
#include <linux/soc/mediatek/opm_device.h>
#else
#include <linux/opm_device.h>
#endif
#endif

#ifdef CC_MT5893
#define DEVICE_MODEL_NUM "mt5893"
#endif

extern void DRVCUST_EdidUpdateNotify(void);

#define EDID_FW_NAME    DEVICE_MODEL_NUM"_edid.fw"
#define EDID_FW_BASE_NAME    DEVICE_MODEL_NUM"_edid_base.fw"

#define HDMI_EDID_SUPPORT_MAXNUM   64
#define GET_BANK_NUM(p) (*((p) + 0x6))
#define GET_TABLE_ADDR(p) ((*((p) + 0x10) << 8)|(*((p) + 0x11)))
#define GET_BLOCK_START_ADDR(p) ((*((p) + 0X20)<<8)|(*((p) + 0x21)))
#define GET_BLOCK_END_ADDR(p) ((*((p) + 0x26)<<16)|(*((p) + 0x27)<<8)|(*((p) + 0x28)))

typedef struct
{
    //Byte0:1
    UINT8 u1ParticularReserve_8_f;
    UINT8 u1ParticularReserve_0: 1;
    UINT8 u1Panel_less: 1;
    UINT8 u1CBA: 1;
    UINT8 u1ParticularReserve_3_7: 5;

    //Byte2:3
    //UINT8 u1GeneralReserve_8_f;
	UINT8 u1Hdmi21Bridge: 1;
	UINT8 u1GeneralReserve_1_7: 7;
    UINT8 u1HDR: 1;
    UINT8 u1xvYCC: 1;
    UINT8 u1BT20201: 1;
    UINT8 u12D3D: 1;
    UINT8 u1JPN_WW: 1;  //JPN 1, WW 0
    UINT8 u14K2K: 2;        //0:2K, 1:4K
    UINT8 u1DolbyVision: 1;

    //Byte4:5
    UINT8 u1AdaptiveReserve_8_f_0;
    UINT8 u1AdaptiveReserve_8_f_1;

    //Byte6:9
    UINT8 u1ReserveByte6;
    UINT8 u1XID_ID_Byte1;
    UINT8 u1XID_ID_Byte0;
    UINT8 u1XID_Expansion;

    //Byte10:12
    UINT8 u1MID_ID_Byte1;
    UINT8 u1MID_ID_Byte0;
    UINT8 u1MID_Expansion_Atmos;

    //Byte13:15
    UINT8 u1SID_ID_Byte1;
    UINT8 u1SID_ID_Byte0;
    UINT8 u1SID_Expansion_Atmos;

    UINT32 u4MID_ID;
    UINT32 u4SID_ID;
    UINT32 u4XID_ID;
    UINT8 u1ATMOS;
} M3_Table_T;

typedef struct
{
    //Byte0:1
    UINT8 u1ParticularReserve_8_f;
    UINT8 u1ParticularReserve_0: 1;
    UINT8 u1Panel_less: 1;
    UINT8 u1CBA: 1;
    UINT8 u1ParticularReserve_3_7: 5;

    //Byte2:3
    UINT8 u1GeneralReserve_8_f;
    UINT8 u1HDR: 1;
    UINT8 u1xvYCC: 1;
    UINT8 u1BT20201: 1;
    UINT8 u12D3D: 1;
    UINT8 u1JPN_WW: 1;  //JPN 1, WW 0
    UINT8 u1GeneralReserve_5_7: 3;

    //Byte4:5
    UINT8 u1AdaptiveReserve_8_f;
    UINT8 u1ATMOS: 1;
    UINT8 u1AdaptiveReserve_1_7: 7;

    //Byte6:9
    UINT8 u1ReserveByte6;
    UINT8 u1ReserveByte7;
    UINT8 u1ReserveByte8;
    UINT8 u1ReserveByte9;

    //Byte10:12
    UINT8 u1MID_ID_Byte2;
    UINT8 u1MID_ID_Byte1;
    UINT8 u1MID_ID_Byte0;

    //Byte13:15
    UINT8 u1SID_ID_Byte2;
    UINT8 u1SID_ID_Byte1;
    UINT8 u1SID_ID_Byte0;

    UINT32 u4MID_ID;
    UINT32 u4SID_ID;
} Trinity_Table_T;

typedef union
{
    Trinity_Table_T TrinityTable;
    M3_Table_T M3Table;
}uSelectTable;

typedef struct
{
    UINT32 u4PanelCtrl;
    UINT8 u1Panel_less;
    UINT8 u1Panel3DType;
    UINT8 u1PanelWCG;

    UINT8 u1MVIDestination;
    UINT8 u1ATMOS;
    UINT8 u1CBA;
    UINT8 u1MVINO_3D;
    UINT8 u1HFVSDBFlag;
    UINT8 u1HDR;

    UINT32 u4TableIDAddr;
    UINT16 u2TableSize;
    UINT32 u4EepHeaderAddr;
    UINT32 u4EepBlockEndAddr;
    UINT32 u4MID;
    UINT32 u4SID;
    UINT32 u4XID;

    UINT32 u4EepMIDStartAddr;
    UINT32 u4EepSIDStartAddr;
    UINT32 u4EepXIDStartAddr;

    UINT32 u4PanleSize;

    UINT8 u1DisByte0;
    UINT8 u1DisByte1;
    UINT8 u1ImageByte0;
    UINT8 u1ImageByte1;
    UINT8 u1ImageByte2;

    UINT8 u1Platform;
    UINT8 u14K2K;
    UINT8 u1BankNum;
	UINT8 u1Hdmi21Bridge;

    UINT8 u1DolbyVision;   //1:Dolby 0:None
    UINT8 u1DolbyBlock[6];

    UINT8 u1BlockFlag; //1:find the edid whole block
    UINT16 u2BlockOffset;//pEepBlock point offset in eep.bin
    UINT16 u2BlockSize;

    UINT8 *pTargetMIDEDID;
    UINT8 *pTargetSIDEDID;
    UINT8 *pTargetXIDEDID;
    UINT8 *pEepBlock;
    uSelectTable uSelect;
} EDID_SELECT_INFO_T;


//edid special address
typedef struct
{
    UINT8 audio_start_addr;        //audio data block address
    UINT8 speaker_end_addr;     //speaker allocation data block address
    UINT8 atmos_addr;
    UINT8 padding_start_addr;   //padding start address
    UINT8 remain_afc_1;
    UINT8 remain_afc_2;
    UINT8 remain_afc_ex1;
    UINT8 remain_afc_ex2;
    UINT8 remain_afc_ex3;
    UINT8 remain_afc_ex4;
} EDID_SPEC_ADDR_INFO_T;

typedef enum {
    EDID_SPEC_TYPE_MID,
    EDID_SPEC_TYPE_SID,
    EDID_SPEC_TYPE_XID,
} EDID_SPEC_TYPE;

typedef enum {
    CLI_FLAG_SETID,
    CLI_FLAG_SEARCH,
} CLI_FLAG_T;

typedef enum{
    ID_MID_TYPE = 0,
    ID_SID_TYPE,
    ID_XID_TYPE,
}ID_EDID_TYPE;


typedef struct
{
    UINT32 u4FixedFlag; //changed flag.
    UINT8 u1Platform;
    UINT8 u14K2K;
    UINT8 u1BankNum;
    UINT32 u4PanelCtrl;
    UINT8 u1Panel_less;
    UINT8 u1Panel3DType;
    UINT8 u1PanelWCG;
    UINT8 u1MVIDestination;
    UINT8 u1ATMOS;
    UINT8 u1CBA;
    UINT8 u1MVINO_3D;
    UINT8 u1HFVSDBFlag;
    UINT8 u1HDR;
    UINT32 u4MID;
    UINT32 u4SID;
    UINT8 pu1SearchData[16];
    UINT8 u1eARCConnect;
    UINT8 u1DolbyVision;
    //add next for debug.
} CUST_CLI_T;

typedef struct
{
    UINT8* pData;
    UINT8 u1TI4Flag;
    UINT8 u1MIDPA;
    UINT8 u1SIDPA;
    UINT8 u1XIDPA;
#if defined(__KERNEL__)&&!defined(CC_UBOOT)
    struct platform_device *pDevice;
#endif
    UINT16 u2BlockOffset;
    UINT32 u4TableIDAddr;
    UINT32 u4HeaderStartAddr;
    UINT32 u4HeaderEndAddr;
    UINT8 u1ReqFWDone;
    UINT16 u2TableSize;
    UINT8 u1BlockFlag;
    UINT8 u1BankNum;
    UINT8 u1Level;
    CUST_CLI_T eCLI;
}CUST_EDIDOBJ_T;

CUST_EDIDOBJ_T eEdidObj =
{
    .pData = NULL,
#if defined(__KERNEL__)&&!defined(CC_UBOOT)
    .pDevice = NULL,
#endif
    .u1TI4Flag = 0,
    .u1MIDPA = 0,
    .u1SIDPA = 0,
    .u1XIDPA = 0,
    .u1Level = 0,
    .u2BlockOffset = 0,
    .u4TableIDAddr = 0,
    .u4HeaderStartAddr = 0,
    .u4HeaderEndAddr = 0,
    .u1ReqFWDone = 0,
    .u2TableSize = 0,
    .u1BlockFlag = 0,
    .u1BankNum = 0
};

#if defined(CC_HDMI_EARC_SUPPORT)&&!defined(CC_UBOOT)&&!defined(CC_MTK_LOADER)
extern CLI_EXEC_T arHDMIEARCCmdTbl[];
#endif

#ifndef CC_VGA_EDID_DISABLE
UINT8 VGA_EDID_TABLE[256] =
{
    0x00, 0xFF, 0xFF, 0xFF,  0xFF, 0xFF, 0xFF, 0x00,   0x36, 0x8B, 0x10, 0x00,  0x01, 0x01, 0x01, 0x01,
    0x07, 0x14, 0x01, 0x03,  0x1F, 0x5D, 0x34, 0x78,   0xCA, 0x31, 0xC3, 0xA3,  0x55, 0x4A, 0x9B, 0x24,
    0x10, 0x47, 0x4A, 0xAF,  0xCF, 0x00, 0x01, 0x01,   0x01, 0x01, 0x01, 0x01,  0x01, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x01,  0x01, 0x01, 0x1A, 0x36,   0x80, 0xA0, 0x70, 0x38,  0x1F, 0x40, 0x30, 0x20,
    0x35, 0x00, 0xA2, 0x0B,  0x32, 0x00, 0x00, 0x1A,   0x00, 0x00, 0x00, 0xFD,  0x00, 0x32, 0x55, 0x1F,
    0x46, 0x0F, 0x00, 0x0A,  0x20, 0x20, 0x20, 0x20,   0x20, 0x20, 0x00, 0x00,  0x00, 0xFF, 0x00, 0x53,
    0x4B, 0x46, 0x4A, 0x42,  0x4C, 0x30, 0x37, 0x30,   0x32, 0x30, 0x32, 0x39,  0x00, 0x00, 0x00, 0xFC,
    0x00, 0x53, 0x56, 0x34,  0x32, 0x32, 0x58, 0x56,   0x54, 0x0A, 0x20, 0x20,  0x20, 0x20, 0x00, 0x5D,
    0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00
};
void vDrvLoadVgaEdid2Table(void)
{
    UINT64 u8Offset;
    UINT8 idx = 0;
    //read form eeprom or flash to VGA_EDID_TABLE

#ifdef CC_MULTI_EDID
    UINT32 u4EdidOffset;
    if(DRVCUST_InitQuery(eEdidVgaIndexOffset, &u4EdidOffset) == 0)
    {
        EEPROM_Read((UINT64)u4EdidOffset, (UPTR)&idx, 1);
    }
#endif

    if((idx+1)*VGA_EDID_SIZE > VGA_EDID_STORAGE_SIZE)
    {
        u8Offset = 0;
    }
    else
    {
        u8Offset = idx*VGA_EDID_SIZE;
    }
    //LOG(0, "read edid from eeprom\n");
#ifndef CC_DISABLE_VGA_EDID_FROM_EEP //wait for eeprom ready
    if(EEPVGAEDID_Read(u8Offset,  (UINT32) VGA_EDID_TABLE, VGA_EDID_SIZE ))
    {
        Printf("read eeprom edid fail\n");
    }
#endif

}
#endif

#ifndef CC_HDMI_EDID_DISABLE
/*
All value of Port 0 is in HDMIEDID_CEC_192k_DeepColor12B_P0
Arrangement of HDMICEC_SETTING is
Port2 CEC physical address
Port3 CEC physical address
Port4 CEC physical address
*/
UINT8 HDMICEC_SETTING[3]=
{
    0x20, // Port2 CEC physical address
    0x30, // Port2 CEC physical address
    0x40, // Port2 CEC physical address
};

UINT8 HDMIEDID_table[256] =
{
    0x00, 0xFF, 0xFF, 0xFF,  0xFF, 0xFF, 0xFF, 0x00,   0x4D, 0xD9, 0x04, 0x7F,  0x01, 0x01, 0x01, 0x01,
    0x01, 0x1C, 0x01, 0x03,  0x80, 0xA0, 0x5A, 0x78,   0x0A, 0x0D, 0xC9, 0xA0,  0x57, 0x47, 0x98, 0x27,
    0x12, 0x48, 0x4C, 0x21,  0x08, 0x00, 0x81, 0x80,   0xA9, 0xC0, 0x71, 0x4F,  0xB3, 0x00, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x01,  0x01, 0x01, 0x08, 0xE8,   0x00, 0x30, 0xF2, 0x70,  0x5A, 0x80, 0xB0, 0x58,
    0x8A, 0x00, 0x40, 0x84,  0x63, 0x00, 0x00, 0x1E,   0x02, 0x3A, 0x80, 0x18,  0x71, 0x38, 0x2D, 0x40,
    0x58, 0x2C, 0x45, 0x00,  0x40, 0x84, 0x63, 0x00,   0x00, 0x1E, 0x00, 0x00,  0x00, 0xFC, 0x00, 0x53,
    0x4F, 0x4E, 0x59, 0x20,  0x54, 0x56, 0x20, 0x20,   0x2A, 0x30, 0x30, 0x0A,  0x00, 0x00, 0x00, 0xFD,
    0x00, 0x17, 0x3E, 0x0E,  0x88, 0x3C, 0x00, 0x0A,   0x20, 0x20, 0x20, 0x20,  0x20, 0x20, 0x01, 0xB8,
    0x02, 0x03, 0x5C, 0xF0,  0x5B, 0x61, 0x60, 0x5D,   0x5E, 0x5F, 0x62, 0x1F,  0x10, 0x14, 0x05, 0x13,
    0x04, 0x20, 0x22, 0x3C,  0x3E, 0x12, 0x16, 0x03,   0x07, 0x11, 0x15, 0x02,  0x06, 0x01, 0x65, 0x66,
    0x2F, 0x0D, 0x7F, 0x07,  0x15, 0x07, 0x50, 0x35,   0x05, 0x50, 0x3D, 0x07,  0xBC, 0x57, 0x06, 0x00,
    0x83, 0x0F, 0x00, 0x00,  0x6E, 0x03, 0x0C, 0x00,   0x10, 0x00, 0xB8, 0x3C,  0x2F, 0x00, 0x80, 0x01,
    0x02, 0x03, 0x04, 0x67,  0xD8, 0x5D, 0xC4, 0x01,   0x78, 0x80, 0x01, 0xE2,  0x00, 0xCB, 0xE3, 0x05,
    0xFF, 0x01, 0xE3, 0x06,  0x0D, 0x01, 0xE5, 0x0F,   0x03, 0x00, 0x00, 0x06,  0x01, 0x1D, 0x00, 0x72,
    0x51, 0xD0, 0x1E, 0x20,  0x6E, 0x28, 0x55, 0x00,   0x40, 0x84, 0x63, 0x00,  0x00, 0x1E, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0xED
};

UINT8 HDMI2EDID_table[256] =
{
    0x00, 0xFF, 0xFF, 0xFF,  0xFF, 0xFF, 0xFF, 0x00,   0x4D, 0xD9, 0x04, 0x7F,  0x01, 0x01, 0x01, 0x01,
    0x01, 0x1C, 0x01, 0x03,  0x80, 0xA0, 0x5A, 0x78,   0x0A, 0x0D, 0xC9, 0xA0,  0x57, 0x47, 0x98, 0x27,
    0x12, 0x48, 0x4C, 0x21,  0x08, 0x00, 0x81, 0x80,   0xA9, 0xC0, 0x71, 0x4F,  0xB3, 0x00, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x01,  0x01, 0x01, 0x08, 0xE8,   0x00, 0x30, 0xF2, 0x70,  0x5A, 0x80, 0xB0, 0x58,
    0x8A, 0x00, 0x40, 0x84,  0x63, 0x00, 0x00, 0x1E,   0x02, 0x3A, 0x80, 0x18,  0x71, 0x38, 0x2D, 0x40,
    0x58, 0x2C, 0x45, 0x00,  0x40, 0x84, 0x63, 0x00,   0x00, 0x1E, 0x00, 0x00,  0x00, 0xFC, 0x00, 0x53,
    0x4F, 0x4E, 0x59, 0x20,  0x54, 0x56, 0x20, 0x20,   0x2A, 0x30, 0x30, 0x0A,  0x00, 0x00, 0x00, 0xFD,
    0x00, 0x17, 0x3E, 0x0E,  0x88, 0x3C, 0x00, 0x0A,   0x20, 0x20, 0x20, 0x20,  0x20, 0x20, 0x01, 0xB8,
    0x02, 0x03, 0x5C, 0xF0,  0x5B, 0x61, 0x60, 0x5D,   0x5E, 0x5F, 0x62, 0x1F,  0x10, 0x14, 0x05, 0x13,
    0x04, 0x20, 0x22, 0x3C,  0x3E, 0x12, 0x16, 0x03,   0x07, 0x11, 0x15, 0x02,  0x06, 0x01, 0x65, 0x66,
    0x2F, 0x0D, 0x7F, 0x07,  0x15, 0x07, 0x50, 0x35,   0x05, 0x50, 0x3D, 0x07,  0xBC, 0x57, 0x06, 0x00,
    0x83, 0x0F, 0x00, 0x00,  0x6E, 0x03, 0x0C, 0x00,   0x10, 0x00, 0xB8, 0x3C,  0x2F, 0x00, 0x80, 0x01,
    0x02, 0x03, 0x04, 0x67,  0xD8, 0x5D, 0xC4, 0x01,   0x78, 0x80, 0x01, 0xE2,  0x00, 0xCB, 0xE3, 0x05,
    0xFF, 0x01, 0xE3, 0x06,  0x0D, 0x01, 0xE5, 0x0F,   0x03, 0x00, 0x00, 0x06,  0x01, 0x1D, 0x00, 0x72,
    0x51, 0xD0, 0x1E, 0x20,  0x6E, 0x28, 0x55, 0x00,   0x40, 0x84, 0x63, 0x00,  0x00, 0x1E, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0xED
};

UINT8 HDMI8KEDID_table[256] =
{
    0x00, 0xFF, 0xFF, 0xFF,  0xFF, 0xFF, 0xFF, 0x00,   0x4D, 0xD9, 0x04, 0x7F,  0x01, 0x01, 0x01, 0x01,
    0x01, 0x1C, 0x01, 0x03,  0x80, 0xA0, 0x5A, 0x78,   0x0A, 0x0D, 0xC9, 0xA0,  0x57, 0x47, 0x98, 0x27,
    0x12, 0x48, 0x4C, 0x21,  0x08, 0x00, 0x81, 0x80,   0xA9, 0xC0, 0x71, 0x4F,  0xB3, 0x00, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x01,  0x01, 0x01, 0x08, 0xE8,   0x00, 0x30, 0xF2, 0x70,  0x5A, 0x80, 0xB0, 0x58,
    0x8A, 0x00, 0x40, 0x84,  0x63, 0x00, 0x00, 0x1E,   0x02, 0x3A, 0x80, 0x18,  0x71, 0x38, 0x2D, 0x40,
    0x58, 0x2C, 0x45, 0x00,  0x40, 0x84, 0x63, 0x00,   0x00, 0x1E, 0x00, 0x00,  0x00, 0xFC, 0x00, 0x53,
    0x4F, 0x4E, 0x59, 0x20,  0x54, 0x56, 0x20, 0x20,   0x2A, 0x30, 0x30, 0x0A,  0x00, 0x00, 0x00, 0xFD,
    0x00, 0x17, 0x3E, 0x0E,  0x88, 0x3C, 0x00, 0x0A,   0x20, 0x20, 0x20, 0x20,  0x20, 0x20, 0x01, 0xB8,
    0x02, 0x03, 0x5C, 0xF0,  0x5B, 0x61, 0x60, 0x5D,   0x5E, 0x5F, 0x62, 0x1F,  0x10, 0x14, 0x05, 0x13,
    0x04, 0x20, 0x22, 0x3C,  0x3E, 0x12, 0x16, 0x03,   0x07, 0x11, 0x15, 0x02,  0x06, 0x01, 0x65, 0x66,
    0x2F, 0x0D, 0x7F, 0x07,  0x15, 0x07, 0x50, 0x35,   0x05, 0x50, 0x3D, 0x07,  0xBC, 0x57, 0x06, 0x00,
    0x83, 0x0F, 0x00, 0x00,  0x6E, 0x03, 0x0C, 0x00,   0x10, 0x00, 0xB8, 0x3C,  0x2F, 0x00, 0x80, 0x01,
    0x02, 0x03, 0x04, 0x67,  0xD8, 0x5D, 0xC4, 0x01,   0x78, 0x80, 0x01, 0xE2,  0x00, 0xCB, 0xE3, 0x05,
    0xFF, 0x01, 0xE3, 0x06,  0x0D, 0x01, 0xE5, 0x0F,   0x03, 0x00, 0x00, 0x06,  0x01, 0x1D, 0x00, 0x72,
    0x51, 0xD0, 0x1E, 0x20,  0x6E, 0x28, 0x55, 0x00,   0x40, 0x84, 0x63, 0x00,  0x00, 0x1E, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,   0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0xED
};

UINT8 u1MhlEdid_P0[256]=
{
    0x00, 0xFF, 0xFF, 0xFF,  0xFF, 0xFF, 0xFF, 0x00,   0x36, 0x8B, 0x01, 0x00,  0x01, 0x01, 0x01, 0x01,
    0x01, 0x0F, 0x01, 0x03,  0x80, 0x3C, 0x22, 0x78,   0x0A, 0x0D, 0xC9, 0xA0,  0x57, 0x47, 0x98, 0x27,
    0x12, 0x48, 0x4C, 0xBF,  0xEF, 0x00, 0x01, 0x01,   0x01, 0x01, 0x01, 0x01,  0x01, 0x01, 0x01, 0x01,
    0x01, 0x01, 0x01, 0x01,  0x01, 0x01, 0x01, 0x1D,   0x00, 0x72, 0x51, 0xD0,  0x1E, 0x20, 0x6E, 0x28,
    0x55, 0x00, 0xC4, 0x8E,  0x21, 0x00, 0x00, 0x1E,   0x01, 0x1D, 0x80, 0x18,  0x71, 0x1C, 0x16, 0x20,
    0x58, 0x2C, 0x25, 0x00,  0xC4, 0x8E, 0x21, 0x00,   0x00, 0x9E, 0x00, 0x00,  0x00, 0xFC, 0x00, 0x4D,
    0x54, 0x4B, 0x20, 0x4C,  0x43, 0x44, 0x54, 0x56,   0x0A, 0x20, 0x20, 0x20,  0x00, 0x00, 0x00, 0xFD,
    0x00, 0x31, 0x4C, 0x0F,  0x50, 0x0E, 0x00, 0x0A,   0x20, 0x20, 0x20, 0x20,  0x20, 0x20, 0x01, 0x56,
    0x02, 0x03, 0x31, 0x74,  0x56, 0x84, 0x10, 0x1F,   0x05, 0x13, 0x14, 0x20,  0x02, 0x11, 0x06, 0x15,
    0x22, 0x4E, 0x56, 0x57,  0x59, 0x5D, 0x5E, 0x5F,   0x62, 0x63, 0x64, 0x26,  0x0F, 0x7F, 0x01, 0x17,
    0x7F, 0x18, 0x83, 0x01,  0x00, 0x00, 0x6A, 0x03,   0x0C, 0x00, 0x10, 0x00,  0xF8, 0x2D, 0x2F, 0x80,
    0x00, 0x01, 0x1D, 0x00,  0xBC, 0x52, 0xD0, 0x1E,   0x20, 0xB8, 0x28, 0x55,  0x40, 0xC4, 0x8E, 0x21,
    0x00, 0x00, 0x1E, 0x01,  0x1D, 0x80, 0xD0, 0x72,   0x1C, 0x16, 0x20, 0x10,  0x2C, 0x25, 0x80, 0xC4,
    0x8E, 0x21, 0x00, 0x00,  0x9E, 0x8C, 0x0A, 0xD0,   0x8A, 0x20, 0xE0, 0x2D,  0x10, 0x10, 0x3E, 0x96,
    0x00, 0x13, 0x8E, 0x21,  0x00, 0x00, 0x18, 0x8C,   0x0A, 0xD0, 0x90, 0x20,  0x40, 0x31, 0x20, 0x0C,
    0x40, 0x55, 0x00, 0x13,  0x8E, 0x21, 0x00, 0x00,   0x18, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x65
};

void vDrvLoadHdmiEdid2Table(void)
{
#ifndef CC_FPGA
    UINT64 u8Offset;
    UINT8 idx = 0;
    //read form eeprom or flash to VGA_EDID_TABLE

#ifdef CC_MULTI_EDID
    UINT32 u4EdidOffset;
    if(DRVCUST_InitQuery(eEdidHdmiIndexOffset, &u4EdidOffset) == 0)
    {
        EEPROM_Read((UINT64)u4EdidOffset, (UPTR)&idx, 1);
    }
#endif

    if((idx+1)*HDMI_EDID_SIZE > HDMI_EDID_STORAGE_SIZE)
    {
        u8Offset = 0;
    }
    else
    {
        u8Offset = idx*HDMI_EDID_SIZE;
    }
    //read form eeprom or flash to HDMIEDID_CEC_192k_DeepColor12B_P0
    if (EEPHDMIEDID_Read(u8Offset,  (UINT32) HDMIEDID_table, HDMI_EDID_SIZE ))
    {
        LOG(0, "read eeprom edid fail\n");
    }

#endif
}

#ifdef CC_HDMI_2_0_HDCP_BIN
#ifndef CC_MTK_LOADER
void vHDMIEDIDCLIDebug(EDID_SELECT_INFO_T* prSelectInfo);
UINT8 u1CheckCLIFlag(CLI_FLAG_T tflag);
void vSetCLIFlag(CLI_FLAG_T tflag);
#endif
void vHDMIDebugPrintf(char *str, UINT8 *pData, UINT32 u4Length)
{
    UINT32 i=0;

    if(eEdidObj.u1Level == 0)
    {
        return;
    }
    if(str!=NULL)
    {
        LOG(1, "%s", str);
    }
    for(i=0;i<u4Length;i++)
    {
        if((i%16) == 0)
        {
            Printf("\n");
        }
        Printf("0x%02x,",pData[i]);
    }
    Printf("\n");
}

void vHDMIEDIDGetPlatformType(UINT8 *pu1Info)
{
    EEPROM_Read(0x10000, (UPTR)(pu1Info), 0x1);
}

void vHDMIEDIDGet4K2K(UINT8 *pu1Info)
{
    UINT32 u4Value = 0;
    //bit[1:0], 0:2k, 1:4k 2:8k 3:8k
    EEPROM_Read(0x10010, (UPTR)(&u4Value), 0x1);
    *pu1Info = (UINT8)(u4Value&0x03);
}

void vHDMIEDIDGetDolbyVision(UINT8 *pu1Info)
{
    UINT32 u4Value = 0;
    //1:dolby vision, 0:none.
    EEPROM_Read(0x1020c, (UPTR)(&u4Value), 0x1);
    *pu1Info = (u4Value>0)?1:0;
}

void vHDMIEDIDGetHdmi21Bridge(UINT8 *pu1Info)
{
    UINT32 u4Value = 0;
    /* 1: HDMI2.1 bridge, 0: none */
    EEPROM_Read(0x1008F, (UPTR)(&u4Value), 0x1);
    *pu1Info = u4Value & 0x01;
}

void vHDMIEDIDGetBankNum(UINT8 *pu1Info)
{
    EEPROM_Read(0x1008E, (UPTR)(pu1Info), 0x1);
}

void vHDMIEDIDGetCBA(UINT8 *pu1Info)
{
    *pu1Info = 0;
}

void vHDMIEDIDGetDestination(UINT8 *pu1Info)
{
    EEPROM_Read(0x10200, (UPTR)(pu1Info), 0x1);
}

void vHDMIEDIDGet3D(UINT8 *pu1Info)
{
    EEPROM_Read(0x10206, (UPTR)(pu1Info), 0x1);
}

void vHDMIEDIDGetHDR(UINT8 *pu1Info)
{
    EEPROM_Read(0x10209, (UPTR)(pu1Info), 0x1);
}

void vHDMIEDIDGetHFVSDBFlag(UINT8 *pu1hfvsdbInfo)
{
    EEPROM_Read(0x38E, (UPTR)(pu1hfvsdbInfo), 0x1);
}
void vHDMIEDIDSetHFVSDBFlag(UINT8 *pu1hfvsdbInfo)
{
    EEPROM_Write(0x38E, (UPTR)(pu1hfvsdbInfo), 0x1);
}

void vHDMIEDIDGetLDDDP(UINT8 *pu1LDDP)
{
    EEPROM_Read(0x38F, (UPTR)(pu1LDDP), 0x1);
}

void vHDMIEDIDSetLDDDP(UINT8 *pu1LDDP)
{
    EEPROM_Write(0x38F, (UPTR)(pu1LDDP), 0x1);
}

#if defined(__KERNEL__)&&!defined(CC_UBOOT)
extern struct platform_device request_edid_device;
struct device* pHDMIEDIDGetDevice(void)
{
    struct device *dev = &request_edid_device.dev;
    if (IS_ERR(eEdidObj.pDevice))
    {
       LOG(0,"[EDID]request device fail\n");
       return NULL;
    }
    LOG(0,"[EDID]dev =%p.\n",dev);
    return dev;
}
#endif

BOOL bEEPHDMIEDIDRead(UPTR u4MemPtr, UINT32 u4MemLen, UINT32 u4Offset)
{
    INT32 i4Ret = 0;
    UINT32 u4PartId = 0;

    if(u4Offset >= (HDMI_EDID_SUPPORT_MAXNUM * 512) + 1024)
    {
        LOG(0, "[EDID]offset reach max\n");
        return FALSE;
    }
    i4Ret = DRVCUST_InitQuery(eEdidHdmi2StandardFlashId,&u4PartId);
    if(i4Ret != 0)
    {
        return FALSE;
    }
    i4Ret = EEPHDMI_Read(u4PartId, (UINT64)u4Offset, u4MemPtr, u4MemLen, 0xFFFF);
    LOG(1,"[EDID]PartId:0x%x ,u4MemLen:0x%x, Ret:0x%x\n",u4PartId, u4MemLen, i4Ret);
    if(i4Ret)
    {
        return FALSE;
    }

    return TRUE;
}

BOOL bHDMIEDIDCreatSelectInfo(EDID_SELECT_INFO_T* prSelectInfo, UINT8 *pEdid14, UINT8 *pEdid20, UINT8 *pEdid8K)
{
#ifdef CC_PANEL_FROM_FLASH
    UINT32 u4PanelCtrl;
#endif

    if(prSelectInfo == NULL)
    {
        return FALSE;
    }
    x_memset(prSelectInfo, 0, sizeof(EDID_SELECT_INFO_T));

    vHDMIEDIDGetCBA(&prSelectInfo->u1CBA);
    vHDMIEDIDGetPlatformType(&prSelectInfo->u1Platform);
    vHDMIEDIDGetDestination(&prSelectInfo->u1MVIDestination);
    vHDMIEDIDGet3D(&prSelectInfo->u1MVINO_3D);
    vHDMIEDIDGetHDR(&prSelectInfo->u1HDR);
    vHDMIEDIDGetHFVSDBFlag(&prSelectInfo->u1HFVSDBFlag);
    vHDMIEDIDGetLDDDP(&prSelectInfo->u1ATMOS);
    vHDMIEDIDGet4K2K(&prSelectInfo->u14K2K);
    vHDMIEDIDGetBankNum(&prSelectInfo->u1BankNum);
    vHDMIEDIDGetDolbyVision(&prSelectInfo->u1DolbyVision);
	vHDMIEDIDGetHdmi21Bridge(&prSelectInfo->u1Hdmi21Bridge);

#ifdef CC_PANEL_FROM_FLASH
    u4PanelCtrl =  FlashPanel_GetControlWord3();
    prSelectInfo->u4PanelCtrl = u4PanelCtrl;
    prSelectInfo->u1Panel_less = ((u4PanelCtrl>>31) & (0x1))? 0 : 1;
    prSelectInfo->u1Panel3DType = (u4PanelCtrl & (0x0C000000))>>26;   // modify at Oct11; from "(0x70000000))>>28"
    prSelectInfo->u1PanelWCG = (u4PanelCtrl & 0x3);
    prSelectInfo->u4PanleSize = FlashPanel_GetInchSize();  // need to change to panelSizeApi;
#else
    prSelectInfo->u1Panel_less = 0;
    prSelectInfo->u1Panel3DType = 0;
    prSelectInfo->u1PanelWCG = 0;
    prSelectInfo->u4PanleSize = 0x38;
#endif

#ifndef CC_MTK_LOADER
    vHDMIEDIDCLIDebug(prSelectInfo);
#endif
    prSelectInfo->u2BlockOffset = 0;
    prSelectInfo->u1BlockFlag = 0;
    prSelectInfo->pTargetMIDEDID = pEdid14;
    prSelectInfo->pTargetSIDEDID = pEdid20;
    prSelectInfo->pTargetXIDEDID = pEdid8K;
    x_memset(prSelectInfo->pTargetXIDEDID, 0, 256);
    prSelectInfo->pEepBlock = eEdidObj.pData;
    eEdidObj.u1TI4Flag = prSelectInfo->u1HFVSDBFlag;
    return TRUE;
}

/*
 * To avoid allocating too many memories to store the firmware,
 * we only checkout the matched whole block and store the related addresses.
 * @u1Type, 0:search emmc data  !0:search firmware data.
 */
BOOL bHDMIEDIDSearchFirmware(EDID_SELECT_INFO_T* prSelectInfo, UINT8 u1Type, UINT8 *pFW, UINT32 u4Size)
{
    UINT8 u1HeaderSize = 0x40;
    UINT32 u4Offset = 0;
    UINT32 u4NextOffset = 0;
    char pHeaderFlag[7] = "FMT300";
    UINT8 *pEDIDEepData = NULL;

    pEDIDEepData = u1Type? pFW : prSelectInfo->pEepBlock;
    LOG(1, "[EDID]*******************Search Whole Block******************\n");
    while(1)
    {
        if(!u1Type)
        {
            if(bEEPHDMIEDIDRead((UPTR)pEDIDEepData, (UINT32)u1HeaderSize, u4Offset) == FALSE)
            {
                LOG(0, "[EDID]EEP Read Fail!\n");
                return FALSE;
            }
        }
        if(x_memcmp(pEDIDEepData, pHeaderFlag,6) != 0)
        {
            LOG(1, "[EDID]reach end, current offset:0x%x\n", u4Offset);
            break;
        }
        u4NextOffset = GET_BLOCK_END_ADDR(pEDIDEepData) + 1;
        if(u4NextOffset < u4Offset)
        {
            LOG(0, "[EDID]edid struct error!\n");
            break;
        }
        LOG(1, "[EDID]Current Offset:0x%x, Next Offset:0x%x\n", u4Offset, u4NextOffset);
        LOG(1, "[EDID]Current Edid Bank is 0x%x\n",*(pEDIDEepData + 0x06));
        if(GET_BANK_NUM(pEDIDEepData) != prSelectInfo->u1BankNum)
        {
            if(GET_BANK_NUM(pEDIDEepData) == 0)
            {
                //save bank[0] offset
                prSelectInfo->u2BlockOffset = u4Offset;
                prSelectInfo->u2BlockSize = u4NextOffset - u4Offset -1;
                prSelectInfo->u1BlockFlag = 2;
            }
            u4Offset = u4NextOffset;
            pEDIDEepData = u1Type? (pFW + u4Offset) : pEDIDEepData;
            continue;
        }
        prSelectInfo->u2BlockOffset = u4Offset;
        prSelectInfo->u2BlockSize = u4NextOffset - u4Offset -1;
        prSelectInfo->u1BlockFlag = 1;
        break;
    }

    if(prSelectInfo->u1BlockFlag == 0)
    {
        LOG(0, "[EDID]No Active Edid\n");
        return FALSE;
    }
    if(u1Type)
    {
        /*copy the matched whole block from the firmware.*/
        x_memcpy(prSelectInfo->pEepBlock, pFW + prSelectInfo->u2BlockOffset, prSelectInfo->u2BlockSize);
    }
    else
    {
        /*copy the matched whole block from emmc.*/
        if(bEEPHDMIEDIDRead((UPTR)(prSelectInfo->pEepBlock), (UINT32)prSelectInfo->u2BlockSize, prSelectInfo->u2BlockOffset) == FALSE)
        {
            LOG(0, "[EDID]EEP Read Fail!\n");
            return FALSE;
        }
    }

    pEDIDEepData = prSelectInfo->pEepBlock;
    if((prSelectInfo->u2BlockOffset > GET_TABLE_ADDR(pEDIDEepData))||\
            (prSelectInfo->u2BlockOffset > GET_BLOCK_START_ADDR(pEDIDEepData)))
    {
        LOG(0, "[EDID]edid internal address error!\n");
        return FALSE;
    }
    prSelectInfo->u4TableIDAddr= GET_TABLE_ADDR(pEDIDEepData) - prSelectInfo->u2BlockOffset;
    prSelectInfo->u4EepHeaderAddr = GET_BLOCK_START_ADDR(pEDIDEepData) - prSelectInfo->u2BlockOffset;
    prSelectInfo->u4EepBlockEndAddr = GET_BLOCK_END_ADDR(pEDIDEepData) - prSelectInfo->u2BlockOffset;
    prSelectInfo->u2TableSize = prSelectInfo->u4EepHeaderAddr - prSelectInfo->u4TableIDAddr;
    if(prSelectInfo->u2TableSize > 512)
    {
        prSelectInfo->u2TableSize = 512;
    }
    LOG(0, "[EDID]match edid block, offset:0x%x, block flag:0x%x, firmware:%d\n", \
            prSelectInfo->u2BlockOffset, prSelectInfo->u1BlockFlag, u1Type);
    LOG(0, "[EDID]Table Size:0x%x, ID Addr:0x%x, Start Data addr:0x%x, End addr:0x%x\n",\
            prSelectInfo->u2TableSize, prSelectInfo->u4TableIDAddr + prSelectInfo->u2BlockOffset , \
            prSelectInfo->u4EepHeaderAddr + prSelectInfo->u2BlockOffset , \
            prSelectInfo->u4EepBlockEndAddr + prSelectInfo->u2BlockOffset);
    return TRUE;
}

BOOL bHDMIEDIDGetWholeBlock(EDID_SELECT_INFO_T* prSelectInfo)
{
#if defined(__KERNEL__)&&!defined(CC_UBOOT)
    const struct firmware *pfw;
    struct device* pdev;
#endif
    if((prSelectInfo == NULL) || (prSelectInfo->pEepBlock == NULL))
    {
        LOG(0, "EDID Buffer Error\n");
        return FALSE;
    }

#if defined(__KERNEL__)&&!defined(CC_UBOOT)
    /*For EDID A/B Update*/
    if(eEdidObj.u1ReqFWDone == 0)
    {
        if(!(pdev = pHDMIEDIDGetDevice()))
        {
            LOG(0, "[EDID]Get Device Fail!\n");
            return FALSE;
        }
        if(request_firmware(&pfw, EDID_FW_NAME, pdev) == 0)
        {
            eEdidObj.u1ReqFWDone = 0x1;
            LOG(0,"[EDID]request_edid_firmware:%s, size:%d\n", EDID_FW_NAME, pfw->size);
        }
        else if(request_firmware(&pfw, EDID_FW_BASE_NAME, pdev) == 0)
        {
            eEdidObj.u1ReqFWDone = 0x2;
            LOG(0,"[EDID]request_edid_firmware:%s, size:%d\n", EDID_FW_BASE_NAME, pfw->size);
        }

        if(eEdidObj.u1ReqFWDone)
        {
            if(bHDMIEDIDSearchFirmware(prSelectInfo, eEdidObj.u1ReqFWDone, (UINT8*)pfw->data, pfw->size) == FALSE)
            {
                eEdidObj.u1ReqFWDone = 0;
                release_firmware(pfw);
                return FALSE;
            }
            release_firmware(pfw);
        }
        else
        {
            if(bHDMIEDIDSearchFirmware(prSelectInfo, 0, NULL, 0) == FALSE)
            {
                return FALSE;
            }
        }

        /*Store the related address for next edid making*/
        eEdidObj.u1BankNum = prSelectInfo->u1BankNum;
        eEdidObj.u2BlockOffset = prSelectInfo->u2BlockOffset;
        eEdidObj.u1BlockFlag = prSelectInfo->u1BlockFlag;
        eEdidObj.u2TableSize = prSelectInfo->u2TableSize;
        eEdidObj.u4TableIDAddr = prSelectInfo->u4TableIDAddr;
        eEdidObj.u4HeaderStartAddr = prSelectInfo->u4EepHeaderAddr;
        eEdidObj.u4HeaderEndAddr = prSelectInfo->u4EepBlockEndAddr;
        return TRUE;
    }
#endif
    if(eEdidObj.u1ReqFWDone)
    {
        prSelectInfo->u2BlockOffset = eEdidObj.u2BlockOffset;
        prSelectInfo->u1BlockFlag = eEdidObj.u1BlockFlag;
        prSelectInfo->u2TableSize = eEdidObj.u2TableSize;
        prSelectInfo->u4TableIDAddr = eEdidObj.u4TableIDAddr;
        prSelectInfo->u4EepHeaderAddr = eEdidObj.u4HeaderStartAddr;
        prSelectInfo->u4EepBlockEndAddr = eEdidObj.u4HeaderEndAddr;
        LOG(0, "[EDID]match edid block, offset:0x%x, block flag:0x%x, firmware:%d\n", \
                eEdidObj.u2BlockOffset, eEdidObj.u1BlockFlag, eEdidObj.u1ReqFWDone);
        LOG(0, "[EDID]Table Size:0x%x, ID Addr:0x%x, Start Data addr:0x%x, End addr:0x%x\n",\
                eEdidObj.u2TableSize, eEdidObj.u4TableIDAddr + eEdidObj.u2BlockOffset , \
                eEdidObj.u4HeaderStartAddr + eEdidObj.u2BlockOffset , eEdidObj.u4HeaderEndAddr + eEdidObj.u2BlockOffset);
        return TRUE;
    }
    return FALSE;
}

void vHDMIEDIDPrintfSelectInfo(EDID_SELECT_INFO_T* prSelectInfo)
{
    LOG(1, "[EDID]MVIDestination:0x%x\n", prSelectInfo->u1MVIDestination);
    LOG(1, "[EDID]MVINO_3D:0x%x\n", prSelectInfo->u1MVINO_3D);
    LOG(1, "[EDID]IT4:0x%x\n", prSelectInfo->u1HFVSDBFlag);
    LOG(1, "[EDID]HDR:0x%x\n", prSelectInfo->u1HDR);
    LOG(1, "[EDID]LDDDP:0x%x\n", prSelectInfo->u1ATMOS);
    LOG(1, "[EDID]Panel ControlWord3:0x%x\n", prSelectInfo->u4PanelCtrl);
    LOG(1, "[EDID]Panel less:0x%x\n", prSelectInfo->u1Panel_less);
    LOG(1, "[EDID]Panel3DType:0x%x\n", prSelectInfo->u1Panel3DType);
    LOG(1, "[EDID]PanelWCG:0x%x\n", prSelectInfo->u1PanelWCG);
    LOG(1, "[EDID]PanelSize:0x%x\n", prSelectInfo->u4PanleSize);
    LOG(1, "[EDID]Platform:0x%x\n", prSelectInfo->u1Platform);
    LOG(1, "[EDID]4K2K:0x%x\n", prSelectInfo->u14K2K);
    LOG(1, "[EDID]BankNum:0x%x\n", prSelectInfo->u1BankNum);
    LOG(1, "[EDID]Dolby Vision:0x%x\n", prSelectInfo->u1DolbyVision);
	LOG(1, "[EDID]Hdmi2.1 bridge:0x%x\n", prSelectInfo->u1Hdmi21Bridge);
    if(prSelectInfo->u1Platform >= 0x04)
    {
        LOG(1,"[EDID]M3 platform\n");
    }
    else
    {
        LOG(1,"[EDID]Trinity platform\n");
    }
}

BOOL bHDMIEDIDGetTrinityMIDAndSID(EDID_SELECT_INFO_T* prSelectInfo ,Trinity_Table_T* prSelectTable)
{
    UINT32 u4Offset = 0;
    UINT16 u2Count, u2TableSize;
    Trinity_Table_T rSelectTableSrc;
    UINT8* pEDIDEepData = NULL;

    if(prSelectInfo == NULL)
    {
        return FALSE;
    }

    //Make search data
    if(prSelectInfo->u1MVIDestination == 0xF)
    {
        prSelectTable->u1JPN_WW = 1;
    }
    if((prSelectInfo->u1MVINO_3D == 0)&&(prSelectInfo->u1Panel3DType != 0))
    {
        prSelectTable->u12D3D = 1;
    }
    if(prSelectInfo->u1PanelWCG == 0)
    {
        prSelectTable->u1BT20201 = 0;
        prSelectTable->u1xvYCC = 0;
    }
    else
    {
        prSelectTable->u1BT20201 = 1;
        prSelectTable->u1xvYCC = 1;
    }
    prSelectTable->u1CBA = prSelectInfo->u1CBA;
    prSelectTable->u1HDR = prSelectInfo->u1HDR;
    prSelectTable->u1ATMOS = prSelectInfo->u1ATMOS;
    prSelectTable->u1Panel_less = prSelectInfo->u1Panel_less;

#ifndef CC_MTK_LOADER
    if(u1CheckCLIFlag(CLI_FLAG_SETID))
    {
        LOG(0, "[EDID]Set fixed MID_ID:0x%x, SID_ID:0x%x\n", prSelectInfo->u4MID, prSelectInfo->u4SID);
        return TRUE;
    }
    if(u1CheckCLIFlag(CLI_FLAG_SEARCH))
    {
        x_memcpy(prSelectTable, eEdidObj.eCLI.pu1SearchData, 16);
        LOG(0, "[EDID]Set fixed search condition, 0x%2x%2x%2x%2x\n", \
                eEdidObj.eCLI.pu1SearchData[2],\
                eEdidObj.eCLI.pu1SearchData[3],\
                eEdidObj.eCLI.pu1SearchData[4],\
                eEdidObj.eCLI.pu1SearchData[5]);
    }
#endif

    vHDMIDebugPrintf("[EDID]Target Eep Header:", (UINT8 *)prSelectTable, 16);
    LOG(1, "[EDID]*******************Search EEP Header******************\n");

    //Calculate MID&SID
    if(prSelectTable->u1CBA == 1)
    {
        if(prSelectTable->u1JPN_WW == 1)
        {
            prSelectInfo->u4MID = 0x01F100;
            prSelectInfo->u4SID = 0x01FC00;
        }
        else
        {
            prSelectInfo->u4MID = 0x01F000;
            prSelectInfo->u4SID = 0x01F600;
        }
    }
    else if(prSelectTable->u1Panel_less == 1)
    {
        if(prSelectTable->u1JPN_WW == 1)
        {
            prSelectInfo->u4MID = 0x023700;
            prSelectInfo->u4SID = 0x023F01;
        }
        else
        {
            prSelectInfo->u4MID = 0x023300;
            prSelectInfo->u4SID = 0x023B01;
        }
    }
    else
    {
        //Read whole header
        u4Offset = prSelectInfo->u4TableIDAddr;
        u2TableSize = prSelectInfo->u2TableSize;
        pEDIDEepData = prSelectInfo->pEepBlock;
        for(u2Count = 0; u2Count < (u2TableSize/16); u2Count++)
        {
            x_memset(&rSelectTableSrc, 0, sizeof(Trinity_Table_T));
            x_memcpy(&rSelectTableSrc, (pEDIDEepData + u2Count*16 + u4Offset), 16);
            rSelectTableSrc.u4MID_ID = (rSelectTableSrc.u1MID_ID_Byte2<<16) |\
                                       (rSelectTableSrc.u1MID_ID_Byte1<<8) |\
                                       rSelectTableSrc.u1MID_ID_Byte0;
            rSelectTableSrc.u4SID_ID = (rSelectTableSrc.u1SID_ID_Byte2<<16)|\
                                       (rSelectTableSrc.u1SID_ID_Byte1<<8) |\
                                       rSelectTableSrc.u1SID_ID_Byte0;

            LOG(1, "[EDID]Header Addr:0x%x\n", prSelectInfo->u2BlockOffset + u2Count*16 + u4Offset);
            vHDMIDebugPrintf(NULL, (UINT8 *)&rSelectTableSrc, 16);

            if(x_memcmp(prSelectTable, (UINT8 *)&rSelectTableSrc, 6) == 0) //Compare 6 Bytes
            {
                break;
            }
        }
        if(u2Count>= (u2TableSize/16))
        {
            prSelectInfo->u4MID = 0x01ED00;
            prSelectInfo->u4SID = 0x01ED00;
        }
        else
        {
            prSelectInfo->u4MID = rSelectTableSrc.u4MID_ID;
            prSelectInfo->u4SID = rSelectTableSrc.u4SID_ID;
        }
    }
    LOG(1, "[EDID]Trinity MID_ID:0x%x, SID_ID:0x%x\n", prSelectInfo->u4MID, prSelectInfo->u4SID);
    return TRUE;
}

BOOL bHDMIEDIDGetM3MIDAndSID(EDID_SELECT_INFO_T* prSelectInfo ,M3_Table_T* prSelectTable)
{
    UINT32 u4Offset = 0;
    UINT16 u2Count, u2TableSize;
    M3_Table_T rSelectTableSrc;
    UINT8* pEDIDEepData = NULL;

    if(prSelectInfo == NULL)
    {
        return FALSE;
    }

    //Make search data
    if(prSelectInfo->u1MVIDestination == 0xF)
    {
        prSelectTable->u1JPN_WW = 1;
    }
    if((prSelectInfo->u1MVINO_3D == 0)&&(prSelectInfo->u1Panel3DType != 0))
    {
        prSelectTable->u12D3D = 1;
    }
    if(prSelectInfo->u1PanelWCG == 0)
    {
        prSelectTable->u1BT20201 = 0;
        prSelectTable->u1xvYCC = 0;
    }
    else
    {
        prSelectTable->u1BT20201 = 1;
        prSelectTable->u1xvYCC = 1;
    }
    prSelectTable->u1CBA = prSelectInfo->u1CBA;
    prSelectTable->u1HDR = prSelectInfo->u1HDR;
    prSelectTable->u1ATMOS = prSelectInfo->u1ATMOS;
    prSelectTable->u1Panel_less = prSelectInfo->u1Panel_less;
    prSelectTable->u14K2K = prSelectInfo->u14K2K;
    prSelectTable->u1DolbyVision = prSelectInfo->u1DolbyVision;
	prSelectTable->u1Hdmi21Bridge = prSelectInfo->u1Hdmi21Bridge;

#ifndef CC_MTK_LOADER
    if(u1CheckCLIFlag(CLI_FLAG_SETID))
    {
        LOG(0, "[EDID]Set fixed MID_ID:0x%x, SID_ID:0x%x, XID_ID:0x%x\n", prSelectInfo->u4MID, prSelectInfo->u4SID, prSelectInfo->u4XID);
        return TRUE;
    }
    if(u1CheckCLIFlag(CLI_FLAG_SEARCH))
    {
        x_memcpy(prSelectTable, eEdidObj.eCLI.pu1SearchData, 16);
        LOG(0, "[EDID]Set fixed search condition, 0x%2x%2x%2x%2x\n", \
                eEdidObj.eCLI.pu1SearchData[2],\
                eEdidObj.eCLI.pu1SearchData[3],\
                eEdidObj.eCLI.pu1SearchData[4],\
                eEdidObj.eCLI.pu1SearchData[5]);
    }
#endif

    vHDMIDebugPrintf("[EDID]Target Eep Header:", (UINT8 *)prSelectTable, 16);
    LOG(1, "[EDID]*******************Search EEP Header******************\n");

    //Calculate MID&SID
    if(prSelectTable->u1CBA == 1)
    {
        if(prSelectTable->u14K2K == 1)
        {
            prSelectInfo->u4MID = 0x04C7;
            prSelectInfo->u4SID = 0x04C9;
        }
        else
        {
            prSelectInfo->u4MID = 0x0507;
            prSelectInfo->u4SID = 0x0507;
        }
    }
    else if(prSelectTable->u1Panel_less == 1)
    {
        if(prSelectTable->u1JPN_WW == 1)
        {
            if(prSelectTable->u14K2K == 1)
            {
                prSelectInfo->u4MID = 0x04C4;
                prSelectInfo->u4SID = 0x04C6;
            }
            else
            {
                prSelectInfo->u4MID = 0x0506;
                prSelectInfo->u4SID = 0x0506;
            }
        }
        else
        {
            if(prSelectTable->u14K2K == 1)
            {
                prSelectInfo->u4MID = 0x04C3;
                prSelectInfo->u4SID = 0x04C5;
            }
            else
            {
                prSelectInfo->u4MID = 0x0505;
                prSelectInfo->u4SID = 0x0505;
            }
        }
    }
    else
    {
        //Read whole header
        u4Offset = prSelectInfo->u4TableIDAddr;
        u2TableSize = prSelectInfo->u2TableSize;
        pEDIDEepData = prSelectInfo->pEepBlock;
        for(u2Count = 0; u2Count < (u2TableSize/16); u2Count++)
        {
            x_memset(&rSelectTableSrc, 0, sizeof(M3_Table_T));
            x_memcpy(&rSelectTableSrc, (pEDIDEepData + u2Count*16 + u4Offset), 16);
            rSelectTableSrc.u4MID_ID = (rSelectTableSrc.u1MID_ID_Byte1<<8) | rSelectTableSrc.u1MID_ID_Byte0;
            rSelectTableSrc.u4SID_ID = (rSelectTableSrc.u1SID_ID_Byte1<<8) | rSelectTableSrc.u1SID_ID_Byte0;
            rSelectTableSrc.u4XID_ID = (rSelectTableSrc.u1XID_ID_Byte1<<8) | rSelectTableSrc.u1XID_ID_Byte0;

            LOG(1, "[EDID]Header Addr:0x%x\n", prSelectInfo->u2BlockOffset + u2Count*16 + u4Offset);
            vHDMIDebugPrintf(NULL, (UINT8 *)&rSelectTableSrc, 16);

            if(x_memcmp(prSelectTable, &rSelectTableSrc, 6) == 0) //Compare 6 Bytes
            {
                break;
            }
        }
        if(u2Count>= (u2TableSize/16))
        {
            prSelectInfo->u4MID = 0x04CB;
            prSelectInfo->u4SID = 0x04CB;
            prSelectInfo->u4XID = 0;
        }
        else
        {
            prSelectInfo->u4MID = rSelectTableSrc.u4MID_ID;
            prSelectInfo->u4SID = rSelectTableSrc.u4SID_ID;
            prSelectInfo->u4XID = rSelectTableSrc.u4XID_ID;
        }
    }
    LOG(1, "[EDID]M3 MID_ID:0x%x, SID_ID:0x%x, XID_ID:0x%x\n", \
        prSelectInfo->u4MID, prSelectInfo->u4SID, prSelectInfo->u4XID);
    return TRUE;
}

BOOL bHDMIEDIDGetMIDAndSIDAndXID(EDID_SELECT_INFO_T* prSelectInfo)
{
    if(prSelectInfo == NULL)
    {
        return FALSE;
    }
    x_memset(&prSelectInfo->uSelect, 0, sizeof(uSelectTable));

    //to do in detail
    if(prSelectInfo->u1Platform >= 0x04)
    {
        return bHDMIEDIDGetM3MIDAndSID(prSelectInfo, &prSelectInfo->uSelect.M3Table);
    }
    else
    {
        return bHDMIEDIDGetTrinityMIDAndSID(prSelectInfo, &prSelectInfo->uSelect.TrinityTable);
    }

    return TRUE;
}

BOOL bHDMIEDIDSearchIDData(EDID_SELECT_INFO_T* prSelectInfo)
{
    UINT16 u2Count;
    UINT32 u4Offset, u4EdidID;
    UINT8 u1SearchResult = 0;
    UINT8* pEDIDEepData = NULL;

    if(prSelectInfo == NULL)
    {
        return FALSE;
    }

    if((prSelectInfo->pEepBlock == NULL)||\
            (prSelectInfo->pTargetMIDEDID == NULL)||\
            (prSelectInfo->pTargetSIDEDID == NULL)||\
            (prSelectInfo->pTargetXIDEDID == NULL))
    {
        LOG(0, "[EDID]Buffer NULL\n");
        return FALSE;
    }

    LOG(1, "[EDID]*******************Search ID Data******************\n");

    pEDIDEepData = prSelectInfo->pEepBlock;
    for(u2Count = 0; u2Count < HDMI_EDID_SUPPORT_MAXNUM; u2Count++)//u2TableSize*2, MID and SID
    {
        u4Offset = prSelectInfo->u4EepHeaderAddr + u2Count*512;
        if(u4Offset > (prSelectInfo->u4EepBlockEndAddr))
        {
            LOG(0, "[EDID]Error, reach end of the edid block!\n");
            return FALSE;
        }

        //to do in detail
        if(prSelectInfo->u1Platform >= 0x04)//m3
        {
            u4EdidID = (*(pEDIDEepData + 2 + u4Offset)<<8) |(*(pEDIDEepData + 3 + u4Offset));
        }
        else
        {
            u4EdidID = (*(pEDIDEepData + 2 + u4Offset)<<16) | (*(pEDIDEepData + 3 + u4Offset)<<8) | (*(pEDIDEepData + 4 + u4Offset));
        }

        LOG(1, "[EDID]Current ID: 0x%x, addr:0x%x\n", u4EdidID, prSelectInfo->u2BlockOffset + u4Offset);
        vHDMIDebugPrintf(NULL, pEDIDEepData + u4Offset, 16);

        if(u4EdidID == prSelectInfo->u4MID)
        {
            u1SearchResult |= 0x01;
            prSelectInfo->u4EepMIDStartAddr = u4Offset + 16;
            LOG(1, "[EDID]MID Data found, start addr:0x%x\n\n\n",prSelectInfo->u4EepMIDStartAddr + prSelectInfo->u2BlockOffset);
            LOG(1, "[EDID]*******************Found MID Data******************\n");
        }

        if(u4EdidID == prSelectInfo->u4SID)
        {
            u1SearchResult |= 0x02;
            prSelectInfo->u4EepSIDStartAddr = u4Offset + 16;
            LOG(1, "[EDID]SID Data found, start addr:0x%x\n\n\n",prSelectInfo->u4EepSIDStartAddr + prSelectInfo->u2BlockOffset);
            LOG(1, "[EDID]*******************Found SID Data******************\n");
        }

        if(u4EdidID == prSelectInfo->u4XID)
        {
            u1SearchResult |= 0x04;
            prSelectInfo->u4EepXIDStartAddr = u4Offset + 16;
            LOG(1, "[EDID]XID Data found, start addr:0x%x\n\n\n",prSelectInfo->u4EepXIDStartAddr + prSelectInfo->u2BlockOffset);
            LOG(1, "[EDID]*******************Found XID Data******************\n");
        }

        if(((prSelectInfo->u4XID == 0)&&(u1SearchResult == 0x03))||\
            ((prSelectInfo->u4XID != 0)&&(u1SearchResult == 0x07)))
        {
            break;
        }
    }

    if(((prSelectInfo->u4XID == 0)&&(u1SearchResult != 0x03))||\
        ((prSelectInfo->u4XID != 0)&&(u1SearchResult != 0x07)))
    {
        LOG(0, "[EDID]Error, Search Result:0x%x!\n",u1SearchResult);
        return FALSE;
    }

    x_memcpy(prSelectInfo->pTargetMIDEDID, (pEDIDEepData + prSelectInfo->u4EepMIDStartAddr), 256);
    x_memcpy(prSelectInfo->pTargetSIDEDID, (pEDIDEepData + prSelectInfo->u4EepSIDStartAddr), 256);

    if(prSelectInfo->u4XID)
    {
        x_memcpy(prSelectInfo->pTargetXIDEDID, (pEDIDEepData + prSelectInfo->u4EepXIDStartAddr), 256);
    }
    return TRUE;
}

void vHDMIEDIDCalculateChecksum(UINT8 *pu1EdidData)
{
    UINT8 u1CheckSum = 0;
    UINT8 i;

    for(i=0; i<=0x7E; i++)
    {
        u1CheckSum += *(pu1EdidData + i);
    }
    *(pu1EdidData + 0x7F) = 0x100 - u1CheckSum;

    u1CheckSum = 0;
    for(i=0x80; i<=0xFE; i++)
    {
        u1CheckSum += *(pu1EdidData + i);
    }
    *(pu1EdidData + 0xFF) = 0x100 - u1CheckSum;
}

BOOL bHDMIEDIDGetDisplaySize(EDID_SELECT_INFO_T* prSelectInfo)
{
    UINT32 u4DisplaySizeHTemp, u4DisplaySizeVTemp, u4DisplaySizeH, u4DisplaySizeV;

    if(prSelectInfo == NULL)
    {
        return FALSE;
    }

    u4DisplaySizeHTemp = ((UINT32)(16 * prSelectInfo->u4PanleSize * 2540 * 1000) / 183576);
    u4DisplaySizeVTemp = ((UINT32)(9 * prSelectInfo->u4PanleSize * 2540 * 1000)/ 183576);

    u4DisplaySizeH = (u4DisplaySizeHTemp + 5)/10;
    u4DisplaySizeV = (u4DisplaySizeVTemp + 5)/10;

    prSelectInfo->u1DisByte0 = (u4DisplaySizeHTemp +50)/100;
    prSelectInfo->u1DisByte1 = (u4DisplaySizeVTemp +50)/100;

    prSelectInfo->u1ImageByte0 = (UINT8)u4DisplaySizeH;
    prSelectInfo->u1ImageByte1 = (UINT8)u4DisplaySizeV;
    prSelectInfo->u1ImageByte2 = (((u4DisplaySizeH>>8)&0x0F)<<4) |((u4DisplaySizeV>>8)&0x0F);

    LOG(1, "[EDID]Display Size:0x%x 0x%x\n", \
            prSelectInfo->u1DisByte0, \
            prSelectInfo->u1DisByte1);
    LOG(1, "[EDID]Image Size:0x%x 0x%x 0x%x\n\n", \
            prSelectInfo->u1ImageByte0, \
            prSelectInfo->u1ImageByte1, \
            prSelectInfo->u1ImageByte2);

    return TRUE;
}

BOOL _bHDMIEDIDFixDisplaySize(EDID_SELECT_INFO_T* prSelectInfo, UINT8 u1Type)
{
    UINT8 u1Count, u1ImageSizeAddr;
    UINT8 *pu1EdidData = NULL;
    UINT32 u4EepStartAddr;

    if(u1Type == EDID_SPEC_TYPE_SID)
    {
        u4EepStartAddr = prSelectInfo->u4EepSIDStartAddr;
        pu1EdidData = prSelectInfo->pTargetSIDEDID;
    }
    else if(u1Type == EDID_SPEC_TYPE_MID)
    {
        u4EepStartAddr = prSelectInfo->u4EepMIDStartAddr;
        pu1EdidData = prSelectInfo->pTargetMIDEDID;
    }
    else if(u1Type == EDID_SPEC_TYPE_XID)
    {
        u4EepStartAddr = prSelectInfo->u4EepXIDStartAddr;
        pu1EdidData = prSelectInfo->pTargetXIDEDID;
    }
    else
    {
        return FALSE;
    }
    //Change eep infromation
    for(u1Count=1; u1Count<=0xf; u1Count++)
    {
        u1ImageSizeAddr = *(prSelectInfo->pEepBlock+ u4EepStartAddr + 256 + u1Count);
        if(u1ImageSizeAddr != 0xFF)
        {
            *(pu1EdidData + u1ImageSizeAddr) = prSelectInfo->u1ImageByte0;
            *(pu1EdidData + u1ImageSizeAddr + 1) = prSelectInfo->u1ImageByte1;
            *(pu1EdidData + u1ImageSizeAddr + 2) = prSelectInfo->u1ImageByte2;
        }
    }

    *(pu1EdidData + 0x15) = prSelectInfo->u1DisByte0;
    *(pu1EdidData + 0x16) = prSelectInfo->u1DisByte1;

    vHDMIEDIDCalculateChecksum(pu1EdidData);

    return TRUE;
}

BOOL bHDMIEDIDFixDisplaySize(EDID_SELECT_INFO_T* prSelectInfo)
{
    if(prSelectInfo == NULL)
    {
        return FALSE;
    }
    if((prSelectInfo->pEepBlock == NULL)||\
            (prSelectInfo->pTargetMIDEDID == NULL)||\
            (prSelectInfo->pTargetSIDEDID == NULL)||\
            (prSelectInfo->pTargetXIDEDID == NULL))
    {
        LOG(0, "[EDID]Buffer NULL\n");
        return FALSE;
    }

    if(bHDMIEDIDGetDisplaySize(prSelectInfo) == FALSE)
    {
        LOG(0, "[EDID]GetDisplayImageSize Fail\n");
        return FALSE;
    }

    //Change MID eep infromation
    if(_bHDMIEDIDFixDisplaySize(prSelectInfo, EDID_SPEC_TYPE_MID) == FALSE)
    {
        return FALSE;
    }

    //Change SID eep infromation
    if(_bHDMIEDIDFixDisplaySize(prSelectInfo, EDID_SPEC_TYPE_SID) == FALSE)
    {
        return FALSE;
    }

    if(prSelectInfo->u4XID)
    {
        //Change XID eep infromation
        if(_bHDMIEDIDFixDisplaySize(prSelectInfo, EDID_SPEC_TYPE_XID) == FALSE)
        {
            return FALSE;
        }
    }

    vHDMIDebugPrintf("[EDID]MID edid data:\n", prSelectInfo->pTargetMIDEDID, 256);
    vHDMIDebugPrintf("[EDID]SID edid data:\n", prSelectInfo->pTargetSIDEDID, 256);
    vHDMIDebugPrintf("[EDID]XID edid data:\n", prSelectInfo->pTargetXIDEDID, 256);
    return TRUE;
}

BOOL _bHDMIEDIDFixDolbyBlock(EDID_SELECT_INFO_T* prSelectInfo, UINT8 u1Type)
{
    UINT8 u1DolbyBlockAddr;
    UINT8 *pu1EdidData = NULL;
    UINT32 u4EepStartAddr;
    UINT8 u1Tmp=0;

    if(u1Type == EDID_SPEC_TYPE_SID)
    {
        u4EepStartAddr = prSelectInfo->u4EepSIDStartAddr;
        pu1EdidData = prSelectInfo->pTargetSIDEDID;
    }
    else if(u1Type == EDID_SPEC_TYPE_MID)
    {
        u4EepStartAddr = prSelectInfo->u4EepMIDStartAddr;
        pu1EdidData = prSelectInfo->pTargetMIDEDID;
    }
    else if(u1Type == EDID_SPEC_TYPE_XID)
    {
        u4EepStartAddr = prSelectInfo->u4EepXIDStartAddr;
        pu1EdidData = prSelectInfo->pTargetXIDEDID;
    }
    else
    {
        return FALSE;
    }

    u1DolbyBlockAddr = *(prSelectInfo->pEepBlock+ u4EepStartAddr + 0x1c0);
    if(u1DolbyBlockAddr > 0xFA)
    {
        LOG(0, "[EDID]Dolby VSDB Addr:0x%x over 0xFA\n", u1DolbyBlockAddr);
        return TRUE;
    }
    LOG(1, "[EDID]Dolby VSDB Addr:0x%x\n", u1DolbyBlockAddr);
    x_memset(&(prSelectInfo->u1DolbyBlock[0]), 0, 6);
    x_memcpy(prSelectInfo->u1DolbyBlock, (pu1EdidData + u1DolbyBlockAddr), 4);

    u1Tmp = FlashPanel_GetDVTargetMinPQv2();
    prSelectInfo->u1DolbyBlock[0] = (u1Tmp&0xFB) + (prSelectInfo->u1DolbyBlock[0]&0x04);
    u1Tmp = FlashPanel_GetDVTargetMaxPQv2();
    prSelectInfo->u1DolbyBlock[1] = (u1Tmp&0xFB) + (prSelectInfo->u1DolbyBlock[1]&0x04);
    u1Tmp = FlashPanel_GetDVGx();
    prSelectInfo->u1DolbyBlock[2] = ((u1Tmp<<1)&0xfe) + (prSelectInfo->u1DolbyBlock[2]&0x01);
    u1Tmp = FlashPanel_GetDVGy();
    prSelectInfo->u1DolbyBlock[3] = ((u1Tmp<<1)&0xfe) + (prSelectInfo->u1DolbyBlock[3]&0x01);
    u1Tmp = FlashPanel_GetDVBx();
    prSelectInfo->u1DolbyBlock[4] = u1Tmp&0x7;
    u1Tmp = FlashPanel_GetDVBy();
    prSelectInfo->u1DolbyBlock[5] = u1Tmp&0x7;
    u1Tmp = FlashPanel_GetDVRx();
    prSelectInfo->u1DolbyBlock[4] += (u1Tmp<<3)&0xf8;
    u1Tmp = FlashPanel_GetDVRy();
    prSelectInfo->u1DolbyBlock[5] += (u1Tmp<<3)&0xf8;
    LOG(1, "[EDID]RAW Dolby PQ Data: 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n",\
                                                                FlashPanel_GetDVTargetMinPQv2(),\
                                                                FlashPanel_GetDVTargetMaxPQv2(),\
                                                                FlashPanel_GetDVGx(),\
                                                                FlashPanel_GetDVGy(),\
                                                                FlashPanel_GetDVBx(),\
                                                                FlashPanel_GetDVBy(),\
                                                                FlashPanel_GetDVRx(),\
                                                                FlashPanel_GetDVRy());
    vHDMIDebugPrintf("[EDID]Dolby Color Data:\n", prSelectInfo->u1DolbyBlock, 6);
    x_memcpy((pu1EdidData + u1DolbyBlockAddr), prSelectInfo->u1DolbyBlock, 6);

    return TRUE;
}

BOOL bHDMIEDIDFixDolbyBlock(EDID_SELECT_INFO_T* prSelectInfo)
{
    if((prSelectInfo == NULL)||\
        (prSelectInfo->pEepBlock == NULL)||\
        (prSelectInfo->pTargetMIDEDID == NULL)||\
        (prSelectInfo->pTargetSIDEDID == NULL)||\
        (prSelectInfo->pTargetXIDEDID == NULL))
    {
        LOG(0, "[EDID]Buffer NULL\n");
        return FALSE;
    }

    if(prSelectInfo->u1DolbyVision == 0)
    {
        return TRUE;
    }

    if(_bHDMIEDIDFixDolbyBlock(prSelectInfo, EDID_SPEC_TYPE_MID) == FALSE)
    {
        return FALSE;
    }

    if(_bHDMIEDIDFixDolbyBlock(prSelectInfo, EDID_SPEC_TYPE_SID) == FALSE)
    {
        return FALSE;
    }

    if(prSelectInfo->u4XID)
    {
        if(_bHDMIEDIDFixDolbyBlock(prSelectInfo, EDID_SPEC_TYPE_XID) == FALSE)
        {
            return FALSE;
        }
    }

    LOG(1, "[EDID]Fix Dolby VSDB\n");
    return TRUE;
}

#if defined(CC_HDMI_EARC_SUPPORT)&&!defined(CC_UBOOT)&&!defined(CC_MTK_LOADER)
BOOL bHDMIEDIDFilterDataBlock(EARCEDIDInfo_t *pEdidInfo, UINT8 *pData)
{
    UINT8 *u1BlockData;
    UINT8 u1SADOffset = 0;
    UINT8 u1SADLength = 0;
    UINT8 u1SADBOffset = 0;
    UINT8 u1SADBLength = 0;
    UINT8 u1IDFlag = 0;
    UINT16 u2Cnt = 1;
    UINT8 u1MaxCnt = 0;

    u1BlockData = pEdidInfo->u1DataBlock;
    vHDMIDebugPrintf("[EDID]Raw audio data:\n", u1BlockData, 256);

    do
    {
        if(u1BlockData[u2Cnt] == 1)
        {
            break;
        }
        if(u1BlockData[u2Cnt+1] ==0)
        {
            LOG(1,"[EDID]No Block ID 1!!\n");
            return FALSE;
        }
        u2Cnt += u1BlockData[u2Cnt+1] + 2;
    }while(u2Cnt < 256);

    if(u2Cnt >= 253)
    {
        LOG(1,"[EDID]No Block ID 1!\n");
        return FALSE;
    }

    u1MaxCnt = u2Cnt  +2 + u1BlockData[u2Cnt+1];
    u2Cnt += 2;
    while((u2Cnt < u1MaxCnt)&&(u1IDFlag != 3))
    {
        switch(u1BlockData[u2Cnt]>>5)
        {
            case 1:
                u1SADOffset = u2Cnt;
                u1SADLength = u1BlockData[u2Cnt]&0x1f;
                u1IDFlag |= 0x01;
                LOG(1, "[EDID]SAD Block Offset:0x%x, Length:0x%x\n", u1SADOffset, u1SADLength);
                break;
            case 4:
                u1SADBOffset = u2Cnt;
                u1SADBLength = u1BlockData[u2Cnt]&0x1f;
                u1IDFlag |= 0x02;
                LOG(1, "[EDID]SADB Block Offset:0x%x, Length:0x%x\n", u1SADBOffset, u1SADBLength);
                break;
            default:
                break;
        }
        u2Cnt += 1 + (u1BlockData[u2Cnt]&0x1f);
        if(u2Cnt >= 256)
        {
            LOG(1, "[EDID]No SAD/SADB Block!\n");
            return FALSE;
        }
    }

    if(u1IDFlag == 3)
    {
        if(((u1SADLength + u1SADBLength + 2) >= 128)||\
                ((u1SADOffset + u1SADLength + 1) >= 256)||\
                ((u1SADBOffset + u1SADBLength + 1) >= 256))
        {
            LOG(1, "[EDID]Structure error!\n");
            return FALSE;
        }
        x_memcpy(pData, &u1BlockData[u1SADOffset], 1 + u1SADLength);
        x_memcpy(pData +1 + u1SADLength, &u1BlockData[u1SADBOffset], 1 + u1SADBLength);
    }
    else
    {
        LOG(1, "[EDID]No SAD/SADB Block!\n");
        return FALSE;
    }
    return TRUE;
}

/*
 * @u1EdidType:  0:mid; 1:sid;
 */
BOOL _bHDMIEDIDChangeAudioDataBlock(EDID_SELECT_INFO_T* prSelectInfo, UINT8 u1EDIDType)
{
    EDID_SPEC_ADDR_INFO_T t_SpecAddr;
    UINT8 *pEDIDData;
    UINT8 u1NoAudioDataByteNum;
    UINT8 u1VariableDataNum;
    UINT8 u1ShortAudioDescNum;
    UINT8 u1MaxValue;
    UINT8 pu1VariableData[0x80] = {0};
    UINT8 pu1AudioDataBlock[0x80] = {0};
    UINT8 pu1TmpADB[0x80] = {0};
    UINT8 u1ProductID[6]={0};
    UINT8 u1AudioFormatCode;
    UINT8 u1AudioCodeExt;
    UINT8 u1TmpLength;
    UINT8 u1deleteCnt=0;
    UINT8 u1RawByteNum;
    INT8  i1ByteNumDelta;
    UINT8 u1NewByteNumTmp;
    UINT16 i,j;
    UINT16 u2RemainAFC;
    UINT32 u4RemainAFC_EX;
    EARCEDIDInfo_t *pEdidInfo;
    UINT8 u1TmpRawPAAddr;

    if(u1EDIDType == EDID_SPEC_TYPE_MID)
    {
        x_memcpy(&t_SpecAddr,(prSelectInfo->pEepBlock + prSelectInfo->u4EepMIDStartAddr + 0x1A0),10);
        x_memcpy(&u1ProductID[0],(prSelectInfo->pEepBlock + prSelectInfo->u4EepMIDStartAddr + 0x1B0),6);
        u1TmpRawPAAddr = *(prSelectInfo->pEepBlock + prSelectInfo->u4EepMIDStartAddr + 0x100);
        LOG(1, "[EDID]u1RawMIDPAAddr(0x%x) \n", u1TmpRawPAAddr);
        pEDIDData = prSelectInfo->pTargetMIDEDID;
    }
    else if(u1EDIDType == EDID_SPEC_TYPE_SID)
    {
        x_memcpy(&t_SpecAddr,(prSelectInfo->pEepBlock + prSelectInfo->u4EepSIDStartAddr + 0x1A0),10);
        x_memcpy(&u1ProductID[0],(prSelectInfo->pEepBlock + prSelectInfo->u4EepSIDStartAddr + 0x1B0),6);
        u1TmpRawPAAddr = *(prSelectInfo->pEepBlock + prSelectInfo->u4EepSIDStartAddr + 0x100);
        LOG(1, "[EDID]u1RawSIDPAAddr(0x%x) \n", u1TmpRawPAAddr);
        pEDIDData = prSelectInfo->pTargetSIDEDID;
    }
    else if(u1EDIDType == EDID_SPEC_TYPE_XID)
    {
        x_memcpy(&t_SpecAddr,(prSelectInfo->pEepBlock + prSelectInfo->u4EepXIDStartAddr + 0x1A0),10);
        x_memcpy(&u1ProductID[0],(prSelectInfo->pEepBlock + prSelectInfo->u4EepXIDStartAddr + 0x1B0),6);
        u1TmpRawPAAddr = *(prSelectInfo->pEepBlock + prSelectInfo->u4EepXIDStartAddr + 0x100);
        LOG(1, "[EDID]u1RawXIDPAAddr(0x%x) \n", u1TmpRawPAAddr);
        pEDIDData = prSelectInfo->pTargetXIDEDID;
    }
    else
    {
        return FALSE;
    }

    for(i = 128 ; i < 253 ; i++)   // if 255, HDMIEDID may overflow
    {
        if((pEDIDData[i] == 0x3) && (pEDIDData[i+1] == 0xc) && (pEDIDData[i+2] == 0x0))
        {
            u1TmpRawPAAddr = (UINT8)(i+0x3);
            LOG(1, "[EDID]PA Found in table: (0x%x) \n", u1TmpRawPAAddr);
        }
    }

    LOG(1, "[EDID]audio start addr:0x%x, speaker end addr:0x%x,padding start addr:0x%x\n",\
            t_SpecAddr.audio_start_addr, t_SpecAddr.speaker_end_addr, t_SpecAddr.padding_start_addr);
    if((t_SpecAddr.audio_start_addr <0x80)||(t_SpecAddr.speaker_end_addr < 0x80)||(t_SpecAddr.padding_start_addr < 0x80))
    {
        LOG(0, "[EDID]audio error address!\n");
        return FALSE;
    }

#ifndef CC_AUD_DOLBY_SUPPORT_MS12v2  // MS12v2 can decode the ATMOS. So no need to change this flag dynamically.
    if(prSelectInfo->u1ATMOS)
    {
        *(pEDIDData + t_SpecAddr.atmos_addr) |= 0x1;
    }
    else
    {
        *(pEDIDData + t_SpecAddr.atmos_addr) &= 0xfe;
    }
#endif // CC_AUD_DOLBY_SUPPORT_MS12v2

    u1HDMIEARCGetEDIDInfo(&pEdidInfo);
    
    if(pEdidInfo->bEARCConnect != HDMI_EARC_CONNECT)
    {
        LOG(1, "[EDID] no eARC,goto cal_productID!\n");
		i1ByteNumDelta = 0;
        goto cal_productID;
    }

    /*eARC connect begin to replace audio data block*/
    u1NoAudioDataByteNum = *(pEDIDData + 0x82) - (t_SpecAddr.speaker_end_addr - t_SpecAddr.audio_start_addr + 1);
    u1MaxValue = t_SpecAddr.speaker_end_addr - t_SpecAddr.audio_start_addr + 1 + 0xFF - t_SpecAddr.padding_start_addr;
    u1VariableDataNum = t_SpecAddr.padding_start_addr - t_SpecAddr.speaker_end_addr -1;
    x_memcpy(pu1VariableData,(pEDIDData + t_SpecAddr.speaker_end_addr + 1), u1VariableDataNum);
    LOG(1, "[EDID]byte number without audio data:0x%x\n",u1NoAudioDataByteNum);
    LOG(1, "[EDID]max value:0x%x, variable data number:0x%x\n",u1MaxValue,u1VariableDataNum);

    /*delete unecessary block in eARC raw data block.*/
    if(bHDMIEDIDFilterDataBlock(pEdidInfo, pu1AudioDataBlock) == FALSE)
    {
        LOG(1, "[EDID]Get Audio Data Block Fail!\n");
        return FALSE;
    }
    vHDMIDebugPrintf("[EDID]Filter audio data:\n", pu1AudioDataBlock, 128);

    u2RemainAFC = ((UINT16)t_SpecAddr.remain_afc_1<<8) + (UINT16)t_SpecAddr.remain_afc_2;
    u4RemainAFC_EX = ((UINT32)t_SpecAddr.remain_afc_ex1<<24) + \
                     ((UINT32)t_SpecAddr.remain_afc_ex2<<16) + \
                     ((UINT32)t_SpecAddr.remain_afc_ex3<<8) + \
                     (UINT32)t_SpecAddr.remain_afc_ex4;
    LOG(1, "[EDID]u2RemainAFC:0x%x, u4RemainAFC_EX:0x%x\n",u2RemainAFC,u4RemainAFC_EX);
    pu1TmpADB[0] = *pu1AudioDataBlock;
    pu1TmpADB[1] =0x09;
    pu1TmpADB[2] =0x07;
    pu1TmpADB[3] =0x01;
    u1ShortAudioDescNum = (*pu1AudioDataBlock) & 0x1f;
    for(i=1, j=4; i < u1ShortAudioDescNum; i+=3)
    {
        u1AudioFormatCode = ((*(pu1AudioDataBlock + i))>>3) & 0xf;
        u1AudioCodeExt = ((*(pu1AudioDataBlock + i + 2))>>3) & 0x1f;
        LOG(1, "[EDID]audio format code:0x%x\n",u1AudioFormatCode);
        if(u1AudioFormatCode == 1)
        {
            pu1TmpADB[1] |= *(pu1AudioDataBlock + i);
            pu1TmpADB[2] |= (*(pu1AudioDataBlock + i + 1) & 0x07);
            pu1TmpADB[3] |= *(pu1AudioDataBlock + i + 2);
            LOG(1, "[EDID]store audio data block:0x%x, 0x%x, 0x%x\n", pu1TmpADB[1], pu1TmpADB[2], pu1TmpADB[3]);
            continue;
        }
        else if(u1AudioFormatCode==15)
        {
            if((u2RemainAFC&1)&&(u4RemainAFC_EX&(0x80000000>>u1AudioCodeExt)))
            {
                x_memcpy(&pu1TmpADB[j],(pu1AudioDataBlock + i),3);
                LOG(1, "[EDID]store ext audio data block:0x%x, 0x%x, 0x%x\n",pu1TmpADB[j],pu1TmpADB[j+1],pu1TmpADB[j+2]);
                j+=3;
            }
            continue;
        }
        if(u2RemainAFC&(0x8000>>u1AudioFormatCode))
        {
            x_memcpy(&pu1TmpADB[j],(pu1AudioDataBlock + i),3);
            LOG(1, "[EDID]store audio data block:0x%x, 0x%x, 0x%x\n",pu1TmpADB[j],pu1TmpADB[j+1],pu1TmpADB[j+2]);

#ifndef CC_AUD_DOLBY_SUPPORT_MS12v2  // MS12v2 can decode the ATMOS. So no need to change this flag dynamically.
            if(u1AudioFormatCode == 0x0A)
            {
                pu1TmpADB[j+2] = (prSelectInfo->u1ATMOS)?(pu1TmpADB[j+2]|0x01):(pu1TmpADB[j+2]&0xFE);
            }
#endif // CC_AUD_DOLBY_SUPPORT_MS12v2

            j+=3;
        }
    }
    /*u1TmpLength excludes (audio tag + speaker block)*/
    u1TmpLength = j - 1;
    LOG(1, "[EDID]audio descriptor bytes:0x%x, tmp length:0x%x\n",u1ShortAudioDescNum,u1TmpLength);
    /*modify eARC audio data block, control its size less than maxValue.*/
    if((u1TmpLength + 5) > u1MaxValue)
    {
        u1deleteCnt = (u1TmpLength + 5 - u1MaxValue)/3;
        if((u1TmpLength + 5 - u1MaxValue)%3)
        {
            u1deleteCnt += 1;
        }
        u1deleteCnt = u1deleteCnt * 3;
        u1TmpLength -= u1deleteCnt;
        LOG(1, "[EDID]delete count:0x%x, tmp length:0x%x\n",u1deleteCnt,u1TmpLength);
    }
    pu1TmpADB[0] = (pu1TmpADB[0] & 0xE0) | u1TmpLength;
    t_SpecAddr.speaker_end_addr = t_SpecAddr.audio_start_addr + u1TmpLength + 4;
    t_SpecAddr.padding_start_addr = t_SpecAddr.speaker_end_addr + 1 + u1VariableDataNum;
    LOG(1, "[EDID]speaker end addr:0x%x, pad start addr:0x%x\n", t_SpecAddr.speaker_end_addr, t_SpecAddr.padding_start_addr);
    /*append speak allocation block*/
    x_memcpy(&pu1TmpADB[u1TmpLength + 1], (pu1AudioDataBlock + u1ShortAudioDescNum + 1), 4);
    /*add new audio data block to edid table.*/
    vHDMIDebugPrintf("[EDID]new audio data:\n", pu1TmpADB, u1TmpLength + 5);
    x_memcpy((pEDIDData + t_SpecAddr.audio_start_addr), &pu1TmpADB[0], u1TmpLength + 5);
    /*add evacuated variable data*/
    vHDMIDebugPrintf("[EDID]variable data:\n", pu1VariableData, u1VariableDataNum);
    x_memcpy((pEDIDData + t_SpecAddr.speaker_end_addr + 1), pu1VariableData, u1VariableDataNum);
    /*add padding*/
    x_memset((pEDIDData + t_SpecAddr.padding_start_addr), 0, (0xFF - t_SpecAddr.padding_start_addr));
    /*calculate byte number*/
    u1RawByteNum = *(pEDIDData + 0x82);
    *(pEDIDData + 0x82) = u1NoAudioDataByteNum + u1TmpLength + 5;
    /*need to update PA based on earc audio block data*/
    u1NewByteNumTmp = *(pEDIDData + 0x82);
    i1ByteNumDelta = u1NewByteNumTmp - u1RawByteNum;

cal_productID:
#if SUPPORT_ATMOS_UPDATE
    if((pEdidInfo->bEARCConnect)&&(prSelectInfo->u1ATMOS))
    {
        *(pEDIDData + 0x0A) = u1ProductID[4];
        *(pEDIDData + 0x0B) = u1ProductID[5];
    }
    else if(pEdidInfo->bEARCConnect)
    {
        *(pEDIDData + 0x0A) = u1ProductID[2];
        *(pEDIDData + 0x0B) = u1ProductID[3];
    }
    else if(prSelectInfo->u1ATMOS)
    {
        *(pEDIDData + 0x0A) = u1ProductID[0];
        *(pEDIDData + 0x0B) = u1ProductID[1];
    }
#else
    if(pEdidInfo->bEARCConnect)
    {
        *(pEDIDData + 0x0A) = u1ProductID[2];
        *(pEDIDData + 0x0B) = u1ProductID[3];
    }
#endif

    LOG(1, "[EDID]product ID:0x%x, 0x%x  byte num:0x%x\n",\
            *(pEDIDData + 0x0A), *(pEDIDData + 0x0B),*(pEDIDData + 0x82));

	if(u1EDIDType == EDID_SPEC_TYPE_MID)
    {
        LOG(1, "[EDID]MID PA(0x%x) update to 0x%x:\n", u1TmpRawPAAddr, (UINT8)(u1TmpRawPAAddr+i1ByteNumDelta));
		*(prSelectInfo->pEepBlock + prSelectInfo->u4EepMIDStartAddr + 0x100) = (UINT8)(u1TmpRawPAAddr + i1ByteNumDelta);
		eEdidObj.u1MIDPA = (UINT8)(u1TmpRawPAAddr + i1ByteNumDelta);
    }
    else if(u1EDIDType == EDID_SPEC_TYPE_SID)
    {
        LOG(1, "[EDID]SID PA(0x%x) update to 0x%x:\n", u1TmpRawPAAddr, (u1TmpRawPAAddr+i1ByteNumDelta));
		*(prSelectInfo->pEepBlock + prSelectInfo->u4EepSIDStartAddr + 0x100) = (UINT8)(u1TmpRawPAAddr + i1ByteNumDelta);
		eEdidObj.u1SIDPA = (UINT8)(u1TmpRawPAAddr + i1ByteNumDelta);
    }
    else if(u1EDIDType == EDID_SPEC_TYPE_XID)
    {
        LOG(1, "[EDID]XID PA(0x%x) update to 0x%x:\n", u1TmpRawPAAddr, (UINT8)(u1TmpRawPAAddr+i1ByteNumDelta));
		*(prSelectInfo->pEepBlock + prSelectInfo->u4EepXIDStartAddr + 0x100) = (UINT8)(u1TmpRawPAAddr + i1ByteNumDelta);
		eEdidObj.u1XIDPA = (UINT8)(u1TmpRawPAAddr + i1ByteNumDelta);
    }
    else
    {
        LOG(1, "[EDID]NO PA update!\n");
    }

    if(prSelectInfo->u4XID)
    {
        eEdidObj.u1XIDPA = *(prSelectInfo->pEepBlock + prSelectInfo->u4EepXIDStartAddr + 0x100);
    }
    else
    {
        eEdidObj.u1XIDPA = 0;
    }
    LOG(1, "[%s][EDID] MID_PA:0x%x, SID_PA:0x%x, XID_PA:0x%x\n",\
        __FUNCTION__,eEdidObj.u1MIDPA, eEdidObj.u1SIDPA, eEdidObj.u1XIDPA);

    vHDMIEDIDCalculateChecksum(pEDIDData);
    vHDMIDebugPrintf(NULL, pEDIDData, 256);
    return TRUE;
}

BOOL bHDMIEDIDChangeAudioDataBlock(EDID_SELECT_INFO_T* prSelectInfo)
{
    if((prSelectInfo == NULL)||(prSelectInfo->pEepBlock == NULL)||(prSelectInfo->u4EepMIDStartAddr == 0)||\
            (prSelectInfo->u4EepSIDStartAddr == 0))
    {
        return FALSE;
    }

    if(prSelectInfo->u1Platform < 0x04)//only for m3
    {
        return TRUE;
    }

    //mid edid change
    if(_bHDMIEDIDChangeAudioDataBlock(prSelectInfo, EDID_SPEC_TYPE_MID) == FALSE)
    {
        return FALSE;
    }

    //sid edid change
    if(_bHDMIEDIDChangeAudioDataBlock(prSelectInfo, EDID_SPEC_TYPE_SID) == FALSE)
    {
        return FALSE;
    }

    //xid edid change
    if(prSelectInfo->u4XID)
    {
        if(_bHDMIEDIDChangeAudioDataBlock(prSelectInfo, EDID_SPEC_TYPE_XID) == FALSE)
        {
            return FALSE;
        }
    }

    return TRUE;
}
#endif

void vHDMIEDIDReadEDID(UINT8 u1Type, UINT8* pBuff, UINT32* pOffset)
{
    if((pBuff == NULL) || (pOffset == NULL))
    {
        LOG(0,"%s invalid input PARAM\n",__FUNCTION__);
        return;
    }

    switch(u1Type)
    {
        case EDID_SPEC_TYPE_MID:
            x_memcpy(pBuff, HDMIEDID_table, 256);
            *pOffset = eEdidObj.u1MIDPA;
            LOG(1, "[EDID]Read MID, u1Type:%d\n",u1Type);
            break;
        case EDID_SPEC_TYPE_SID:
            x_memcpy(pBuff, HDMI2EDID_table, 256);
            *pOffset = eEdidObj.u1SIDPA;
            LOG(1, "[EDID]Read SID, u1Type:%d\n",u1Type);
            break;
        case EDID_SPEC_TYPE_XID:
            x_memcpy(pBuff, HDMI8KEDID_table, 256);
            *pOffset = eEdidObj.u1XIDPA;
            LOG(1, "[EDID]Read XID, u1Type:%d\n",u1Type);
            break;
        default:
           break;
    }
    LOG(1, "[EDID]physical address: 0x%x\n",*pOffset);
    vHDMIDebugPrintf("[EDID]Read edid data:\n", pBuff, 256);
}

#if defined(__KERNEL__)&&!defined(CC_UBOOT)
BOOL bHDMIEDIDUpdateNotify(EDID_SELECT_INFO_T* prSelectInfo)
{
    if((prSelectInfo == NULL)||(prSelectInfo->pEepBlock == NULL)||(prSelectInfo->u4EepMIDStartAddr == 0)||\
            (prSelectInfo->u4EepSIDStartAddr == 0))
    {
        return FALSE;
    }

    if(prSelectInfo->u1Platform < 0x04)//only for m3
    {
        return TRUE;
    }

    eEdidObj.u1MIDPA = *(prSelectInfo->pEepBlock + prSelectInfo->u4EepMIDStartAddr + 0x100);
    eEdidObj.u1SIDPA = *(prSelectInfo->pEepBlock + prSelectInfo->u4EepSIDStartAddr + 0x100);

    if(prSelectInfo->u4XID)
    {
        eEdidObj.u1XIDPA = *(prSelectInfo->pEepBlock + prSelectInfo->u4EepXIDStartAddr + 0x100);
    }
    else
    {
        eEdidObj.u1XIDPA = 0;
    }

    LOG(1, "[EDID]MID_PA:0x%x, SID_PA:0x%x, XID_PA:0x%x\n",\
        eEdidObj.u1MIDPA, eEdidObj.u1SIDPA, eEdidObj.u1XIDPA);

    DRVCUST_EdidUpdateNotify();
    return TRUE;
}
#endif

BOOL bHDMIMakeEDID(UINT8 *pEdid14, UINT8 *pEdid20, UINT8 *pEdid8K)
{
    EDID_SELECT_INFO_T rSelectInfo;
    UINT16 u2EDIDDataSize;
    BOOL bRet = TRUE;

    if((pEdid14 == NULL) || (pEdid20 == NULL) || (pEdid8K == NULL))
    {
        return FALSE;
    }

    u2EDIDDataSize = (HDMI_EDID_SUPPORT_MAXNUM * 512) + 1024;
    if(eEdidObj.pData == NULL)
    {
        eEdidObj.pData = (UINT8*) x_mem_alloc(sizeof(UINT8) * u2EDIDDataSize);
        if(eEdidObj.pData == NULL)
        {
            LOG(0, "EDID Buffer malloc fail\n");
            bRet = FALSE;
            goto Exit;
        }
    }

    if(bHDMIEDIDCreatSelectInfo(&rSelectInfo, pEdid14, pEdid20, pEdid8K) == FALSE)
    {
        LOG(0, "[EDID]CreatSelectInfo Fail\n");
        bRet = FALSE;
        goto Exit;
    }
    vHDMIEDIDPrintfSelectInfo(&rSelectInfo);

    if(bHDMIEDIDGetWholeBlock(&rSelectInfo) == FALSE)
    {
        LOG(0, "[EDID]bHDMIEDIDRead Fail\n");
        bRet = FALSE;
        goto Exit;
    }

    if(bHDMIEDIDGetMIDAndSIDAndXID(&rSelectInfo) == FALSE)
    {
        LOG(0, "[EDID]GetMIDAndSID Fail\n");
        bRet = FALSE;
        goto Exit;
    }

    if(bHDMIEDIDSearchIDData(&rSelectInfo) == FALSE)
    {
        LOG(0, "[EDID]SearchIDData Fail\n");
        bRet = FALSE;
        goto Exit;
    }

    if(bHDMIEDIDFixDisplaySize(&rSelectInfo) == FALSE)
    {
        LOG(0, "[EDID]FixDisplayImageSize Fail\n");
        bRet = FALSE;
        goto Exit;
    }

    if(bHDMIEDIDFixDolbyBlock(&rSelectInfo) == FALSE)
    {
        LOG(0, "[EDID]FixDolbyBlock Fail\n");
        bRet = FALSE;
        goto Exit;
    }

#if defined(CC_HDMI_EARC_SUPPORT)&&!defined(CC_UBOOT)&&!defined(CC_MTK_LOADER)
    if(bHDMIEDIDChangeAudioDataBlock(&rSelectInfo) == FALSE)
    {
        LOG(0, "[EDID]ChangeAudioDataBlock Fail\n");
        bRet = FALSE;
        goto Exit;
    }
#endif

#if defined(__KERNEL__)&&!defined(CC_UBOOT)
    if(bHDMIEDIDUpdateNotify(&rSelectInfo) == FALSE)
    {
        LOG(0, "[EDID]UpdateNotify Fail\n");
        bRet = FALSE;
        goto Exit;
    }
    LOG(0, "[EDID]Make Edid Success\n");
#endif

Exit:
    return bRet;
}

void vHDMI20ReadSramEDID(UINT8 u1PortId)
{
    UINT16 u2EDIDIdx = 0;

    LOG(0, "HDMI EDID Port %d:\n", u1PortId);
    while (u2EDIDIdx < 256)
    {
        if ((u2EDIDIdx % 16) == 0)
        {
            Printf("0x%08X ", u2EDIDIdx);
        }
        vIO32Write1B(PDWNC_EDID2_ADDR, u2EDIDIdx);

        if (u2EDIDIdx == IO32ReadFldAlign(PDWNC_EDID2_CTL1 + (u1PortId - 1) * 4, FLD_EDID2_OFFSET1) && (u1PortId != 0))
        {
            Printf("0x%02X ", IO32ReadFldAlign(PDWNC_EDID2_CTL1 + (u1PortId - 1) * 4, FLD_EDID2_PHY_ADDR1));
        }
        else if ((u2EDIDIdx == 255) && (u1PortId != 0))
        {
            Printf("0x%02X ", IO32ReadFldAlign(PDWNC_EDID2_CTL1 + (u1PortId - 1) * 4, FLD_EDID2_CHKSUM1));
        }
        else
        {
            Printf("0x%02X ", IO32ReadFldAlign(PDWNC_EDID2_DATA, FLD_EDID2_EDID_DATA));
        }
        if (((u2EDIDIdx + 1) % 16) == 0)
        {
            Printf("\n");
        }
        u2EDIDIdx++;
    }
}

void vHDMI14ReadSramEDID(UINT8 u1PortId)
{
    UINT16 u2EDIDIdx = 0;

    LOG(0, "HDMI EDID Port %d:\n", u1PortId);
    while (u2EDIDIdx < 256)
    {
        if ((u2EDIDIdx % 16) == 0)
        {
            Printf("0x%08X ", u2EDIDIdx);
        }
        vIO32Write1B(PDWNC_EDID1_ADDR, u2EDIDIdx);

        if (u2EDIDIdx == IO32ReadFldAlign(PDWNC_EDID1_CTL1 + (u1PortId - 1) * 4, FLD_EDID1_OFFSET1) && (u1PortId != 0))
        {
            Printf("0x%02X ", IO32ReadFldAlign(PDWNC_EDID1_CTL1 + (u1PortId - 1) * 4, FLD_EDID1_PHY_ADDR1));
        }
        else if ((u2EDIDIdx == 255) && (u1PortId != 0))
        {
            Printf("0x%02X ", IO32ReadFldAlign(PDWNC_EDID1_CTL1 + (u1PortId - 1) * 4, FLD_EDID1_CHKSUM1));
        }
        else
        {
            Printf("0x%02X ", IO32ReadFldAlign(PDWNC_EDID1_DATA, FLD_EDID1_EDID_DATA));
        }
        if (((u2EDIDIdx + 1) % 16) == 0)
        {
            Printf("\n");
        }
        u2EDIDIdx++;
    }
}

void vHDMI20ReadEDIDFromSram(void)
{
    EDID_SELECT_INFO_T rSelectInfo;

    if(bHDMIEDIDCreatSelectInfo(&rSelectInfo, NULL, NULL, NULL) == FALSE)
    {
        LOG(0, "[EDID]CreatSelectInfo Fail\n");
        return;
    }
    vHDMIEDIDPrintfSelectInfo(&rSelectInfo);

    vHDMI20ReadSramEDID(0);
    vHDMI20ReadSramEDID(1);
    vHDMI14ReadSramEDID(2);
    vHDMI14ReadSramEDID(3);
}

BOOL bHDMICustEDIDMake(UINT8 u1ParaCount, UINT8* pu1_SearchData, UINT8* pu1EDID14, UINT8* pu1EDID20, UINT8* pu1EDID8K)
{
    BOOL bRet = TRUE;

    if((pu1_SearchData == NULL)||(pu1EDID14 == NULL)||(pu1EDID20 == NULL)||(pu1EDID8K == NULL))
    {
        return FALSE;
    }

    if(u1ParaCount == 1)
    {
        bRet = bHDMIMakeEDID(pu1EDID14, pu1EDID20, pu1EDID8K);
        return bRet;
    }
    if(u1ParaCount== 5)
    {
        x_memcpy(eEdidObj.eCLI.pu1SearchData, pu1_SearchData, 16);
#ifndef CC_MTK_LOADER
        vSetCLIFlag(CLI_FLAG_SEARCH);
#endif
        bHDMIMakeEDID(pu1EDID14, pu1EDID20, pu1EDID8K);
    }
    return TRUE;
}

void vMHL20EDIDReadFromEep(UINT8 *aupEdid)
{
    INT32 i4Ret;

    {
        i4Ret = EEPMHL20EDID_Read((UINT32)aupEdid, FLASH_MHL_2_0_EDID_SIZE);
        if (i4Ret)
        {
            Printf(" read edid data  fail\n");
        }
    }
}
#endif

UINT8* pu1DrvLoadHdmi14Edid(void)
{
#if (defined(CC_HDMI_2_0_HDCP_BIN)&&(!defined(CC_UBOOT)))
    if(bHDMIMakeEDID(HDMIEDID_table, HDMI2EDID_table, HDMI8KEDID_table) == FALSE)
    {
        Printf("HDMI Edid Data Fail\n");
    }
#endif
    return (UINT8 *)HDMIEDID_table;
}

UINT8* pu1DrvLoadHdmi20Edid(void)
{
    return (UINT8 *)HDMI2EDID_table;
}

BOOL fgDrvEdidHandleSAD(BOOL fgSet,UINT8 u1FormatNum,UINT8 *pu1AudioDataBlock)
{
    return TRUE;
}

//retval: 0 for select EDID1, 1 for select EDID2
UINT8 u1DrvGetHdmiEdidPortSel(UINT8 u1Port)
{
    UINT8 u1EdidIdx = 0;
    u1EdidIdx = (eEdidObj.u1TI4Flag>>(u1Port-1))&0x1;
    return u1EdidIdx;
}

UINT8* pu1DrvLoadHdmiStandardEdid(void)
{
#if (defined(CC_HDMI_2_0_HDCP_BIN)&&(!defined(CC_UBOOT)))
    if(bHDMIMakeEDID(HDMIEDID_table, HDMI2EDID_table, HDMI8KEDID_table) == FALSE)
    {
        Printf("HDMI Edid Data Fail\n");
    }
#endif
    return HDMIEDID_table;
}

UINT8* pu1DrvLoadHdmiEnhancedEdid(void)
{
    return HDMI2EDID_table;
}

void vPostHdmiEdidProcess(UINT8* pu1Edid)
{

}

UINT8* pu1DrvLoadHdmiEdid1(void)
{
    UINT8* pu1HDMIEdid1 = pu1DrvLoadHdmiStandardEdid();
    vPostHdmiEdidProcess(pu1HDMIEdid1);

    return pu1HDMIEdid1;
}

UINT8* pu1DrvLoadHdmiEdid2(void)
{
    UINT8* pu1HDMIEdid2 = pu1DrvLoadHdmiEnhancedEdid();
    vPostHdmiEdidProcess(pu1HDMIEdid2);

    return pu1HDMIEdid2;
}

UINT8* pu1DrvLoadMhlEdid(void)
{
    return (UINT8 *)u1MhlEdid_P0;
}

UINT8* pu1DrvGetMhlEdidTable(void)
{
    return (UINT8 *)u1MhlEdid_P0;
}

//CLI For Debug
#ifndef CC_MTK_LOADER
INT32 u4HDMIDebugLogCmd(INT32 i4Argc, const CHAR** szArgv)
{
    if(i4Argc != 2)
    {
        LOG(0, "usage: 0:disable log  1:enable log\n");
        return 0;
    }
    eEdidObj.u1Level = (UINT8)StrToInt(szArgv[1])?1:0;
    Printf("set debug lvl:0x%x\n",eEdidObj.u1Level);
    CLI_Parser_Arg("sif.hdmi.cust.d_l %d",eEdidObj.u1Level);
    return 0;
}

UINT8 u1CheckCLIFlag(CLI_FLAG_T tflag)
{
    UINT8 u1Ret=0;
    switch(tflag)
    {
        case CLI_FLAG_SETID:
            if(eEdidObj.eCLI.u4FixedFlag&(1<<15))
                u1Ret = 1;
            break;
        case CLI_FLAG_SEARCH:
            if(eEdidObj.eCLI.u4FixedFlag&(1<<16))
                u1Ret = 1;
            break;
        default:
            break;
    }
    return u1Ret;
}

void vSetCLIFlag(CLI_FLAG_T tflag)
{
    if(tflag == CLI_FLAG_SEARCH)
    {
        eEdidObj.eCLI.u4FixedFlag |= 1<<16;
    }
}

INT32 u4HDMIDebugSetStatusCmd(INT32 i4Argc, const CHAR** szArgv)
{
    UINT32 u4Type;
    UINT32 u4Status;

    if(i4Argc < 3)
    {
        LOG(0, "usage: type,status\n");
        Printf("type: \n"
                "0:Cancel\n"
                "1:Make Edid\n"
                "2:Platform\n"
                "3:4K2K\n"
                "4:BankNum\n"
                "5:PanelCtrl\n"
                "6:Panel_less\n"
                "7:Panel3DType\n");
        Printf("8:PanelWCG\n"
                "9:MVIDestination\n"
                "10:ATMOS\n"
                "11:CBA\n"
                "12:MVINO_3D\n"
                "13:HFVSDBFlag\n"
                "14:HDR\n"
                "15:MID_ID  SID_ID\n");
        Printf("16:General+Adaptive\n"
                "17:Request Firmware\n"
                "18:Current Block Information\n"
                "19:Dolby Vision\n"
                "\n");
        return 0;
    }

    u4Type = (UINT32)StrToInt(szArgv[1]);
    u4Status = (UINT32)StrToInt(szArgv[2]);

    if(u4Type>30)
    {
        return 0;
    }

    switch(u4Type)
    {
        case 0:
            LOG(0,"clear fixed flag\n");
            eEdidObj.eCLI.u4FixedFlag = 0;
            return 0;
            break;
        case 1:
            //only call to make edid.
            break;
        case 2:
            eEdidObj.eCLI.u1Platform = (UINT8)u4Status;
            break;
        case 3:
            eEdidObj.eCLI.u14K2K= (UINT8)u4Status;
            break;
        case 4:
            eEdidObj.eCLI.u1BankNum= (UINT8)u4Status;
            break;
        case 5:
            eEdidObj.eCLI.u4PanelCtrl= u4Status;
            break;
        case 6:
            eEdidObj.eCLI.u1Panel_less= (UINT8)u4Status;
            break;
        case 7:
            eEdidObj.eCLI.u1Panel3DType = (UINT8)u4Status;
            break;
        case 8:
            eEdidObj.eCLI.u1PanelWCG = (UINT8)u4Status;
            break;
        case 9:
            eEdidObj.eCLI.u1MVIDestination = (UINT8)u4Status;
            break;
        case 10:
            eEdidObj.eCLI.u1ATMOS = (UINT8)u4Status;
            break;
        case 11:
            eEdidObj.eCLI.u1CBA = (UINT8)u4Status;
            break;
        case 12:
            eEdidObj.eCLI.u1MVINO_3D = (UINT8)u4Status;
            break;
        case 13:
            eEdidObj.eCLI.u1HFVSDBFlag = (UINT8)u4Status;
            break;
        case 14:
            eEdidObj.eCLI.u1HDR = (UINT8)u4Status;
            break;
        case 15:
            if(i4Argc != 4)
            {
                return 0;
            }
            eEdidObj.eCLI.u4MID = u4Status;
            eEdidObj.eCLI.u4SID = (UINT32)StrToInt(szArgv[2]);
            LOG(0, "set mid:0x%x, sid:0x%x\n",eEdidObj.eCLI.u4MID, eEdidObj.eCLI.u4SID);
            break;
        case 16:
            if(i4Argc != 3)
            {
                return 0;
            }
            x_memset(&(eEdidObj.eCLI.pu1SearchData[0]), 0, 16);
            eEdidObj.eCLI.pu1SearchData[2] = (u4Status>>24)&0xff;
            eEdidObj.eCLI.pu1SearchData[3] = (u4Status>>16)&0xff;
            eEdidObj.eCLI.pu1SearchData[4] = (u4Status>>8)&0xff;
            eEdidObj.eCLI.pu1SearchData[5] = u4Status&0xff;
            LOG(0, "general+adaptive:0x%x, 0x%x,0x%x, 0x%x\n",\
                    eEdidObj.eCLI.pu1SearchData[2],\
                    eEdidObj.eCLI.pu1SearchData[3],\
                    eEdidObj.eCLI.pu1SearchData[4],\
                    eEdidObj.eCLI.pu1SearchData[5]);
            break;
        case 17:
            eEdidObj.u1ReqFWDone = 0;
            break;
        case 18:
            LOG(0, "[EDID]Offset:0x%x, Block Flag:0x%x, Firmware Flag:%d, Bank Number:%d\n", \
                    eEdidObj.u2BlockOffset, eEdidObj.u1BlockFlag, eEdidObj.u1ReqFWDone,eEdidObj.u1BankNum);
            LOG(0, "[EDID]Table Size:0x%x, ID Addr:0x%x, Start Data addr:0x%x, End addr:0x%x\n",\
                    eEdidObj.u2TableSize, eEdidObj.u4TableIDAddr, eEdidObj.u4HeaderStartAddr, eEdidObj.u4HeaderEndAddr);
            return 0;
        case 19:
            eEdidObj.eCLI.u1DolbyVision = (UINT8)u4Status;
        default:
            return 0;
            break;
    }
    eEdidObj.eCLI.u4FixedFlag |= 1<<u4Type;

    bHDMIMakeEDID(HDMIEDID_table, HDMI2EDID_table, HDMI8KEDID_table);
    return 0;
}

void vHDMIEDIDCLIDebug(EDID_SELECT_INFO_T* prSelectInfo)
{
    UINT32 u4Status = eEdidObj.eCLI.u4FixedFlag;
    UINT32 i=1;

    if(u4Status ==0)
    {
        return;
    }

    while((i<30)&&(u4Status>>=1))
    {
        //LOG(0,"cli debug status:0x%04x, i:0x%x\n",u4Status,i);
        if((u4Status&1) == 0)
        {
            i++;
            continue;
        }

        switch(i)
        {
            case 2:
                LOG(0, "[EDID]fix platform:0x%x\n",eEdidObj.eCLI.u1Platform);
                prSelectInfo->u1Platform = eEdidObj.eCLI.u1Platform;
                break;
            case 3:
                LOG(0, "[EDID]fix 4k2k:0x%x\n",eEdidObj.eCLI.u14K2K);
                prSelectInfo->u14K2K = eEdidObj.eCLI.u14K2K;
                break;
            case 4:
                LOG(0, "[EDID]fix bank num:0x%x\n",eEdidObj.eCLI.u1BankNum);
                prSelectInfo->u1BankNum = eEdidObj.eCLI.u1BankNum;
                break;
            case 5:
                LOG(0, "[EDID]fix PanelCtrl:0x%x\n",eEdidObj.eCLI.u4PanelCtrl);
                prSelectInfo->u4PanelCtrl = eEdidObj.eCLI.u4PanelCtrl;
                break;
            case 6:
                LOG(0, "[EDID]fix Panel_less:0x%x\n",eEdidObj.eCLI.u1Panel_less);
                prSelectInfo->u1Panel_less = eEdidObj.eCLI.u1Panel_less;
                break;
            case 7:
                LOG(0, "[EDID]fix Panel3DType:0x%x\n",eEdidObj.eCLI.u1Panel3DType);
                prSelectInfo->u1Panel3DType = eEdidObj.eCLI.u1Panel3DType;
                break;
            case 8:
                LOG(0, "[EDID]fix PanelWCG:0x%x\n",eEdidObj.eCLI.u1PanelWCG);
                prSelectInfo->u1PanelWCG = eEdidObj.eCLI.u1PanelWCG;
                break;
            case 9:
                LOG(0, "[EDID]fix MVIDestination:0x%x\n",eEdidObj.eCLI.u1MVIDestination);
                prSelectInfo->u1MVIDestination = eEdidObj.eCLI.u1MVIDestination;
                break;
            case 10:
                LOG(0, "[EDID]fix ATMOS:0x%x\n",eEdidObj.eCLI.u1ATMOS);
                prSelectInfo->u1ATMOS = eEdidObj.eCLI.u1ATMOS;
                break;
            case 11:
                LOG(0, "[EDID]fix CBA:0x%x\n",eEdidObj.eCLI.u1CBA);
                prSelectInfo->u1CBA = eEdidObj.eCLI.u1CBA;
                break;
            case 12:
                LOG(0, "[EDID]fix MVINO_3D:0x%x\n",eEdidObj.eCLI.u1MVINO_3D);
                prSelectInfo->u1MVINO_3D = eEdidObj.eCLI.u1MVINO_3D;
                break;
            case 13:
                LOG(0, "[EDID]fix HFVSDBFlag:0x%x\n",eEdidObj.eCLI.u1HFVSDBFlag);
                prSelectInfo->u1HFVSDBFlag = eEdidObj.eCLI.u1HFVSDBFlag;
                break;
            case 14:
                LOG(0, "[EDID]fix HDR:0x%x\n",eEdidObj.eCLI.u1HDR);
                prSelectInfo->u1HDR = eEdidObj.eCLI.u1HDR;
                break;
            case 15:
                prSelectInfo->u4MID = eEdidObj.eCLI.u4MID;
                prSelectInfo->u4SID = eEdidObj.eCLI.u4SID;
                break;
            case 19:
                LOG(0, "[EDID]fix DolbyVison:0x%x\n",eEdidObj.eCLI.u1DolbyVision);
                prSelectInfo->u1DolbyVision = eEdidObj.eCLI.u1DolbyVision;
                break;
            default:
                break;
        }
        i++;
    }
}

CLIMOD_DEBUG_FUNCTIONS(HDMI)
    CLI_EXEC_T arSifHDMIcustCmdTbl[] = {
        CLIMOD_DEBUG_CLIENTRY(HDMI),
#ifdef CC_HDMI_2_0_HDCP_BIN
        {"dl", NULL, u4HDMIDebugLogCmd, NULL, "enable/disable log", CLI_GUEST},
        //{"earc", NULL, u4HDMIDebugEARCCmd, NULL, "test earc i2c", CLI_GUEST},
        {"ss", NULL, u4HDMIDebugSetStatusCmd, NULL, "set some status", CLI_GUEST},
#endif
#if defined(CC_HDMI_EARC_SUPPORT)&&!defined(CC_UBOOT)&&!defined(CC_MTK_LOADER)
        {"earc", "earc", NULL, arHDMIEARCCmdTbl, "HDMI earc command", CLI_GUEST },
#endif
        {NULL, NULL, NULL, NULL, NULL, CLI_SUPERVISOR}
    };
#endif
#endif//CC_HDMI_EDID_DISABLE

#endif // _EDID_CUSTOMIZATION_H_
