/**
 * @file hv_drv_OsdPalette.c
 * @brief Osd Driver Palette management c file.
 * @details This file provides the following functions: \n
 *          (1) palette initialization functions \n
 *          (2) palette copy functions \n
 *          (3) palette transfer 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"

static OsdSRAMChange s_stPaletteChange;

VOID Hv_Drv_OsdPalette_Copy(USHORT16 usOffset, UINT32 uiSrcAddr, USHORT16 usLength)
{
    OsdWindowPhyId enCurrentWinIndex = Hv_Cal_OsdWindow_GetCurrentWindow();
    UINT32 uiDstAddr = OSD_PALETTE_DDR_START;

    HV_ASSERT_TRUE_VOID(enCurrentWinIndex <= PHY_WIN_3);
    HV_ASSERT_TRUE_VOID(usOffset < 512);
    HV_ASSERT_TRUE_VOID(usOffset * 4 + usLength <= 2048);

    /* each window occupy 2K palette address */
    uiDstAddr += (enCurrentWinIndex - PHY_WIN_0) << 11;
    uiDstAddr += (usOffset << 2);

    //HV_MEMCPY((VOID*)uiDstAddr, (VOID*)uiSrcAddr, usLength);
    memmove((VOID*)uiDstAddr, (VOID*)uiSrcAddr, usLength);

    Hv_Drv_OsdPalette_SetChangeRange(OSD_SRAM_CHANGE_PARTIAL, uiDstAddr, uiDstAddr + usLength);
}

VOID Hv_Drv_OsdPalette_Move(USHORT16 usSrcOffset, USHORT16 usDstOffset, USHORT16 usColorCounts)
{
    OsdWindowPhyId enCurrentWinIndex = Hv_Cal_OsdWindow_GetCurrentWindow();
    UINT32 uiPaletteAddr = OSD_PALETTE_DDR_START;
    UINT32 uiSrcAddr = 0;

    HV_ASSERT_TRUE_VOID(enCurrentWinIndex <= PHY_WIN_3);
    HV_ASSERT_TRUE_VOID((usSrcOffset < 512) && (usSrcOffset + usColorCounts < 512));
    HV_ASSERT_TRUE_VOID((usDstOffset < 512) && (usDstOffset + usColorCounts < 512));

    /* each window occupy 2K palette address */
    uiPaletteAddr += (enCurrentWinIndex - PHY_WIN_0) << 11;
    uiSrcAddr = uiPaletteAddr + (usSrcOffset << 2);

    Hv_Drv_OsdPalette_Copy(usDstOffset, uiSrcAddr, usColorCounts * 4);
}

VOID Hv_Drv_OsdPalette_SetChangeRange(OsdSRAMChangeType enType,
                        UINT32 uiChangeStart, UINT32 uiChangeEnd)
{
    Hv_Drv_OsdMemory_SetSRAMChange(&s_stPaletteChange, enType, uiChangeStart, uiChangeEnd);

    OSD_DRV_LOG_DEBUG("Updated Osd Palette change, type: %s range: 0x%x - 0x%x",
            Hv_Drv_OsdCommon_GetSRAMChangeTypeStr(enType),
            uiChangeStart, uiChangeEnd);
}

VOID Hv_Drv_OsdPalette_TransferPalette(VOID)
{
    UINT32 uiAddr = 0, uiLength = 0;
    OsdSRAMChange *pstChange = &s_stPaletteChange;

    if (OSD_SRAM_CHANGE_NONE == pstChange->enType)
    {
        return;
    }
    else if (OSD_SRAM_CHANGE_FULL == pstChange->enType)
    {
        Hv_Drv_OsdDMA_Pend(OSD_PALETTE_DDR_START, OSD_PALETTE_BUFFER_BASE_ADDR,
                OSD_PALETTE_BUFFER_SIZE);
    }
    else
    {
        uiAddr = OSD_PALETTE_BUFFER_BASE_ADDR + pstChange->uiChangeStart - OSD_PALETTE_DDR_START;
        uiLength = pstChange->uiChangeEnd - pstChange->uiChangeStart;

        Hv_Drv_OsdDMA_Pend(pstChange->uiChangeStart, uiAddr, uiLength);
    }
    OSD_DRV_LOG_DEBUG("Palette total size = 0x%x", OSD_PALETTE_BUFFER_SIZE);

    Hv_Drv_OsdPalette_SetChangeRange(OSD_SRAM_CHANGE_NONE, 0, 0);
}

