/* 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"
#else
#define DEVICE_MODEL_NUM "mt5895"
#endif

#include "drv_hdmi2.h"

extern void DRVCUST_EdidUpdateNotify(void);

#define EDID_FW_NAME    DEVICE_MODEL_NUM"_edid.fw"

struct soedid_env_info {
	UINT8 banknum;
	UINT8 soc_resolution;
	UINT8 destination;
	UINT8 dovi_support;
	UINT8 hdr_support;
	UINT8 panelless;
	UINT8 wcg_support;
	UINT8 panel_resolution;
    UINT8 no_atmos;
    UINT8 edid_512;
	UINT16 display_inch_size;

	/* panel data */
	UINT8 pnl_data_dovi[8];
	UINT8 pnl_data_vrr[3];
    UINT8 pnl_data_hdr[3];

	/* earc */
	UINT8 *replace_adb;
	UINT8 replace_adb_len;
	UINT8 *replace_sadb;
	UINT8 replace_sadb_len;
};

/* panel_table_cust.c */
extern UINT32 FlashPanel_GetVRRMin(void);
extern UINT32 FlashPanel_GetVRRMax(void);
extern UINT8 FlashPanel_GetMaxLuminance(void);
extern UINT8 FlashPanel_GetAvgLuminance(void);
extern UINT8 FlashPanel_GetMinLuminance(void);

/* sony edid */
extern UINT32 soedid_query_max_firmware_size(void);
extern UINT32 soedid_query_context_size(void);
extern BOOL soedid_create_context(UINT8 **sctx, UINT8 *ctx_mem);
extern BOOL soedid_destroy_context(UINT8 *sctx);
extern BOOL soedid_set_firmware(UINT8 *sctx, UINT8 *fw, UINT32 fw_size);
extern BOOL soedid_set_env_info(UINT8 *sctx, struct soedid_env_info *env_info);
extern BOOL soedid_make_edid(UINT8 *sctx, UINT8 *out_edid, UINT8 port, UINT8 type);
extern UINT16 soedid_query_edid_size(UINT8 *sctx);
extern UINT16 soedid_query_pa_offset(UINT8 *sctx);
extern void soedid_register_cbfunc_debug_print_data(UINT8 *sctx, void(*cbfunc)(char *str, UINT8 *data, UINT32 data_len));

#define MAX_EARC_ADB_LEN	(256)
#define MAX_EARC_SADB_LEN	(4)

typedef struct
{
    UINT32 u4PanelCtrl;
    UINT8 u1HFVSDBFlag;
    UINT8  u1VRRFlag;
	UINT8  u1Adb[MAX_EARC_ADB_LEN];
	UINT8  u1AdbLen;
	UINT8  u1Sadb[MAX_EARC_SADB_LEN];
	UINT8  u1SadbLen;

 	struct soedid_env_info sEnvInfo;
} EDID_SELECT_INFO_T;


typedef struct
{
    UINT32 u4FixedFlag; //changed flag.
    UINT8 u1DolbyVision;
    //add next for debug.
	UINT8 u1PanelLess;
	UINT8 u1Destination;
	UINT8 u1SoCReso;
	UINT8 u1Edid8K;
	UINT8 u1Hdr;
	UINT8 u1Wcg;
	UINT8 u1TI4;
    UINT8 u1NoATMOS;
	UINT8 u1Edid512;
    UINT8 u1Vrr;
    UINT16 u2VrrData;
    UINT8 u1BankNum;
} CUST_CLI_T;

typedef struct
{
    UINT8* pu1EdidFw;
	UINT32 u4EdidFwSize;
	UINT8* pu1EdidCtxBuff;
	UINT8* hExtEdidCtx;
    UINT8  u1TI4Flag;
#if defined(__KERNEL__)&&!defined(CC_UBOOT)
    struct platform_device *pDevice;
#endif
    UINT8 u1ReqFWDone;
    CUST_CLI_T eCLI;
	/* debug control */
	UINT8 u1Level;

	/* storage for created EDID */
	UINT8 u1Edid[4][512];
	UINT16 u2EdidSize[4];
	UINT16 u2PAOffset[4];
}CUST_EDIDOBJ_T;

