#include "p_apps.h"

#include "Ac97.h"
#include "PalmChip.h"

volatile DCHAR Ac97_iBuf;
volatile DCHAR Ac97_iDtmfCode;
volatile DSHORT Ac97_iDtmfDuration;

XCHAR Ac97_bMuteInput = FALSE;	// save boolean space

#define AC97_MAX_BUF_SIZE	24
#define AC97_MAX_BUF_NUM	2

// used by G.723.1 and iLBC
#define OUT_30_DMA_HIGH		0x08
#define OUT_30_DMA_X1		0xd0	// 720 = 0x2d0
#define IN_30_DMA_HIGH		0
#define IN_30_DMA_X1		120

// used by GSM610 only
#define OUT_20_DMA_HIGH		0x04
#define OUT_20_DMA_X1		0xe0	// 480 = 0x1e0
#define IN_20_DMA_HIGH		0
#define IN_20_DMA_X1		80

// used by G.711 and G.729
#define OUT_10_DMA_HIGH		0
#define OUT_10_DMA_X1		240		// we can not output 8k or 16k with Ac97 yet, so it is for 48k only
#define IN_10_DMA_HIGH		0
#define IN_10_DMA_X1		40		// 10ms 8000Hz Sampling 16 bit data, 160 bytes in total

//static CCHAR _cInDmaHigh[CODEC_NULL] = {IN_10_DMA_HIGH, IN_30_DMA_HIGH, IN_10_DMA_HIGH, IN_10_DMA_HIGH, IN_20_DMA_HIGH, IN_30_DMA_HIGH};
static CCHAR _cInDmaX1[CODEC_NULL] = {IN_10_DMA_X1, IN_30_DMA_X1, IN_10_DMA_X1, IN_10_DMA_X1, IN_20_DMA_X1, IN_30_DMA_X1};
static CCHAR _cOutDmaHigh[CODEC_NULL] = {OUT_10_DMA_HIGH, OUT_30_DMA_HIGH, OUT_10_DMA_HIGH, OUT_10_DMA_HIGH, OUT_20_DMA_HIGH, OUT_30_DMA_HIGH};
static CCHAR _cOutDmaX1[CODEC_NULL] = {OUT_10_DMA_X1, OUT_30_DMA_X1, OUT_10_DMA_X1, OUT_10_DMA_X1, OUT_20_DMA_X1, OUT_30_DMA_X1};

void Ac97InitBuffer()
{
	DCHAR i;

	SdramClearDataCache();
	for (i = 0; i < AC97_MAX_BUF_SIZE*AC97_MAX_BUF_NUM; i += 2)
	{
		SdramWrite(AC97_OUT_SDRAM_HI, i, SRAM_DMA_DWORD);
		SdramWrite(AC97_IN_SDRAM_HI, i, SRAM_DMA_DWORD);
	}
	Ac97_iBuf = AC97_MAX_BUF_SIZE;

	Ac97StartCodec();

	Ac97Input(0, _cInDmaX1[Dsp_iType], 0);
//	Ac97Input(_cInDmaHigh[Dsp_iType], _cInDmaX1[Dsp_iType], 0);
	Ac97Output(_cOutDmaHigh[Dsp_iType], _cOutDmaX1[Dsp_iType], 0);
}

void Ac97SwapBuffer()
{
	// DMA 7, ac97 input
	XBYTE[DMA7_START_ADDR2] = Ac97_iBuf;
	XBYTE[DMA7_START_ADDR3] = AC97_IN_SDRAM_HI;
	XBYTE[DMA7_HIGH] = 0;
//	XBYTE[DMA7_HIGH] = _cInDmaHigh[Dsp_iType];
//	XBYTE[DMA7_X1] = _cInDmaX1[Dsp_iType];
//	XBYTE[DMA7_Y1] = 0;					// can be omitted
	XBYTE[DMA7_START_ADDR1] = 0;		// startup DMA

	// DMA 6, ac97 output

	if (XBYTE[SDRAM_STATUS1] & 0x20)
	{
		XBYTE[SDRAM_STATUS1] = 0x20;	// Stop previous SDRAM transfer first
	}
	XBYTE[DMA6_START_ADDR2] = Ac97_iBuf;
	XBYTE[DMA6_START_ADDR3] = AC97_OUT_SDRAM_HI;
	XBYTE[DMA6_HIGH] = _cOutDmaHigh[Dsp_iType];
//	XBYTE[DMA6_X1] = _cOutDmaX1[Dsp_iType];	
//	XBYTE[DMA6_Y1] = 0;				// can be omitted
	XBYTE[DMA6_START_ADDR1] = 0;		// startup DMA

/*
	Ac97_iBuf += AC97_MAX_BUF_SIZE;
	if (Ac97_iBuf == AC97_MAX_BUF_SIZE*AC97_MAX_BUF_NUM)
	{
		Ac97_iBuf = 0;
	}
*/
	if (Ac97_iBuf)
	{
		Ac97_iBuf = 0;
	}
	else
	{
		Ac97_iBuf = AC97_MAX_BUF_SIZE;
	}

}

