/**
 * @file hv_cal_OsdDataPath.c
 * @brief Osd Cal DataPath 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"

BOOL bOsdScalerup = HV_FALSE;

VOID Hv_Cal_OsdDP_EnableWin3(VOID)
{
    HV_W32_FIELD(DISP_TOP_KOSD_TOP_00, osd_engine_win3_bld_en, 0);
    HV_W32_FIELD(OSD_KV_TOP_CTRL_28, win3_bld_en, 1);
}

VOID Hv_Cal_OsdDP_SetVideoBlendEnable(BOOL bEnable)
{
    HV_W32_FIELD(DISP_TOP_SUB_LDG_8C, reg_video_osd_bld_en, bEnable);
}

VOID Hv_Cal_OsdDP_SetVideoBlendPosition(OsdArea *pstArea)
{
    HV_W32_FIELD(DISP_TOP_SUB_LDG_90, reg_osd_bld_hstart, pstArea->usX);
    HV_W32_FIELD(DISP_TOP_SUB_LDG_90, reg_osd_bld_length, pstArea->usWidth);

    HV_W32_FIELD(DISP_TOP_SUB_LDG_94, reg_osd_bld_vstart, pstArea->usY);
    HV_W32_FIELD(DISP_TOP_SUB_LDG_94, reg_osd_bld_height, pstArea->usHeight);
}

OsdHsBlendMode Hv_Cal_OsdDP_GetHsBlendMode(VOID)
{
    BOOL bOsdEnable = HV_FALSE;
    BOOL bDDREnable = HV_FALSE;
    UCHAR8 ucHsMode = 0;
    HV_R32_DECL_VAR();

    ucHsMode = HV_R32_FIELD(DISP_TOP_SUB_OSD_TOP_70, reg_hs_bld_mode);
    bOsdEnable = HV_R32_FIELD(DISP_TOP_SUB_OSD_TOP_70, reg_osd_bld_en);
    bDDREnable = HV_R32_FIELD(DISP_TOP_SUB_OSD_TOP_70, reg_ddr_bld_en);

    if (0 == ucHsMode)
    {
        if (bOsdEnable)
        {
            return OSD_HSBLEND_MODE_DDR_FIRST;
        }
        else
        {
            return OSD_HSBLEND_MODE_DDR_ONLY;
        }
    }
    else
    {
        if (bDDREnable)
        {
            return OSD_HSBLEND_MODE_OSD_FIRST;
        }
        else
        {
            return OSD_HSBLEND_MODE_OSD_ONLY;
        }
    }
}

VOID Hv_Cal_OsdDP_SetHsBlendMode(OsdHsBlendMode enMode)
{
    BOOL bOsdEnable = HV_FALSE;
    BOOL bDDREnable = HV_FALSE;
    UCHAR8 ucHsMode = 0;

    switch (enMode)
    {
        case OSD_HSBLEND_MODE_DDR_ONLY:
        {
            bDDREnable = HV_TRUE;
            break;
        }
        case OSD_HSBLEND_MODE_OSD_ONLY:
        {
            bOsdEnable = HV_TRUE;
            ucHsMode = 1;
            break;
        }
        case OSD_HSBLEND_MODE_DDR_FIRST:
        {
            bOsdEnable = HV_TRUE;
            bDDREnable = HV_TRUE;
            break;
        }
        case OSD_HSBLEND_MODE_OSD_FIRST:
        {
            bOsdEnable = HV_TRUE;
            bDDREnable = HV_TRUE;
            ucHsMode = 1;
            break;
        }
        default:
        {
            break;
        }
    }

    HV_W32_FIELD(DISP_TOP_KOSD_TOP_3C, regs_display_en, bOsdEnable);

    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_70, reg_hs_bld_mode, ucHsMode);
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_70, reg_osd_bld_en, bOsdEnable);
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_70, reg_ddr_bld_en, bDDREnable);
}

VOID Hv_Cal_OsdDP_GetOsdCanvas(OsdArea *pstArea)
{
    HV_R32_DECL_VAR();

    HV_ASSERT_TRUE_VOID(pstArea != NULL);

    pstArea->usX = HV_R32_FIELD(DISP_TOP_SUB_OSD_TOP_78, reg_osd_hstart);
    pstArea->usY = HV_R32_FIELD(DISP_TOP_SUB_OSD_TOP_78, reg_osd_vstart);
    pstArea->usWidth = HV_R32_FIELD(DISP_TOP_SUB_OSD_TOP_7C, reg_osd_width);
    pstArea->usHeight = HV_R32_FIELD(DISP_TOP_SUB_OSD_TOP_7C, reg_osd_height);
}

VOID Hv_Cal_OsdDP_SetOsdCanvas(OsdArea *pstArea)
{
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_78, reg_osd_hstart, pstArea->usX);
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_78, reg_osd_vstart, pstArea->usY);

    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_7C, reg_osd_width, pstArea->usWidth);
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_7C, reg_osd_height, pstArea->usHeight);
}

VOID Hv_Cal_OsdDP_GetDDRCanvas(OsdArea *pstArea)
{
    HV_R32_DECL_VAR();

    HV_ASSERT_TRUE_VOID(pstArea != NULL);

    pstArea->usX = HV_R32_FIELD(DISP_TOP_SUB_OSD_TOP_80, reg_ddr_hstart);
    pstArea->usY = HV_R32_FIELD(DISP_TOP_SUB_OSD_TOP_80, reg_ddr_vstart);
    pstArea->usWidth = HV_R32_FIELD(DISP_TOP_SUB_OSD_TOP_84, reg_ddr_width);
    pstArea->usHeight = HV_R32_FIELD(DISP_TOP_SUB_OSD_TOP_84, reg_ddr_height);
}

VOID Hv_Cal_OsdDP_SetDDRCanvas(OsdArea *pstArea)
{
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_80, reg_ddr_hstart, pstArea->usX);
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_80, reg_ddr_vstart, pstArea->usY);

    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_84, reg_ddr_width, pstArea->usWidth);
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_84, reg_ddr_height, pstArea->usHeight);
}

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

    HV_ASSERT_TRUE_VOID(pusWidth != NULL && pusHeight != NULL);

    *pusWidth = HV_R32_FIELD(DISP_TOP_SUB_OSD_TOP_70, reg_osd_pre_scl_hsize);
    *pusHeight = HV_R32_FIELD(DISP_TOP_SUB_OSD_TOP_74, reg_osd_pre_scl_vsize);
}

VOID Hv_Cal_OsdDP_SetPreScalerSize(USHORT16 usWidth, USHORT16 usHeight)
{
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_70, reg_osd_pre_scl_hsize, usWidth);
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_74, reg_osd_pre_scl_vsize, usHeight);

    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_74, reg_osd_pre_scl_htotal, Hv_Cal_OsdTmg_GetPanelHtotal());
}

VOID Hv_Cal_OsdDP_SetPreScalerHtotal(USHORT16 usHtotal)
{
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_74, reg_osd_pre_scl_htotal, usHtotal);
}

VOID Hv_Cal_OsdDP_SetMtxCanvas(USHORT16 usWidth, USHORT16 usHeight)
{
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_A4, reg_osd_mtx_hsize, usWidth);
    HV_W32_FIELD(DISP_TOP_SUB_OSD_TOP_A8, reg_osd_mtx_vsize, usHeight);
}

VOID Hv_Cal_OsdDP_SetDrawMode(OsdDrawMode enMode)
{
    UCHAR8 ucMode = 0;

    switch (enMode)
    {
        case OSD_DRAW_WHOLE:
        {
            ucMode = 0;
            break;
        }
        case OSD_DRAW_EFFECTIVE:
        {
            ucMode = 2;
            break;
        }
        default:
        {
            break;
        }
    }

    HV_W32_FIELD(DISP_TOP_KOSD_TOP_2C, reg_wrot_mode, ucMode);
}

VOID Hv_Cal_OsdDP_SetSBufferDelay(VOID)
{
    HV_W32_FIELD(OSD_KV_TOP_CTRL_2C, index_buffer_delay, 1);
    HV_W32_FIELD(OSD_KV_TOP_CTRL_30, resource_buffer_delay, 1);
}

USHORT16 Hv_Cal_OsdDP_GetRealHActive(VOID)
{
    if (bOsdScalerup)
    {
        return (_PANEL_OSD_H_ACTIVE / 2);
    }
    else
    {
        return _PANEL_OSD_H_ACTIVE;
    }
}

USHORT16 Hv_Cal_OsdDP_GetRealVActive(VOID)
{
    if (bOsdScalerup)
    {
        return (_PANEL_OSD_V_ACTIVE / 2);
    }
    else
    {
        return _PANEL_OSD_V_ACTIVE;
    }
}

USHORT16 Hv_Cal_OsdDP_GetRealVTotal(VOID)
{
    USHORT16 usVActive = 0;

    usVActive = Hv_Cal_OsdDP_GetRealVActive();

    return usVActive + 10;
}

USHORT16 Hv_Cal_OsdDP_GetScreenHActive(VOID)
{
    return _PANEL_OSD_H_ACTIVE;
}

USHORT16 Hv_Cal_OsdDP_GetScreenVActive(VOID)
{
    return _PANEL_OSD_V_ACTIVE;
}

VOID Hv_Cal_OsdDP_SetOsdScalerup(BOOL bEnable)
{
    USHORT16 usHActive = 0;
    USHORT16 usVActive = 0;
    OsdArea stArea;

    bOsdScalerup = bEnable;

    /* could not set scaler param here in case of DDR draw */
    //Hv_Cal_OsdScaler_SetScalerRatio();

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

    stArea.usX = 0;
    stArea.usY = 0;
    stArea.usWidth = usHActive;
    stArea.usHeight = usVActive;
    Hv_Cal_OsdDP_SetOsdCanvas(&stArea);
    //Hv_Cal_OsdDP_SetDDRCanvas(&stArea);

    return;
}

