//----------------------------------------------------------------------------------------------------
// ID Code      : RTD2528R_Memory.c No.0000
// Update Note  : 
//
//----------------------------------------------------------------------------------------------------

#define __RTD2528R_MEMORY__

#include  "Core\Header\Include.h"

#if(_SCALER_TYPE == _RTD2528R)

#if(_OD_SUPPORT == _ON)
//--------------------------------------------------
// Description  : Reset SDRAM
// Input Value  : NONE
// Output Value : NONE
//--------------------------------------------------
void CMemorySDRAMReset(void)
{
    CScalerPageSelect(_PAGE4);
    CScalerSetBit(_P4_SDR_PRCG_A4, ~_BIT4, _BIT4);
    CTimerDelayXms(5);
    CScalerSetBit(_P4_SDR_PRCG_A4, ~_BIT4, 0x00);
}

//--------------------------------------------------
// Description  : Load OD Table to LUT
// Input Value  : ucColor   --> LUT Channel Select
// Output Value : NONE
//--------------------------------------------------
void CMemoryLoadODLUT(BYTE ucColor)
{
    BYTE repeat;

    CScalerPageSelect(_PAGE3);
    CScalerSetBit(_P3_LS_LUT_ROW_ADDR_AE, ~_BIT7, _BIT7);

    if((ucColor == _OD_TABLE_COMMON))
    {
        CScalerSetBit(_P3_LS_LUT_COL_ADDR_AF, ~(_BIT7 | _BIT6), _OD_TABLE_COMMON << 6);
        CMemoryLoadODTable(tOD_TABLE[_OD_TABLE_COMMON]);
    }
    else
    {
        for(repeat=0 ; repeat<3 ; repeat++)
        {
            CScalerSetBit(_P3_LS_LUT_COL_ADDR_AF, ~(_BIT7 | _BIT6), repeat << 6);            
            CMemoryLoadODTable(tOD_TABLE[repeat]);
        }
    }

    CScalerSetBit(_P3_LS_LUT_ROW_ADDR_AE, ~_BIT7, 0x00);
}

//--------------------------------------------------
// Description  : Load OD Table to LUT
// Output Value : pChannelArray    --> OD Table Start Address
// Output Value : NONE
//--------------------------------------------------
void CMemoryLoadODTable(BYTE *pChannelArray)
{
    CScalerWrite(_P3_LS_LUT_DATA_B0, 1088, pChannelArray, _NON_AUTOINC);
}


//--------------------------------------------------
// Description  : OD On/Off Select
// Output Value : pArray    --> OD Table Start Address
// Output Value : NONE
//--------------------------------------------------
void CMemorySetODOnOff(BYTE ucSelect)
{
    CScalerPageSelect(_PAGE3);

    CScalerSetBit(_P3_LS_CTRL0_A1, ~(_BIT6 | _BIT5), (_BIT6 | _BIT5));
    CScalerSetByte(_P3_LS_CTRL1_A2, ((BYTE)_OD_LBNRT_ENABLE<<4 | _OD_LBNRT_MODE<<3 | _OD_LBNRT_LEVEL) | _BIT7 | _BIT6);//cyc_test
    CScalerSetByte(_P3_LS_STATUS0_B6, 0x01);

    if(ucSelect == _ON)
        CScalerSetBit(_P3_LS_CTRL0_A1, ~_BIT7, _BIT7);
    else
        CScalerSetBit(_P3_LS_CTRL0_A1, ~_BIT7, 0x00);

    CScalerSetByte(_P3_LS_CTRL0_A1, 0x00);	
}

