/**
 * @file hv_cal_OsdTiming.c
 * @brief Osd Cal Timing interface file.
 * @details This file provides the following functions: \n
 *          (1) Osd CAL layer initialization functions \n
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2022-08-31
 * @copyright Copyright(c),2022-8, Hiview Software. All rights reserved.
 * @par History:
 * <table>
 * <tr><th>Author         <th>Date        <th>Change Description
 * <tr><td>OSD Group      <td>2022-08-31   <td>create
 * </table>
*/

#include "hv_cal_Osd.h"
#include "hv_drv_Osd.h"
#include "PanelConfig.h"

static USHORT16 s_usPanelHtotal = 0;
static UCHAR8 s_ucHtotalRatio = 1;

USHORT16 Hv_Cal_OsdTmg_GetPanelHtotal(VOID)
{
    return s_usPanelHtotal;
}

VOID Hv_Cal_OsdTmg_SetPanelHtotal(USHORT16 usPanelHtotal)
{
    USHORT16 usHtotal = 0;

    s_usPanelHtotal = usPanelHtotal;
    usHtotal = s_ucHtotalRatio * s_usPanelHtotal;

    /* update htotal register */
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_44, reg_osd_ctrl_htot, usHtotal);
    Hv_Cal_OsdDP_SetPreScalerHtotal(usPanelHtotal);
}

USHORT16 Hv_Cal_OsdTmg_GetCurrentHtotal(VOID)
{
    return s_ucHtotalRatio * s_usPanelHtotal;
}

VOID Hv_Cal_OsdTmg_SetHtotalRatio(UCHAR8 ucRatio)
{
    s_ucHtotalRatio = ucRatio;
}

VOID Hv_Cal_OsdTmg_ClkSrcSelect(UCHAR8 ucClkSrcSel)
{
    HV_W32_FIELD(SYS_SH06_TOP_0C, reg_osd_src_sel, ucClkSrcSel);
}

BOOL Hv_Cal_OsdTmg_GetClockEnable(VOID)
{
    HV_R32_DECL_VAR();

    return HV_R32_FIELD(DISP_TOP_DTC_TOP1_00, reg_osd_clk_en);
}
/*dtc_top1*/
VOID Hv_Cal_OsdTmg_SetClockEnable(BOOL bEnable)
{
    HV_W32_FIELD(DISP_TOP_DTC_TOP1_00, reg_osd_clk_en, bEnable);
}

//sub_ldg osd: video bld
VOID Hv_Cal_OsdTmg_SetOsdWClockGateEnable(BOOL bEnable)
{
    HV_W32_FIELD(DISP_TOP_SUB_LDG_00, reg_clk_osdw_gate_en, bEnable);
}

VOID Hv_Cal_OsdTmg_SetOsdRClockGateEnable(BOOL bEnable)
{
    HV_W32_FIELD(DISP_TOP_SUB_LDG_00, reg_clk_osdr_gate_en, bEnable);
}

/**
 * 0: disable
 * 1: 2
 * 2: 4
 * 3: 8
 * 4: 16
 * 5: 32
 * 6: 32
 * 7: 32
 */
VOID Hv_Cal_OsdTmg_SetClockDiv(UCHAR8 ucDivNum)
{
    HV_W32_FIELD(DISP_TOP_DTC_TOP1_00, reg_osd_div_num, ucDivNum);
}

static UCHAR8 Hv_Cal_OsdTmg_GetClockDiv(VOID)
{
    HV_R32_DECL_VAR();

    return HV_R32_FIELD(DISP_TOP_DTC_TOP1_00, reg_osd_div_num);
}

/*dpu_ldg_dpc*/
VOID Hv_Cal_OsdTmg_SetRdmaClockEnable(BOOL bEnable)
{
    HV_W32_FIELD(DISP_TOP_DPU_LDG_DPC_04, reg_ldg_rdma_osd_clk_en, bEnable);
}

VOID Hv_Cal_OsdTmg_SetWdmaClockEnable(BOOL bEnable)
{
    HV_W32_FIELD(DISP_TOP_DPU_LDG_DPC_04, reg_ldg_wdma_osd_clk_en, bEnable);
}

VOID Hv_Cal_OsdTmg_SetGraphicClockEnable(BOOL bEnable)
{
    HV_W32_FIELD(DISP_TOP_DPU_LDG_DPC_04, reg_ldg_rdma_bmp_clk_en, bEnable);
}

