/**
 * @file hv_cal_OsdDMA.c
 * @brief Osd Cal DMA 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_drv_Osd.h"
#include "hv_cal_Osd.h"

VOID Hv_Cal_OsdInnerDMA_DebugPrint(VOID)
{
    HV_R32_DECL_VAR();
    OSD_DRV_LOG_INFO("OSD DMA state:");
    OSD_DRV_LOG_INFO("  RDMA_STATE_FLAG = 0x%x", HV_R32_FIELD(OSD_KV_DMA_CTRL_80, RDMA_STATE_FLAG));
    OSD_DRV_LOG_INFO("  RDMA_READ_LENGTH_ERR = 0x%x", HV_R32_FIELD(OSD_KV_DMA_CTRL_80, RDMA_READ_LENGTH_ERR));
    OSD_DRV_LOG_INFO("  DMA_READ_GOING_FLAG = 0x%x", HV_R32_FIELD(OSD_KV_DMA_CTRL_80, DMA_READ_GOING_FLAG));
    OSD_DRV_LOG_INFO("  DMA_READ_DONE_FLAG = 0x%x", HV_R32_FIELD(OSD_KV_DMA_CTRL_80, DMA_READ_DONE_FLAG));
    OSD_DRV_LOG_INFO("  DMA_RESET_ERR_FLAG = 0x%x", HV_R32_FIELD(OSD_KV_DMA_CTRL_80, DMA_RESET_ERR_FLAG));
    OSD_DRV_LOG_INFO("  DMA_START_ERR_FLAG = 0x%x", HV_R32_FIELD(OSD_KV_DMA_CTRL_80, DMA_START_ERR_FLAG));
    OSD_DRV_LOG_INFO("  rdma_int_sta = 0x%x", HV_R32_FIELD(OSD_KV_DMA_CTRL_A0, rdma_int_sta));
}

BOOL Hv_Cal_OsdInnerDMA_GetStartFlag(VOID)
{
    HV_R32_DECL_VAR();

    return HV_R32_FIELD(OSD_KV_DMA_CTRL_00, DMA_START);
}

VOID Hv_Cal_OsdInnerDMA_Start(VOID)
{
    HV_W32(OSD_KV_DMA_CTRL_00, 0x02);
}

VOID Hv_Cal_OsdInnerDMA_ClearStart(VOID)
{
    HV_W32(OSD_KV_DMA_CTRL_00, 0x00);
}

BOOL Hv_Cal_OsdInnerDMA_CheckDone(VOID)
{
    HV_R32_DECL_VAR();

    return HV_R32_FIELD(OSD_KV_DMA_CTRL_80, DMA_READ_DONE_FLAG) == 1;
}

BOOL Hv_Cal_OsdInnerDMA_CheckGoing(VOID)
{
    HV_R32_DECL_VAR();

    return HV_R32_FIELD(OSD_KV_DMA_CTRL_80, DMA_READ_GOING_FLAG) == 1;
}

VOID Hv_Cal_OsdInnerDMA_ClearDoneFlag(VOID)
{
    HV_W32_FIELD(OSD_KV_DMA_CTRL_78, DMA_READ_DONE_CTRL1, 1);
    HV_W32_FIELD(OSD_KV_DMA_CTRL_78, DMA_READ_DONE_CTRL1, 0);
}

VOID Hv_Cal_OsdInnerDMA_ClearStartError(VOID)
{
    HV_W32_FIELD(OSD_KV_DMA_CTRL_78, DMA_READ_START_ERROR_CTRL, 1);
    HV_W32_FIELD(OSD_KV_DMA_CTRL_78, DMA_READ_START_ERROR_CTRL, 0);
}

VOID Hv_Cal_OsdInnerDMA_SetTotalGroups(UCHAR8 ucNum)
{
    HV_ASSERT_TRUE_VOID(ucNum > 0 && ucNum <= 8);

    HV_W32_FIELD(OSD_KV_DMA_CTRL_08, DMA_READ_NUM, ucNum - 1);
}

VOID Hv_Cal_OsdInnerDMA_SetGroupInfo(UCHAR8 ucIndex, UINT32 uiDstAddr, UINT32 uiSrcAddr, UINT32 uiLength)
{
    UINT32 uiAddrOff = 0;

    HV_ASSERT_TRUE_VOID(ucIndex < 8);

    uiAddrOff = ucIndex * 8;

    uiSrcAddr = VIRT_TO_PHY(uiSrcAddr);
    HV_W32_FIELD_EX(OSD_KV_DMA_CTRL_10, uiAddrOff, DMA_READ0_ADDR, uiSrcAddr >> 4);

    HV_W32_FIELD_EX(OSD_KV_DMA_CTRL_14, uiAddrOff, DMA_READ0_Burst_Num, uiLength >> 4);
    HV_W32_FIELD_EX(OSD_KV_DMA_CTRL_14, uiAddrOff, DMA_READ0_CTRL, (uiDstAddr - OSD_CTRL_BASE_ADDR) >> 4);
}

static UINT32 Hv_Cal_OsdOuterRDMA_GetAddrOffet(OsdDataPath enPath)
{
    if (OSD_DATAPATH_DDRREAD == enPath)
    {
        return (HV_DPU_RVDM_04_BASE_ADDRESS - HV_DPU_RVDM_02_BASE_ADDRESS);
    }
    return 0;
}

VOID Hv_Cal_OsdOuterRDMA_SetEnable(OsdDataPath enPath, BOOL bEnable)
{
    UINT32 uiAddrOff = Hv_Cal_OsdOuterRDMA_GetAddrOffet(enPath);

    HV_W32_FIELD_EX(DISP_TOP_DPU_RVDM_02_04, uiAddrOff, reg_02_dm_rd_enable, bEnable);
}

VOID Hv_Cal_OsdOuterRDMA_SetDDRAddr(OsdDataPath enPath, UINT32 uiAddr)
{
    UINT32 uiAddrOff = Hv_Cal_OsdOuterRDMA_GetAddrOffet(enPath);

    uiAddr &= 0x7fffffff;
    HV_W32_FIELD_EX(DISP_TOP_DPU_RVDM_02_48, uiAddrOff, reg_02_dm_sw_start_adr, uiAddr);
}

VOID Hv_Cal_OsdOuterRDMA_SetColStep(OsdDataPath enPath, USHORT16 usStep)
{
    UINT32 uiAddrOff = Hv_Cal_OsdOuterRDMA_GetAddrOffet(enPath);

    HV_ASSERT_TRUE_VOID(usStep != 0 && ((usStep & 0x0f) == 0));

    HV_W32_FIELD_EX(DISP_TOP_DPU_RVDM_02_0C, uiAddrOff, reg_02_dm_rd_col_step, usStep);
}

VOID Hv_Cal_OsdOuterRDMA_SetColDirection(OsdDataPath enPath, OsdDMADirection enDirection)
{
    UINT32 uiAddrOff = Hv_Cal_OsdOuterRDMA_GetAddrOffet(enPath);

    HV_W32_FIELD_EX(DISP_TOP_DPU_RVDM_02_04, uiAddrOff, reg_02_dm_rd_col_step_dir, enDirection);
}

VOID Hv_Cal_OsdOuterRDMA_SetLineStep(OsdDataPath enPath, USHORT16 usStep)
{
    UINT32 uiAddrOff = Hv_Cal_OsdOuterRDMA_GetAddrOffet(enPath);

    HV_ASSERT_TRUE_VOID((usStep & 0x0f) == 0);

    HV_W32_FIELD_EX(DISP_TOP_DPU_RVDM_02_10, uiAddrOff, reg_02_dm_rd_line_step, usStep);
}

VOID Hv_Cal_OsdOuterRDMA_SetLineDirection(OsdDataPath enPath, OsdDMADirection enDirection)
{
    UINT32 uiAddrOff = Hv_Cal_OsdOuterRDMA_GetAddrOffet(enPath);

    HV_W32_FIELD_EX(DISP_TOP_DPU_RVDM_02_04, uiAddrOff, reg_02_dm_rd_line_step_dir, enDirection);
}

VOID Hv_Cal_OsdOuterRDMA_SetDataBlock(OsdDataPath enPath, USHORT16 usDataCount, UCHAR8 ucBurstLen)
{
    USHORT16 usDataCountAligned = ALIGN(usDataCount, DMA_COLDATA_ALIGN_BYTES);
    USHORT16 usDataCountIn16Bytes = usDataCountAligned >> 4;
    UINT32 uiAddrOff = Hv_Cal_OsdOuterRDMA_GetAddrOffet(enPath);

    HV_ASSERT_TRUE_VOID(ucBurstLen > 0);
    HV_ASSERT_TRUE_VOID(usDataCountAligned >= 64);

    HV_W32_FIELD_EX(DISP_TOP_DPU_RVDM_02_18, uiAddrOff, reg_02_dm_rd_col_dat_num, usDataCountIn16Bytes);

    HV_W32_FIELD_EX(DISP_TOP_DPU_RVDM_02_04, uiAddrOff, reg_02_dm_rd_burst_len, ucBurstLen - 1); /* 31 */
    HV_W32_FIELD_EX(DISP_TOP_DPU_RVDM_02_08, uiAddrOff, reg_02_dm_rd_burst_num, usDataCountIn16Bytes / ucBurstLen);
    HV_W32_FIELD_EX(DISP_TOP_DPU_RVDM_02_04, uiAddrOff, reg_02_dm_rd_burst_rmd, usDataCountIn16Bytes % ucBurstLen);
}

