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

/*-----------------------------------------------------------------------------
 *
 * $Author$
 * $Date  $
 * $RCSfile: drv_hdmi.h,v $
 * $Revision$
 *
 *---------------------------------------------------------------------------*/

#ifndef _DRV_HDMI21PHY_H_
#define _DRV_HDMI21PHY_H_

//#include "typedef.h"
//#include "x_timer.h"
//#include "drv_mhlcom.h"
#include "x_typedef.h"
#include "drv_hdmi2.h"

typedef enum
{
    HDMI_RX_FREQ_DVI,
    HDMI_RX_FREQ_MON_CK,
    HDMI_RX_FREQ_MON_CK2,
    HDMI_RX_FREQ_DEEPCLRCK
}HdmiRxFreq_t;

typedef enum
{
    HDMI_RX_FREQ_METER_LP,
    HDMI_RX_FREQ_METER_HP

}HdmiRxFreqMeter_t;

typedef enum
{
    HDMI21ANA_CDRST_DELAY_CDRDONE,
    HDMI21ANA_CDRST_DELAY_100us,
    HDMI21ANA_CDRST_DELAY_2ms
}HDMI2ANA_CDR_RST_DELAY_ITEM;

typedef enum
{
    HDMI21_SETTING_NONE = 0,
    HDMI21_SETTING_STATE00 = 1,
    HDMI21_SETTING_STATE01 = 2,
    HDMI21_SETTING_STATE02 = 3,
    HDMI21_SETTING_STATE03 = 4,
    HDMI21_SETTING_STATE04 = 5,
    HDMI21_SETTING_STATE05 = 6,
    HDMI21_SETTING_STATE05_1 = 7,
    HDMI21_SETTING_STATE06 = 8,
    HDMI21_SETTING_STATE06_1 = 9,
    HDMI21_SETTING_STATE07 = 10,
    HDMI21_SETTING_STATE08 = 11,
    HDMI21_SETTING_STATE08_1 = 12,
    HDMI21_SETTING_STATE08_2 = 13,
    HDMI21_SETTING_STATE09_0 = 14,
    HDMI21_SETTING_STATE09 = 15,
    HDMI21_SETTING_STATE09_1 = 16,
    HDMI21_SETTING_STATE10 = 17,
    HDMI21_SETTING_STATE10_1 = 18,
    HDMI21_SETTING_STATE10_2 = 19,
    HDMI21_SETTING_STATE11 = 20,
    HDMI21_SETTING_STATE11_1 = 21,
    HDMI21_SETTING_STATE11_2 = 22,
    HDMI21_SETTING_STATE12 = 23,
    HDMI21_SETTING_STATE12_1 = 24,
    HDMI21_SETTING_STATE13 = 25,
}HdmiRxSettingState_t;

typedef enum
{
    HDMI21_RXCDRMODE_NONE = 0,
    HDMI21_RXCDRMODE_OVERSAMPLE_8X,
    HDMI21_RXCDRMODE_OVERSAMPLE_4X,
    HDMI21_RXCDRMODE_OVERSAMPLE_2X,
    HDMI21_RXCDRMODE_OVERSAMPLE_HALF_RATE,
}HdmiRxCDRMode_t;

typedef enum
{
    HDMI21_HDMIRXPLL_SOURCE_TMDSCK = 0,
    HDMI21_HDMIRXPLL_SOURCE_MDPLL = 1,
}HdmiRxPLLource_t;

typedef struct
{
    UINT32 u4CntTarget;
    UINT16 u2PatMask;
    UINT16 u2TargetPat;
    UINT32* apu4DebugBufWP[8];
    INT16 s2Par1;
    INT16 s2Par2;
    INT16 s2Par1Min;
    INT16 s2Par1Max;
    INT16 s2Par2Min;
    INT16 s2Par2Max;
}HDMI21PHY_DEBUG_PARA;

#define u2AgingCnt_time 2 // Verification time=100
#define HDMI21PHY_VERIFICATION_LEQOS_TEST 0

