www.pudn.com > drivers.rar > peripherals.c


/**************************************************************************** 
Legend R&D Communication Lab 
+--------------------------------------------------------------------+ 
| PROJECT: Poloview Rev.1                 $Workfile:: peripherals.c		$| 
| $Author:  Leo Liu                            $Revision: 0.9				$| 
| CREATED: 11.04.2002                      $Modtime:: 06.06.02 18:50	$| 
+--------------------------------------------------------------------+ 
 
   MODULE  : Baseband & MMI driver 
 
   PURPOSE : This Module implements poloview rev.1 baseband & mmi driver. 
   $Log:: ../driver/board/peripherals.c  
   ---------------------------------------------------------------------------- 
   								HISTORY 
   NOTES: 
	0.x means major version, 0.xx means trifle revision. a means debug verion, b means release version. 
   --------------------------- 
   Ver0.91b 020606 
	Adding four L1 voice band adjust function for engineering mode 
   Ver0.92b 020703 
   	Patch potential bug of adjust melody amp's status. 
	Patch bug of adjust melody light's status. 
	Fix bug of the audio channel switch function. 
	add the compile switch of rvf_trace 
   Ver1.01a 020828 
   	From this version on, it's for poloview2.0 only!!! 
	Add sim cd feature to support new hw filp detect machanism, compatible with 1.0's mmi interface. 
	In this implematation, using GPIO2 for flip status double checking. 
	(FIX ME: in this sim cd, the interrupt will be trigged automaticly once(three times before None-Hisr)  
	sooner after welcome animations over. So mmi have to call flip status check to make sure it will not 
	do any fault. Esp. when close folder before welcome over and auto-swith on conditions!!!) 
  Ver1.01b 020913 
	remove #include nucleus.h and Type define of T_HISR_INFOS into .c file to avoid conflict with cbuild. 
  Ver1.02b 020917 
  	add version ctrl feature. change light/midi drivers to fit pview 2.0 hw design. 
  Ver1.03a 020918 
  	add self voice loop function for engineering mode. need test. 
  Ver1.04a 021011 
  	add support of OKI melody for PCBA3.0. need test 
  Ver1.05a 021021 
  	Change OKI melody interrupt response mode. 
  Ver1.06a 030211 
	Modify audio channel switch function to fit headset mode. 
  Ver1.07a 030226 
  	Adding function to fix "self-resonation" problem when a call income without ringing. 
  Ver1.08a 030307 
  	To match revised audio.c 
  Ver1.10a 030318 
    Fix Headset audio channel switch bug. Known bug is headset audio performance. 
  Ver1.10b 030318 
    Fix HW bug of headset plug out when calling. 
  Ver1.11b 030416 
   Fix "Shout" imcompatible with 086 vertion. 
  Ver1.12a 030421 
   Fix "small mic voice" bug when using headset. 
*****************************************************************************/			  
 
/* FIXME: These operation directly to spi will cause potential conflict. But by using TI's 
   API can avoid these problem --  these api's call riviera to check & OS's mutex semaphore. 
   However I'm to lazy to do any revision of now ;-) */ 
 
/*====================== INCLUDES ===============================*/ 
 
#include "peripherals.h" 
#include "mem.h" 
#include "armio.h" 
#include "spi_drv.h" 
#include "abb.h" 
#include "l1audio_abb.h" 
#include  
#include "nucleus.h" 
 
#include "l1_confg.h" 
#include "audio/audio_api.h" 
#include "inc_audio.h" 
#include "kpd/Kpd_messages_i.h" 
#include "kpd/kpd_env.h" 
#include "bspTwl3029_Aux.h" 
#include "lls/lls_api.h" 
signed short audioParameter; 
 
signed short audioRecParameter = -4;		   /* P710 Edward 2005/06/29 由-9 变为-4  */ 
signed short audioMicParameter = -4 ;              /* P710 Edward 2005/06/29 由零变为-4  */ 
signed short audioHanSpkGainParameter = 5;		/* P710 Edward  2005/06/13 插上耳机后SpeaK Gain 变为3   */ 
signed short audioRecSpkGainParameter = -2;		/* P710 Edward  2005/06/13 没有耳机后SpeaK Gain 变为-2 */ 
//T_AUDIO_AEC_CFG audioAecParameter; 
 
 
// ==========   
typedef struct  
{  NU_HISR  hisr;		 
    char     hisr_stack[512];		 
} T_HISR_INFOS; 
 
