/*=============================================================
 * Copyright (c)      Realtek Semiconductor Corporation, 2005 *
 * All rights reserved.                                       *
 *============================================================*/
/*======================= Description ========================*/
/**
 * @file
 * @author
 * @date        2005/09/22
 * @version     0.1
 * @ingroup
 *
 * @Note
 */

/*======================= CVS Headers =========================
  $Header$
  $Log$
  Revision 1.1  2006/02/20 07:50:43  forster
  no message

  Revision 1.12  2006/02/15 02:54:48  jerry
  +: Add PTW M34x0g audio series processor.

  Revision 1.11  2006/02/14 10:30:06  yteng
  +:_RTD2553V_VD2612_NEXGEN_PCB  kingee

  Revision 1.10  2006/02/14 02:21:25  yteng
  +:_RTD2553V_VD2612_NEXGEN_PCB audio kingee

  Revision 1.9  2006/02/13 13:30:45  hill
  no message

  Revision 1.8  2006/02/13 13:22:38  hill
  *:modify  volume pwm cycle

  Revision 1.7  2006/02/13 11:55:13  yteng
  +:_RTD2553V_VD2612_NEXGEN_PCB  kingee

  Revision 1.6  2006/02/13 05:54:21  yteng
  +:_RTD2553V_VD2612_NEXGEN_PCB  kingee

  Revision 1.5  2006/02/10 08:24:08  leo_liu
  no message

  Revision 1.4  2006/02/09 13:40:06  hill
  *:modify audio mute when source video8 power up

  Revision 1.3  2006/02/08 08:54:33  hill
  *: modify for Customer ID2

  Revision 1.2  2006/02/07 02:26:42  kevin_liu
  :+Audio decoder STV8217

  Revision 1.1.1.1  2006/02/06 06:03:22  forster
  no message

  Revision 1.1.1.1  2006/01/16 09:33:56  frankcheng
  2533v code refine.

  Revision 1.14  2005/12/27 07:55:54  jerry
  +: Add the CD4052 switch table(input/output).

  Revision 1.13  2005/12/17 02:06:47  hill
  +: add osd audio function

  Revision 1.12  2005/11/21 07:15:43  hill
  +: when tv auto scan not to check mute

  Revision 1.11  2005/11/18 06:44:03  hill
  *: modify Techview change source sound of explosion

  Revision 1.10  2005/11/15 08:00:20  hill
  +: add for Techview board setting

  Revision 1.9  2005/11/01 03:06:37  kenlin
  +:Add modify Audio controm for 2553+2613 DTV IF  board

  Revision 1.8  2005/10/17 01:16:27  hill
  *:removed temp

  Revision 1.7  2005/10/14 07:29:34  weihao
  *: Fixed show dropped font in VBI

  Revision 1.6  2005/10/13 14:12:27  joshlin
  *:update for AN5832SA

  Revision 1.5  2005/10/11 07:18:34  joshlin
  *:update for warning message

  Revision 1.4  2005/10/11 06:51:23  joshlin
  *:update for 2612+2553V demo board v1.0

  Revision 1.3  2005/09/29 07:10:18  weihao
  *: move constant and define

  Revision 1.2  2005/09/27 12:58:35  hill
  *: update for winbond 128K

  Revision 1.1  2005/09/23 07:19:58  joshlin
  +:create for audio function


*=============================================================*/

#define __AUDIO__

#include "Core\Header\Include.h"

//-------------------------------------------------------------
// Macro	Function
//-------------------------------------------------------------


//-------------------------------------------------------------
// Local Variables
//-------------------------------------------------------------


BIT AudioMute = 0;
BIT CurrEarPhone = 0;

//-------------------------------------------------------------
// Local Function
//-------------------------------------------------------------

//-------------------------------------------------------------
// Audio Core Function
//-------------------------------------------------------------
BYTE oldEarphone=0xff;
		//0xff: undefine status,
		//0x00: last status is not inserted,
		//oxo1: last status is inserted
bit GET_EARPHONE_STATUS_CHANGE(void)
{
	bit result = 0;
	bit detect;
	
	detect = GET_EARPHONE_INSERT();
	
	if (oldEarphone == 0xff)
		result = 0;
	else 
	{
		if (detect==1 && oldEarphone==0x00)
			result = 1;
		else if (detect==0 && oldEarphone==0x01)
			result = 1;
	}

	oldEarphone = (detect) ? (0x01) : (0x00);

	//if (result)
	//	DebugPrintf("earphone insert change...%d\n", detect);
	
	return result;
		
}

bit GET_EARPHONE_INSERT(void)
{
	if (GET_HEADPHONE_INSERT())
	{
		CTimerDelayXms(5);
		if (GET_HEADPHONE_INSERT())
			return _TRUE;
	}
	return _FALSE;
}