void CMemorySetODCompress(void)
{
    BYTE compress = 0, resolution = 0; 
    WORD efficiency = 0, target = 0; 

    CScalerPageSelect(_PAGE3);
    CScalerSetBit(_P3_LS_CTRL0_A1, ~(_BIT2 | _BIT1 | _BIT0),(((Panel[ucPanelSelect].PanelConfig & 0x80) << 2) | 0x00));

    // Calculate and set display clock frequency
    ((DWORD *)pData)[0] = (DWORD)(stDisplayInfo.DHTotal) * (DWORD)stModeInfo.IHFreq * (DWORD)(stDisplayInfo.DVHeight) / stModeInfo.IVHeight / 10;

//    efficiency = (((DWORD)(Panel[ucPanelSelect].DHWidth * ((DWORD *)pData)[0] * 6 * 3 * 2)) * 1000) / 
//                 ((DWORD)(Panel[ucPanelSelect].DHTotal * (_MEMORY_SPEED * 1000) * _MEMORY_SIZE));                

    efficiency = (DWORD)Panel[ucPanelSelect].DHWidth * ((DWORD *)pData)[0] / _MEMORY_SPEED * 6 * 3 * 2 / Panel[ucPanelSelect].DHTotal / _MEMORY_SIZE;

    if(efficiency >= 800)
        compress = 1;
    else
        compress = 0;

    compress = (compress | _OD_COMPRESSION);

    CScalerSetBit(_P3_LS_CTRL0_A1, ~_BIT4, (compress << 4));

    if(compress == _TRUE)
    {
        efficiency = (efficiency * 5) / 6;//Rounding to 5bit/4bit
    
        if(efficiency >= 0.8)
        {
            CScalerSetBit(_P3_LS_CPRS_CTRL_A4, ~(_BIT6 | _BIT5), 0x00);
            resolution = 4;
        }
        else
        {
            CScalerSetBit(_P3_LS_CPRS_CTRL_A4, ~(_BIT6 | _BIT5), _BIT5);
            resolution = 5;
        }
    }
    else
        resolution = 6;

    pData[0] = (HIBYTE(_COMPRESS_GROUP_NUMBER) & 0x03);
    pData[1] = (LOBYTE(_COMPRESS_GROUP_NUMBER));
    CScalerWrite(_P3_LS_GRP_NUM_H_A7, 2, pData, _AUTOINC);

    target = (WORD)resolution * _COMPRESS_GROUP_NUMBER * 3 / 64;

    pData[0] = (HIBYTE(target) & 0x01);
    pData[1] = (LOBYTE(target));
    CScalerWrite(_P3_LS_TG_SIZE_H_A5, 2, pData, _AUTOINC);    
}

void CMemorySetODFIFO(void)
{
    BYTE resolution = 0, remain = 0, length = 128;
    WORD number = 0;

    CScalerRead(_P3_LS_CTRL0_A1, 1, pData, _NON_AUTOINC);

    if((pData[0] & 0x10) == 0x10)
    {
        CScalerRead(_P3_LS_CPRS_CTRL_A4, 1, pData, _NON_AUTOINC);    

        if((pData[0] & 0x20) == 0x20)
            resolution = 5;
        else
            resolution = 4;
    }
    else
    {
        resolution = 6;
    }

    ((DWORD *)pData)[0] = (((DWORD)Panel[ucPanelSelect].DHWidth * Panel[ucPanelSelect].DVHeight) * 3 * resolution % 64) ? 
                          ((((DWORD)Panel[ucPanelSelect].DHWidth * Panel[ucPanelSelect].DVHeight) * 3 * resolution / 64) + 1) : 
                          (((DWORD)Panel[ucPanelSelect].DHWidth * Panel[ucPanelSelect].DVHeight) * 3 * resolution / 64);// One frame total pixel for SDRAM (unit : 64 bits)

    if((((DWORD *)pData)[0] % length) != 0)
    {
        ((DWORD *)pData)[0] = ((((DWORD *)pData)[0] + 4) & 0xfc);
        number = ((DWORD *)pData)[0] / length;
        remain = ((DWORD *)pData)[0] % length;
    }
    else
    {
        ((DWORD *)pData)[0] = ((DWORD *)pData)[0] - length;
        number = ((DWORD *)pData)[0] / length;
        remain = length;
    }
    
    CScalerPageSelect(_PAGE3);
    CScalerSetByte(_P3_LS_WTLVL_W_C0, (length / 2));
    CScalerSetByte(_P3_LS_WTLVL_R_C1, (length / 2));

    pData[0] = (HIBYTE(number));
    pData[1] = (LOBYTE(number));
    CScalerWrite(_P3_LS_MEM_FIFO_RW_NUM_H_C2, 2, pData, _AUTOINC);

    CScalerSetByte(_P3_LS_MEM_FIFO_RW_LEN_C4, length);
    CScalerSetByte(_P3_LS_MEM_FIFO_RW_REMAIN_C5, remain);

    pData[0] = ((_OD_START_ADDRESS >> 16) & 0x3f);
    pData[1] = ((_OD_START_ADDRESS >> 8) & 0xff);
    pData[3] = (_OD_START_ADDRESS & 0xff);
    CScalerWrite(_P3_LS_MEM_START_ADDR_H_C6, 3, pData, _AUTOINC);    
}
#endif //End of #if(_OD_SUPPORT == _ON)

#endif  // End of #if(_SCALER_TYPE == _RTD2528R)
