static void pcmStrmOpenDevice( pcmStrmMediaHdl *ihdl )
{
   MHdl *hdl = (MHdl *)ihdl;

   ihdl->end_status = MEDIA_NONE;
   ihdl->mh.dsp_rb_base = 0;
   mhdlDisallowSleep( (MHdl*)ihdl );

   if( ihdl->pcmStrm.is8KVoice ){
      MHdl *hdl = (MHdl *)ihdl;
      FC_Buf *fcBufHdr;
      hdl->rbInfo.param = (void *)L1Audio_FC_GetAudioBufferHeader();
      L1Audio_FC_WriteBufferToDSP( &hdl->rbInfo );
      fcBufHdr = (FC_Buf *)hdl->rbInfo.param;
      SAC_SphPlayPar.pucRingBuf   = fcBufHdr->pBuf;
      SAC_SphPlayPar.u4RingBufLen = fcBufHdr->uBufLength;
      SAC_SphPlayPar.pucWritePtr  = fcBufHdr->pWrite;
      SAC_SphPlayPar.u4PlyMod     = 1;
      
      SAC_SphPlayPar.u4WbPcm = 0;
      ihdl->mh.fc_aud_id = L1Audio_FC_HookHandler( (void *)ihdl, pcmStrmMsgHandler, 1, 0 );
      if( L1SP_PCMPlayback_CheckFlag() )
         SetSpeechEnhancement(true);//META taste function
      L1Audio_PutMessageAndWait(MSG_L1AUDIO2FAS_SPEECH_IDLE_PLAY_START, ihdl->mh.fc_aud_id, (kal_uint32)&SAC_SphPlayPar, KAL_TRUE );
      
      AM_PCM8K_PlaybackOn( );
   } else {
      hdl->rbInfo.fc_format = FC_MEDIA_FORMAT_PCM;
      hdl->rbInfo.fc_operation = MEDIA_OPERATE_PLAYBACK;
      {
         kal_uint16 msg16;
         
         msg16 = (hdl->rbInfo.fc_format << 8) | hdl->rbInfo.fc_operation;
         hdl->fc_aud_id = L1Audio_FC_HookHandler( (void *)hdl, pcmStrmMsgHandler, 0, msg16 );
      }
      
#if __DRIVER_PRESERVE_DSP_SHARE_BUFFER__
      ihdl->mh.rbInfo.param = (void *)L1Audio_FC_GetAudioBufferHeader();
#endif
         
      // Fill bitstream information to FC
      {
         FC_Buf *fcBufHdr = (FC_Buf *)ihdl->mh.rbInfo.param;
         
         fcBufHdr->uTime = ihdl->mh.start_time;
         fcBufHdr->uSamplingFreq = ihdl->pcmStrm.sampleFreq;
         fcBufHdr->uChannelNum = ihdl->pcmStrm.isStereo + 1;
      }
      
      L1Audio_FC_AudioPlaybackOn(ihdl->mh.fc_aud_id, &ihdl->mh.rbInfo);
      AM_AudioPlaybackOn( ASP_TYPE_PCM_HI, ihdl->pcmStrm.freqType );
   }
}
static void pcmStrmCloseDevice( MHdl *hdl )
{
   pcmStrmMediaHdl *ihdl = (pcmStrmMediaHdl *)hdl;
   if ( ihdl->pcmStrm.is8KVoice ) {
      if( L1SP_PCMPlayback_CheckFlag() )
         SetSpeechEnhancement(false);//META taste function
      L1Audio_PutMessageAndWait(MSG_L1AUDIO2FAS_SPEECH_IDLE_PLAY_STOP, ihdl->mh.fc_aud_id, 0, KAL_TRUE );
      L1Audio_FC_ReleaseAudioBufferHeader( (FC_Buf **) &hdl->rbInfo.param );
      L1Audio_FC_UnHookHandler(ihdl->mh.fc_aud_id, 1);
      AM_PCM8K_PlaybackOff( true );
   }else{
      L1Audio_FC_AudioPlaybackOff(hdl->fc_aud_id);
      L1Audio_FC_ReleaseAudioBufferHeader( (FC_Buf **) &hdl->rbInfo.param );
      L1Audio_FC_UnHookHandler(hdl->fc_aud_id, 0);
      AM_AudioPlaybackOff( true );
   }
   mhdlAllowSleep( hdl );
}
void PcmEx_Stop(void)
{
	
	ASSERT( PNW_STATE_RUN == pcmEx.state); 

	if(true == pcmEx.isEnhOn) {
		SetSpeechEnhancement(false);
	}

   /* the begining of configure the SAL */ 
	ASSERT(SAL_PcmEx_CheckStateUL(SAL_PCMEX_TYPE_PNW, SAL_PCMEX_OFF) || SAL_PcmEx_CheckStateUL(SAL_PCMEX_TYPE_PNW, SAL_PCMEX_RDY));
	ASSERT(SAL_PcmEx_CheckStateDL(SAL_PCMEX_TYPE_PNW, SAL_PCMEX_OFF) || SAL_PcmEx_CheckStateDL(SAL_PCMEX_TYPE_PNW, SAL_PCMEX_RDY));
               
   SAL_PcmEx_SetStateUL(SAL_PCMEX_TYPE_PNW, SAL_PCMEX_OFF);
   SAL_PcmEx_SetStateDL(SAL_PCMEX_TYPE_PNW, SAL_PCMEX_OFF);

   AM_PCM_EX_Off(pcmEx.am_type, (uint32)(&pcmEx));
   
   L1Audio_UnhookHisrHandler(DP_D2C_PCM_EX_DL); 
   L1Audio_UnhookHisrHandler(DP_D2C_PCM_EX_UL); 
	
   L1Audio_ClearFlag( pcmEx.aud_id );
   L1Audio_FreeAudioID( pcmEx.aud_id );   

	// set to default. 
   pcmEx.pnw_dl_hdlr = pcmEx.pnw_ul_hdlr = NULL;
	pcmEx.cfgUL1 = 0;
	pcmEx.cfgUL2 = 0;
	pcmEx.cfgUL3 = 0;
	pcmEx.cfgUL4 = 0;
	pcmEx.cfgDL = 0;

	// pcmEx.dspPcmExMicLen = 0; 
	// pcmEx.dspPcmExSpkLen = 0;

   pcmEx.bandInfo = PCMEX_BAND_UNSET;	
   pcmEx.am_type  = AM_PCMEX_TYPE_UNDEF;   
				
   pcmEx.state = PNW_STATE_IDLE;        
   
   
}
/**

@pcmNway_dl_hdlr
@pcmNway_ul_hdlr: 
*/
void Idle_PcmEx_Start(void (*pcmNway_dl_hdlr)(void), void (*pcmNway_ul_hdlr)(void), 
	uint32 cfgUL1, uint32 cfgUL2, uint32 cfgUL3, uint32 cfgUL4, uint32 cfgDL,
	PCMEX_BAND band, PCMEX_IDLE_ENH_SETTING enhSetting)
{
   uint32 I;
   kal_bool flag;

	// prevent re-entry!! 
 	ASSERT(PNW_STATE_IDLE == pcmEx.state); 
 
   pcmEx.aud_id = L1Audio_GetAudioID();
   L1Audio_SetFlag( pcmEx.aud_id );      /*Be careful.Before Locking SleepMode, to access DSP sherrif tasks much time. So access DSP must be after SetFlag*/

	// band and am type setting
	pcmEx.bandInfo = band;	
	switch(band){
		case PCMEX_BAND_NB:
		{
			ASSERT(enhSetting != PCMEX_IDLE_ENH_SETTING_NONE);
			
			if(PCMEX_IDLE_ENH_SETTING_DMNR_REC_ONLY_CAL == enhSetting) {
				// pcmEx.dspPcmExMicLen = 322; //160*2+2 samples(word)
				// pcmEx.dspPcmExSpkLen = -1; 		
				pcmEx.am_type = AM_PCMEX_TYPE_REC_ONLY_CAL;
			}
			else if (PCMEX_IDLE_ENH_SETTING_DMNR_CAL == enhSetting) {
				// pcmEx.dspPcmExMicLen = 322; //160*2+2 samples(word)
				// pcmEx.dspPcmExSpkLen = 160; 
				pcmEx.am_type = AM_PCMEX_TYPE_REC_PLAY_CAL;
		
			} else {
				// pcmEx.dspPcmExMicLen = 160;
				// pcmEx.dspPcmExSpkLen = 160;
				pcmEx.am_type = AM_PCMEX_TYPE_IDLE;
			}
		}
			break;
		case PCMEX_BAND_WB:
		{
			ASSERT(enhSetting != PCMEX_IDLE_ENH_SETTING_NONE);
			
			if(PCMEX_IDLE_ENH_SETTING_DMNR_REC_ONLY_CAL == enhSetting) {
				// pcmEx.dspPcmExMicLen = 642; //320*2+2 samples(word)
				// pcmEx.dspPcmExSpkLen = -1; 		
				pcmEx.am_type = AM_PCMEX_TYPE_REC_ONLY_CAL;
			}
			else if (PCMEX_IDLE_ENH_SETTING_DMNR_CAL == enhSetting) {
				// pcmEx.dspPcmExMicLen = 642; //320*2+2 samples(word)
				// pcmEx.dspPcmExSpkLen = 160;
				pcmEx.am_type = AM_PCMEX_TYPE_REC_PLAY_CAL;
		
			} else {
				// pcmEx.dspPcmExMicLen = 320;
				// pcmEx.dspPcmExSpkLen = 320;
				pcmEx.am_type = AM_PCMEX_TYPE_IDLE;
			}
		}
			break;
		default: // include PCMEX_BAND_DYNAMIC and PCMEX_BAND_UNSET cases
			ASSERT(0);
	}
 	pcmEx.cfgUL1 = cfgUL1;
	pcmEx.cfgUL2 = cfgUL2;
	pcmEx.cfgUL3 = cfgUL3;
	pcmEx.cfgUL4 = cfgUL4;
	pcmEx.cfgDL = cfgDL; 
	
	pcmEx.pnw_dl_hdlr = pcmNway_dl_hdlr; 
	pcmEx.pnw_ul_hdlr = pcmNway_ul_hdlr; 
	
   L1Audio_HookHisrHandler(DP_D2C_PCM_EX_DL,(L1Audio_EventHandler)pcmEx_hisrDlHdlr, 0);
   L1Audio_HookHisrHandler(DP_D2C_PCM_EX_UL,(L1Audio_EventHandler)pcmEx_hisrUlHdlr, 0);

	// check DSP state and turn on 
   ASSERT(SAL_PcmEx_CheckStateUL(SAL_PCMEX_TYPE_PNW, SAL_PCMEX_OFF) && SAL_PcmEx_CheckStateDL(SAL_PCMEX_TYPE_PNW, SAL_PCMEX_OFF));
   AM_PCM_EX_On(pcmEx.am_type, (uint32)(&pcmEx));//to config pnw

   SAL_PcmEx_SetStateUL(SAL_PCMEX_TYPE_PNW, SAL_PCMEX_ON);
   SAL_PcmEx_SetStateDL(SAL_PCMEX_TYPE_PNW, SAL_PCMEX_ON);  

	// wait for ready
   for(I = 0; ;I ++){
      kal_bool is_ready = true;

      if( (pcmEx.cfgDL & (USE_D2M_PATH+USE_M2D_PATH)) && (!SAL_PcmEx_CheckStateDL(SAL_PCMEX_TYPE_PNW, SAL_PCMEX_RDY)))
         is_ready &= false;
      if( (pcmEx.cfgUL1 & (USE_D2M_PATH+USE_M2D_PATH)) && (!SAL_PcmEx_CheckStateUL(SAL_PCMEX_TYPE_PNW, SAL_PCMEX_RDY)))
         is_ready &= false;    
		
      if(is_ready)
         break;
#ifndef L1D_TEST
      ASSERT(I < 22);  // wait 200ms  
      kal_sleep_task(2);
#endif
   }      
	
   pcmEx.state = PNW_STATE_RUN;

	if(PCMEX_IDLE_ENH_SETTING_WITH == enhSetting) {
		pcmEx.isEnhOn = true;
		SetSpeechEnhancement(true);
	}
   
   /* the end of configure the SAL */             
}