#if _VOLUME_TDA7496_SUPPORT
/**
	This routine will init audio function.
	used in CMainSystemInitial()
*/
UINT8 code VolumeCurve[31]=
{
/*
	255,248,241,234,227,220,213,206,199,192,155,
	148,141,134,127,120,113,107,101,95,89,
	83,77,71,65,65,59,59,53,53,48,
	*/
	#ifdef  TUOBU_AT090
	255,192,187,182,177,172,167,163,159,157,155,
	148,141,134,127,120,113,107,101,95,89,
	83,77,71,65,65,59,59,53,53,48,
	#else
//	255,192,187,182,177,172,167,163,159,157,155,
	//148,146,143,140,138,136,133,129,125,122,
//	120,117,115,113,108,105,102,100,98,95,
	255,145,140,135,130,125,120,116,112,109,107,
	100,93,86,79,72,65,59,53,47,41,
	35,29,23,17,17,11,11,5,5,0,
	#endif
};
void CAudioInit(void)
{

	SET_AUDIO_CHIP_MUTE();
	SET_EARPHONE_MUTE();

	//SET_MUTE_PROCESS(_ENABLE);
	SET_EARPHONE_MUTE();

	SET_AUDIO_CHIP_STBY(0);
	
	CAudioSetSource(GET_INPUTPORT_TYPE(stSystemData.InputSource));
}

void CAudioSetSource(BYTE inputPort)
{
	// B  A  CD4052
	//-------------
	// 0  0  0X 0Y
	// 0  1  1X 1Y
	// 1  0  2X 2Y
	// 1  1  3X 3Y
	
	//pt2662b1a
	switch(inputPort)
	{
	#if(_PCB_TYPE==_PCB_PT2660A1A)
		case _VIDEO_AV_PORT:
		case _VIDEO_SV_PORT:
		case _YPBPR_A0_PORT:
			bAUDIO_SEL_B = 0;
			bAUDIO_SEL_A = 0;
			break;

		case _DSUB_A0_PORT:
			bAUDIO_SEL_B = 0;
			bAUDIO_SEL_A = 1;
			break;

		case _HDMI_PORT:
		case _HDMI_PORT2:
			bAUDIO_SEL_B = 1;
			bAUDIO_SEL_A = 0;
			break;

		case _VIDEO_TV_PORT:
			bAUDIO_SEL_B = 1;
			bAUDIO_SEL_A = 0;
			break;
		default:
			bAUDIO_SEL_B = 0;
			bAUDIO_SEL_A = 0;
			break;
			
	#elif _PCB_TYPE==_PCB_PT2660_KTC57924G
	
		case _VIDEO_AV_PORT:
		case _VIDEO_SV_PORT:
			SET_AUDIO_AV();
			break;

		case _DSUB_A0_PORT:
			SET_AUDIO_PC();
			break;
		default:
			break;
			//20080818 ccy add			
	#elif _PCB_TYPE== _PCB_TEST
/*	
		case _VIDEO_AV_PORT:
			bAUDIO_SEL_A  = 0;
			bAUDIO_SEL_B  = 1;
			break;
		case _VIDEO_SV_PORT:
			bAUDIO_SEL_A  = 1;
			bAUDIO_SEL_B  = 0;
			break;
		case _DSUB_A0_PORT:
			bAUDIO_SEL_A = 0;
			bAUDIO_SEL_B = 0;
			break;
		case _VIDEO_TV_PORT:
			bAUDIO_SEL_A = 1;
			bAUDIO_SEL_B = 1;
		default:
			break;
*/
			case _VIDEO_AV_PORT:
			SET_AV_AUDIO();
			break;
		case _VIDEO_SV_PORT:
			SET_AV_AUDIO();
			break;
		case _DSUB_A0_PORT:
			SET_NC_AUDIO();
			break;
		case _VIDEO_TV_PORT:
			SET_TV_AUDIO();
			break;
		case  _YPBPR_A0_PORT://_VIDEO_DMB_PORT:
			SET_DMB_AUDIO();
			break;
		default:
			SET_NC_AUDIO();
			break;

#else
		case _VIDEO_AV_PORT:
		case _VIDEO_SV_PORT:
		case _YPBPR_A0_PORT:
			bAUDIO_SEL_B = 0;
			bAUDIO_SEL_A = 0;
			break;

		case _DSUB_A0_PORT:
			bAUDIO_SEL_B = 0;
			bAUDIO_SEL_A = 1;
			break;

		case _HDMI_PORT:
		case _HDMI_PORT2:
			bAUDIO_SEL_B = 1;
			bAUDIO_SEL_A = 0;
			break;
			
		case _VIDEO_TV_PORT:
			bAUDIO_SEL_B = 1;
			bAUDIO_SEL_A = 1;
			break;

		default:
			bAUDIO_SEL_B = 0;
			bAUDIO_SEL_A = 0;
			break;
#endif
	}
}


void CAudioSetVolume(BYTE value)	//range 0~50~100
{
	static UINT8 valuelast=0;
	/*if (!value)
	{
		//if (GET_EARPHONE_INSERT())
		//{
			SET_AUDIO_CHIP_MUTE();
			SET_EARPHONE_MUTE();

		//}
	}
	else
	{*/
		if (value>30)
			value=10;
		MCU_PWM4H_DUT_FF50 = VolumeCurve[value];
		//value = ((WORD)value*_AUDIO_MAX)/100;	//expand to 0-255
/********************************************
		if(value<=16)
			MCU_PWM1H_DUT_FF4B=value+12;
		else
			MCU_PWM1H_DUT_FF4B=value;
*********************************************/		//disable by lbh 20090922
			//MCU_PWM1H_DUT_FF4B=pwmval;
	if (!value)
	{
		//if (GET_EARPHONE_INSERT())
		//{
			SET_AUDIO_CHIP_MUTE();
			SET_EARPHONE_MUTE();

		//}
	}
		if (valuelast==0 && value!=0)
		{
			if (!GET_EARPHONE_INSERT())
			{
				CLR_AUDIO_CHIP_MUTE();
			}
		}
	//}
	valuelast = value;
}