typedef struct
{
    UINT32 u4TAPN1[u2AgingCnt_time];
    UINT32 u4TAP0[u2AgingCnt_time];
    UINT32 u4TAP1[u2AgingCnt_time];
    UINT32 u4TAP2[u2AgingCnt_time];
    UINT32 u4TAP3[u2AgingCnt_time];
    UINT32 u4TAP4[u2AgingCnt_time];
    UINT32 u4TAP5[u2AgingCnt_time];
    UINT32 u4LEQ[u2AgingCnt_time];
    UINT32 u4VGA[u2AgingCnt_time];
    UINT32 u4XDBG[u2AgingCnt_time];
    UINT32 u4XDBGD[u2AgingCnt_time];
    UINT32 u4PIEDGE[u2AgingCnt_time];
    UINT32 u4PIEDBG[u2AgingCnt_time];
    UINT32 u4D0L_OS[u2AgingCnt_time];
    UINT32 u4DLEV1_OS[u2AgingCnt_time];
    UINT32 u4DLEV0_OS[u2AgingCnt_time];
    UINT32 u4EDBG_OS[u2AgingCnt_time];
    UINT32 u4E0_OS[u2AgingCnt_time];
    UINT32 u4D1H_OS[u2AgingCnt_time];
    UINT32 u4D1L_OS[u2AgingCnt_time];
    UINT32 u4D0H_OS[u2AgingCnt_time];
    UINT32 u4E1_OS[u2AgingCnt_time];
    #if HDMI21PHY_VERIFICATION_LEQOS_TEST
    UINT32 u4LEQ_OS_Pre[u2AgingCnt_time];
    #endif
    UINT32 u4LEQ_OS[u2AgingCnt_time];
    UINT32 u4HTOTAL[u2AgingCnt_time];
    UINT32 u4HACTIVE[u2AgingCnt_time];
    UINT32 u4VTOTAL[u2AgingCnt_time];
    UINT32 u4VACTIVE[u2AgingCnt_time];
    UINT32 u4CRCValue[u2AgingCnt_time];
    BOOL fgCRCFAIL[u2AgingCnt_time];
    BOOL fgCRCREADY[u2AgingCnt_time];
    UINT32 u4DCRCValue[u2AgingCnt_time];
    BOOL fgDCRCFAIL[u2AgingCnt_time];
    BOOL fgDCRCREADY[u2AgingCnt_time];
}HDMI21PHY_CALIBRATION_DATA;

typedef struct
{
    UINT32 u4Times;
    UINT32 u4HTOTAL;
    UINT32 u4HACTIVE;
    UINT32 u4VTOTAL;
    UINT32 u4VACTIVE;
    UINT32 u4DCRCValue;
    BOOL fgDCRCFAIL;
    BOOL fgDCRCREADY;
}HDMI21PHY_STRESSTEST;

typedef struct
{
    BOOL fgSigDetCalTimeout;
}HDMI21PHY_CALSTATUS;

