/**
 * @file hv_drv_DpuSubMute.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_DpuSubMute.h"
#include "hv_cal_SubMute.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"
#include "hv_cal_MainMute.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) - 10)
#define HACT_MAX_VS_HACT_OFFSET(HACT)           ((HACT) + 10)
#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) + 16)
#define HTOTAL_MAX_VS_HTOTAL_OFFSET(HTOTAL)     ((HTOTAL) * 2  + 1)
#define FRM_TRIG_POS_VS_HTOTAL_OFFSET(HTOTAL)   (ROUND_DIV((HTOTAL) * 4, 16)) /* 5 line date, 5 * htotal / 16(pixel unit) */



Status Hv_Drv_DpuScaler_SubMute_Init(VOID)
{
    Hv_Cal_DpuScaler_SetMuteSubForceStable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubForceFreeRun(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubHminDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubHmaxDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubVminDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubVmaxDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubHttlMaxDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubSh12ProgSrcStableEn(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubVttlMinDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubHttlMaxDetEnable(HV_ENABLE);

    Hv_Cal_DpuScaler_SetMuteSubHsBporth(HS_BPORTH);
    Hv_Cal_DpuScaler_SetMuteSubVsBporth(VS_BPORTH);
    Hv_Cal_DpuScaler_SetMuteSubHsWidth(8);
    Hv_Cal_DpuScaler_SetMuteSubVsWidth(2);
    Hv_Cal_DpuScaler_SetMuteSubFreerunKeepTime(FREERUN_KEEPTIME);
    Hv_Cal_DpuScaler_SetMuteSubRxLocknDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubRxDeDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubHsPos(HS_POS);
    Hv_Cal_DpuScaler_SetMuteSubVsPos(VS_POS);
    Hv_Cal_DpuScaler_SetMuteSubForceFreeRun(HV_DISABLE);
    Hv_Cal_DpuScaler_SetMuteSubNormPostDelay(NORM_POST_DELAY);
    Hv_Cal_DpuScaler_SetMuteSubFreerun2normThreshold(FREERUN2NORMTHRESHOLD);
    /*自己配置时钟不必检测，小分辨率时无法配置检测必然失败，固关掉*/
    Hv_Cal_DpuScaler_SetMuteSubClkDetEnable(HV_DISABLE);
    Hv_Cal_DpuScaler_SetMuteSubInclkUnlockedTh(INCLK_UNLOCKED_THRESHOLD);
    Hv_Cal_DpuScaler_SetMuteSubRxclkStableSel(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubInclkNoCkOption(INCLK_NOCK_OPTION);
    Hv_Cal_DpuScaler_SetMuteSubAntiglitchTh(HV_DISABLE);
    Hv_Cal_DpuScaler_SetMuteSubHttlMinDetEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubNoDeEnable(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubHtotalOutMode(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubVsMeasureEn(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubNormClrDelay(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubHttlMinCompEn(HV_ENABLE);
    Hv_Cal_DpuScaler_SetMuteSubVblankMin(VBLANK_MIN);
    Hv_Cal_DpuScaler_SetMuteSubInclkFreqLowTh(INCLK_FREQ_LOW_TH);
    Hv_Cal_DpuScaler_SetMuteSubInclkFreqHighTh(INCLK_FREQ_HIGH_TH);
    Hv_Cal_DpuScaler_SetSubMuteThreahold();
    Hv_Cal_DpuScaler_SetMuteSubStateW4Enable(0);
    return HV_SUCCESS;
}



static Status Hv_Drv_DpuScaler_SetSubMuteNormDelay(const VideoTimingParam* pstVideoTiming, UINT32 uiPixelClock)
{
    UINT32 uiValue = 32;    
    return Hv_Cal_DpuScaler_SetMuteSubNormDelay(uiValue);    
}

#if 0
static Status Hv_Drv_DpuScaler_SetSubNormalMuteNoDeTh(const VideoTimingParam* pstRxVideoTiming)
{
    HV_R32_DECL_VAR();
    HV_ASSERT_TRUE(pstRxVideoTiming->usVTotal > 0);
  
    UINT32 uiMonCyclRefClkVblank = 0;
    for(UCHAR8 ucLoop = 0; ucLoop < 200; ucLoop++)
    {
        uiMonCyclRefClkVblank = Hv_Cal_DpuScaler_GetDtcMonCycleRefclkVblank();
        if(0 == uiMonCyclRefClkVblank)
        {
            HV_LOG_INFO(VIDEO,"DTC Monitor is unstable,MonCyclRefClkVblank=%u", uiMonCyclRefClkVblank);
            Hv_Vos_Delayus(1000);
        }
        else
        {
            break;
        }        
    }
    UINT32 uiValue = (UINT64) uiMonCyclRefClkVblank * OSC_CLK * 1000000 / HV_CHIP_CLK_APB * \
                    (pstRxVideoTiming->usVTotal - pstRxVideoTiming->usVActive + 10) / \
                    (pstRxVideoTiming->usVTotal - pstRxVideoTiming->usVActive);    
    return Hv_Cal_DpuScaler_SetMuteSubNoDeTh(uiValue);    
}
#endif
Status Hv_Drv_DpuScaler_SetSubMuteTiming(const VideoTimingParam*  pstVideoTiming, UINT32 uiPixelClock, BOOL bOsdVrrEnable)
{
    HV_ASSERT_VALID_PTR(pstVideoTiming);

    UINT32 uiMuteTrigPos = FRM_TRIG_POS_VS_HTOTAL_OFFSET(pstVideoTiming->usHTotal);
    Hv_Cal_DpuScaler_SetMuteSubFrmTrigPos(uiMuteTrigPos);
    Hv_Cal_DpuScaler_SetMuteSubHtotal(HTOTAL_OFFSET(pstVideoTiming->usHTotal));
    Hv_Cal_DpuScaler_SetMuteSubVtotal(pstVideoTiming->usVTotal);
    Hv_Cal_DpuScaler_SetMuteSubHact(HACT_OFFSET(pstVideoTiming->usHActive));
    Hv_Cal_DpuScaler_SetMuteSubVact(pstVideoTiming->usVActive);

    Hv_Cal_DpuScaler_SetMuteSubHactMin(HACT_MIN_VS_HACT_OFFSET(pstVideoTiming->usHActive));
    Hv_Cal_DpuScaler_SetMuteSubHactMax(HACT_MAX_VS_HACT_OFFSET(pstVideoTiming->usHActive));

    Hv_Cal_DpuScaler_SetMuteSubVactMin(VACT_MIN_VS_VACT_OFFSET(pstVideoTiming->usVActive));
    Hv_Cal_DpuScaler_SetMuteSubVactMax(VACT_MAX_VS_VACT_OFFSET(pstVideoTiming->usVActive));
    Hv_Cal_DpuScaler_SetMuteSubHactOut(HACT_OUT_VS_HACT_OFFSET(pstVideoTiming->usHActive));
    Hv_Cal_DpuScaler_SetMuteSubVactOut(pstVideoTiming->usVActive);
    Hv_Cal_DpuScaler_SetMuteSubHtotalMin(HTOTAL_MIN_VS_HACT_OFFSET(pstVideoTiming->usHActive));
    Hv_Cal_DpuScaler_SetMuteSubHtotalMax(HTOTAL_MAX_VS_HTOTAL_OFFSET(pstVideoTiming->usHTotal));
    Hv_Cal_DpuScaler_SetMuteSubNormOption();

    Hv_Drv_DpuScaler_SetSubMuteNormDelay(pstVideoTiming, uiPixelClock);
    //if (bOsdVrrEnable == 1)
    //{
        Hv_Cal_DpuScaler_SetMuteSubNoDeTh(1200000);
    //}
    //else
    //{
        //Hv_Drv_DpuScaler_SetSubNormalMuteNoDeTh(pstVideoTiming);
    //}
    return HV_SUCCESS;
}
UINT32 Hv_Drv_DpuScaler_GetSubMuteState(VOID)
{    
   return Hv_Cal_DpuScaler_GetMuteSubState(); 
}

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

Status Hv_Drv_DpuScaler_SubMuteForceFreeRun(BOOL bSwitch)
{    
    Hv_Cal_DpuScaler_SubMuteForceFreeRun(bSwitch);
    return HV_SUCCESS;
}


VOID Hv_Drv_DpuScaler_SubMuteClearEn(VOID)
{
    Hv_Cal_DpuScaler_SubClearMuteEn();
    return;
}
UINT32 Hv_Drv_DpuScaler_GetSubMuteStatus(VOID)
{
    return Hv_Cal_DpuScaler_GetSubMuteStatus();
}