void CAudioChipWrVolumeGradual(BYTE value, BYTE gradualDir)
{
#define _STEP_DLY	3
	UINT16 i;	//define 16bit, some audio chip range is 0-255

	/*if (stAudioData.Volume==0)
	{
		SET_AUDIO_CHIP_MUTE();
		CTimerDelayXms(5);
		return;
	}
	else*/
	//{
		//value = ((WORD)value*_AUDIO_MAX)/100;	//expand to 0-255
		//value = VolumeCurve[value];
	//}

	if (gradualDir)
	{
		//inc
	#if 1
		for(i=0;i<value;i++)
		{
			MCU_PWM4H_DUT_FF50=VolumeCurve[i];
			CTimerDelayXms(_STEP_DLY);
		}
		MCU_PWM4H_DUT_FF50=VolumeCurve[value];
	#else
		i = _AUDIO_REG_H_LIMIT;
		do {
			MCU_PWM1H_DUT_FF4B=i;
			CTimerDelayXms(_STEP_DLY);
			i--;
		}while(i>value);
		MCU_PWM1H_DUT_FF4B=value;
	#endif
	}
	else
	{
		//dec
	#if 1
		for(i=value;i>0;i--)
		{
			MCU_PWM4H_DUT_FF50=VolumeCurve[i];
			CTimerDelayXms(_STEP_DLY);
		}
		MCU_PWM4H_DUT_FF50=VolumeCurve[0];
	#else
		do {
			MCU_PWM1H_DUT_FF4B=value;
			CTimerDelayXms(_STEP_DLY);
			value++;
		}while(value<_AUDIO_REG_H_LIMIT);
		MCU_PWM1H_DUT_FF4B=255;
	#endif
	}
	/*if (stAudioData.Volume==0)
	{
		SET_AUDIO_CHIP_MUTE();
		CTimerDelayXms(5);
	}*/
}

void SET_MUTE_PROCESS(bit x)	
{
	if (!x)
	{
		//DebugPrintf("clr mute, earphone=%d\n", GET_EARPHONE_INSERT());
		//premier, review??? keep in mute status while mute flag is get
		if (GET_AUDIO_MUTE())
			return;
	
		//CAudioSetSource(GET_INPUTPORT_TYPE(stSystemData.InputSource));
		//20070330, re open PT2314 mute function
		CAudioChipWrVolumeGradual(stAudioData.Volume, 1);
		if (GET_EARPHONE_INSERT())
		{
			SET_AUDIO_CHIP_MUTE();
			CLR_EARPHONE_MUTE();
 		}
		else if(stAudioData.Volume!=0)
		{
			CLR_AUDIO_CHIP_MUTE();
			SET_EARPHONE_MUTE();
		}
	}
	else
	{
		
		//DebugPrintf("set mute, earphone=%d\n", GET_EARPHONE_INSERT());
		//20080825 ccy modify 
#if (_PCB_TYPE == _PCB_TEST)
		if(!GET_AUDIO_CHIP_MUTE())
		CAudioChipWrVolumeGradual(stAudioData.Volume, 0);			//add by lbh 20090922
#else		
		CAudioChipWrVolumeGradual(stAudioData.Volume, 0);
#endif
		if(stAudioData.Volume!=0)
		{
			if(!GET_AUDIO_CHIP_MUTE())
			SET_AUDIO_CHIP_MUTE();
			CTimerDelayXms(5);
		}
		SET_EARPHONE_MUTE();
	}
}
#endif


#if _VOLUME_PT2314_SUPPORT

#define bI2C_SDA_PT2314	bIICSDA
#define bI2C_SCL_PT2314		bIICSCL



#define _ADDR_PT2314		0x88

#define _AUDIO_L			1
#define _AUDIO_R			2
#define _AUDIO_LR			3

#define _AUDIO_VOL_ADDR		0x00	
#define _AUDIO_BAL_L_ADDR		0xc0	
#define _AUDIO_BAL_R_ADDR		0xe0
#define _AUDIO_BASE_ADDR		0x60
#define _AUDIO_TREBLE_ADDR	0x70

#define _AUDIO_BAL_L_INIT		0x0e	
#define _AUDIO_BAL_R_INIT		0x07
#define _AUDIO_BASE_INIT		0x08
#define _AUDIO_TREBLE_INIT		0x08



void CI2CDelay(void)
{
	//CLOCK: 24MHz
	//8 _nop()_ cause PT2314 can't capture the bus, then SDA is frever LOW unless PT2314 recieve a STOP.
    	_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
    	_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
}