CUST_EDIDOBJ_T eEdidObj =
{
    .pu1EdidFw = NULL,
	.u4EdidFwSize = 0,
	.pu1EdidCtxBuff = NULL,
	.hExtEdidCtx = NULL,
#if defined(__KERNEL__)&&!defined(CC_UBOOT)
    .pDevice = NULL,
#endif

	.u1Level = 0,
    .u1TI4Flag = 0,
    .u1ReqFWDone = 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,  (UPTR)VGA_EDID_TABLE, VGA_EDID_SIZE ))
    {
        Printf("read eeprom edid fail\n");
    }
#endif

}
#endif /* CC_VGA_EDID_DISABLE */

#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 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)
{
	; /* do nothing */
}

#ifdef CC_HDMI_2_0_HDCP_BIN
UINT8 u1DrvGetHdmiEdidPortSel(UINT8 u1Port);
#ifndef CC_MTK_LOADER
void vHDMIEDIDCLIDebug(EDID_SELECT_INFO_T* prSelectInfo);
#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");
}

BOOL bHDMIIsInternalPort(UINT8 u1Port)
{
    UINT32 u4Value;
    UINT32 u4Addr;

    if ((u1Port < HDMI_SWITCH_1) || (u1Port > HDMI_SWITCH_4))
    {
        u1Port = HDMI_SWITCH_1;
    }
    u4Addr = 0x10090 + (u1Port - 1u);
    EEPROM_Read(u4Addr, (UPTR)(&u4Value), 0x1);
    return (BOOL)(u4Value & 0x20u)? TRUE: FALSE;
}

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

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