/**
 * osd_clock * video_htotal * (video_vtotal - coef) / (video_clk * reg_cnt_htotal)
 *
 * osd_clock == video_clk
 */
VOID Hv_Cal_OsdTmg_SetVthr(USHORT16 usHtot)
{
    UINT32 uiCoef = 50;
    FLOAT32 fRes = 0;

    HV_ASSERT_TRUE_VOID(0 != usHtot);

    fRes = (PANEL_H_TOTAL_TYP * (PANEL_V_TOTAL_MIN - uiCoef)) / (usHtot);

    HV_W32_FIELD(DISP_TOP_KOSD_TOP_5C, reg_en_apb_enable, 0);
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_58, reg_cnt_htotal, usHtot);
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_58, reg_cnt_vthr, fRes);
}

VOID Hv_Cal_OsdTmg_GetVthr(USHORT16 *pusHtot, USHORT16 *pusVthr)
{
    HV_R32_DECL_VAR();

    if (NULL != pusHtot)
    {
        *pusHtot = HV_R32_FIELD(DISP_TOP_KOSD_TOP_58, reg_cnt_htotal);
    }
    if (NULL != pusVthr)
    {
        *pusVthr = HV_R32_FIELD(DISP_TOP_KOSD_TOP_58, reg_cnt_vthr);
    }
}

VOID Hv_Cal_OsdTmg_SetTmgVbph(UCHAR8 ucVbph)
{
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_4C, reg_osd_ctrl_vbph, ucVbph);
}

VOID Hv_Cal_OsdTmg_SetTmgHbph(UCHAR8 ucHbph)
{
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_4C, reg_osd_ctrl_hbph, ucHbph);
}

VOID Hv_Cal_OsdTmg_SetTmgSize(USHORT16 usHact, USHORT16 usVact)
{
    USHORT16 usVTotal = 0;
    USHORT16 usHTotal = 0;

    usHTotal = s_ucHtotalRatio * s_usPanelHtotal;
    usVTotal = Hv_Cal_OsdDP_GetRealVTotal();

    HV_W32_FIELD(DISP_TOP_KOSD_TOP_40, reg_osd_ctrl_hdly, 0);

    //  > usOsdHAct + 86 + hbph
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_44, reg_osd_ctrl_htot, usHTotal);
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_44, reg_osd_ctrl_vtot, usVTotal);

    Hv_Cal_OsdTmg_SetTmgHbph(1);
    Hv_Cal_OsdTmg_SetTmgVbph(5);

    HV_W32_FIELD(DISP_TOP_KOSD_TOP_48, reg_osd_ctrl_hact, usHact);
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_48, reg_osd_ctrl_vact, usVact);

    HV_W32_FIELD(DISP_TOP_KOSD_TOP_50, reg_osd_ctrl_hsyn, 0x1);
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_50, reg_osd_ctrl_vsyn, 0x1);

    // same as hact
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_54, reg_osd_ctrl_osd_hact, usHact);

    // set prescaler htotal
    //Hv_Cal_OsdDP_SetPreScalerHtotal(usHTotal);

    Hv_Cal_OsdTmg_SetVthr(usHTotal);
}

VOID Hv_Cal_OsdTmg_GetTmgSize(USHORT16 *pusWidth, USHORT16 *pusHeight)
{
    HV_R32_DECL_VAR();

    if (NULL != pusWidth)
    {
        *pusWidth = HV_R32_FIELD(DISP_TOP_KOSD_TOP_48, reg_osd_ctrl_hact);
    }
    if (NULL != pusHeight)
    {
        *pusHeight = HV_R32_FIELD(DISP_TOP_KOSD_TOP_48, reg_osd_ctrl_vact);
    }
}

VOID Hv_Cal_OsdTmg_Init(VOID)
{
    USHORT16 usHActive = 0;
    USHORT16 usVActive = 0;

    s_usPanelHtotal = Hv_Cal_OsdTmg_GetPanelHtotal();

    Hv_Cal_OsdTmg_ClkSrcSelect(3);
    Hv_Cal_OsdTmg_SetClockDiv(0);

    Hv_Cal_OsdTmg_SetClockEnable(1);
    Hv_Cal_OsdTmg_SetOsdWClockGateEnable(1);
    Hv_Cal_OsdTmg_SetOsdRClockGateEnable(1);

    usHActive = Hv_Cal_OsdDP_GetRealHActive();
    usVActive = Hv_Cal_OsdDP_GetRealVActive();
    Hv_Cal_OsdTmg_SetTmgSize(usHActive, usVActive);

    return;
}
