/**
 * @file hv_drv_DpuMainMute.c
 * @brief dpu driver source code.
 * @details This file provides the following functions: \n
 *          (1) Initialization and reset functions \n
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2022-08-23
 * @copyright Copyright(c),2022-8, Hiview Software. All rights reserved.
 * @par History:
 * <table>
 * <tr><th>Author                        <th>Date         <th>Change Description
 * <tr><td>HiView SoC Software Team      <td>2022-08-23   <td>init
 * </table>
*/


#include "hv_drv_DpuMainMute.h"
#include "hv_cal_MainMute.h"
#include "hv_vos_Comm.h"
#include "hv_chip_Irq.h"
#include "hv_comm_Assert.h"
#include "hv_comm_DataBase.h"
#include "hv_chip_Clk.h"


#define HS_BPORTH                               0x04
#define VS_BPORTH                               0x04
#define FREERUN_KEEPTIME                        7
#define HS_POS                                  4
#define VS_POS                                  4
#define NORM_POST_DELAY                         4
#define FREERUN2NORMTHRESHOLD                   0xF
#define INCLK_UNLOCKED_THRESHOLD                2
#define INCLK_NOCK_OPTION                       0xFF
#define VBLANK_MIN                              0x08
#define RX_PIXEL_CLK_MIN                        10    /* Pixel minimum clock MHz */
#define RX_PIXEL_CLK_MAX                        735   /* Pixel maximum clock MHz */
#define OSC_CLK                                 27    /* osc_clk MHz */
#define OSC_CLK_MIN_PCT                         97    /* osc_clk have ±3% diff freq, Minimum 100 - 3 = 97  */
#define OSC_CLK_MAX_PCT                         103   /* osc_clk have ±3% diff freq, Maximum 100 + 3 = 103 */
/*2048 is a const value for calc inclk*/
#define INCLK_FREQ_LOW_TH                       (ROUND_DIV(2048 * OSC_CLK * 100, RX_PIXEL_CLK_MIN * OSC_CLK_MIN_PCT)) 
/*2048 is a const value for calc inclk*/
#define INCLK_FREQ_HIGH_TH                      ((2048 * OSC_CLK) / ROUND_DIV(RX_PIXEL_CLK_MAX * OSC_CLK_MAX_PCT, 100))

#define HTOTAL_OFFSET(HTOTAL)                   (HTOTAL)
#define HACT_OFFSET(HACT)                       (HACT)
#define HACT_MIN_VS_HACT_OFFSET(HACT)           ((HACT) - 0xA)
#define HACT_MAX_VS_HACT_OFFSET(HACT)           ((HACT) + 0xA)
#define HACT_OUT_VS_HACT_OFFSET(HACT)           (HACT)
#define VACT_MIN_VS_VACT_OFFSET(VACT)           ((VACT) - 0x05)
#define VACT_MAX_VS_VACT_OFFSET(VACT)           ((VACT) + 0x06)
#define HTOTAL_MIN_VS_HACT_OFFSET(HACT)         ((HACT) + 0x10)
#define HTOTAL_MAX_VS_HTOTAL_OFFSET(HTOTAL)     ((HTOTAL) * 2  + 1)
#define FRM_TRIG_POS_VS_HTOTAL_OFFSET(HTOTAL)   (ROUND_DIV((HTOTAL) * 4, 0x10)) /* 5 line date, 5 * htotal / 16(pixel unit) */