T_HISR_INFOS SIM_CD_hisr; 
T_HISR_INFOS SIM_CD_hisr = {0}; 
 
extern void ABB_Audio_Config_3 (UWORD16 data); 
 
/****************************************************************************** 
* $Author       :   LI Xiaohan 05/08/26 
* 
* $Function     :   Enable25Volt 
* 
* $Description  :   在轮询检测hook的机制中,只有为耳机mic加了2.5V电压之后才有 
                    可能正确检测HOOK的存在。此处为HOOK检测而对耳机mic加2.5V电压。 
* 
* $Returns      :   NONE 
* 
* $Arguments    :   NONE 
*******************************************************************************/ 
void Enable25Volt() 
{ 
    SYS_UWORD16 usVBCTRL1; 
    SYS_UWORD16 usVBCTRL2; 
     
    /*usVBCTRL1 = ABB_Read_Register_on_page(PAGE1, VBCTRL1); 
    usVBCTRL2 = ABB_Read_Register_on_page(PAGE1, VBCTRL2); 
 
    DRV_SEND_TRACE_PARAM("VBCTRL1: ", usVBCTRL1, RV_TRACE_LEVEL_DEBUG_HIGH);	// only for trace 
    DRV_SEND_TRACE_PARAM("VBCTRL2: ", usVBCTRL2, RV_TRACE_LEVEL_DEBUG_HIGH);	// only for trace 
 
    if (!(usVBCTRL1 & 0x14) 
        || !(usVBCTRL2 & 0x07)) 
    { 
        DRV_SEND_TRACE("!!!!!!!!!!!!!!!", RV_TRACE_LEVEL_DEBUG_HIGH);	// only for trace 
         
        usVBCTRL1 = 0x14; 
        ABB_Audio_Config(usVBCTRL1); 
        spi_abb_write(PAGE1, VBCTRL1, (unsigned long)(usVBCTRL1)); 
 
        usVBCTRL2 = 0x07; 
	    ABB_Audio_Config_2(usVBCTRL2); 
 	    spi_abb_write(PAGE1, VBCTRL2, (unsigned long)(usVBCTRL2)); 
    }*/ 
} 
 
 
 
/* 
 * MmiDvEnaKpdLt 
 * 返回值	False 0			键盘背光开失败 
 * 			True none zero	键盘背光开成功 
 * 暂时请不要使用返回值 
*/  
SYS_BOOL  MmiDvEnaKpdLt(void) 
{ 
	SYS_UWORD16 ACDLED_Status; 
 
	Set_KbdLight_Mode(1); 
	lls_switch_on(LLS_KEYPAD_LIGHT); //Switch backlight on	 
	lls_switch_on(LLS_SUBKEYPAD_LIGHT); //light sub keypad  
	 
#if 0 
	Set_KbdLight_Mode(1); 
	ACDLED_Status = ABB_Read_Register_on_page(PAGE1, AUXLED); 
	ACDLED_Status |= 0x002; 
	ABB_Write_Register_on_page(PAGE1, AUXLED, ACDLED_Status); 
#endif 
	return 1; 
} 
 
 
 
/* 
 * MmiDvEnaKpdLt 
 * 返回值	False 0			键盘背光关失败 
 * 			True none zero	键盘背光关成功 
 * 暂时请不要使用返回值 
*/  
SYS_BOOL  MmiDvDisKpdLt(void) 
{ 
	Set_KbdLight_Mode(0); 
	lls_switch_off(LLS_KEYPAD_LIGHT); //Switch backlight on	 
	lls_switch_off(LLS_SUBKEYPAD_LIGHT); //light sub keypad  
	 
	#if 0 
	SYS_UWORD16 ACDLED_Status; 
	 
	ACDLED_Status = ABB_Read_Register_on_page(PAGE1, AUXLED); 
	ACDLED_Status &= ~0x002;		// jiangbo.2006/01/06 
	ABB_Write_Register_on_page(PAGE1, AUXLED, ACDLED_Status);	 
 
	Set_KbdLight_Mode(0); 
    #endif 
	return 1; 
}	 
 
 
 