void vHDMIEDIDGetDestination(UINT8 *pu1Info)
{
    EEPROM_Read(0x10200, (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)
{
    EEPROM_Read(0x1020c, (UPTR)(pu1Info), 0x1);
}

UINT8 gVRRValue = 0xFF;

void vHDMIEDIDGetVRRFlag(UINT8 *pu1VRR)
{
    if (gVRRValue == 0xFF)
    {
        EEPROM_Read(0x10510, (UPTR)(pu1VRR), 0x1);
        gVRRValue = *pu1VRR;
    }
    else
        *pu1VRR = gVRRValue;
}

void vHDMIEDIDSetVRRFlag(UINT8 *pu1VRR)
{
    EEPROM_Write(0x10510, (UPTR)(pu1VRR), 0x1);
    gVRRValue = *pu1VRR;
}

void vHDMIEDIDUpdateVRRFlag(void)
{
    UINT8 u1Temp;
    EEPROM_Read(0x10510, (UPTR)&u1Temp, 0x1);
    vHDMIEDIDSetVRRFlag(&u1Temp);
}

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

void vHDMIEDIDSetHFVSDBFlag(UINT8 *pu1hfvsdbInfo)
{
    if (*pu1hfvsdbInfo == 0)
    {   /* for FDR */
        vHDMIEDIDSetVRRFlag(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(CC_UBOOT)&&!defined(CC_MTK_LOADER)
extern UINT8 DRVCUST_GetHDMIPortNumber(void);

BOOL bHDMIEDIDGetCCIRSetting(void)
{
    BOOL bRet = FALSE;
    UINT8 u1VrrFlag;
    UINT8 u1Port = DRVCUST_GetHDMIPortNumber();

    if ((u1Port < HDMI_SWITCH_1) || (u1Port > HDMI_SWITCH_4))
    {
        u1Port = HDMI_SWITCH_1;
    }
    vHDMIEDIDGetVRRFlag(&u1VrrFlag);
    u1VrrFlag = (u1VrrFlag >> (u1Port - 1u)) & 0x1;
    if (u1VrrFlag)
    {
        bRet = TRUE;
    }
    return bRet;
}

void vHDMIEDIDSetCCIRSetting(BOOL bBypass)
{
    UNUSED(bBypass);
}

#define CUSTOMER_CCIR_GET_STATUS bHDMIEDIDGetCCIRSetting
#define CUSTOMER_CCIR_SET_STATUS vHDMIEDIDSetCCIRSetting

#endif

#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

#if defined(CC_HDMI_EARC_SUPPORT)&&!defined(CC_UBOOT)&&!defined(CC_MTK_LOADER)
BOOL bHDMIEDIDFilterDataBlock(EARCEDIDInfo_t *pEdidInfo, UINT8 *pu1Adb, UINT8 *pu1AdbLen, UINT8 *pu1Sadb, UINT8 *pu1SadbLen )
{
    UINT8 *u1BlockData;
    UINT8 u1SADLength = 0;
    UINT8 u1SADBLength = 0;
    UINT8 u1IDFlag = 0;
    UINT16 u2Cnt = 1;
    UINT8 u1MaxCnt = 0;
	UINT8 u1Length;

    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))
    {
        u1Length = u1BlockData[u2Cnt]&0x1f;
		if ((u1Length + u2Cnt + 1u) > 256)
		{
            LOG(1, "[EDID]Structure error!\n");
            return FALSE;
		}

        switch(u1BlockData[u2Cnt]>>5)
        {
            case 1:
                u1IDFlag |= 0x01;
                LOG(1, "[EDID]SAD Block Offset:0x%x, Length:0x%x\n", u2Cnt, u1Length);
				if (u1SADLength + u1Length <= MAX_EARC_ADB_LEN)
				{
					x_memcpy(&pu1Adb[u1SADLength], &u1BlockData[u2Cnt + 1], u1Length);
	                u1SADLength += u1Length;
				}
                break;
            case 4:
                u1IDFlag |= 0x02;
                LOG(1, "[EDID]SADB Block Offset:0x%x, Length:0x%x\n", u2Cnt, u1Length);
                if (u1SADBLength + u1Length <= MAX_EARC_SADB_LEN)
				{
					x_memcpy(&pu1Sadb[u1SADBLength], &u1BlockData[u2Cnt + 1], u1Length);
					u1SADBLength += u1Length;
				}
                break;
            default:
                break;
        }
        u2Cnt += u1Length + 1u;
    }

    if(u1IDFlag != 0)
    {
		*pu1AdbLen = u1SADLength;
		*pu1SadbLen = u1SADBLength;
    }
    else
    {
        LOG(1, "[EDID]No SAD/SADB Block!\n");
        return FALSE;
    }
    return TRUE;
}
#endif /* defined(CC_HDMI_EARC_SUPPORT)&&!defined(CC_UBOOT)&&!defined(CC_MTK_LOADER) */

BOOL bHDMIEDIDCreatSelectInfo(EDID_SELECT_INFO_T* prSelectInfo, UINT8 u1Port)
{
	UINT32 vrr_min;
	UINT32 vrr_max;
    UINT8 u1Tmp;

#if defined(CC_HDMI_EARC_SUPPORT)&&!defined(CC_UBOOT)&&!defined(CC_MTK_LOADER)
    EARCEDIDInfo_t *pEdidInfo;
#endif

    if(prSelectInfo == NULL)
    {
        return FALSE;
    }
    if ((u1Port < HDMI_SWITCH_1) || (u1Port > HDMI_SWITCH_4)) {
        u1Port = HDMI_SWITCH_1;
    }
    x_memset(prSelectInfo, 0, sizeof(EDID_SELECT_INFO_T));

#ifdef CC_PANEL_FROM_FLASH
	prSelectInfo->u4PanelCtrl = FlashPanel_GetControlWord3();
	prSelectInfo->sEnvInfo.display_inch_size = FlashPanel_GetInchSize();
#endif

	/* Ti4 */
	vHDMIEDIDGetHFVSDBFlag(&prSelectInfo->u1HFVSDBFlag);
	LOG(1, "[EDID]TI4:0x%x\n", prSelectInfo->u1HFVSDBFlag);

	/* search condition delived from MVI */
    vHDMIEDIDGetBankNum(&prSelectInfo->sEnvInfo.banknum);
    LOG(1, "[EDID]BankNum:0x%x\n", prSelectInfo->sEnvInfo.banknum);

    vHDMIEDIDGet4K2K(&prSelectInfo->sEnvInfo.soc_resolution);
    LOG(1, "[EDID]8K4K2K:0x%x\n", prSelectInfo->sEnvInfo.soc_resolution);

    vHDMIEDIDGetDestination(&prSelectInfo->sEnvInfo.destination);
    LOG(1, "[EDID]Destination:0x%x\n", prSelectInfo->sEnvInfo.destination);

    vHDMIEDIDGetDolbyVision(&prSelectInfo->sEnvInfo.dovi_support);
    LOG(1, "[EDID]DolbyVision:0x%x\n", prSelectInfo->sEnvInfo.dovi_support);

    vHDMIEDIDGetHDR(&prSelectInfo->sEnvInfo.hdr_support);
    LOG(1, "[EDID]HDR:0x%x\n", prSelectInfo->sEnvInfo.hdr_support);

	/* search condition delived from Panel.bin */
	prSelectInfo->sEnvInfo.panelless = (prSelectInfo->u4PanelCtrl >> 31) & 0x1;
    LOG(1, "[EDID]PanelLess:0x%x\n", prSelectInfo->sEnvInfo.panelless);

    prSelectInfo->sEnvInfo.wcg_support = prSelectInfo->u4PanelCtrl & 0x3;
    LOG(1, "[EDID]WCG:0x%x\n", prSelectInfo->sEnvInfo.wcg_support);

	prSelectInfo->sEnvInfo.panel_resolution = (prSelectInfo->u4PanelCtrl >> 20) & 0x3;
    LOG(1, "[EDID]PanelResolution:0x%x\n", prSelectInfo->sEnvInfo.panel_resolution);

	/* dovi vsdb */
	prSelectInfo->sEnvInfo.pnl_data_dovi[0] = FlashPanel_GetDVTargetMinPQv2(); /* minPQv2, GloDim, minLuma */
   	prSelectInfo->sEnvInfo.pnl_data_dovi[1] = FlashPanel_GetDVTargetMaxPQv2(); /* maxPQv2, 0, interface */
    prSelectInfo->sEnvInfo.pnl_data_dovi[2] = FlashPanel_GetDVGx(); /* unique_gx */
    prSelectInfo->sEnvInfo.pnl_data_dovi[3] = FlashPanel_GetDVGy(); /* unique_gy */
    prSelectInfo->sEnvInfo.pnl_data_dovi[4] = FlashPanel_GetDVBx(); /* unique_bx */
    prSelectInfo->sEnvInfo.pnl_data_dovi[5] = FlashPanel_GetDVBy(); /* unique_by */
    prSelectInfo->sEnvInfo.pnl_data_dovi[6] = FlashPanel_GetDVRx(); /* unique_rx */
    prSelectInfo->sEnvInfo.pnl_data_dovi[7] = FlashPanel_GetDVRy(); /* unique_ry */
    vHDMIDebugPrintf("[EDID]RAW Dolby PQ Data:\n", prSelectInfo->sEnvInfo.pnl_data_dovi, 8);
    /* edid 512 and VRR */
    vHDMIEDIDUpdateVRRFlag();
    vHDMIEDIDGetVRRFlag(&u1Tmp);
    u1Tmp = u1Tmp >> (u1Port - 1u);
    prSelectInfo->sEnvInfo.edid_512 = (u1Tmp >> 4) & 0x1;
    LOG(1, "[EDID]Edid512:0x%x\n", prSelectInfo->sEnvInfo.edid_512);

    prSelectInfo->u1VRRFlag = u1Tmp & 0x1;
    LOG(1, "[EDID]VRRFlag:0x%x\n", prSelectInfo->u1VRRFlag);

    /* vrr vsdb */
	vrr_min = FlashPanel_GetVRRMin();
	vrr_max = FlashPanel_GetVRRMax();
	prSelectInfo->sEnvInfo.pnl_data_vrr[0] = ((vrr_max >> 2) & 0xC0u) | vrr_min;
	prSelectInfo->sEnvInfo.pnl_data_vrr[1] = vrr_max & 0xFFu;
    vHDMIDebugPrintf("[EDID]Panel Data VRR:\n", prSelectInfo->sEnvInfo.pnl_data_vrr, 2);

    /* hdr smdb */
    prSelectInfo->sEnvInfo.pnl_data_hdr[0] = FlashPanel_GetMaxLuminance();
    prSelectInfo->sEnvInfo.pnl_data_hdr[1] = FlashPanel_GetAvgLuminance();
    prSelectInfo->sEnvInfo.pnl_data_hdr[2] = FlashPanel_GetMinLuminance();

   /* atmos flag */
   vHDMIEDIDGetLDDDP(&prSelectInfo->sEnvInfo.no_atmos);
   LOG(1, "[EDID]NoATMOS:0x%x\n", prSelectInfo->sEnvInfo.no_atmos);

	/* earc */
#if defined(CC_HDMI_EARC_SUPPORT)&&!defined(CC_UBOOT)&&!defined(CC_MTK_LOADER)
	u1HDMIEARCGetEDIDInfo(&pEdidInfo);
	if (pEdidInfo->bEARCConnect == HDMI_EARC_CONNECT)
	{
		if (bHDMIEDIDFilterDataBlock(pEdidInfo, prSelectInfo->u1Adb, &prSelectInfo->u1AdbLen,
									 prSelectInfo->u1Sadb, &prSelectInfo->u1SadbLen) == TRUE)
		{
			prSelectInfo->sEnvInfo.replace_adb = prSelectInfo->u1Adb;
			prSelectInfo->sEnvInfo.replace_adb_len = prSelectInfo->u1AdbLen;
			prSelectInfo->sEnvInfo.replace_sadb = prSelectInfo->u1Sadb;
			prSelectInfo->sEnvInfo.replace_sadb_len = prSelectInfo->u1SadbLen;

		    vHDMIDebugPrintf("[EDID]Filter audio data (ADB):\n", prSelectInfo->sEnvInfo.replace_adb, prSelectInfo->sEnvInfo.replace_adb_len);
		    vHDMIDebugPrintf("[EDID]Filter audio data (SADB):\n", prSelectInfo->sEnvInfo.replace_sadb, prSelectInfo->sEnvInfo.replace_sadb_len);

		} else {
	        LOG(1, "[EDID]Get Audio Data Block Fail!\n");
		}
	}
#endif

#ifndef CC_MTK_LOADER
    vHDMIEDIDCLIDebug(prSelectInfo);
#endif
    if (prSelectInfo->u1VRRFlag == 0)
    {
        prSelectInfo->sEnvInfo.pnl_data_vrr[0] = 0;
        prSelectInfo->sEnvInfo.pnl_data_vrr[1] = 0;
    }

    eEdidObj.u1TI4Flag = prSelectInfo->u1HFVSDBFlag;
    return TRUE;
}


/* in M5, we consider an interface of this function is not suitable because M5 has a respective EDID RAM by hdmi port.
 * So we change the meaning of u1Type to "target port".
 */
void vHDMIEDIDReadEDID(UINT8 u1Type, UINT8* pBuff, UINT32* pOffset)
{
    if((pBuff == NULL) || (pOffset == NULL))
    {
        LOG(0,"%s invalid input PARAM\n",__FUNCTION__);
        return;
    }

	if (u1Type < 4u) {
		x_memcpy(pBuff, &eEdidObj.u1Edid[u1Type][0], eEdidObj.u2EdidSize[u1Type]);
		*pOffset = eEdidObj.u2PAOffset[u1Type];
        LOG(1, "[EDID]Read EDID, port:%d\n", u1Type);
	    LOG(1, "[EDID]physical address: 0x%x\n",*pOffset);
	    vHDMIDebugPrintf("[EDID]Read edid data:\n", pBuff, eEdidObj.u2EdidSize[u1Type]);
    }
}

#if defined(__KERNEL__)&&!defined(CC_UBOOT)
BOOL bHDMIEDIDUpdateNotify(EDID_SELECT_INFO_T* prSelectInfo)
{
    if (prSelectInfo == NULL)
	{
		return FALSE;
	}

    DRVCUST_EdidUpdateNotify();
    return TRUE;
}
#endif

BOOL bHDMIMakeEDID(UINT8 u1Port)
{
    BOOL bRet = FALSE;

#if defined(__KERNEL__)&&!defined(CC_UBOOT)
    EDID_SELECT_INFO_T rSelectInfo;
	UINT8 u1EdidType;

    if(eEdidObj.pu1EdidFw == NULL)
    {
        eEdidObj.pu1EdidFw = (UINT8*)x_mem_alloc(soedid_query_max_firmware_size());
        if(eEdidObj.pu1EdidFw == NULL)
        {
            LOG(0, "EDID Buffer malloc fail\n");
            goto Exit;
        }
	}
	if (eEdidObj.pu1EdidCtxBuff == NULL)
	{
		eEdidObj.pu1EdidCtxBuff = (UINT8*)x_mem_alloc(soedid_query_context_size());
		if (eEdidObj.pu1EdidCtxBuff == NULL)
		{
			LOG(0, "EDID buffer malloc fail\n");
			goto Exit;
		}
	}
	if (eEdidObj.hExtEdidCtx == NULL)
	{
		if (soedid_create_context(&eEdidObj.hExtEdidCtx, eEdidObj.pu1EdidCtxBuff) == FALSE)
		{
            LOG(0, "extEDID init fail\n");
            goto Exit;
		}
		soedid_register_cbfunc_debug_print_data(eEdidObj.hExtEdidCtx, vHDMIDebugPrintf);
	}

	if (eEdidObj.u1ReqFWDone == 0)
	{
		const struct firmware *pfw;
		struct device* pdev;

		if (!(pdev = pHDMIEDIDGetDevice())) {
			LOG(0, "[EDID]Get Device Fail!\n");
			goto Exit;
		}

		if (request_firmware(&pfw, EDID_FW_NAME, pdev) < 0) {
			eEdidObj.u4EdidFwSize = 0;
			LOG(0, "[EDID]request_edid_firmware failed\n");
			goto Exit;
		}
		eEdidObj.u1ReqFWDone = 0x1;
		LOG(0, "[EDID]request_edid_firmware:%s, size:%lu\n", EDID_FW_NAME, pfw->size);
		if (pfw->size > soedid_query_max_firmware_size()) {
			LOG(0, "[EDID]firmware size error\n");
			release_firmware(pfw);
			goto Exit;
		}
		x_memcpy(eEdidObj.pu1EdidFw, pfw->data, pfw->size);
		eEdidObj.u4EdidFwSize = pfw->size;
		release_firmware(pfw);

		soedid_set_firmware(eEdidObj.hExtEdidCtx, eEdidObj.pu1EdidFw, eEdidObj.u4EdidFwSize);
	}

    if (bHDMIEDIDCreatSelectInfo(&rSelectInfo, u1Port) == FALSE) {
        LOG(0, "[EDID]CreatSelectInfo Fail\n");
        goto Exit;
    }
	soedid_set_env_info(eEdidObj.hExtEdidCtx, &rSelectInfo.sEnvInfo);

	/* create edid */
	u1EdidType = u1DrvGetHdmiEdidPortSel(u1Port);
	LOG(1, "[EDID] invoke MakeEdid (port:%d, type:%d)\n", u1Port, u1EdidType);
	if (soedid_make_edid(eEdidObj.hExtEdidCtx, &eEdidObj.u1Edid[u1Port - 1u][0], u1Port - 1u, u1EdidType) == FALSE) {
		LOG(0, "[EDID]MakeEdid failed (port:%d, type:%d)\n",u1Port, u1EdidType);
		goto Exit;
	}

	eEdidObj.u2EdidSize[u1Port - 1u] = soedid_query_edid_size(eEdidObj.hExtEdidCtx);
	eEdidObj.u2PAOffset[u1Port - 1u] = soedid_query_pa_offset(eEdidObj.hExtEdidCtx);

    if (bHDMIIsInternalPort(u1Port))
    {
        if(bHDMIEDIDUpdateNotify(&rSelectInfo) == FALSE)
        {
            LOG(0, "[EDID]UpdateNotify Fail\n");
            goto Exit;
        }
    }
    bRet = TRUE;
    LOG(0, "[EDID]Make Edid Success\n");
Exit:
#endif
    return bRet;
}

#endif

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

//retval: 0 for select EDID1, 1 for select EDID2
UINT8 u1DrvGetHdmiEdidPortSel(UINT8 u1Port)
{
	UINT8 u1Tmp;

	if ((u1Port < HDMI_SWITCH_1) || (u1Port > HDMI_SWITCH_4)) {
		u1Port = HDMI_SWITCH_1;
	}
	u1Tmp = eEdidObj.u1TI4Flag >> (u1Port - 1u);
    return (u1Tmp & 0x1u) | ((u1Tmp >> 3) & 0x2u);
}

UINT8* pu1DrvLoadHdmiStandardEdid(void)
{
	LOG(0, "[EDID] unsupported function call %s\n", __FUNCTION__);
    return &eEdidObj.u1Edid[HDMI_SWITCH_1][0]; /* fail safe: this function returns port1's EDID */
}

UINT8* pu1DrvLoadHdmiEnhancedEdid(void)
{
	LOG(0, "[EDID] unsupported function call %s\n", __FUNCTION__);
    return &eEdidObj.u1Edid[HDMI_SWITCH_2][0]; /* fail safe: this function returns port2's EDID */
}

void vPostHdmiEdidProcess(UINT8* pu1Edid)
{

}

UINT8* pu1DrvGetEdidStorage(UINT8 u1Port)
{
	if ((u1Port < HDMI_SWITCH_1) || (u1Port > HDMI_SWITCH_4)) {
		u1Port = HDMI_SWITCH_1;
	}

	if (bHDMIMakeEDID(u1Port) == FALSE) {
		LOG(0, "[EDID] make edid failed port:%d", u1Port);
	}

	return &eEdidObj.u1Edid[u1Port - 1u][0];
}

UINT16 u2DrvGetEdidSize(UINT8 u1Port)
{
	if ((u1Port < HDMI_SWITCH_1) || (u1Port > HDMI_SWITCH_4)) {
		u1Port = HDMI_SWITCH_1;
	}

    return eEdidObj.u2EdidSize[u1Port - 1u];
}


UINT8* pu1DrvLoadHdmiEdid(UINT8 u1Port)
{
    UINT8* pu1Edid = pu1DrvGetEdidStorage(u1Port);
    vPostHdmiEdidProcess(pu1Edid);
    return pu1Edid;
}

UINT8* pu1DrvLoadHdmiEdid1(void)
{
	LOG(0, "[EDID] unsupported function call %s\n", __FUNCTION__);
    return &eEdidObj.u1Edid[0][0]; /* fail safe: this function returns port1's EDID */
}

UINT8* pu1DrvLoadHdmiEdid2(void)
{
	LOG(0, "[EDID] unsupported function call %s\n", __FUNCTION__);
    return &eEdidObj.u1Edid[1][0]; /* fail safe: this function returns port2's EDID */
}

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;
}

INT32 u4HDMIDebugSetStatusCmd(INT32 i4Argc, const CHAR** szArgv)
{
	UINT32 u4Type;
	UINT8 u1Status;
	UINT8 u1Port;

	if (i4Argc < 3)
	{
		LOG(0, "usage: type,status\n");
		Printf("type: \n"
			"0:Cancel\n"
			"1:Make Edid\n"
			"3:BankNum\n"
			"4:PanelLess\n"
			"5:Destination\n"
			"6:SOC 8K4K2K\n"
			"7:Edid8K\n");
		Printf("8:HDR\n"
			"9:WCG\n"
            "10:DolbyVision\n"
            "11:NoAtmos\n"
            "12:Edid512\n"
            "13:VRR\n"
            "14:VRRData (16bits)\n");
		Printf("16:TI4\n"
			"17:RequestFirmware\n"
			"\n");

	} else {
		u4Type = (UINT32)StrToInt(szArgv[1]);
		u1Status = (UINT8)StrToInt(szArgv[2]);

		switch (u4Type)
		{
		case 0:
			LOG(0, "clear fixed flag\n");
			eEdidObj.eCLI.u4FixedFlag = 0;
			break;
		case 1:
			//only call to make edid.
			break;
		case 3:
			eEdidObj.eCLI.u1BankNum = u1Status;
			break;
		case 4:
			eEdidObj.eCLI.u1PanelLess = u1Status;
			break;
		case 5:
			eEdidObj.eCLI.u1Destination = u1Status;
			break;
		case 6:
			eEdidObj.eCLI.u1SoCReso = u1Status;
			break;
		case 7:
			eEdidObj.eCLI.u1Edid8K = u1Status;
			break;
		case 8:
			eEdidObj.eCLI.u1Hdr = u1Status;
			break;
		case 9:
			eEdidObj.eCLI.u1Wcg = u1Status;
			break;
		case 10:
			eEdidObj.eCLI.u1DolbyVision = u1Status;
			break;
        case 11:
            eEdidObj.eCLI.u1NoATMOS = u1Status;
            break;
        case 12:
            eEdidObj.eCLI.u1Edid512 = u1Status;
            break;
        case 13:
            eEdidObj.eCLI.u1Vrr = u1Status;
            break;
        case 14:
            eEdidObj.eCLI.u2VrrData = (UINT16)StrToInt(szArgv[2]);
            break;
		case 16:
			eEdidObj.eCLI.u1TI4 = u1Status;
			break;
		case 17:
			eEdidObj.u1ReqFWDone = 0;
			break;
		default:
			return 0;
			break;
		}
		eEdidObj.eCLI.u4FixedFlag |= 1 << u4Type;

		for (u1Port = HDMI_SWITCH_1; u1Port <= HDMI_SWITCH_4; u1Port++) {
			bHDMIMakeEDID(u1Port);
		}
	}

	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 3:
                LOG(0, "[EDID]fix BankNum:0x%x\n",eEdidObj.eCLI.u1BankNum);
                prSelectInfo->sEnvInfo.banknum = eEdidObj.eCLI.u1BankNum;
                break;
            case 4:
                LOG(0, "[EDID]fix PanelLess:0x%x\n",eEdidObj.eCLI.u1PanelLess);
                prSelectInfo->sEnvInfo.panelless = eEdidObj.eCLI.u1PanelLess;
                break;
            case 5:
                LOG(0, "[EDID]fix Destination:0x%x\n",eEdidObj.eCLI.u1Destination);
                prSelectInfo->sEnvInfo.destination = eEdidObj.eCLI.u1Destination;
                break;
            case 6:
                LOG(0, "[EDID]fix SoC 8K4K2K:0x%x\n",eEdidObj.eCLI.u1SoCReso);
                prSelectInfo->sEnvInfo.soc_resolution = eEdidObj.eCLI.u1SoCReso;
                break;
            case 7:
                LOG(0, "[EDID]fix Edid8K:0x%x\n",eEdidObj.eCLI.u1Edid8K);
                prSelectInfo->sEnvInfo.panel_resolution = eEdidObj.eCLI.u1Edid8K;
                break;
            case 8:
                LOG(0, "[EDID]fix HDR:0x%x\n",eEdidObj.eCLI.u1Hdr);
                prSelectInfo->sEnvInfo.hdr_support = eEdidObj.eCLI.u1Hdr;
                break;
            case 9:
                LOG(0, "[EDID]fix WCG:0x%x\n",eEdidObj.eCLI.u1Wcg);
                prSelectInfo->sEnvInfo.wcg_support = eEdidObj.eCLI.u1Wcg;
                break;
            case 10:
                LOG(0, "[EDID]fix DolbyVision:0x%x\n",eEdidObj.eCLI.u1DolbyVision);
                prSelectInfo->sEnvInfo.dovi_support = eEdidObj.eCLI.u1DolbyVision;
                break;
            case 11:
                LOG(0, "[EDID]fix NoATMOS:0x%x\n",eEdidObj.eCLI.u1NoATMOS);
                prSelectInfo->sEnvInfo.no_atmos = eEdidObj.eCLI.u1NoATMOS;
                break;
            case 12:
                LOG(0, "[EDID]fix Edid512:0x%x\n",eEdidObj.eCLI.u1Edid512);
                prSelectInfo->sEnvInfo.edid_512 = eEdidObj.eCLI.u1Edid512;
                break;
            case 13:
                LOG(0, "[EDID]fix VRR:0x%x\n",eEdidObj.eCLI.u1Vrr);
                prSelectInfo->u1VRRFlag = eEdidObj.eCLI.u1Vrr;
                break;
            case 14:
                LOG(0, "[EDID]fix VRRData:0x%x\n",eEdidObj.eCLI.u2VrrData);
                prSelectInfo->sEnvInfo.pnl_data_vrr[0] = eEdidObj.eCLI.u2VrrData >> 4;
                prSelectInfo->sEnvInfo.pnl_data_vrr[1] = eEdidObj.eCLI.u2VrrData & 0xFF;
                break;
            case 16:
                LOG(0, "[EDID]fix TI4:0x%x\n",eEdidObj.eCLI.u1TI4);
                prSelectInfo->u1HFVSDBFlag = eEdidObj.eCLI.u1TI4;
                break;
            default:
                break;
        }
        i++;
    }
}

#if !defined(CC_UBOOT)&&!defined(CC_MTK_LOADER)
INT32 u4HDMIDebugGetCCIRSettingCmd(INT32 i4Argc, const CHAR** szArgv)
{
    UNUSED(i4Argc);
    UNUSED(szArgv);
    Printf("ccir setting: %d\n",bHDMIEDIDGetCCIRSetting());
    return 0;
}
#endif

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
#if !defined(CC_UBOOT)&&!defined(CC_MTK_LOADER)
        {"gccir", NULL, u4HDMIDebugGetCCIRSettingCmd, NULL, "get CCIR setting", CLI_GUEST},
#endif
        {NULL, NULL, NULL, NULL, NULL, CLI_SUPERVISOR}
    };
#endif
#endif//CC_HDMI_EDID_DISABLE

#endif//_EDID_CUSTOMIZATION_H_
