
#include <stdlib.h>
#include <stdio.h>

#include "ag101.h"
#include "symbol.h"
#include "ssp.h"

int TxFIFOLen = 0;

void fLib_SetSSPFrame(UINT32 base_address,UINT32 frame)
{
    UINT32 data;

    data = inw(base_address + SSP_CONTROL0);
    data &= 0xFFF;
    data |= frame;
    outw(base_address + SSP_CONTROL0, frame);
}

void fLib_SSPClearTxFIFO(UINT32 base_address)
{
    UINT32 data;

    data = inw(base_address + SSP_CONTROL2);
    data |= SSP_TXFCLR;
    outw(base_address + SSP_CONTROL2, data);
}


void fLib_SSPClearRxFIFO(UINT32 base_address)
{
    UINT32 data;

    data = inw(base_address + SSP_CONTROL2);
    data |= SSP_RXFCLR;
    outw(base_address + SSP_CONTROL2, data);
}

void fLib_SetSSP_ColdReset(UINT32 base_address)
{
    UINT32  ctrl;
	
    outw(base_address + SSP_CONTROL2, SSP_ACCRST);
    do
    {
        ctrl = inw(base_address + SSP_CONTROL2);
    }while((ctrl & SSP_ACCRST) != 0);
}


void fLib_SetSSP_Enable(UINT32 base_address,int enable)
{
    UINT32  ctrl;

    ctrl = inw(base_address + SSP_CONTROL2);
    if(enable)
        ctrl |= SSP_SSPEN + SSP_TXDOE;
    else
        ctrl &= ~(SSP_SSPEN + SSP_TXDOE);

    outw(base_address + SSP_CONTROL2, ctrl);
}

void fLib_SetSSP_IntMask(UINT32 base_address,int Mask)
{
    UINT32  ctrl;
    ctrl = inw(base_address + SSP_INT_CONTROL);
    ctrl &= ~0x3F;
    ctrl |= Mask;
    outw(base_address + SSP_INT_CONTROL, ctrl);
}

void fLib_SSP_GetTxFIFOLen(UINT32 base_address)
{
    UINT32 len;

    len = (inw(base_address + SSP_INFO) & SSP_TXFIFO_DEPTH);

    TxFIFOLen = (len >> 16) + 1;
    return;
}


void fLib_AC97_SetSlotValidReg(UINT32 base_address,UINT32 SlotValid)
{
    outw(base_address + SSP_ACLINK_SLOT_VALID, SlotValid);
}

void fLib_AC97_WriteData(UINT32 base_address,UINT32 *data, UINT32 Len)
{
    UINT32  tx_cnt;

    while(Len != 0)
    {
        tx_cnt = (inw(base_address + SSP_STATUS) & SSP_TFVE) >> 12;

        for(; tx_cnt < TxFIFOLen; tx_cnt++, data++, Len--)
        {
            if(Len == 0)
                return ;

            outw(base_address + SSP_DATA, *data);
        }
    }
    return;
}

int fLib_ReturnTxFIFO_Count(UINT32 base_address)
{
    int count = 0;

    count = (inw(base_address+SSP_STATUS)&SSP_TFVE)>>12;

    return count;
}

void fLib_AC97_WriteRegisterEx(UINT32 base_address,UINT32 Reg_Index, UINT32 data)
{
    UINT32 TxBuf[2];

    TxBuf[0] = 0x00000+(Reg_Index<<12);
    TxBuf[1] = data << 4;

    fLib_SSPClearTxFIFO(base_address);
    fLib_SSPClearRxFIFO(base_address);
    fLib_AC97_SetSlotValidReg(base_address,0xE000); 

    fLib_AC97_WriteData(base_address,TxBuf, 2);
    fLib_SetSSP_Enable(base_address,TRUE);

    while(fLib_ReturnTxFIFO_Count(base_address)>0)
        ;

    fLib_SetSSP_Enable(base_address,FALSE);
}