/* 
 * MmiDvIsMdLtOn 
 * 检测是否打开melody lamp 
 * 返回值	False 0	   			Melody LED没有打开 
 *			  True none zero	Melody LED正在发光 
*/ 
SYS_BOOL  MmiDvIsMdLtOn(void) 
{ 
	#if PVIEW1 
	// return	( *((volatile SYS_UWORD8 *) PM_REG) &= 0x01 );		// leo remarked it 020628, &= may cause potential error 
	return	( *((volatile SYS_UWORD8 *) PM_REG) & 0x01 ); 
	#endif 
 
	return 0; 
} 
 
 
 
/* 
 * MmiDvEnaMdLt 
 * 打开灯,打开灯,可以先打开,再设频率; 也可以先设频率,再打开 
 * 返回值	False 0	   Melody LED没有打开 
 *			  True none zero	Melody LED正在发光 
 * 暂时请不要使用返回值 
*/  
  SYS_BOOL  MmiDvEnaMdLt(void) 
{ 
	#if PVIEW1 
	DRV_SEND_TRACE_PARAM("Peripheral: MmiDvEnaMdLt Bfr_Ena ASIC_CFG: ", *((volatile SYS_UWORD16 *) ASIC_CONFIG_REG), RV_TRACE_LEVEL_DEBUG_HIGH);	// only for trace 
	*((volatile SYS_UWORD16 *) ASIC_CONFIG_REG) |= 0x0040;	// set Asic to be LPG not DCD_Modem  
	*((volatile SYS_UWORD8 *) LCR_REG) &= 0xbf;	// reset whole PWM circuit but not control reg 
	*((volatile SYS_UWORD8 *) LCR_REG) |= 0x40;	//  disable reset 
	*((volatile SYS_UWORD8 *) PM_REG) = 0x01;	// enable function colck 
	DRV_SEND_TRACE_PARAM("Peripheral: MmiDvEnaMdLt Aft_Ena LCR_REG: ", *((volatile SYS_UWORD8 *) LCR_REG), RV_TRACE_LEVEL_DEBUG_HIGH);	// only for trace 
	DRV_SEND_TRACE_PARAM("Peripheral: MmiDvEnaMdLt Aft_Ena PM_REG: ", *((volatile SYS_UWORD8 *) PM_REG), RV_TRACE_LEVEL_DEBUG_HIGH);	// only for trace 
	 
	#endif 
 
	return 0; 
} 
 
 
 