/**
 * @brief        Get Analog RG base address
 * @param        ePort---- HDMI port number
 * @retval       Base address
*/
extern UINT16 u2HDMI21GetPhyAnaBaseAddr(E_HDMI_SWITCH_NUM ePort);
/**
 * @brief        Enable analog EQ macro in general analog set flow
 * @param        ePort---- HDMI port number
*/
extern void vHDMI21PhyAnaEQMacroEnable(UINT16 u2HdmiAnaBase);
/**
 * @brief        Set analog all
 * @param        ePort---- HDMI port number
*/
extern void vHDMI21PhyAnaSetting(E_HDMI_SWITCH_NUM ePort);
/**
 * @brief        Get analog CDR LPO value
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        eChannel---- TMDS data channel to get, see HdmiTmdsDataChannel_t.
 * @retval       CDR LPO value
*/
extern UINT8 bHDMI21PhyAnaGetCDRLPO(UINT16 u2HdmiAnaBase,HdmiTmdsDataChannel_t eChannel);
/**
 * @brief        Fix analog LEQ control code
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        bFix---- TRUE for fix LEQ control code, FALSE for auto LEQ control
 * @param        u1EQInitVal---- Fix LEQ control code
*/
extern void vHDMI21PhyAnaFixEQ(UINT16 u2HdmiAnaBase,BOOL bFix, UINT8 u1EQInitVal);
/**
 * @brief        Get analog LEQ control code
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        u1Lane---- TMDS data channel to get, see HdmiTmdsDataChannel_t
 * @retval       LEQ control code
*/
extern UINT8 u1HDMI21PhyRGS_RO_LEQ_CTRL(UINT16 u2HdmiAnaBase, HdmiTmdsDataChannel_t u1Lane);
/**
 * @brief        Enable/Disable analog TMDS termination
 * @param        u2HdmiAnaOfst----  Base address by port
 * @param        fgOnOff---- TRUE for enable, FALSE for disable
*/
extern void vHDMI21PhyAnaTermCtrl(UINT16 u2HdmiAnaBase,BOOL bOnOff);
/**
 * @brief        Reset analog CDR.
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        u1Enable---- 1 for reset, 0 for release
*/
extern void vHDMI21PhyAnaCDR_RST(UINT16 u2HdmiAnaBase,UINT8 u1Enable);
/**
 * @brief        Reset analog EQOSC.
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        u1Enable---- 1 for reset, 0 for release
*/
extern void vHDMI21PhyAnaEQOSC_RSTB(UINT16 u2HdmiAnaBase,UINT8 u1Rstb);
/**
 * @brief        Reset analog SAOSC.
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        u1Rstb---- 1 for reset, 0 for release
*/
extern void vHDMI21PhyAnaSAOSC_RSTB(UINT16 u2HdmiAnaBase,UINT8 u1Rstb);
/**
 * @brief        Reset analog CDR.
 * @param        u2HdmiAnaBase---- Base address by port
*/
extern void vHDMI21PhyAnaCDRReset(UINT16 u2HdmiAnaBase);
/**
 * @brief        Reset analog VGA.
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        u1Rstb---- 1 for reset, 0 for release
*/
extern void vHDMI21PhyAnaVGA_RSTB(UINT16 u2HdmiAnaBase,UINT8 u1Rstb);
/**
 * @brief        Analog partial setting by state
 * @param        ePort---- HDMI port number
 * @param        eSettingState ---- partial module setting
*/
extern void vHDMI21PhyAnaSwitchCase(HdmiRxSettingState_t eSettingState, E_HDMI_SWITCH_NUM ePort);
/**
 * @brief        Get analog Phy clock status
 * @param        ePort---- HDMI port number
*/
extern void vHDMI21PhyClockStatus(E_HDMI_SWITCH_NUM ePort);
/**
 * @brief        Get analog Phy status
 * @param        ePort---- HDMI port number
*/
extern void vHDMI21PhyStatus(E_HDMI_SWITCH_NUM ePort);
/**
 * @brief        Get analog Phy firmware parameter
 * @param        ePort---- HDMI port number
*/
extern void vHDMI21PhyParameterStatus(E_HDMI_SWITCH_NUM ePort);
/**
 * @brief        Reset DEEPPLL
 * @param        ePort---- HDMI port number
*/
extern void vHDMI21PhyAnaFixColorDepth(E_HDMI_SWITCH_NUM ePort);
/**
 * @brief        Reset analog all
 * @param        ePort---- HDMI port number
*/
extern void vHDMI21PhyAnaAllReset(E_HDMI_SWITCH_NUM ePort);
/**
 * @brief        Analog init
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        bRX21Mode---- 1 for HDMI 2.1 reset Mode, 0 for other
*/
extern void vHDMI21PhyAnaInit(UINT16 u2HdmiAnaBase, BOOL bRX21Mode);
/**
 * @brief        Reset analog LEQ/VGA/DFE/XDBG/SIGDET_REF_RSTB
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        bRX21Mode---- 1 for with SIGDET_REF_RSTB reset, 0 for without SIGDET_REF_RSTB reset
*/
extern void vHDMI21PhyAnaLEQ_VGA_DFE_XDBG_Timer_Rst(UINT16 u2HdmiAnaBase, BOOL fgTimerRst);
/**
 * @brief        Reset/Release analog DFE
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        u1Rstb---- 1 for release, 0 for reset
*/
extern void vHDMI21PhyAnaDFE_RSTB(UINT16 u2HdmiAnaBase,UINT8 u1Rstb);
/**
 * @brief        Reset/Release analog XDBG
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        u1Rstb---- 1 for release, 0 for reset
*/
extern void vHDMI21PhyAnaXDBG_RSTB(UINT16 u2HdmiAnaBase,UINT8 u1Rstb);
/**
 * @brief        Reset/Release analog EDBG
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        u1Rst---- 1 for reset, 0 for release
*/
extern void vHDMI21PhyAnaEDBG_RSTB(UINT16 u2HdmiAnaBase,UINT8 u1Rstb);
/**
 * @brief        Check analog edebug ready or not
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        eChannel---- TMDS data channel to get, see HdmiTmdsDataChannel_t
 * @retval       TRUE for debug1 ready, FALSE for not
*/
extern BOOL bHDMI21PhyAnaGetEDBGReady(UINT16 u2HdmiAnaBase,HdmiTmdsDataChannel_t eChannel);
/**
 * @brief        Get analog edebug status
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        u1EvenSel---- TRUE for select even data, FALSE for select odd data
 * @param        eChannel---- TMDS data channel to get, see HdmiTmdsDataChannel_t
 * @retval       eDebug1 status
*/
extern UINT32 wHDMI21PhyAnaGetEDBGStatus(UINT16 u2HdmiAnaBase,UINT8 u1EvenOddSel,HdmiTmdsDataChannel_t eChannel);
/**
 * @brief        Set analog edebug control parameter
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        s1Par1---- Parameter 1
 * @param        s1Par2---- Parameter 2
*/
extern void vHDMI21PhyAnaEDBGParSet(UINT16 u2HdmiAnaBase,INT16 s2Par1,INT16 s2Par2);
/**
 * @brief        Enable analog edebug
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        bEnable---- TRUE for enable, FALSE for disable
*/
extern void vHDMI21PhyAnaEDBGEnable(UINT16 u2HdmiAnaBase,BOOL bEnable);
/**
 * @brief        Enable analog PI Calibration
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        bEnable---- TRUE for enable, FALSE for disable
*/
extern void vHDMI21PhyAnaPICALEnable(UINT16 u2HdmiAnaBase);
/**
 * @brief        Set analog edebug pattern
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        u2PatMask---- Pattern mask
 * @param        u2TargetPat---- Target pattern
*/
extern void vHDMI21PhyAnaEDBGPatSet(UINT16 u2HdmiAnaBase,UINT16 u2PatMask, UINT16 u2TargetPat);
/**
 * @brief        Set analog edebug count target
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        u4CntTarget---- Count target
*/
extern void vHDMI21PhyAnaEDBGCntTargetSet(UINT16 u2HdmiAnaBase,UINT32 u4CntTarget);
/**
 * @brief        Judge HDMI PHY CDR Mode by TMDS Clock
 * @param        u4ClkKhz---- TMDS Clock
 * @retval       CDR Mode
*/
extern HdmiRxCDRMode_t u1HDMI21PhyJudgeCDRMode(UINT32 u4ClkKhz,BOOL b40xMode, BOOL bFRLMode);
/**
 * @brief        Get HDMI PHY CDR Mode
 * @param        ePort---- HDMI port number
 * @retval       CDR Mode
*/
extern UINT8 u1HDMI21PhyGetCDRMode(E_HDMI_SWITCH_NUM ePort);
/**
 * @brief        Re ALG under FFE setting
 * @param        ePort---- HDMI port number
*/
extern void vHDMI21PhyAnaFFE_REALG(E_HDMI_SWITCH_NUM ePort);
/**
 * @brief        Get HDMI PHY RefClk (TMDS Clock)
 * @param        ePort---- HDMI port number
 * @retval       tmdsclk(KHz)
*/
extern UINT32 u4HDMI21PhyGetRefClkKhz(E_HDMI_SWITCH_NUM ePort);
extern void vHDMI21PhyGPOSetALG_DONE(UINT16 u2HdmiAnaBase);
extern void vHDMI21PhySaveCalibrationData(E_HDMI_SWITCH_NUM ePort);
extern void vHDMI21PhyPrintCalibrationData(void);
extern void vHDMI21PhyAnaImpedenceMeasure(E_HDMI_SWITCH_NUM ePort, UINT16 u2Value);
extern void vHDMI21PhyAnaVGAVerification(E_HDMI_SWITCH_NUM ePort);
extern void vHDMI21PhyAnaDACLinearity_AUTO(E_HDMI_SWITCH_NUM ePort);
extern void vHDMI21PhyAnaDACCTRLVerification_AUTO(E_HDMI_SWITCH_NUM ePort);
extern BOOL vHDMI21PhySaveStressTest(E_HDMI_SWITCH_NUM ePort);
extern void vHDMI21PhyAnaSetFixEQ(E_HDMI_SWITCH_NUM ePort,BOOL bFix, UINT8 u1EQVal);
extern void vHDMI21PhyAnaDACLinearity_DEBUG(E_HDMI_SWITCH_NUM ePort);
extern void vHDMI21PhyAna0p9V_Check(E_HDMI_SWITCH_NUM ePort);
extern void vHDMI21PhyAnaDAC_DEBUG(E_HDMI_SWITCH_NUM ePort);
/**
 * @brief        Set HDMI PHY enter Power Down mode
*/
extern void vApiHDMI21PhyAnaPowerDownMode(void);
extern void vApiHDMI21PhyAnaWriteLatencyCheck(UINT8 u1Case);
extern void vApiHDMI21PhyAnaPLLEQBandCheck(E_HDMI_SWITCH_NUM ePort,UINT32 u4TmdsClkKhz,BOOL b40xMode);
/**
 * @brief        Get HDMI PHY Dig FIFO reset
 * @param        u2HdmiAnaBase---- Base address by port
 * @param        bEnable---- TRUE for enable, FALSE for disable
*/
extern void vHDMI21PhyDigFIFOAutoSync(UINT16 u2HdmiAnaBase, BOOL fgEnable);
extern void _vHDMI2PhyAna3Lane_Enable(UINT16 u2HdmiAnaBase,BOOL fg3lane); //0: 4lane 1: 3lane
extern UINT8 bHDMI2CheckLaneDataLane(E_HDMI_SWITCH_NUM ePort);
extern BOOL fgHDMI21PhyGetSCDT(UINT16 u2HdmiBase);

#endif
