/* 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: jiewen.zhou $
 * $Date: 2016/01/21 $
 * $RCSfile: drv_vdoclk.h,v $
 * $Revision: #3 $
 *
 *---------------------------------------------------------------------------*/


#ifndef _VDO_CLK_H_
#define _VDO_CLK_H_

#include "typedef.h"
#include "hw_ckgen.h"
#include "hw_scpos.h"
#include "hw_vfe.h"
#include "hw_ddds.h"
#include "hw_pll_group.h"


// PLL related define macros.
#ifdef CC_UP8032_ATV
#define EnableSDDSCalibration  0
#define EnableDDDSCalibration  0
#else
  #ifdef NDEBUG
	#define EnableSDDSCalibration  1	
	#define EnableDDDSCalibration  1
  #else
	#define EnableSDDSCalibration  0
	#define EnableDDDSCalibration  0
  #endif
#endif

#if EnableDDDSCalibration
    #ifndef CC_MTK_LOADER
        #include "feature.h"
    #else /* CC_MTK_LOADER */
        #define u8Div6432(a, b, c)  ((a) / (b))
    #endif /* CC_MTK_LOADER */
#endif

#define USE_MT8202_PLL_SETTING              0
#define THERMAL_COMPENSATION_ENABLE 0
#define CHANGE_SDDS_KPI 1            //Michael 20090123 ***
#define ENABLE_DDDS2_FEEDBACK 1
#define DDDS_OUT_DIV2 1

#define NEW_PHASE_ALGORITHM   1
#if NEW_PHASE_ALGORITHM         // Phase3Channel can be 1 or 0 only when NEW_PHASE_ALGORITHM=1
#define VGA_HW_AUTO	  0 // please always fix to 0
#define Phase3Channel       1

   #if Phase3Channel
        #define CHANNEL_NUM  3
   #else
        #define CHANNEL_NUM  1
   #endif
   #define MAX_PHASE_ARRAY  33  
    extern void vYPbPrPhaseIsr_New(void) ; //YPbPr Auto Phase 2006/11/07
    extern void vVgaPhaseIsr_New(void) ;
    extern void vDrvInitPhaseVar(void);
    extern UINT32	 _dBestSumALL[CHANNEL_NUM];
    //extern UINT8   _bMaxSlope[CHANNEL_NUM];
    extern UINT8   _bChBestPhase[CHANNEL_NUM];
    extern UINT32	 _dSumTmpPhase[CHANNEL_NUM][MAX_PHASE_ARRAY];
    extern UINT32 _dwPhase3CH[CHANNEL_NUM];
#else
#define VGA_HW_AUTO	1 // 1
#define Phase3Channel     0 // please always fix to 0
	extern void vYPbPrPhaseIsr(void) ; //YPbPr Auto Phase 2006/11/07
    extern void vVgaPhaseIsr(void) ;
    extern void vDrvInitPhaseVar(void);


#endif
 extern UINT32	_dSumTmp[3];
extern UINT8 _u1TconMode;

typedef enum _VOPLL_SRC
{
    VOPLL_CLK_SRC_XTAL = 0,
    VOPLL_CLK_SRC_DDDS = 1
} _VOPLL_SRC_T;

void vDrvSetDviPll(UINT8 u1Mode) ;
void vDrvClkInit(void);
void vDrvSetVoSpreSTEP(UINT32 bVal);
void vDrvSlicerCheck(void); //for slicer CLI
UINT32 vDrvReadVoSpreSTEP(void);
void vDrvSetVOSpread(UINT32 u4Permillage);
UINT32 DDDS_GetSpreadSpectrum(void);
UINT32 DDDS_GetSpreadSpectrumFreq(void);
//void DDDS_SetSpreadSpectrum(UINT32 u4Period, UINT32 u4Range);
void DDDS_SetSpreadSpectrum(UINT32 u4Freq, UINT32 u4Range);
void SetSpreadSpectrumOnOff(UINT8 Onoff);
void vDDDSInit(void);
void vDrvVOFreqSet(UINT32 u4DCLK);
void vDrvSetSSMDRAsInputHsync(void);//for dynamic MDR 
void vDrvVGASetClock(UINT16 wHtotal);
void vDrvTVADCPLLIni(void);
void vDrvVOPLLPWUPIni(void);
void vDrvVOPLLFreqSet(UINT32 u4CLK);
void vDrvVOPLLSet(void);
void vDrvVOPLLDDDS_SS_TestMode(UINT8 u1Mode);
void vDrvLvdsVOPLLAnalogTest(UINT8 u1mode);
void vDrvMLDSVOPLLFreqSet(UINT32 u4Freq, UINT8 MLVDS_PORT,UINT8 MLVDS_RATION);
void vDrvVOPLLStatus(void);
void vDrvChkPLLFreq(void);
void vDrvPLLVCO_TestMode(UINT8 u1Mode);
void u1VOPLLSource(UINT8 u1arg1);
void vDrvVOPLLAutoKVCOBand(void);
void vDrvSetOCLKClockSchemaInit(void);
void vThermalCompInit(void);
void vDrvThermalCompensate(void);
UINT8 vAdcpllCurPhaseDelay(void);
void vDrvAdcpllSetPhaseDelay(UINT8 bVal);
UINT8 vCurTemperature(void);
void vDrvCLKINDefaultSet(void) ;
void vDrvCLKIN2DefaultSet(void) ;
UINT16 u2DDDS_CalErrorLimit(UINT32 _u4Permillage);
void vPGA_LPF_BW(UINT8 bLPF);
void vSet_VFE_LPF(UINT16 wInputPixClk);