VOID Hv_Cal_OsdOuterRDMA_SetOutstandingReq(OsdDataPath enPath, UCHAR8 ucReqCount)
{
    UINT32 uiAddrOff = Hv_Cal_OsdOuterRDMA_GetAddrOffet(enPath);

    HV_ASSERT_TRUE_VOID(ucReqCount != 0);

    HV_W32_FIELD_EX(DISP_TOP_DPU_RVDM_02_04, uiAddrOff, reg_02_dm_rd_outstanding, ucReqCount);
}

VOID Hv_Cal_OsdOuterRDMA_SetAccessMode(OsdDataPath enPath, OsdDMAMode enMode)
{
    UINT32 uiAddrOff = Hv_Cal_OsdOuterRDMA_GetAddrOffet(enPath);

    HV_W32_FIELD_EX(DISP_TOP_DPU_RVDM_02_04, uiAddrOff, reg_02_dm_rd_access_mode, enMode);
}

VOID Hv_Cal_OsdOuterRDMA_SetBufferDepth(OsdDataPath enPath, USHORT16 usDepth)
{
    UINT32 uiAddrOff = Hv_Cal_OsdOuterRDMA_GetAddrOffet(enPath);

    HV_ASSERT_TRUE_VOID(usDepth > 0 && usDepth <= DMA_MAX_BUFFER_DEPTH);

    HV_W32_FIELD_EX(DISP_TOP_DPU_RVDM_02_00, uiAddrOff, reg_02_dm_rd_buf_size, usDepth);
}