/* 
 * MmiDvSetMdLt	 
 * 设定工作方式 
 * BlinkFreq(unit ms): 125,250,500,1000,1500,2000,2500,3000,permanent  
 * MdLtOnTime(unit ms):4,8,16,31,47,63,78,94 
 * 返回值 False 0	  失败 
 *	          True none zero	成功 
 * 暂时请不要使用返回值 
*/  
	SYS_BOOL  MmiDvSetMdLt(SYS_UWORD16 BlinkFreq, SYS_UWORD16 MdLtOnTime) 
{ 
	#if PVIEW1 
	//DRV_SEND_TRACE_PARAM("Peripheral: MmiDvSetMdLt Aft_Rst PM_REG: ", *((volatile SYS_UWORD16 *) PM_REG), RV_TRACE_LEVEL_DEBUG_HIGH);	// only for trace 
	DRV_SEND_TRACE_PARAM("Peripheral: MmiDvSetMdLt In ASIC_CFG: ", *((volatile SYS_UWORD16 *) ASIC_CONFIG_REG), RV_TRACE_LEVEL_DEBUG_HIGH);	// only for trace 
	DRV_SEND_TRACE_PARAM("Peripheral: MmiDvSetMdLt In LCR_REG: ", *((volatile SYS_UWORD8 *) LCR_REG), RV_TRACE_LEVEL_DEBUG_HIGH);	// only for trace 
	DRV_SEND_TRACE_PARAM("Peripheral: MmiDvSetMdLt In PM_REG: ", *((volatile SYS_UWORD8 *) PM_REG), RV_TRACE_LEVEL_DEBUG_HIGH);	// only for trace 
	switch(BlinkFreq){ 
		case	125: 
			*((volatile SYS_UWORD8 *) LCR_REG) &= 0xf8; 
			break; 
		case	250: 
			*((volatile SYS_UWORD8 *) LCR_REG) &= 0xf9; 
			*((volatile SYS_UWORD8 *) LCR_REG) |= 0x01; 
			break; 
		case	500: 
			*((volatile SYS_UWORD8 *) LCR_REG) &= 0xfa; 
			*((volatile SYS_UWORD8 *) LCR_REG) |= 0x02; 
			break; 
		case	1000: 
			*((volatile SYS_UWORD8 *) LCR_REG) &= 0xfb; 
			*((volatile SYS_UWORD8 *) LCR_REG) |= 0x03; 
			break; 
		case	1500: 
			*((volatile SYS_UWORD8 *) LCR_REG) &= 0xfc; 
			*((volatile SYS_UWORD8 *) LCR_REG) |= 0x04; 
			break; 
		case	2000: 
			*((volatile SYS_UWORD8 *) LCR_REG) &= 0xfd; 
			*((volatile SYS_UWORD8 *) LCR_REG) |= 0x05; 
			break; 
		case	2500: 
			*((volatile SYS_UWORD8 *) LCR_REG) &= 0xfe; 
			*((volatile SYS_UWORD8 *) LCR_REG) |= 0x06; 
			break; 
		case	3000: 
			*((volatile SYS_UWORD8 *) LCR_REG) |= 0x07; 
			break; 
		case	permanent: 
		default: 
			*((volatile SYS_UWORD8 *) LCR_REG) |= 0x80; 
			break; 
	} 
	switch(MdLtOnTime){ 
		case	4: 
			*((volatile SYS_UWORD8 *) LCR_REG) &= 0xc7; 
			break; 
		case	8: 
			*((volatile SYS_UWORD8 *) LCR_REG) &= 0xcf; 
			*((volatile SYS_UWORD8 *) LCR_REG) |= 0x08; 
			break; 
		case	16: 
			*((volatile SYS_UWORD8 *) LCR_REG) &= 0xd7; 
			*((volatile SYS_UWORD8 *) LCR_REG) |= 0x10; 
			break; 
		case	31: 
			*((volatile SYS_UWORD8 *) LCR_REG) &= 0xdf; 
			*((volatile SYS_UWORD8 *) LCR_REG) |= 0x18; 
			break; 
		case	47: 
			*((volatile SYS_UWORD8 *) LCR_REG) &= 0xe7; 
			*((volatile SYS_UWORD8 *) LCR_REG) |= 0x20; 
			break; 
		case	63: 
			*((volatile SYS_UWORD8 *) LCR_REG) &= 0xef; 
			*((volatile SYS_UWORD8 *) LCR_REG) |= 0x28; 
			break; 
		case	78: 
			*((volatile SYS_UWORD8 *) LCR_REG) &= 0xf7; 
			*((volatile SYS_UWORD8 *) LCR_REG) |= 0x30; 
			break; 
		case	94: 
		default: 
			*((volatile SYS_UWORD8 *) LCR_REG) |= 0x38; 
			break; 
	} 
	DRV_SEND_TRACE_PARAM("Peripheral: MmiDvSetMdLt Aft_set ASIC_CFG: ", *((volatile SYS_UWORD16 *) ASIC_CONFIG_REG), RV_TRACE_LEVEL_DEBUG_HIGH);	// only for trace 
	DRV_SEND_TRACE_PARAM("Peripheral: MmiDvSetMdLt Aft_set LCR_REG: ",*((volatile SYS_UWORD8 *) LCR_REG),RV_TRACE_LEVEL_DEBUG_HIGH);	// only for trace 
	DRV_SEND_TRACE_PARAM("Peripheral: MmiDvSetMdLt Aft_set PM_REG: ",*((volatile SYS_UWORD8 *) PM_REG),RV_TRACE_LEVEL_DEBUG_HIGH);	// only for trace 
 
	if(!MmiDvIsMdLtOn()) 
		MmiDvEnaMdLt(); 
	return 1;		// temply O.K 
 
	#endif 
 
	return 0; 
} 
 
 
/* 
 * MmiDvDisMdAmp 
 * 关灯 
 * 返回值	False  0	失败 
 *			  True  !0	成功 
 * 请暂时不使用返回值 
*/ 
	SYS_BOOL  MmiDvDisMdLt(void) 
{ 
	#if PVIEW1 
	*((volatile SYS_UWORD8 *) LCR_REG) = 0x00; 
	*((volatile SYS_UWORD8 *) PM_REG) = 0x00; 
	*((volatile SYS_UWORD16 *) ASIC_CONFIG_REG) &= ~(0x0040);	// set Asic to be DCD_MODEM not LPG   
	// return (!MmiDvIsMdLtOn()); 
	#endif 
 
	return 0; 
} 
 
 
 