BOOL Hv_Cal_OsdDP_GetOsdScalerup(VOID)
{
    return bOsdScalerup;
}

/* reconfig osd datapath based on the newest panel htotal */
VOID Hv_Cal_OsdDP_ReconfigDataPath(VOID)
{
    USHORT16 usHActive = 0;
    USHORT16 usVActive = 0;
    OsdArea stArea;

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

    stArea.usX = 0;
    stArea.usY = 0;
    stArea.usWidth = usHActive;
    stArea.usHeight = usVActive;
    Hv_Cal_OsdDP_SetOsdCanvas(&stArea);
    Hv_Cal_OsdDP_SetDDRCanvas(&stArea);

    Hv_Cal_OsdDP_SetPreScalerSize(usHActive, usVActive);

    usHActive = Hv_Cal_OsdDP_GetScreenHActive();
    usVActive = Hv_Cal_OsdDP_GetScreenVActive();

    Hv_Cal_OsdDP_SetMtxCanvas(usHActive, usVActive);

    /* scaler */
    Hv_Cal_OsdScaler_SetScalerRatio();
}

VOID Hv_Cal_OsdDP_Init(VOID)
{
    OsdArea stArea;
    USHORT16 usHActive = 0;
    USHORT16 usVActive = 0;

    Hv_Cal_OsdDP_EnableWin3();
    Hv_Cal_OsdDP_SetSBufferDelay();

#if (HV_PROJECT_CONFIG_OSD_SCALER == HV_CONFIG_ON)
    Hv_Cal_OsdDP_SetOsdScalerup(HV_TRUE);
#else
    Hv_Cal_OsdDP_SetOsdScalerup(HV_FALSE);
#endif

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

    stArea.usX = 0;
    stArea.usY = 0;
    stArea.usWidth = usHActive;
    stArea.usHeight = usVActive;
    Hv_Cal_OsdDP_SetOsdCanvas(&stArea);
    Hv_Cal_OsdDP_SetDDRCanvas(&stArea);

    Hv_Cal_OsdDP_SetPreScalerSize(usHActive, usVActive);

    usHActive = Hv_Cal_OsdDP_GetScreenHActive();
    usVActive = Hv_Cal_OsdDP_GetScreenVActive();

    Hv_Cal_OsdDP_SetMtxCanvas(usHActive, usVActive);

    stArea.usX = 0;
    stArea.usY = 0;
    stArea.usWidth = usHActive;
    stArea.usHeight = usVActive;
    Hv_Cal_OsdDP_SetVideoBlendPosition(&stArea);

    Hv_Cal_OsdDP_SetVideoBlendEnable(1);
}