// PT2314: MAX RATE OF IIC IS 100KHZ.
void CPt2314Start(void) 
{
	BYTE times=5;

	while ((bI2C_SCL_PT2314==0)||(bI2C_SDA_PT2314==0))
	{
		//Force to stop IIC while the SDA maybe keep LOW by any device, 
		// for example, PT2314 delay is short than 8 nops at 24MHz.
		CI2CDelay();
	    	bI2C_SCL_PT2314 = 0;
		CI2CDelay();
	    	bI2C_SDA_PT2314 = 0; 	
		CI2CDelay();
	    	bI2C_SCL_PT2314 = 1;
	    	CI2CDelay();
	    	bI2C_SDA_PT2314 = 1;
		CI2CDelay();

		CTimerDelayXms(15);
		if (!(times--))
			break;
	}
	
	CI2CDelay();
    	bI2C_SDA_PT2314 = 1; 		
    	CI2CDelay();
    	bI2C_SCL_PT2314 = 1;
    	CI2CDelay();
    	bI2C_SDA_PT2314 = 0;
	CI2CDelay();
    	bI2C_SCL_PT2314 = 0;
	CI2CDelay();
}

void CPt2314Stop(void) 
{
    	CI2CDelay();
    	bI2C_SCL_PT2314 = 0;
    	CI2CDelay();
    	bI2C_SDA_PT2314  = 0;    
    	CI2CDelay();
    	bI2C_SCL_PT2314 = 1;
    	CI2CDelay();
    	bI2C_SDA_PT2314 = 1;
    	CI2CDelay();

}

bit CPt2314DataIn(BYTE bytedata) 
{  
  	BYTE data i;
  	bit ack;

    	CI2CDelay();
    	bI2C_SCL_PT2314 = 0;
    	CI2CDelay();
	
  	for(i=0; i<8; i++) 
  	{
    		bI2C_SDA_PT2314 = bytedata & 0x80;
    		CI2CDelay();
    		bI2C_SCL_PT2314 = 1;
    		CI2CDelay();
    		bytedata <<= 1;
    		bI2C_SCL_PT2314 = 0; 
    		CI2CDelay();
   	}
	
   	bI2C_SDA_PT2314 = 1;
    	CI2CDelay();
   	bI2C_SCL_PT2314 = 1;
    	CI2CDelay();
   	ack = bI2C_SDA_PT2314;
    	CI2CDelay();
   	bI2C_SCL_PT2314 = 0; 
    	CI2CDelay();

  	return ack;
}

//x = 0-15
unsigned char code tPt2314BassTrebleMap[]=
{
	0,
	1,
	2,
	3,
	4,
	5,
	6,
	7,

	15,
	14,
	13,
	12,
	11,
	10,
	9,
	8,
};

void CPt2314WrProcedure(BYTE n, BYTE data0, BYTE data1)
{
	bit ack = 0;
	BYTE times=5;
	
	do {
		if (ack==1)
		{
			//20080306
			//CTimerDelayXms(5);
			CTimerDelayXms(2);
		}
		
		ack = 0;
		CPt2314Start();
	   	ack |= CPt2314DataIn(_ADDR_PT2314);
		ack |= CPt2314DataIn(data0);
		if (n>1)
			ack |= CPt2314DataIn(data1);
	   	CPt2314Stop();
		//if (ack)
		//	continue;
		//DebugPrintf("pt2314:times=%d\n", times);
	}while((ack) && (times--));

}
void CPt2314WrTreble(void)
{
	bit ack = 0;
	BYTE times=5;

	WORD treble;

#if(_AUDIO_EFFECT_SUPPORT)
	if (GET_AUDIO_EFFECT()==_AUDIO_EFFECT_USER)
		treble = stAudioData.Treble;
	else if (GET_AUDIO_EFFECT()==_AUDIO_EFFECT_MOVIE)
		//treble = tEEPROM_AUDIO_DATA_MOVIE.Treble;
		treble = _AUDIO_EFFECT_MOVIE_TREBLE;
	else if (GET_AUDIO_EFFECT()==_AUDIO_EFFECT_MUSIC)
		//treble = tEEPROM_AUDIO_DATA_MUSIC.Treble;
		treble = _AUDIO_EFFECT_MUSIC_TREBLE;
	else if (GET_AUDIO_EFFECT()==_AUDIO_EFFECT_NEWS)
		//treble = tEEPROM_AUDIO_DATA_NEWS.Treble;
		treble = _AUDIO_EFFECT_NEWS_TREBLE;
	else
		treble = stAudioData.Treble;
	
#else
	treble = stAudioData.Treble;
#endif

	treble *= 15;
	treble/=100;
	
	CPt2314WrProcedure(1,tPt2314BassTrebleMap[treble&0x0f] | 0x70,0);
	
}