/* 
 * MmiDvEnaChgLt 
 * 启用充电指示(第一版绿灯)红灯(第二版) 
 * 返回值	False 0		开失败 
 *		      True !0	开成功 
 * 请暂时不使用返回值 
 * This func will be used when system init 
*/ 
SYS_BOOL  MmiDvEnaChgLt(void) 
{ 
	SYS_UWORD16 BCICTL2_Status; 
#if 0 
	BCICTL2_Status = ABB_Read_Register_on_page(PAGE0, BCICTL2); 
	BCICTL2_Status |= 0x020; 
	ABB_Write_Register_on_page(PAGE0, BCICTL2, BCICTL2_Status); 
#endif 
	return 1;			// need test 
} 
 
 
 
/* 
 * MmiDvDisChgLt 
 * 禁用充电指示灯 
 * Only for Baseband debug. Do not call it in MMI sw!!! 
*/ 
SYS_BOOL  MmiDvDisChgLt(void) 
{ 
	SYS_UWORD16 BCICTL2_Status; 
#if 0 
	BCICTL2_Status = ABB_Read_Register_on_page(PAGE0, BCICTL2); 
	BCICTL2_Status &= 0xfdf; 
	ABB_Write_Register_on_page(PAGE0, BCICTL2, BCICTL2_Status); 
#endif 
	return 1;			// need test 
 
} 
 
 
 
/* 
 * MmiDvEnaNetiLt 
 * 启用网络指示灯(第一版蓝灯)第二版绿灯 
 * 返回值	False 0	开失败 
 *			  True !0	开成功 
 *	暂时不使用返回值 
 * This func will be called when system init 
*/ 
SYS_BOOL  MmiDvEnaNetiLt(void) 
{ 
	SYS_UWORD16 ACDLED_Status; 
#if 0 
	ACDLED_Status = ABB_Read_Register_on_page(PAGE1, AUXLED); 
	ACDLED_Status |= 0x001; 
	ABB_Write_Register_on_page(PAGE1,AUXLED, ACDLED_Status); 
	BBDvCtrlPump(Pump_open);	//open charge pump 
#endif 
	return 1;	// need test 
} 
 
 
 
/* 
 * MmiDvDisNetiLt 
 * 禁用网络指示灯 
 * 返回值	False 0	开失败 
 *			True !0	开成功 
 * 暂时不使用返回值 
 * Only for Baseband debug, Do not call it in MMI sw!!! 
 * 
*/ 
SYS_BOOL  MmiDvDisNetiLt(void) 
{ 
	SYS_UWORD16 ACDLED_Status; 
	#if 0 
	ACDLED_Status = ABB_Read_Register_on_page(PAGE1, AUXLED); 
	ACDLED_Status &= ~0x001;		// jiangbo.2006/01/06 
	ABB_Write_Register_on_page(PAGE1,AUXLED, ACDLED_Status); 
#endif 
	return 1; 
} 
 
 
/* 
 * MmiDvFlipStsDet 
 * 判断当前手机所处状态,上盖有无翻开 
 * 返回值: False 0	 已经翻开上盖 
 *			  True none zero  合上(未翻盖) 
 * This function is for MMI sw inqury 
*/ 
/*	inline SYS_BOOL  MmiDvFlipStsDet(void) 
{ 
	#if PVIEW1 
	UWORD8 Flip_status; 
	Flip_status = (*((volatile SYS_UWORD16 *) ARMIO_GPIO_EVENT_MODE ) & 0x0020); 
	return Flip_status; 
	#endif 
 
	return  !MMIDvGetFlipStatus(); 
}*/ 
 
 
 
 
//================== BaseBand Application Specificated Functions================= 
 