Status Hv_Drv_DpuScaler_MainMute_Init(VOID)
{
    Hv_Cal_DpuScaler_SetMuteForceStable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_MainMuteForceFreeRun(HV_ENABLE);

    Hv_Cal_DpuScaler_SetMuteHminDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteHmaxDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteVminDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteVmaxDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteHttlMaxDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteHttlMinDetEnable(HV_ENABLE);

    Hv_Cal_DpuScaler_SetMuteSh12ProgSrcStableEn(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteVttlMinDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteHsBporth(HS_BPORTH);
    Hv_Cal_DpuScaler_SetMuteVsBporth(VS_BPORTH);
    Hv_Cal_DpuScaler_SetMuteHsWidth(8);
    Hv_Cal_DpuScaler_SetMuteVsWidth(2);
    Hv_Cal_DpuScaler_SetMuteFreerunKeepTime(FREERUN_KEEPTIME);
    Hv_Cal_DpuScaler_SetMuteRxLocknDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteRxDeDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteHsPos(HS_POS);
    Hv_Cal_DpuScaler_SetMuteVsPos(VS_POS);
    
    Hv_Cal_DpuScaler_SetMuteNormPostDelay(NORM_POST_DELAY);
    Hv_Cal_DpuScaler_SetMuteFreerun2normThreshold(FREERUN2NORMTHRESHOLD);
    /*自己配置时钟不必检测，小分辨率时无法配置检测必然失败，固关掉*/
    Hv_Cal_DpuScaler_SetMuteClkDetEnable(HV_DISABLE);
    Hv_Cal_DpuScaler_SetMuteInclkUnlockedTh(INCLK_UNLOCKED_THRESHOLD);
    Hv_Cal_DpuScaler_SetMuteRxclkStableSel(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteInclkNoCkOption(INCLK_NOCK_OPTION);
    Hv_Cal_DpuScaler_SetMuteAntiglitchTh(HV_DISABLE);    
    Hv_Cal_DpuScaler_SetMuteNoDeEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteHtotalOutMode(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteVsMeasureEn(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteNormClrDelay(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteHttlMinCompEn(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteVblankMin(VBLANK_MIN);
    Hv_Cal_DpuScaler_SetMuteInclkFreqLowTh(INCLK_FREQ_LOW_TH);
    Hv_Cal_DpuScaler_SetMuteInclkFreqHighTh(INCLK_FREQ_HIGH_TH);
    Hv_Cal_DpuScaler_SetMuteThreahold(0);
    Hv_Cal_DpuScaler_SetMuteStateW4Enable(0);

    return HV_SUCCESS;
}


static Status Hv_Drv_DpuScaler_SetMuteNormDelay(const VideoTimingParam* pstVideoTiming, UINT32 uiPixelClock)
{
    UINT32 uiValue = 32;
    return Hv_Cal_DpuScaler_SetMuteNormDelay(uiValue);
}
static Status Hv_Drv_DpuScaler_SetNormalMuteNoDeTh(const VideoTimingParam* pstRxVideoTiming)
{
    HV_R32_DECL_VAR();
    HV_ASSERT_TRUE(pstRxVideoTiming->usVTotal > 0);
    UINT32 uiDelay = 2 * (1000 / pstRxVideoTiming->usFrameRate) * 1000;
    Hv_Vos_Delayus(uiDelay);
    UINT32 uiMonCyclRefClkVblank = 0;
    uiMonCyclRefClkVblank = Hv_Cal_DpuScaler_GetDtcMonCycleRefclkVblank();
    HV_LOG_DEBUG(VIDEO,"uiDelay %u,MonCyclRefClkVblank=%u", uiDelay,uiMonCyclRefClkVblank);
    
    UINT32 uiValue = (UINT64) uiMonCyclRefClkVblank * OSC_CLK * 1000000 / HV_CHIP_CLK_APB * \
                    (pstRxVideoTiming->usVTotal - pstRxVideoTiming->usVActive + 10) / \
                    (pstRxVideoTiming->usVTotal - pstRxVideoTiming->usVActive);
    return Hv_Cal_DpuScaler_SetMuteNoDeTh(uiValue);    
}

Status Hv_Drv_DpuScaler_SetMainMuteTiming(const VideoTimingParam*  pstVideoTiming,  UINT32 uiPixelClock, BOOL bOsdVrrEnable)
{
    HV_ASSERT_VALID_PTR(pstVideoTiming);
    static BOOL bInitFlag = 0;
    UINT32 uiMuteTrigPos = FRM_TRIG_POS_VS_HTOTAL_OFFSET(pstVideoTiming->usHTotal);
    Hv_Cal_DpuScaler_SetMuteFrmTrigPos(uiMuteTrigPos);
    Hv_Cal_DpuScaler_SetMuteHtotal(HTOTAL_OFFSET(pstVideoTiming->usHTotal));
    Hv_Cal_DpuScaler_SetMuteVtotal(pstVideoTiming->usVTotal);
    Hv_Cal_DpuScaler_SetMuteHact(HACT_OFFSET(pstVideoTiming->usHActive));
    Hv_Cal_DpuScaler_SetMuteVact(pstVideoTiming->usVActive);

    Hv_Cal_DpuScaler_SetMuteHactMin(HACT_MIN_VS_HACT_OFFSET(pstVideoTiming->usHActive));
    Hv_Cal_DpuScaler_SetMuteHactMax(HACT_MAX_VS_HACT_OFFSET(pstVideoTiming->usHActive));

    Hv_Cal_DpuScaler_SetMuteVactMin(VACT_MIN_VS_VACT_OFFSET(pstVideoTiming->usVActive));
    Hv_Cal_DpuScaler_SetMuteVactMax(VACT_MAX_VS_VACT_OFFSET(pstVideoTiming->usVActive));
    Hv_Cal_DpuScaler_SetMuteHactOut(HACT_OUT_VS_HACT_OFFSET(pstVideoTiming->usHActive));
    Hv_Cal_DpuScaler_SetMuteVactOut(pstVideoTiming->usVActive);
    Hv_Cal_DpuScaler_SetMuteHtotalMin(HTOTAL_MIN_VS_HACT_OFFSET(pstVideoTiming->usHActive));
    Hv_Cal_DpuScaler_SetMuteHtotalMax(HTOTAL_MAX_VS_HTOTAL_OFFSET(pstVideoTiming->usHTotal));
    Hv_Cal_DpuScaler_SetMuteNormOption();
   
    Hv_Drv_DpuScaler_SetMuteNormDelay(pstVideoTiming, uiPixelClock);
    if (HV_TRUE == bOsdVrrEnable)
    {
        Hv_Cal_DpuScaler_SetMuteNoDeTh(1200000);
    }
    else
    {
        if(HV_FALSE == bInitFlag)
        {
            Hv_Cal_DpuScaler_SetMuteNoDeTh(1200000);
            bInitFlag = 1;
        }
        else
        {
            Hv_Drv_DpuScaler_SetNormalMuteNoDeTh(pstVideoTiming);
        }
    }
    return HV_SUCCESS;
}

UINT32 Hv_Drv_DpuScaler_GetMainMuteState(VOID)
{
    return Hv_Cal_DpuScaler_GetMuteState();
}

/* 0 表示Normal, 1 表示 Abnormal */
UINT32 Hv_Drv_DpuScaler_GetMainMuteIntReason(VOID)
{ 
   return Hv_Cal_DpuScaler_GetMuteMainIntReason();   
}

Status Hv_Drv_DpuScaler_MainMuteForceFreeRun(BOOL bSwitch)
{    
    Hv_Cal_DpuScaler_MainMuteForceFreeRun(bSwitch);
    return HV_SUCCESS;
}


VOID Hv_Drv_DpuScaler_MainMuteClearEn(VOID)
{
    Hv_Cal_DpuScaler_ClearMuteEn();
    return;
}
UINT32 Hv_Drv_DpuScaler_GetMainMuteStatus(VOID)
{
    return Hv_Cal_DpuScaler_GetMuteStatus();
}