void	CPt2314WrBass(void)
{
	bit ack = 0;
	BYTE times=5;
	
	WORD base;

#if (_AUDIO_EFFECT_SUPPORT)
	if (GET_AUDIO_EFFECT()==_AUDIO_EFFECT_USER)
		base = stAudioData.Bass;
	else if (GET_AUDIO_EFFECT()==_AUDIO_EFFECT_MOVIE)
		//base = tEEPROM_AUDIO_DATA_MOVIE.Bass;
		base = _AUDIO_EFFECT_MOVIE_BASS;
	else if (GET_AUDIO_EFFECT()==_AUDIO_EFFECT_MUSIC)
		//base = tEEPROM_AUDIO_DATA_MUSIC.Bass;
		base = _AUDIO_EFFECT_MUSIC_BASS;
	else if (GET_AUDIO_EFFECT()==_AUDIO_EFFECT_NEWS)
		//base = tEEPROM_AUDIO_DATA_NEWS.Bass;
		base = _AUDIO_EFFECT_NEWS_BASS;
	else 
		base = stAudioData.Bass;
	
#else
	base = stAudioData.Bass;
#endif
	base *= 15;
	base/=100;


	CPt2314WrProcedure(1, tPt2314BassTrebleMap[base&0x0f] | 0x60, 0);

}

void CPt2314WrBalance(void)
{
	bit ack = 0;
	BYTE times=5;

	BYTE left,right;

//Method 1:
//	<50% decrease L, increase R
//	>50% decrease R, increase L
//	=50% L=R=-6dB
/*
	if (stAudioData.Balance==0)
	{
		left = 0;
	}
	else if (stAudioData.Balance<50)
	{
		left = stAudioData.Balance/10+1;
	}
	else if (stAudioData.Balance<=100)
	{
		left = (stAudioData.Balance-50)/2+6;
	}

	if ((100-stAudioData.Balance)==0)
	{
		right= 0;
	}
	else if ((100-stAudioData.Balance)<50)
	{
		right = (100-stAudioData.Balance)/10+1;
	}
	else if ((100-stAudioData.Balance)<=100)
	{
		right = ((100-stAudioData.Balance)-50)/2+6;
	}
*/
//Method 2:
//	<50% decrease L, R = 0
//	>50% decrease R, L = 0
//	=50% L=R=0dB

	if (stAudioData.Balance<=50)
	{
		left = 0;
	}
	else if (stAudioData.Balance<=100)
	{
		left = ((WORD)(stAudioData.Balance-50) * 31)/50;
	}
	
	if ((100-stAudioData.Balance)<=50)
	{
		right = 0;
	}
	else if ((100-stAudioData.Balance)<=100)
	{
		right = ((WORD)((100-stAudioData.Balance)-50) * 31)/50;
	}

	CPt2314WrProcedure(2, (left&0x1f) | 0xc0, (right&0x1f) | 0xe0);

}


void CPt2314WrAll(void)
{
	bit ack = 0;
	BYTE data times=5;

	CPt2314WrProcedure(2, _AUDIO_VOL_ADDR | 0x3f, 0x43);

	//write mute for earphpne
	CPt2314WrMute(_ENABLE);
	CPt2314WrBass();
	CPt2314WrTreble();
}

void CPt2314WrMute(bit sel)
{
	bit ack = 0;
	BYTE times=5;

    //sel=_DISABLE;
	if (sel==_ENABLE)
	{
		CPt2314WrProcedure(2, 0x1f | _AUDIO_BAL_L_ADDR, 0x1f | _AUDIO_BAL_R_ADDR);
	}
	else
	{
		CPt2314WrBalance();
	}
}