/* 
 * IO_hisr_entry 
 * The entry of NU HISR to handle GPIO event int 
 * The priority will be "1" higher than normal kpd's 
*/ 
 
//UINT16 num=0;		//when no MMI_FUNCFION,  add this codes for test. 
extern void CC_OnEarPhonePress(void); 
void IO_hisr_entry( ) 
{ 
	//MMI_CALLBACK_FUNCFION 
	//CC_OnEarPhonePress(); 
	 
/*	//when no MMI_FUNCFION,  add this codes for test. 
	if(num==0){ 
		drvVibStart(100); 
		num=1; 
	}else{ 
		drvVibStop(TRUE);    
		num=0; 
	} 
*/ 
#if 0 
	AI_ConfigBitAsInput(3);   
 	AI_SelectIOForIT (ARMIO_GPIOIRQ, ARMIO_RISING_EDGE);	// low level is midi inquiry signal 
	AI_MaskIT (ARMIO_MASKIT_GPIO);	// the best way is write it in first line of callback function 
    #endif 
} 
 
 
/* 
 * Flip_Detect_IntHandler 
 * 
 * Handle the Flip detect interrupt 
 * Only for Baseband internal operate 
 * CAUTION : MUST NOT BE CALLED BY MMI SW !!! 
*/ 
void	Flip_Detect_IntHandler(void) 
{ 
    #if 0	// this is for poloview1.0 only, using GPIO to be flip detect routine 
	SYS_UWORD8 flip_sts; 
	 
	SYS_UWORD8 Int_Edge; 
	 
	Int_Edge = MmiDvFlipStsDet();		// 0 already open, !0 not open 
	if (Int_Edge)						// if 1, close->open int,now open, will detect falling edge 
		AI_SelectIOForIT (ARMIO_FLIP, ARMIO_FALLING_EDGE); 
	else								// if 0, open->close int, now close,will detect rising edge 
		AI_SelectIOForIT (ARMIO_FLIP, ARMIO_RISING_EDGE); 
 
	GPIO_In_Status = *((volatile SYS_UWORD16 *) GPIO_LATCH_IN);	// reserve GPIO latch in value to determine which GPIO generates interrupt 
 
	AI_UnmaskIT (ARMIO_MASKIT_GPIO);	// the best way is write it in first line of callback function 
	MmiCcFoldProcess (Int_Edge);		// mmi call back func 
 
	 
	flip_sts = MMIDvGetFlipStatus(); 
	#endif      
 
    #if 0 
	AI_UnmaskSIMCD_IT(); 
	//MmiCcFoldProcess (flip_sts);		// mmi call back func 
	rvf_send_event( kpd_env_ctrl_blk->addr_id, EVENT_MASK(RVF_APPL_EVT_0) ) ; 
    #endif 
} 
 
 
/* 
 * BBDvCtrlPump 
 * 控制Chargepump 的开闭 
 * 参数: Pump_open, Pump_close 
 * This function is only for baseband debug 
*/ 
SYS_BOOL	BBDvCtrlPump(SYS_UWORD8 Ctrl_Cmd) 
{ 
	#if PVIEW2 
	int bit = 4; 
	if (Ctrl_Cmd == Pump_open) 
		*((volatile SYS_UWORD16 *) ARMIO_OUT) |= (1< 0); 
	if(sign < 0) 
		s[i++] = '-'; 
	s[i] = '\0'; 
	MmiDvReverse(s); 
}*/ 
 
/* 
 * reverse 
 * reverse a string 
*/ 
/*void MmiDvReverse(char * s) 
{ 
	int c, i, j; 
	for(i=0, j=strlen(s)-1; i 24, it will be automaticly set to 24 
*/  
void L1DvVbULVloCtrl(SYS_WORD8 newvolume) 
{ 
	 ABB_CAL_UlVolume(newvolume); 
} 
 
