/* 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: 2015/06/05 $
 * $RCSfile: drv_vdoclk.h,v $
 * $Revision: #2 $
 *
 *---------------------------------------------------------------------------*/


#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 ERROR_LIMIT_FOR_PDP 9
#define ERROR_LIMIT_FOR_VB1 7
#define ERRORLIMIT_DEFAULT  0x10

#define DDDS_SYMMETRIC_ERR_LIM  1
#define SUPPORT_SYMMETRIC_SS    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 vDrvSetVoSpreSTEPDown(UINT32 bVal);
void vDrvSetVoSpreSTEPDownEn(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 vDDDSSymmetricErrLimOnOff(UINT8 bEnable);
void vDDDSInit(void);
void vDrvVOFreqSet(UINT32 u4DCLK);
void vDrvSetSSMDRAsInputHsync(void);//for dynamic MDR 
void vDrvVGASetClock(UINT16 wHtotal);
void vDrvTVADCPLLIni(void);
void vDrvVOPLLPWUPIni(void);
void vDrvCalDownErrorLimit(UINT32 u4Error);
UINT32 u4DrvCalStepValue(UINT8 bLevel);
void vDrvCalStepLimit(UINT32 u4Value);
void vDrvEnableStepLimit(UINT8 bEnable);
//void vDrvVOPLLFreqSet(UINT32 u4CLK);
void vDrvVOPLLSet(void);
void vDrvVOPLLDDDS_SS_TestMode(UINT8 u1Mode);
void vDrvLvdsVOPLLAnalogTest(UINT8 u1mode);
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);
void vDrvCalCurrentHsync(void);

#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);

extern UINT8 u1DrvIsBypassPathToMJCPost(void);

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

#define DDDS_480P_SAMPLE_RATE     62  // 1/15.7k = 63.6943 us 
#define DDDS_1080P60_SAMPLE_RATE  14  // 1/67.5k = 14.8148 us
#define DDDS_2160P60_SAMPLE_RATE  7   // 1/135k = 7.4074 us
#endif

extern UINT32   _u4GetLockCw;
extern UINT8   _bCLKSetFlag;

extern UINT32   _u4UiSetCw;

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(REG_PLL_GROUP_CFG8, bSrc, FLD_RG_VGAPLL_SDDS_HSEL)
#define vDrvCLKINHsyncPol(bPol) 	vIO32WriteFldAlign(REG_PLL_GROUP_CFG8, bPol, FLD_RG_VGAPLL_SDDS_HPOR)

//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 vDrvVoDclkSpreSpecSTEPDown(bVal) vIO32WriteFldAlign(DDDS_21, bVal, DDDS_21_SPREAD_STEP_DOWN)
#define vDrvVoDclkSpreSpecSTEPDownEn(bVal) vIO32WriteFldAlign(DDDS_21, bVal, DDDS_21_FIX_STEP_EN)
//#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)                
#define vDrvDDDSCalHsyncEn(bVal)  vIO32WriteFldAlign(DDDS_1F, bVal , DDDS_1F_CAL_HSYNC_EN)
#define DrvDDDSGetCalHsyncEn()    IO32ReadFldAlign(DDDS_1F, DDDS_1F_CAL_HSYNC_EN)
#define DrvDDDSGetHsyncNumber()   IO32ReadFldAlign(STA_DDDS_04, STA_DDDS_04_HSYNC_FREQ_NUM)
#define DrvDDDSGetHsyncStable()   IO32ReadFldAlign(STA_DDDS_04, STA_DDDS_04_HSYNC_STABLE)
#endif