/*
void CPt2314WrSW(BYTE value)
{
	CPt2314Start();
   	CPt2314DataIn(_ADDR_PT2314);
   	CPt2314DataIn(~value&0x1f | 0xe0);
   	CPt2314Stop();
	CTimerDelayXms(10);
}
*/
#if 1//(_AUDIO_CUVRE_SUPPORT)
/*
UINT8 AudioCurve0_9[]=
{
	//0
	63,
	62,
	60,
	57,
	55,	
	53,
	//5
	51,
	49,
	48,
	46,
};
UINT8 AudioCurve10_19[]=
{
	//10
	43,
	30,
};
UINT8 AudioCurve20_29[]=
{
	//20
	29,
	22,
};
UINT8 AudioCurve30_39[]=
{
	//30
	21,
	//10
	17,
};
UINT8 AudioCurve40_49[]=
{
	//40
	16,
	15,
};
UINT8 AudioCurve50_59[]=
{
	//50
	14,
	13,
};
UINT8 AudioCurve60_69[]=
{
	//60
	12,
	11,

};
UINT8 AudioCurve70_79[]=
{
	//70
	10,

	//10
	9,
};
UINT8 AudioCurve80_89[]=
{
	//80
	9,
	8,
};
UINT8 AudioCurve90_99[]=
{
	//90
	7,
	6,	
};
*/
//tv decrease gain
/*
UINT8 code AudioCurve0_9tv[][2]=
{
	// {x, y,}: y for tv source, else is x
	//0
	{63,63,},
	{62,62,},
	{60,60,},
	{57,57,},
	{55,55,},
	{53,53,},
	//5
	{51,51,},
	{49,49+1,},
	{48,48+1,},
	{46,46+2,},
};
UINT8 code AudioCurve10_19tv[][2]=
{
	//10
	{43,43+2,},
	{30,30+3,},
};
UINT8 code AudioCurve20_29tv[][2]=
{
	//20
	{29,29+3,},
	{22,22+3,},
};
UINT8 code AudioCurve30_39tv[][2]=
{
	//30
	{21,21+3,},
	//10
	{17,17+4,},
};
UINT8 code AudioCurve40_49tv[][2]=
{
	//40
	{16,16+4,},
	{15,15+4,},
};
UINT8 code AudioCurve50_59tv[][2]=
{
	//50
	{14,14+4,},
	{13,13+4,},
};
UINT8 code AudioCurve60_69tv[][2]=
{
	//60
	{12,12+4,},
	{11,11+4,},

};
UINT8 code AudioCurve70_79tv[][2]=
{
	//70
	{10,10+4,},

	//10
	{9,9+4,},
};
UINT8 code AudioCurve80_89tv[][2]=
{
	//80
	{9,9+4,},
	{8,8+4,},
};
UINT8 code AudioCurve90_99tv[][2]=
{
	//90
	{7,7+4,},
	{6,6+4,	},
};
*/
UINT8 code AudioCurve0_9tv[][2]=
{
	// {x, y,}: y for tv source, else is x
	//0
	{63,63,},
	{62,62,},
	{60,60,},
	{57,57,},
	{55,55,},
	{53,53,},
	//5
	{51,51,},
	{49-1,49+1-1,},
	{48-2,48+1-1,},
	{46-2,46+2-2,},
};
UINT8 code AudioCurve10_19tv[][2]=
{
	//10
	{43-2,43+2-2,},
	{30-3,30+3-3,},
};
UINT8 code AudioCurve20_29tv[][2]=
{
	//20
	{29-3+4+2+2,29+3-3+4+4,},
	{22-3+4+2+2,22+3-3+4+4,},
};
UINT8 code AudioCurve30_39tv[][2]=
{
	//30
	{21-3+4+2+2,21+3-3+4+4,},
	{17-4+4+2+2,17+4-4+4+4,},
};
UINT8 code AudioCurve40_49tv[][2]=
{
	//40
	{16-4+4+2+2,16+4-4+4+4,},
	{15-4+4+2+2,15+4-4+4+4,},
};
UINT8 code AudioCurve50_59tv[][2]=
{
	//50
	{14-4+4+2+2,14+4-4+4+4,},
	{13-4+4+2+2,13+4-4+4+4,},
};
UINT8 code AudioCurve60_69tv[][2]=
{
	//60
	{12-4+4+2+2,12+4-4+4+4,},
	{11-4+4+2+2,11+4-4+4+4,},

};
UINT8 code AudioCurve70_79tv[][2]=
{
	//70
	{10-4+4+2+2,10+4-4+4+4,},
	{9-4+4+2+2,9+4-4+4+4,},
};
UINT8 code AudioCurve80_89tv[][2]=
{
	//80
	{9-4+4+2,9+4-4+4+4,},
	{8-4+4+2,8+4-4+4+4,},
};
UINT8 code AudioCurve90_99tv[][2]=
{
	//90
	{7-4+4+2,7+4-4+4+4,},
	{6-4+4+2,6+4-4+4+4,	},
};

#endif
//value: 0-100 of slider bar value
UINT8 CPt2314GetCurveValue(UINT8 value)
{
	UINT16 temp;
	UINT8 max,min,num;
	UINT8 src=0;

	if (GET_INPUTPORT_TYPE(stSystemData.InputSource)==_VIDEO_TV_PORT)
		src = 1;
	else
		src = 0;
	
		if (value >= 100)
		{
			temp = AudioCurve90_99tv[1][src];
		}
		else
		{
			if (value<10)
				temp = AudioCurve0_9tv[value][src];
			else{
				if (value<20)
				{
					max = AudioCurve10_19tv[0][src];
					min = AudioCurve10_19tv[1][src];
					num = 10;
				}
				else if (value<30)
				{
					max = AudioCurve20_29tv[0][src];
					min = AudioCurve20_29tv[1][src];
					num =20;
				}
				else if (value<40)
				{
					max = AudioCurve30_39tv[0][src];
					min = AudioCurve30_39tv[1][src];
					num = 30;
				}
				else if (value<50)
				{
					max = AudioCurve40_49tv[0][src];
					min = AudioCurve40_49tv[1][src];
					num = 40;
				}
				else if (value<60)
				{
					max = AudioCurve50_59tv[0][src];
					min = AudioCurve50_59tv[1][src];
					num = 50;
				}
				else if (value<70)
				{
					max = AudioCurve60_69tv[0][src];
					min = AudioCurve60_69tv[1][src];
					num = 60;
				}
				else if (value<80)
				{
					max = AudioCurve70_79tv[0][src];
					min = AudioCurve70_79tv[1][src];
					num = 70;
				}
				else if (value<90)
				{
					max = AudioCurve80_89tv[0][src]; 
					min = AudioCurve80_89tv[1][src];
					num = 80;
				}
				else
				{
					max = AudioCurve90_99tv[0][src];
					min = AudioCurve90_99tv[1][src];
					num = 90;
				}
				temp = max-min;
				temp *= value-num;
				temp /=10;
				temp=max-temp;
			}
		}
	
	return (BYTE)temp;

}