/* 
 * L1DvVbSideTone 
 * Adjust voice band Sidetone 
 * Sidetone from 0 to 255, 175 is the default(means -5dB) 
 * The sidetone changes every "25",hardware support -23,-20,-17,-14,-11,-8,-5,-2,1,1dB 
 *  
*/ 
void L1DvVbSideTone(SYS_WORD8 sidetone) 
{ 
	ABB_SideTone(sidetone); 
} 
 
/* 
 *	L1EMSelfLoopMode 
 *	For self loop test in engineering mode. The operator press a key and open this mode, when speaking to mic, he'll hear his own  
 *    voice in receiver. 
 *	Parameter: TRUE -- open engineering mode, FALSE -- disable it. 
 */ 
void L1EMSelfLoopMode(SYS_BOOL ctrl) 
{ 
	static unsigned short flag = 0;	      // flag is to indicate LoopMode on of off, flag == 1 means on, then if (ctrl && flag), do nothing 
	static unsigned short VBCR1;		// temply save original 
	static unsigned short VBCR2;		// temply save original 
	static unsigned short VBUR;		// temply save original 
	if(!(ctrl^flag))  // if (ctrl &&flag)||(!ctrl && !flag), need not any operate 
		return;		// arleady enter EM mode, do nothing and return. 
	if(ctrl) 
		{ 
			VBUR = ABB_Read_Register_on_page(PAGE1,VBUCTRL);		// FIX ME:set side tone 1dB? Is it the max??? 
			ABB_Write_Register_on_page(PAGE1,VBUCTRL,((VBUR | 0x00A0) & 0xFEBF)); 
			VBCR1 = ABB_Read_Register_on_page(PAGE1,VBCTRL1);	// up & down link set 
			ABB_Write_Register_on_page(PAGE1,VBCTRL1,((VBCR1 | 0x000A) & 0xFFFB)); 
			VBCR2 = ABB_Read_Register_on_page(PAGE1,VBCTRL2);	// micbias active 
			ABB_Write_Register_on_page(PAGE1,VBCTRL2,(VBCR2 & 0xFFFB)); 
			flag = 1;			// entered EM mode 
		} 
	else		// restore original word 
		{ 
			ABB_Write_Register_on_page(PAGE1,VBUCTRL,VBUR); 
			ABB_Write_Register_on_page(PAGE1,VBCTRL1,VBCR1);			 
			ABB_Write_Register_on_page(PAGE1,VBCTRL2,VBCR2); 
			flag = 0; 
		} 
 
} 
#endif 
 
 
/****************************************************************************** 
* 
* $Author       :   LI Xiaohan 04/11/30 
* 
* $Function     :   audio_load_default_cb 
* 
* $Description  :    
* 
* $Returns      :    
* 
* $Arguments    :    
* 
*******************************************************************************/ 
#if 0 
static void audio_load_default_cb(void *result) 
{ 
	if (((T_AUDIO_LOAD_DONE *) result)->status != AUDIO_OK) 
	{ 
        DRV_SEND_TRACE_PARAM("AUDIO_CB: Defaults load failed ",  
            ((T_AUDIO_SAVE_DONE *) result)->status,  
            RV_TRACE_LEVEL_DEBUG_HIGH); 
	} 
	else 
	{ 
        DRV_SEND_TRACE_PARAM("AUDIO_CB: Defaults load OK", NULL_PARAM,  
            RV_TRACE_LEVEL_DEBUG_HIGH); 
	} 
} 
#endif 
 