VOID Hv_Cal_OsdOuterRDMA_SetColNumber(OsdDataPath enPath, USHORT16 usNumber)
{
    UINT32 uiAddrOff = Hv_Cal_OsdOuterRDMA_GetAddrOffet(enPath);

    HV_ASSERT_TRUE_VOID(usNumber > 0);

    HV_W32_FIELD_EX(DISP_TOP_DPU_RVDM_02_20, uiAddrOff, reg_02_dm_rd_total_col_num, usNumber);
}

VOID Hv_Cal_OsdOuterRDMA_SetLineNumber(OsdDataPath enPath, USHORT16 usNumber)
{
    UINT32 uiAddrOff = Hv_Cal_OsdOuterRDMA_GetAddrOffet(enPath);

    HV_ASSERT_TRUE_VOID(usNumber > 0);

    HV_W32_FIELD_EX(DISP_TOP_DPU_RVDM_02_20, uiAddrOff, reg_02_dm_rd_total_line_num, usNumber);
}

VOID Hv_Cal_OsdOuterRDMA_SetUnpackFormat(OsdDataPath enPath, OsdPixelFormat enFormat)
{
    UCHAR8 ucBits = Hv_Cal_Osd_GetPixelBits(enFormat);

    switch (enPath)
    {
        case OSD_DATAPATH_GRAPHIC:
        {
            HV_W32_FIELD(DISP_TOP_DPU_LDG_DPC_0C, reg_bmp_rd_unpack_len, ucBits);
            break;
        }
        case OSD_DATAPATH_DDRREAD:
        {
            HV_W32_FIELD(DISP_TOP_DPU_LDG_DPC_1C, reg_osd_rd_unpack_len, ucBits);
            break;
        }
        default:
        {
            break;
        }
    }
}

VOID Hv_Cal_OsdOuterRDMA_SetUnpackSize(OsdDataPath enPath, USHORT16 usWidth, USHORT16 usHeight)
{
    switch (enPath)
    {
        case OSD_DATAPATH_GRAPHIC:
        {
            HV_W32_FIELD(DISP_TOP_DPU_LDG_DPC_0C, reg_bmp_rd_unpack_hbp, 16);
            HV_W32_FIELD(DISP_TOP_DPU_LDG_DPC_0C, reg_bmp_rd_unpack_height, usHeight);
            HV_W32_FIELD(DISP_TOP_DPU_LDG_DPC_10, reg_bmp_rd_unpack_width, usWidth);
            break;
        }
        case OSD_DATAPATH_DDRREAD:
        {
            HV_W32_FIELD(DISP_TOP_DPU_LDG_DPC_18, reg_osd_rd_unpack_hbp, 16);
            HV_W32_FIELD(DISP_TOP_DPU_LDG_DPC_1C, reg_osd_rd_unpack_height, usHeight);
            HV_W32_FIELD(DISP_TOP_DPU_LDG_DPC_20, reg_osd_rd_unpack_width, usWidth);
            break;
        }
        default:
        {
            break;
        }
    }
}