void CAudioSetSourceHook(inputPort)
{
	switch(inputPort)
	{
	
#if _PCB_TYPE==_PCB_PT2662F1A
		case _VIDEO_AV_PORT:
		case _VIDEO_SV_PORT:
			SET_AUDIO_AV();
			break;
			
		case _YPBPR_A0_PORT:
#if _TYPEOF_INPUT==_TYPEOF_INPUT_8SRC
			if (stSystemData.InputSource==3)
			{
				//YPBPR:
				SET_AUDIO_AV();
			}
			else
			{
				//YCBCR for DVD:
				SET_AUDIO_DVD();
			}
#else
			//YCBCR for DVD:
			//SET_AUDIO_DVD();
			//YPBPR:
			SET_AUDIO_AV();
#endif
			break;

#elif _PCB_TYPE==_PCB_PT2662F1C
		case _VIDEO_AV_PORT:
		case _VIDEO_SV_PORT:
			SET_AUDIO_AV();
			break;
			
		case _YPBPR_A0_PORT:
#if _TYPEOF_INPUT==_TYPEOF_INPUT_8SRC
			if (stSystemData.InputSource==3)
			{
				//YPBPR:
				SET_AUDIO_AV();
			}
			else
			{
				//YCBCR for DVD:
				SET_AUDIO_DVD();
			}
#else
			//YCBCR for DVD:
			//SET_AUDIO_DVD();
			//YPBPR:
			SET_AUDIO_AV();
#endif
			break;

#endif

		default:
			break;
	}
}


void CAudioSetSource(BYTE inputPort)
{
	//PT2314
	//-------------
	// 0  TV
	// 1  PC
	// 2  HDMI1/HDMI2
	// 3  AV/SV/YPbPr
	switch(inputPort)
	{
		case _VIDEO_TV_PORT:
			CPt2314WrChSel(0);
			break;
			
		case _DSUB_A0_PORT:
			CPt2314WrChSel(1);
			break;

#if _HDMI_SUPPORT
		case _HDMI_PORT:
		case _HDMI_PORT2:
			CPt2314WrChSel(2);
			break;
#endif			
		case _VIDEO_AV_PORT:
		case _VIDEO_SV_PORT:
		case _YPBPR_A0_PORT:
			CAudioSetSourceHook(inputPort);
			CPt2314WrChSel(3);
			break;
			
		default:
			break;
	}
}

void CAudioSetVolume(UINT8 value)
{
	bit ack = 0;
	UINT8 times=5;
	UINT16 temp;

	static UINT8 valuelast=0;

	if (!value)
	{
		//if (GET_EARPHONE_INSERT())
		//{
			SET_AUDIO_CHIP_MUTE();
			SET_EARPHONE_MUTE();
		//}
	}
	else
	{
		temp = CPt2314GetCurveValue(value);
		
		CPt2314WrProcedure(1, temp&0x3f, 0);

		if (valuelast==0 && value!=0)
		{
			CPt2314WrBalance();
			//20070324,change
			//CLR_AUDIO_CHIP_MUTE();
			//20070330, add
			if (!GET_EARPHONE_INSERT())
			{
				CLR_AUDIO_CHIP_MUTE();
			}
		}
	}
	valuelast = value;

}

void CPt2314WrChSel(BYTE ch)
{
#if _PCB_TYPE == _PCB_JPE_28_A00082_0020
// 0: +11.25db
// 1: +7.5db
// 2: +3.75db
// 3: +0db
#define _AUDIO_INPUT_GAIN_TV		1
#define _AUDIO_INPUT_GAIN_AV		1
#define _AUDIO_INPUT_GAIN_YPBPR	1
#define _AUDIO_INPUT_GAIN_HDMI	1
#define _AUDIO_INPUT_GAIN_VGA		1

	BYTE gain=0;

	//PT2314
	//-------------
	// 0  TV
	// 1  PC
	// 2  HDMI1/HDMI2
	// 3  AV/SV/YPbPr
	switch(GET_INPUTPORT_TYPE(stSystemData.InputSource))
	{
		case _VIDEO_TV_PORT:
			gain = _AUDIO_INPUT_GAIN_TV;
			break;
			
		case _DSUB_A0_PORT:
			gain = _AUDIO_INPUT_GAIN_VGA;
			break;

#if _HDMI_SUPPORT
		case _HDMI_PORT:
		case _HDMI_PORT2:
			gain = _AUDIO_INPUT_GAIN_HDMI;
			break;
#endif			
		case _VIDEO_AV_PORT:
		case _VIDEO_SV_PORT:
			gain = _AUDIO_INPUT_GAIN_AV;
			break;
		case _YPBPR_A0_PORT:
			gain = _AUDIO_INPUT_GAIN_YPBPR;
			break;
			
		default:
			break;
	}

	//modify input gain
	CPt2314WrProcedure(1, 0x40 | (ch &0x03) | (gain<<4), 0);
	
#elif _PCB_TYPE == _PCB_PT2660A1A
// 0: +11.25db
// 1: +7.5db
// 2: +3.75db
// 3: +0db
#define _AUDIO_INPUT_GAIN_TV		1
#define _AUDIO_INPUT_GAIN_AV		1
#define _AUDIO_INPUT_GAIN_YPBPR	1
#define _AUDIO_INPUT_GAIN_HDMI	1
#define _AUDIO_INPUT_GAIN_VGA		1

	BYTE gain=0;
	BYTE gain=0;

	//PT2314
	//-------------
	// 0  TV
	// 1  PC
	// 2  HDMI1/HDMI2
	// 3  AV/SV/YPbPr
	switch(GET_INPUTPORT_TYPE(stSystemData.InputSource))
	{
		case _VIDEO_TV_PORT:
			gain = _AUDIO_INPUT_GAIN_TV;
			break;
			
		case _DSUB_A0_PORT:
			gain = _AUDIO_INPUT_GAIN_VGA;
			break;

#if _HDMI_SUPPORT
		case _HDMI_PORT:
		case _HDMI_PORT2:
			gain = _AUDIO_INPUT_GAIN_HDMI;
			break;
#endif			
		case _VIDEO_AV_PORT:
		case _VIDEO_SV_PORT:
			gain = _AUDIO_INPUT_GAIN_AV;
			break;
		case _YPBPR_A0_PORT:
			gain = _AUDIO_INPUT_GAIN_YPBPR;
			break;
			
		default:
			break;
	}

	//modify input gain
	CPt2314WrProcedure(1, 0x40 | (ch &0x03) | (gain<<4), 0);
	
#else	//#if _PCB_TYPE == _PCB_JPE_28_A00082_0020

	CPt2314WrProcedure(1, 0x40 | (ch &0x03), 0);

#endif	//#if _PCB_TYPE == _PCB_JPE_28_A00082_0020
}