#ifdef CONFIG_OPM
extern void vDrvVOPLLSuspend(void);
extern void vDrvVOPLLResume(void);
#endif
extern void vDrvTconOn(void);
extern UINT8 u1DrvTconEfuseCheck(void);
extern void vDrvSetDDDSInput(UINT8 bType);
extern void vDrvADCPLLSetFreq(UINT8 bADCCLK) ;
extern void vDrvCLKINSetHtotal(UINT16 wHtotal) ;
extern void vDrvCLKINSetHsyncWid(UINT8 wWidth) ;
extern void vDrvADCPLLSet(UINT16 wPixClk, UINT16 wHtotal) ;
extern void vDrvADCPLLPower(UINT8 bPow) ;
extern void vDrvEnable_SDDS_Calibration(UINT8 bKP0_START,UINT8 bKP0_END, UINT8 bKI0_START, UINT8 bKI0_END);
extern void vDrvEnable_DDDS_Calibration(UINT8 bKP0_START,UINT8 bKP0_END, UINT8 bKI0_START, UINT8 bKI0_END, UINT8 ERROR_LIM,UINT32 u4InitCW);
extern void vDrvSDDS_Response(void);
extern void vDrvDDDS_Response(void);
extern void SDDS_wait_message(void);
extern void DDDS_wait_message(void);
#if CHANGE_SDDS_KPI
extern void vDrvEnableChang_SDDS_BW(void);
extern void Set_SDDS_KPI(UINT8 bValue);
extern void vDrvClkSetLockBandwidth(UINT8 bIsLock);
#endif
extern void Set_DDDS_KPI(UINT8 bValue);
extern void vDrvAllADCPLLPow(UINT8 bPow);
extern void vDrvSetSSWithCLICmd(UINT8 u1Val);
#ifdef CC_FAST_INIT
void VOPLL_pm_resume(void);    
#endif
extern void vDrvSetVopllVcoMonitor(UINT8 bType);

#if EnableSDDSCalibration
extern UINT8 _bSDDSCaliState;
#endif
#if EnableDDDSCalibration
extern UINT8 _bDDDSCaliState;
#endif

extern UINT32   _u4GetLockCw;
extern UINT8   _bCLKSetFlag;

extern UINT32   _u4UiSetCw;

extern UINT32  _u4ErrorLimit;
#ifdef SUPPORT_FREERUN_DCLK_BY_STEP
extern UINT32 TargetErrlimit;
#endif

enum
{
  IntClk,
  ExtClk
};

enum
{
  DCLK_IN_SOG,
  DCLK_IN_HSYNC
};

enum {
Bypass_LPF,
YPbPr_480i_LPF,
YPbPr_480p_LPF,
YPbPr_720p_LPF,
YPbPr_1080p_LPF,
VGA_40MHZ_Less_LPF,
VGA_40_60MHZ_LPF,
VGA_60_90MHZ_LPF,
VGA_90_130MHZ_LPF,
VGA_120MHZ_More_LPF,
Max_Input_timing
};

// define the Thermal compensate state machine
enum 
{
	VDO_THERMALCOM_INI,
	VDO_THERMALCOM_STATE1,
	VDO_THERMALCOM_STATE2,
	VDO_THERMALCOM_STATE3
};

//#define vDrvCLKINSyncSel(bSrc) 	vIO32WriteFldAlign(CKGEN_AFEPLLCFG5, bSrc, FLD_RG_VGAPLL_SDDS_HSEL)
#define vDrvCLKINSyncSel(bSrc) 	vIO32WriteFldAlign(REG_PLL_GROUP_CFG7, bSrc, FLD_RG_VGAPLL_SDDS_HSEL)
//#define vDrvCLKINHsyncPol(bPol) vIO32WriteFldAlign(CKGEN_AFEPLLCFG5, bPol, FLD_RG_VGAPLL_SDDS_HPOR)
#define vDrvCLKINHsyncPol(bPol) 	vIO32WriteFldAlign(REG_PLL_GROUP_CFG7, bPol, FLD_RG_VGAPLL_SDDS_HPOR)
//#define vDrvADCPLLSetRelatch(bPol) vIO32WriteFldAlign(CKGEN_AFEPLLCFG7, bPol, FLD_RG_HRESYNC_POSEL)
//#define vDrvADCPLLSetRelatch(bPol) vIO32WriteFldAlign(REG_PLL_GROUP_CFG9, bPol, FLD_RG_HRESYNC_POSEL)