VOID Hv_Cal_OsdOuterWDMA_SetEnable(OsdDataPath enPath, BOOL bEnable)
{
    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_08, reg_03_dm_wr_enable, bEnable);
}

VOID Hv_Cal_OsdOuterWDMA_SetDDRAddr(OsdDataPath enPath, UINT32 uiAddr)
{
    uiAddr &= 0x7fffffff;
    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_18, reg_03_dm_wr_start_adr, uiAddr);
}

VOID Hv_Cal_OsdOuterWDMA_SetColStep(OsdDataPath enPath, USHORT16 usStep)
{
    HV_ASSERT_TRUE_VOID(usStep != 0 && ((usStep & 0x0f) == 0));

    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_10, reg_03_dm_wr_col_step, usStep);
}

VOID Hv_Cal_OsdOuterWDMA_SetColDirection(OsdDataPath enPath, OsdDMADirection enDirection)
{
    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_08, reg_03_dm_wr_col_step_dir, enDirection);
}

VOID Hv_Cal_OsdOuterWDMA_SetLineStep(OsdDataPath enPath, USHORT16 usStep)
{
    HV_ASSERT_TRUE_VOID((usStep & 0x0f) == 0);

    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_14, reg_03_dm_wr_line_step, usStep);
}

VOID Hv_Cal_OsdOuterWDMA_SetLineDirection(OsdDataPath enPath, OsdDMADirection enDirection)
{
    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_08, reg_03_dm_wr_line_step_dir, enDirection);
}

VOID Hv_Cal_OsdOuterWDMA_SetDataBlock(OsdDataPath enPath, USHORT16 usDataCount, UCHAR8 ucBurstLen)
{
    USHORT16 usDataCountAligned = ALIGN(usDataCount, DMA_COLDATA_ALIGN_BYTES);
    USHORT16 usDataCountIn16Bytes = usDataCountAligned >> 4;

    HV_ASSERT_TRUE_VOID(ucBurstLen > 0);
    HV_ASSERT_TRUE_VOID(usDataCountAligned >= 64);

    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_08, reg_03_dm_wr_burst_len, ucBurstLen - 1);
    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_0C, reg_03_dm_wr_burst_num, usDataCountIn16Bytes / ucBurstLen);
    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_08, reg_03_dm_wr_burst_rmd, usDataCountIn16Bytes % ucBurstLen);
}

VOID Hv_Cal_OsdOuterWDMA_SetOutstandingReq(OsdDataPath enPath, UCHAR8 ucReqCount)
{
    HV_ASSERT_TRUE_VOID(ucReqCount != 0);

    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_08, reg_03_dm_wr_outstanding, ucReqCount);
}

VOID Hv_Cal_OsdOuterWDMA_SetAccessMode(OsdDataPath enPath, OsdDMAMode enMode)
{
    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_08, reg_03_dm_wr_access_mode, enMode);
}

VOID Hv_Cal_OsdOuterWDMA_SetBufferDepth(OsdDataPath enPath, USHORT16 usDepth)
{
    HV_ASSERT_TRUE_VOID(usDepth > 0 && usDepth <= DMA_MAX_BUFFER_DEPTH);

    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_04, reg_03_dm_wr_buf_size, usDepth);
}

VOID Hv_Cal_OsdOuterWDMA_SetColNumber(OsdDataPath enPath, USHORT16 usNumber)
{
    HV_ASSERT_TRUE_VOID(usNumber > 0);

    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_1C, reg_03_dm_wr_total_col_num, usNumber);
}

VOID Hv_Cal_OsdOuterWDMA_SetLineNumber(OsdDataPath enPath, USHORT16 usNumber)
{
    HV_ASSERT_TRUE_VOID(usNumber > 0);

    HV_W32_FIELD(DISP_TOP_DPU_WVDM_03_1C, reg_03_dm_wr_total_line_num, usNumber);
}

VOID Hv_Cal_OsdOuterWDMA_SetPackFormat(OsdDataPath enPath, OsdPixelFormat enFormat)
{
    UCHAR8 ucBits = Hv_Cal_Osd_GetPixelBits(enFormat);

    HV_W32_FIELD(DISP_TOP_DPU_LDG_DPC_08, reg_osd_wr_pack_len, ucBits);
}