void CPt2314WrVolumeGradual(BYTE value, BYTE gradualDir)
{
	bit ack = 0;
	BYTE data times=5;
	UINT8 i;

	if (stAudioData.Volume==0)
	{
		CPt2314WrMute(_ENABLE);
		CTimerDelayXms(5);
		return;
	}
	else
	{
#if 1//(_AUDIO_CUVRE_SUPPORT)
		value = CPt2314GetCurveValue(value);
#else
		value = 100-stAudioData.Volume;
		value = ((WORD)value*63)/100;	
#endif
	}

	if (gradualDir)
	{
		//inc
		i = 0x3f;
		do {
			times = 5;
			CPt2314WrProcedure(1, i, 0);

			//20080306
			//CTimerDelayXms(5);
			CTimerDelayXms(2);
			i--;
			ack = 0;			
		}while(i>value/*i>=value*/);
		//20070413
		CPt2314WrProcedure(1,value, 0);
	}
	else
	{
		//dec
		do {
			ack = 0;
			times = 5;
			CPt2314WrProcedure(1, value, 0);

			//20080306
			//CTimerDelayXms(5);
			CTimerDelayXms(2);
			value++;
			ack = 0;
			
		}while(value<0x3f/*value<=0x3f*/);
		//20070413
		CPt2314WrProcedure(1,0x3f, 0);
	}
}

void SET_MUTE_PROCESS(bit x)	
{
	if (!x)
	{

//20080104, update JPE LA41012 "POP"
		if (GET_AUDIO_MUTE())
			return;
		
		CAudioSetSource(GET_INPUTPORT_TYPE(stSystemData.InputSource));

		if (stAudioData.Volume)
		{
			CPt2314WrMute(_DISABLE);
			CTimerDelayXms(50);
			CPt2314WrVolumeGradual(stAudioData.Volume, 1);

			CTimerDelayXms(50);
			if (GET_EARPHONE_INSERT())
			{
				SET_AUDIO_CHIP_MUTE();
				CLR_EARPHONE_MUTE();
	 		}
			else
			{
				CLR_AUDIO_CHIP_MUTE();
				SET_EARPHONE_MUTE();
			}
		}
	}
	else
	{
		
		//DebugPrintf("set mute, earphone=%d\n", GET_EARPHONE_INSERT());
		CPt2314WrVolumeGradual(stAudioData.Volume, 0);
		//CPt2314WrMute(_ENABLE);
		SET_AUDIO_CHIP_MUTE();
		SET_EARPHONE_MUTE();
		CTimerDelayXms(50);
	}
}


void CAudioInit(void)
{


	//enable AN7522N
	//premier
	//bAUDIO_AN_EN = 0x1;
	//SET_MUTE_PROCESS(_VOLUME_MUTE_ENABLE);
	SET_AUDIO_CHIP_MUTE();
	SET_EARPHONE_MUTE();

	SET_MUTE_PROCESS(_ENABLE);

	SET_AUDIO_CHIP_STBY(0);
	
	CPt2314WrAll();

	CAudioSetSource(GET_INPUTPORT_TYPE(stSystemData.InputSource));

	//enable PWMA,B
	//premier, mask
	//SET_PWMA_SCA_ENA();
	//SET_PWMB_SCA_ENA();

	//init PWMP,  fpwmp=fosc/(2x(1+PWMP)x255)
	//premier
	//PWMP = 0x00;
	

	//set volume
	//premier mask
	//CAudioSetVolume(stAudioData.Volume);


	//enable PWMA,B output
	//premier, mask
	//SET_PWMA_OUT_ENA();
	//SET_PWMB_OUT_ENA();

	//enabel AN5832SA for SAP decode
}

#endif	//endof #if (_VOLUME_PT2314_SUPPORT)