//VFE_14
#define vDrvCLKINFreeRun(bEna) vIO32WriteFldAlign(VFE_17, bEna, DCLK_INIT)
#define vDrvCLKINDclkRST(bEna) vIO32WriteFldAlign(VFE_17, bEna, DCLK_RESETB)
//#define vDrvCLKINPsncoRST(bEna) vIO32WriteFldAlign(VFE_14, bEna, PSNCO_RST) //MT5387 don't have this bit
#define vDrvCLKINMaxPeriod(bVal) vIO32WriteFldAlign(VFE_14, bVal, MAX_PERIOD)
#define vDrvCLKINFMPeriod(bVal) vIO32WriteFldAlign(VFE_14, bVal, FM_PERIOD)
#define vDrvCLKINFreeHsyncPol(bPol) vIO32WriteFldAlign(VFE_17, bPol, HSYNC_POL_VFE)
#define vDrvCLKINSetLockThr(bVal) vIO32WriteFldAlign(VFE_14, bVal, LOCK_THR)
#define vDrvCLKINSetKI0(bVal) vIO32WriteFldAlign(VFE_14, bVal, DCLK1_KI_0)
#define vDrvCLKINSetKI1(bVal) vIO32WriteFldAlign(VFE_14, bVal, DCLK1_KI_1)
#define vDrvCLKINSetLockCnt(bVal) vIO32WriteFldAlign(VFE_14, bVal, LOCK_CNT)
#define vDrvCLKINSetKP0(bVal) vIO32WriteFldAlign(VFE_14, bVal, DCLK1_KP_0)
#define vDrvCLKINSetKP1(bVal) vIO32WriteFldAlign(VFE_14, bVal, DCLK1_KP_1)
#define vDrvCLKINSetErrLim(bVal) vIO32WriteFldAlign(VFE_14, bVal, ERR_LIM)
#define vDrvDDDSSetKI0(bVal) vIO32WriteFldAlign(DDDS_02, bVal, DDDS_02_DDDS_KI_0)
#define vDrvDDDSSetKP0(bVal) vIO32WriteFldAlign(DDDS_02, bVal, DDDS_02_DDDS_KP_0)


//VFE_15
#define vDrvCLKINDCLKFast(bEna) vIO32WriteFldAlign(VFE_15, bEna, DCLK_FAST_LF)
#define vDrvCLKINSetCW(bVal) vIO32WriteFldAlign(VFE_15, bVal, DCLK_FREQ_CW)
#define vDrvCLKINGetCW() IO32ReadFldAlign(VFE_15,  DCLK_FREQ_CW)
#define vDrvCLKINGetCwStatus()   (u4IO32Read4B(VFE_STA_01) & 0x0fffffff)
#define vDrvCLKINGetHtotal()    (IO32ReadFldAlign(VFE_16, DCLK_HLINE_LENGTH)+1)

//VFE_16
#define vDrvCLKINDCLKPFDSEL(bEna) vIO32WriteFldAlign(VFE_14, bEna, DCLK_PFD_SEL)

//VFE_17
#define vDrvCLKINSetSecKI0(bVal) vIO32WriteFldAlign(VFE_17, bVal, DCLK2_KI_0)
#define vDrvCLKINSetSecKI1(bVal) vIO32WriteFldAlign(VFE_17, bVal, DCLK2_KI_1)
#define vDrvCLKINSetSecKP0(bVal) vIO32WriteFldAlign(VFE_17, bVal, DCLK2_KP_0)
#define vDrvCLKINSetSecKP1(bVal) vIO32WriteFldAlign(VFE_17, bVal, DCLK2_KP_1)

// DDDS
#define vDrvVoDclkSpreSpecDir(bVal) vIO32WriteFldAlign(DDDS_05, bVal, DDDS_05_SPREAD_DIR)
#define vDrvVoDclkSpreSpecSTEP(bVal) vIO32WriteFldAlign(DDDS_04, bVal, DDDS_04_SPREAD_STEP)
//#define vDrvVoDclkSpreSpecFIX_STEP(bVal) vIO32WriteFldAlign(DDDS_05, bVal, DDDS_05_FIX_STEP)
#define vDrvVoDclkSpreadInit(bVal) vIO32WriteFldAlign(DDDS_03, bVal, DDDS_03_SPREAD_INIT)
#define vDrvVoDclkSpreSpecPeriod(bVal)    vIO32WriteFldAlign(DDDS_05, bVal, DDDS_05_SPREAD_PERIOD) 
#define vDrvVoDDDSRST(bVal) vIO32WriteFldAlign(DDDS_05, bVal, DDDS_05_DDDS_RESETB)
#define vDrvVoDDDSCW(bVal) vIO32WriteFldAlign(DDDS_00, bVal , DDDS_00_DDDS_FREQ_CW)                


#endif