// vol related functions
void Ac97SetOutputVol()
{
#ifdef _USE_FXS
	Ac97WriteReg(AC97_MASTER_VOL_STEREO, AC97_RIGHTVOL_HI, AC97_SPK_VOL_MAX - Ac97_iHandsetOutputVol);
#else // _USE_FXS
	if (PIO_bHandsetUp)
	{
#ifdef WOLFSON_MIXER
		Ac97WriteReg(AC97_MIXER_VOL, AC97_MIXER_HI, Ac97_iHandsetOutputVol);			// Left channel: MIN., Right channel: Mixer gain + output attenuation = -34.5dB
#endif
#if defined VER_PA168Q || defined VER_PA168P
		Ac97WriteReg(AC97_MASTER_VOL_MONO, AC97_RIGHTVOL_HI, AC97_SPK_VOL_MAX - Ac97_iHandsetOutputVol);
#endif
		Ac97WriteReg(AC97_MASTER_VOL_STEREO, AC97_RIGHTVOL_HI, AC97_SPK_VOL_MAX - Ac97_iHandsetOutputVol);
	}
	else
	{
#ifdef WOLFSON_MIXER
		Ac97WriteReg(AC97_MIXER_VOL, AC97_MUTE_HI, AC97_MUTE_LO);
#endif
		Ac97WriteReg(AC97_HEADPHONE_VOL, AC97_RIGHTVOL_HI, AC97_SPK_VOL_MAX - Ac97_iHandfreeOutputVol);
	}
#endif
}

void Ac97SetInputVol()
{
	if (Ac97_bMuteInput)
	{
		Ac97WriteReg(AC97_RECORD_GAIN, AC97_MUTE_HI, AC97_MUTE_LO);									// mute record gain
		return;
	}
	if (PIO_bHandsetUp)
	{
		Ac97WriteReg(AC97_RECORD_GAIN, Ac97_iHandsetInputVol, Ac97_iHandsetInputVol);				// set record gain 
	}
	else
	{
		Ac97WriteReg(AC97_RECORD_GAIN, Ac97_iHandfreeInputVol, Ac97_iHandfreeInputVol);				// set record gain 
	}
}

void Ac97OutputVolHigher()
{
	if (PIO_bHandsetUp)
	{
		if (Ac97_iHandsetOutputVol < AC97_SPK_VOL_MAX)
		{
			Ac97_iHandsetOutputVol ++;
		}
	}
	else
	{
		if (Ac97_iHandfreeOutputVol < AC97_SPK_VOL_MAX)
		{
			Ac97_iHandfreeOutputVol ++;
		}
	}
	Ac97SetOutputVol();
}

void Ac97OutputVolLower()
{
	if (PIO_bHandsetUp)
	{
		if (Ac97_iHandsetOutputVol)
		{
			Ac97_iHandsetOutputVol --;
		}
	}
	else
	{
		if (Ac97_iHandfreeOutputVol)
		{
			Ac97_iHandfreeOutputVol --;
		}
	}
	Ac97SetOutputVol();
}

void Ac97OnHandsetChange()
{
	if (PIO_bHandsetUp)
	{
		Ac97WriteReg(AC97_HEADPHONE_VOL, AC97_MUTE_HI, AC97_MUTE_LO);      // 

#ifdef AC97_MIC_INPUT
		Ac97WriteReg(AC97_GENERAL_PURPOSE, 0x80, 0);		// select MIC 1, PCM output path: Post-3D			
#else
		Ac97WriteReg(AC97_RECORD_SELECT, AC97_RECMUX_LINE, AC97_RECMUX_LINE);	// select line in as input 
#endif
	}
#ifndef _USE_FXS
	else
	{	// Handfree
		Ac97WriteReg(AC97_MASTER_VOL_STEREO, AC97_MUTE_HI, AC97_MUTE_LO);		// set master volume

#ifdef AC97_MIC_INPUT 
		Ac97WriteReg(AC97_GENERAL_PURPOSE, 0x81, 0);		// select MIC 2, PCM output path: Post-3D
#else
		Ac97WriteReg(AC97_RECORD_SELECT, AC97_RECMUX_MIC, AC97_RECMUX_MIC);		// select mic in as input 
#endif
	}
#endif
	Ac97SetOutputVol();
	Ac97SetInputVol();
}

void Ac97SetInputSampleRate(BOOLEAN b8KSampling)
{
	if (b8KSampling)
	{
		Ac97WriteReg(AC97_PCM_LR_RATE, AC97_8000_HI, AC97_8000_LO);
	}
	else
	{
		Ac97WriteReg(AC97_PCM_LR_RATE, AC97_48000_HI, AC97_48000_LO);
	}
}