VOID Hv_Drv_OsdPalette_ChangeColor(OsdWindowPhyId enWinIndex, USHORT16 usColorIndex, UINT32 uiBGR)
{
    UINT32 uiDstAddr = OSD_PALETTE_DDR_START;

    HV_ASSERT_TRUE_VOID(enWinIndex <= PHY_WIN_3);
    HV_ASSERT_TRUE_VOID(usColorIndex < 512);

    uiDstAddr += (enWinIndex - PHY_WIN_0) << 11;
    uiDstAddr += (usColorIndex << 2);

    *(UINT32 *)uiDstAddr = uiBGR;

    OSD_DRV_LOG_DEBUG("Change win-%d's palette[%d] = 0x%x", enWinIndex, usColorIndex, uiBGR);

    Hv_Drv_OsdPalette_SetChangeRange(OSD_SRAM_CHANGE_PARTIAL, uiDstAddr, uiDstAddr + 4);
}

UINT32 Hv_Drv_OsdPalette_GetColor(OsdWindowPhyId enWinIndex, USHORT16 usColorIndex)
{
    UINT32 uiDstAddr = OSD_PALETTE_DDR_START;
    UINT32 uiBGR = 0;
    HV_ASSERT_TRUE_RET(enWinIndex <= PHY_WIN_3, 0);

    uiDstAddr += (enWinIndex - PHY_WIN_0) << 11;
    uiDstAddr += (usColorIndex << 2);

    uiBGR = *(UINT32 *)uiDstAddr;

    OSD_DRV_LOG_DEBUG("Change win-%d's palette-%d = 0x%x", enWinIndex, usColorIndex, uiBGR);

    return uiBGR;
}

UINT32 Hv_Drv_OsdPalette_GetPaletteColor(USHORT16 usColorIndex)
{
    HV_ASSERT_TRUE_RET(((usColorIndex + 1) * 4) <= g_ausOsdPalettesListLength, 0);

    return g_auiOsdPalettesList[usColorIndex];
}

VOID Hv_Drv_OsdPalette_Init(VOID)
{
    OsdWindowPhyId enWinIndex = PHY_WIN_0;

    for (; enWinIndex <= PHY_WIN_3; ++enWinIndex)
    {
        Hv_Drv_OsdWindow_SetCurrentWindow(enWinIndex);

        Hv_Drv_OsdPalette_Copy(0, (UINT32)g_auiOsdPalettesList, g_ausOsdPalettesListLength);
    }

    Hv_Drv_OsdPalette_SetChangeRange(OSD_SRAM_CHANGE_FULL, 0, 0);
}

#if (HV_PROJECT_CONFIG_OSD_LOGO_USE_SCENE == HV_CONFIG_ON)
VOID Hv_Drv_OsdLogoPalette_Init(VOID)
{
    OsdWindowPhyId enWinIndex = PHY_WIN_0;

    for (; enWinIndex <= PHY_WIN_3; ++enWinIndex)
    {
        Hv_Drv_OsdWindow_SetCurrentWindow(enWinIndex);

        Hv_Drv_OsdPalette_Copy(0, (UINT32)g_auiOsdLogoPalettesList, g_ausOsdLogoPalettesListLength);
    }

    Hv_Drv_OsdPalette_SetChangeRange(OSD_SRAM_CHANGE_FULL, 0, 0);
}
#endif