/****************************************************************************** 
* 
* $Author       :   LI Xiaohan 04/11/30 
* 
* $Function     :   audio_load_default 
* 
* $Description  :    
* 
* $Returns      :    
* 
* $Arguments    :    
* 
*******************************************************************************/ 
#if 0 
void audio_load_default() 
{ 
#define NOT_PRESENT_16BIT 0xFFFF 
	T_AUDIO_MODE_LOAD audio_mode; 
	T_RV_RETURN ret = {NOT_PRESENT_16BIT, NULL}; 
	T_AUDIO_RET audio_ret; 
 
	ret.callback_func = audio_load_default_cb; 
	strcpy(audio_mode.audio_mode_filename, "audef"); 
	audio_ret = audio_mode_load(&audio_mode, ret); 
 
    if (audio_ret != AUDIO_OK) 
    { 
        DRV_SEND_TRACE_PARAM("AUDIO: Defaults load failed ", audio_ret,  
            RV_TRACE_LEVEL_DEBUG_HIGH); 
    } 
    else 
    { 
        DRV_SEND_TRACE_PARAM("AUDIO: Defaults load OK", NULL_PARAM,  
            RV_TRACE_LEVEL_DEBUG_HIGH); 
    } 
} 
#endif 
 
/****************************************************************************** 
* 
* $Author       :   LI Xiaohan 04/11/30 
* 
* $Function     :   audio_load_default 
* 
* $Description  :   audio_AEC_Enable 
* 
* $Returns      :    
* 
* $Arguments    :    
* 
*******************************************************************************/ 
#if 0 
void audio_AEC_Enable() 
{ 
    #if 0 
    T_AUDIO_FULL_ACCESS_WRITE tAudioWrite; 
    T_AUDIO_AEC_CFG tAecCfg; 
    T_RV_RETURN tRet; 
 
    tAecCfg.aec_enable = AUDIO_AEC_ENABLE; 
    tAecCfg.continuous_filtering = 1; 
    tAecCfg.granularity_attenuation = 0x0014; 
    tAecCfg.smoothing_coefficient = 0x0CCC; 
    tAecCfg.max_echo_suppression_level = AUDIO_MAX_ECHO_12dB; 
    tAecCfg.vad_factor = 0x3700; //0x3800; //0x4000; //0x3450; //0x3700; 
    tAecCfg.absolute_threshold =0x1000; //0x3000; //0x0032; // 0x0100; //0x1000; 
    tAecCfg.factor_asd_filtering = 0x1000;  
    tAecCfg.factor_asd_muting = 0x1000;    
    tAecCfg.aec_visibility = 0x0200; 
    tAecCfg.noise_suppression_enable = AUDIO_NOISE_SUPPRESSION_ENABLE; 
    tAecCfg.noise_suppression_level = AUDIO_NOISE_12dB; 
 
    tAudioWrite.variable_indentifier = AUDIO_MICROPHONE_SPEAKER_LOOP_AEC; 
    tAudioWrite.data = &tAecCfg; 
 
    tRet.callback_func = audio_load_default_cb; 
 
    audio_full_access_write(&tAudioWrite, tRet); 
    #endif 
} 
#endif 
/****************************************************************************** 
* $Function     :   	drvVibStart 
* 
* $Description  :    
*				Enable vibrator.  
*				Can change driver voltage-level&Duty-percent  by bspTwl3029_Aux_VibConfig(). 
* 
* $Param     	:    	 
*				U8 	ucReserve:		nouse. Only for reserve. 
* 
* $return   	:    	None 
* 
* $Author      	:   	fang cj	 06/04/24 
* 
*******************************************************************************/ 
void drvVibStart(U8 ucReserve) 
{ 
	ucReserve; 
	bspTwl3029_Aux_VibConfig(NULL, BSP_TWL3029_VIB_TRIM_VSEL_2_7V,   
		BSP_TWL3029_VIB_TRIM_VSEL_2_7V, BSP_TWL3029_VIB_DUTY_CYCLE_100); 
	 
	bspTwl3029_Aux_VibEnable(NULL, BSP_TWL3029_VIB_ENABLE); 
	return; 
} 
/****************************************************************************** 
* $Function     :   	drvVibStop 
* 
* $Description  :    
*				Disable vibrator.  
*				 
* 
* $Param     	:    	 
*				U8 	ucReserve:		nouse. Only for reserve. 
* 
* $return   	:    	None 
* 
* $Author      	:   	fang cj	 06/04/24 
* 
*******************************************************************************/ 
void drvVibStop(U8 ucReserve) 
{ 
	ucReserve; 
	bspTwl3029_Aux_VibEnable(NULL, BSP_TWL3029_VIB_DISABLE); 
	return; 
}