[Feature]Upload Modem source code

Change-Id: Id4294f30faced84d3e6fd6d5e61e1111bf287a37
diff --git a/mcu/driver/audio/src/v1/vm.c b/mcu/driver/audio/src/v1/vm.c
new file mode 100644
index 0000000..d310759
--- /dev/null
+++ b/mcu/driver/audio/src/v1/vm.c
@@ -0,0 +1,2772 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ *
+ * Filename:
+ * ---------
+ * vm.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   VM recording/playback
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#include "kal_public_api.h"
+#include "kal_general_types.h"
+#include "string.h"
+#include "reg_base.h"
+#include "kal_trace.h"
+
+#include "speech_def.h"
+#include "l1aud_common_def.h"
+#include "l1audio.h"
+#include "l1audio_trace_utmd.h"
+#include "l1audio_voc_utmd.h"
+#include "sp_drv.h"
+#include "pcm4way.h"
+#include "am.h"
+#include "media.h"
+#include "afe.h"
+#include "l1sp_trc.h"
+#include "l1audio_sph_trc.h"
+#include "sal_exp.h"
+#include "sal_def.h"
+#include "vm.h"
+#include "gmss_public.h"
+
+/* ------------------------------------------------------------------------------ */
+#define VM_4G_G_SERIAL_DEBUG
+
+#if defined( __UMTS_RAT__ )
+#define _EXTRA_LOG_FOR_BIT_TRUE_
+#endif
+
+#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
+extern kal_bool g_bNeedExtraLog;
+#endif
+
+/* ------------------------------------------------------------------------------ */
+#define VM_STATE_RECORD       0x1
+#define VM_STATE_STOP         0x10
+#define VM_STATE_RECORD_STOP  0x20 // entering vmStop
+
+#define VM_VM_MAGIC_HEADER 0xBB88
+
+#define VM_VM_CTRL_UL_ON   0x0001
+#define VM_VM_CTRL_DL_ON   0x0001
+
+#define VM_EPL_1STSET_RECORD_FLAG      0x0001
+#define VM_EPL_2NDSET_RECORD_FLAG      0x0002
+#define VM_VM_RECORD_FLAG              0x0004
+#define VM_EPL_REFMIC_RECORD_FLAG      0x0008
+#define VM_EPL_ECHOREF_RECORD_FLAG     0x0010
+#define VM_EPL_3RDMIC_RECORD_FLAG      0x0020
+#define VM_EPL_2NDECHOREF_RECORD_FLAG  0x0040
+#define VM_EPL_ALL_RECORD_FLAG (VM_EPL_1STSET_RECORD_FLAG + VM_EPL_2NDSET_RECORD_FLAG + VM_EPL_REFMIC_RECORD_FLAG + VM_EPL_ECHOREF_RECORD_FLAG + VM_EPL_3RDMIC_RECORD_FLAG + VM_EPL_2NDECHOREF_RECORD_FLAG)
+
+#define VM_EPL_BAND_UL0_SHIFT  0
+#define VM_EPL_BAND_UL1_SHIFT  2
+#define VM_EPL_BAND_DL0_SHIFT  4
+#define VM_EPL_BAND_DL1_SHIFT  6
+#define VM_EPL_BAND_UL2_SHIFT  8
+#define VM_EPL_BAND_UL4_SHIFT 10
+#define VM_EPL_BAND_UL3_SHIFT 12
+#define VM_EPL_BAND_UL5_SHIFT 14
+
+#define VM_VM_HEADER_SIZE               6
+#define VM_VM_CONTROL_SIZE             10
+#define VM_VM_MAX_HB_WORD_SIZE ((160+2)*3)   // EVS_128000: 2560 bits = 160 words, UL + DL + DL2
+
+#define VM_VM_SCH_DBGINFO_SIZE        100
+#define VM_VM_ENH_DBGINFO_SIZE        160
+#define VM_VM_DRV_DBGINFO_SIZE         20
+#define VM_VM_SVC_DBGINFO_SIZE         20
+#define VM_VM_DBGINFO_TOTAL_SIZE (VM_VM_SCH_DBGINFO_SIZE + VM_VM_ENH_DBGINFO_SIZE + VM_VM_DRV_DBGINFO_SIZE + VM_VM_SVC_DBGINFO_SIZE)
+
+#define VM_VM_BUFFER_SIZE (VM_VM_HEADER_SIZE + VM_VM_CONTROL_SIZE + VM_VM_MAX_HB_WORD_SIZE + VM_VM_DBGINFO_TOTAL_SIZE)
+
+#define VM_EPL_1STSET_SIZE      (SAL_FB_PCM_SIZE + SAL_FB_PCM_SIZE + 2)
+#define VM_EPL_2NDSET_SIZE      (SAL_FB_PCM_SIZE + SAL_FB_PCM_SIZE + 2)
+#define VM_EPL_REFMIC_SIZE      (SAL_FB_PCM_SIZE + 2 + 2)
+#define VM_EPL_ECHOREF_SIZE     (SAL_FB_PCM_SIZE + 2)
+#define VM_EPL_3RDMIC_SIZE      (SAL_FB_PCM_SIZE + 2)
+#define VM_EPL_2NDECHOREF_SIZE  (SAL_FB_PCM_SIZE + 2)
+
+#define VM_EPL_PCM_BUFFER_SIZE   VM_EPL_1STSET_SIZE
+#define VM_EPL_TOTAL_SIZE       (VM_EPL_1STSET_SIZE + VM_EPL_2NDSET_SIZE + VM_EPL_REFMIC_SIZE + VM_EPL_ECHOREF_SIZE + VM_EPL_3RDMIC_SIZE + VM_EPL_2NDECHOREF_SIZE)
+
+#if defined(__G_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+#define G_CODEC_UL_INFO_HEADER_MAGIC_NUMBER (0x6666)
+#define G_CODEC_DL_INFO_HEADER_MAGIC_NUMBER (0x6667)
+//G.722 bitstream 20ms 160byte
+//G.711 bitstream 10ms  80byte
+//store max 4frame
+#define G_CODEC_MAX_FRAME_NUMBER (4)
+//stream_size+stream
+#define G_CODEC_BITSTREAM_BUFFER_BYTE_SIZE (1*2+80)
+//lost_info + system_time + codec + codec_parameters
+#define G_CODEC_UL_INFO_BYTE_SIZE (4*2)
+//lost_info + system_time + codec + codec_parameters + DL_PCM_buffer_size
+#define G_CODEC_DL_INFO_BYTE_SIZE (5*2)
+//header_magic_number+info_size+info_struct
+#define G_CODEC_UL_INFO_TOTAL_BYTE_SIZE (2*2+G_CODEC_UL_INFO_BYTE_SIZE)
+//header_magic_number+info_size+info_struct
+#define G_CODEC_DL_INFO_TOTAL_BYTE_SIZE (2*2+G_CODEC_DL_INFO_BYTE_SIZE)
+//total byte size
+#define G_CODEC_UL_BITSTREAM_TOTAL_BYTE_SIZE ((G_CODEC_UL_INFO_TOTAL_BYTE_SIZE+G_CODEC_BITSTREAM_BUFFER_BYTE_SIZE)*G_CODEC_MAX_FRAME_NUMBER)
+#define G_CODEC_DL_BITSTREAM_TOTAL_BYTE_SIZE ((G_CODEC_DL_INFO_TOTAL_BYTE_SIZE+G_CODEC_BITSTREAM_BUFFER_BYTE_SIZE)*G_CODEC_MAX_FRAME_NUMBER)
+#endif //#if defined(__G_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+
+#if defined(__G_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+#define G_CODEC_MAX_HB_WORD_SIZE (((G_CODEC_UL_BITSTREAM_TOTAL_BYTE_SIZE+1)>>1) + ((G_CODEC_DL_BITSTREAM_TOTAL_BYTE_SIZE+1)>>1))
+//#define VMREC_OUTPUT_BUF_SIZE (2 * (VM_VM_BUFFER_SIZE + VM_EPL_TOTAL_SIZE + G_CODEC_MAX_HB_WORD_SIZE))
+#define VMREC_OUTPUT_BUF_SIZE 8000  // [REMIND] Please notify AP speech owner when vm buffer change
+#else
+//#define VMREC_OUTPUT_BUF_SIZE (2 * (VM_VM_BUFFER_SIZE + VM_EPL_TOTAL_SIZE))
+#define VMREC_OUTPUT_BUF_SIZE 8000  // [REMIND] Please notify AP speech owner when vm buffer change
+#endif
+
+#define VM_3G_NETWORK_INFO_LEN 7
+
+/* ------------------------------------------------------------------------------ */
+static struct
+{
+    kal_spinlockid lockId;
+    void (*vm_hdlr)(void);  // callback function for vm logging
+    bool isVocOn;           // only use under call AM_IsSpeechOn()
+    bool isVmLOn;           // only use under call AM_IsSpeechOn()
+    bool isMosaic;
+
+    uint16   audId;
+    uint16   state;         // record DSP  runnning status (including 2 hisr)
+
+    uint16   record_info;   // record flag, only use to control EPL record though it also has VM record flag
+
+    uint16   control_1;
+    uint16   control_2;
+    uint16   control_3;
+    uint16   control_4;
+    uint16   control_5;
+    uint16   control_6;
+    uint16   control_7;
+    uint16   control_8;
+    uint16   control_9;
+    uint16   control_10;
+
+    uint16   evs_cur_sd_mode;
+    uint16   sc_len;
+    uint16   sd_len;          // sd1_len + sd2_len
+
+    uint16   vm_lost_count;   // For record EPL dummy
+    uint16   pcm_lost_count;  // For record EPL dummy
+    uint16   vm_counter;      // For record EPL dummy
+
+    uint16   *vmBuf;    // point to buffer for VM
+    uint16   *pcmBuf;   // point to temp buffer to get EPL from DSP in N times
+
+    // related to 'vmRecOutputBuf', which is cycular buffer use to buffer formatted vm data from dsp
+    uint16 pOutputBufWrite;
+    uint16 pOutputBufRead;
+    uint16 outputBufSize;
+} vm;
+
+uint16 vm3GNetworkInfo[VM_3G_NETWORK_INFO_LEN];
+
+static kal_uint16 vmBuffer[VM_VM_BUFFER_SIZE];
+static kal_uint16 vmEPLPCMInputBuf[VM_EPL_PCM_BUFFER_SIZE];
+static kal_uint16 vmRecOutputBuf[VMREC_OUTPUT_BUF_SIZE];
+
+#if defined(__G_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+static kal_uint32 vmGCodecULBitstreamBuf[(G_CODEC_UL_BITSTREAM_TOTAL_BYTE_SIZE + 3) / sizeof(kal_uint32)];
+static kal_uint32 vmGCodecDLBitstreamBuf[(G_CODEC_DL_BITSTREAM_TOTAL_BYTE_SIZE + 3) / sizeof(kal_uint32)];
+static kal_uint32 vmGCodecULBufWritePos;
+static kal_uint32 vmGCodecDLBufWritePos;
+static kal_uint32 vmGCodecULBufLastHeaderPos;
+static kal_uint32 vmGCodecDLBufLastHeaderPos;
+static kal_uint16 *p16vmGCodecULBitstreamBuf;
+static kal_uint16 *p16vmGCodecDLBitstreamBuf;
+#endif
+
+/* ------------------------------------------------------------------------------ */
+#if defined(__G_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+void vmInitGCodecULBuf(void)
+{
+    //memset(vmGCodecULBitstreamBuf, 0, sizeof(vmGCodecULBitstreamBuf));
+    p16vmGCodecULBitstreamBuf = (kal_uint16 *)vmGCodecULBitstreamBuf;
+    vmGCodecULBufWritePos = 0;
+    vmGCodecULBufLastHeaderPos = 0;
+}
+
+void vmInitGCodecDLBuf(void)
+{
+    //memset(vmGCodecDLBitstreamBuf, 0, sizeof(vmGCodecDLBitstreamBuf));
+    p16vmGCodecDLBitstreamBuf = (kal_uint16 *)vmGCodecDLBitstreamBuf;
+    vmGCodecDLBufWritePos = 0;
+    vmGCodecDLBufLastHeaderPos = 0;
+}
+#endif //#if defined(__G_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+
+void vmStoreGCodecULStream(vmGCodecULInfo *pstvmGCodecULInfo, kal_uint16 u16StreamSize, kal_uint8 *pu8StreamData)
+{
+#if defined(__G_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+    kal_uint32 u32TotalBufferSize = sizeof(vmGCodecULBitstreamBuf) >> 1;
+    //bytesize: G_CODEC_UL_INFO_TOTAL_BYTE_SIZE + stream_size + stream_data[]
+    //>>1 => 2byte size
+    kal_uint32 u32NeedSize = (G_CODEC_UL_INFO_TOTAL_BYTE_SIZE + 2 + u16StreamSize + 1) >> 1;
+    kal_uint32 i, j;
+    kal_uint16 u16tempData;
+
+#ifdef VM_4G_G_SERIAL_DEBUG
+    MD_TRC_VM_GFORM_ULSTREAM_ENTER();
+#endif //#ifdef VM_4G_G_SERIAL_DEBUG
+
+    // dsp status check
+    if (vm.state != VM_STATE_RECORD)
+    {
+        return;
+    }
+
+    // application status check
+    if ( (false == vm.isVocOn) && (false == vm.isVmLOn)) // (false == vm.isIdleVmOn) &&
+    {
+        return;
+    }
+
+#ifdef VM_4G_G_SERIAL_DEBUG
+    MD_TRC_VM_GFORM_ULSTREAM_INFO1(u32TotalBufferSize, vmGCodecULBufWritePos, ((u16StreamSize + 1) >> 1), u16StreamSize);
+#endif //#ifdef VM_4G_G_SERIAL_DEBUG
+
+    if ( (u32TotalBufferSize - vmGCodecULBufWritePos) >= u32NeedSize )
+    {
+        vmGCodecULBufLastHeaderPos = vmGCodecULBufWritePos;
+
+        p16vmGCodecULBitstreamBuf[vmGCodecULBufWritePos] = G_CODEC_UL_INFO_HEADER_MAGIC_NUMBER;
+        vmGCodecULBufWritePos++;
+        p16vmGCodecULBitstreamBuf[vmGCodecULBufWritePos] = G_CODEC_UL_INFO_BYTE_SIZE >> 1;
+        vmGCodecULBufWritePos++;
+        p16vmGCodecULBitstreamBuf[vmGCodecULBufWritePos] = pstvmGCodecULInfo->drop_info;
+        vmGCodecULBufWritePos++;
+        p16vmGCodecULBitstreamBuf[vmGCodecULBufWritePos] = (kal_uint16)(ust_get_current_time() / 1000); //ust_get_current_time(): unit is micro second (us) => ust_get_current_time()/1000: unit is ms
+        vmGCodecULBufWritePos++;
+        p16vmGCodecULBitstreamBuf[vmGCodecULBufWritePos] = pstvmGCodecULInfo->codec;
+        vmGCodecULBufWritePos++;
+        p16vmGCodecULBitstreamBuf[vmGCodecULBufWritePos] = pstvmGCodecULInfo->codec_parameters;
+        vmGCodecULBufWritePos++;
+        p16vmGCodecULBitstreamBuf[vmGCodecULBufWritePos] = u16StreamSize;
+        vmGCodecULBufWritePos++;
+        j = 0;
+        for (i = 0; i < (u16StreamSize >> 1); i++)
+        {
+            u16tempData = pu8StreamData[j];
+            j++;
+            u16tempData = (u16tempData << 8) | pu8StreamData[j];
+            j++;
+            p16vmGCodecULBitstreamBuf[vmGCodecULBufWritePos] = u16tempData;
+            vmGCodecULBufWritePos++;
+        }
+        if (u16StreamSize & 0x01)
+        {
+            u16tempData = pu8StreamData[j];
+            u16tempData = (u16tempData << 8) | u16tempData;
+            p16vmGCodecULBitstreamBuf[vmGCodecULBufWritePos] = u16tempData;
+            vmGCodecULBufWritePos++;
+        }
+    }
+    else
+    {
+        MD_TRC_VM_GFORM_ULSTREAM_INFO2(u32NeedSize, u32TotalBufferSize - vmGCodecULBufWritePos);
+        if (vmGCodecULBufWritePos != 0)
+        {
+            p16vmGCodecULBitstreamBuf[vmGCodecULBufLastHeaderPos + 2] += 0x0100;
+        }
+        else
+        {
+            MD_TRC_VM_GFORM_ULSTREAM_INFO3(u32NeedSize, u32TotalBufferSize);
+        }
+    }
+
+#ifdef VM_4G_G_SERIAL_DEBUG
+    MD_TRC_VM_GFORM_ULSTREAM_EXIT();
+#endif //#ifdef VM_4G_G_SERIAL_DEBUG
+#endif //#if defined(__G_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+}
+
+void vmStoreGCodecDLStream(vmGCodecDLInfo *pstvmGCodecDLInfo, kal_uint16 u16StreamSize, kal_uint8 *pu8StreamData)
+{
+#if defined(__G_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+    kal_uint32 u32TotalBufferSize = sizeof(vmGCodecDLBitstreamBuf) >> 1;
+    //bytesize: G_CODEC_DL_INFO_TOTAL_BYTE_SIZE + stream_size + stream_data[]
+    //>>1 => 2byte size
+    kal_uint32 u32NeedSize = (G_CODEC_DL_INFO_TOTAL_BYTE_SIZE + 2 + u16StreamSize + 1) >> 1;
+    kal_uint32 i, j;
+    kal_uint16 u16tempData;
+
+#ifdef VM_4G_G_SERIAL_DEBUG
+    MD_TRC_VM_GFORM_DLSTREAM_ENTER();
+#endif //#ifdef VM_4G_G_SERIAL_DEBUG
+
+    // dsp status check
+    if (vm.state != VM_STATE_RECORD)
+    {
+        return;
+    }
+
+    // application status check
+    if (  (false == vm.isVocOn) && (false == vm.isVmLOn)) // (false == vm.isIdleVmOn) &&
+    {
+        return;
+    }
+
+#ifdef VM_4G_G_SERIAL_DEBUG
+    MD_TRC_VM_GFORM_DLSTREAM_INFO1(u32TotalBufferSize, vmGCodecDLBufWritePos, ((u16StreamSize + 1) >> 1), u16StreamSize);
+#endif //#ifdef VM_4G_G_SERIAL_DEBUG
+
+    if ( (u32TotalBufferSize - vmGCodecDLBufWritePos) >= u32NeedSize )
+    {
+        vmGCodecDLBufLastHeaderPos = vmGCodecDLBufWritePos;
+
+        p16vmGCodecDLBitstreamBuf[vmGCodecDLBufWritePos] = G_CODEC_DL_INFO_HEADER_MAGIC_NUMBER;
+        vmGCodecDLBufWritePos++;
+        p16vmGCodecDLBitstreamBuf[vmGCodecDLBufWritePos] = G_CODEC_DL_INFO_BYTE_SIZE >> 1;
+        vmGCodecDLBufWritePos++;
+        p16vmGCodecDLBitstreamBuf[vmGCodecDLBufWritePos] = pstvmGCodecDLInfo->drop_info;
+        vmGCodecDLBufWritePos++;
+        p16vmGCodecDLBitstreamBuf[vmGCodecDLBufWritePos] = (kal_uint16)(ust_get_current_time() / 1000); //ust_get_current_time(): unit is micro second (us) => ust_get_current_time()/1000: unit is ms
+        vmGCodecDLBufWritePos++;
+        p16vmGCodecDLBitstreamBuf[vmGCodecDLBufWritePos] = pstvmGCodecDLInfo->codec;
+        vmGCodecDLBufWritePos++;
+        p16vmGCodecDLBitstreamBuf[vmGCodecDLBufWritePos] = pstvmGCodecDLInfo->codec_parameters;
+        vmGCodecDLBufWritePos++;
+        p16vmGCodecDLBitstreamBuf[vmGCodecDLBufWritePos] = pstvmGCodecDLInfo->DL_PCM_size;
+        vmGCodecDLBufWritePos++;
+        p16vmGCodecDLBitstreamBuf[vmGCodecDLBufWritePos] = u16StreamSize;
+        vmGCodecDLBufWritePos++;
+        j = 0;
+        for (i = 0; i < (u16StreamSize >> 1); i++)
+        {
+            u16tempData = pu8StreamData[j];
+            j++;
+            u16tempData = (u16tempData << 8) | pu8StreamData[j];
+            j++;
+            p16vmGCodecDLBitstreamBuf[vmGCodecDLBufWritePos] = u16tempData;
+            vmGCodecDLBufWritePos++;
+        }
+        if (u16StreamSize & 0x01)
+        {
+            u16tempData = pu8StreamData[j];
+            u16tempData = (u16tempData << 8) | u16tempData;
+            p16vmGCodecDLBitstreamBuf[vmGCodecDLBufWritePos] = u16tempData;
+            vmGCodecDLBufWritePos++;
+        }
+    }
+    else
+    {
+        MD_TRC_VM_GFORM_DLSTREAM_INFO2(u32NeedSize, u32TotalBufferSize - vmGCodecDLBufWritePos);
+        if (vmGCodecDLBufWritePos != 0)
+        {
+            p16vmGCodecDLBitstreamBuf[vmGCodecDLBufLastHeaderPos + 2] += 0x0100;
+        }
+        else
+        {
+            MD_TRC_VM_GFORM_DLSTREAM_INFO3(u32NeedSize, u32TotalBufferSize);
+        }
+    }
+
+#ifdef VM_4G_G_SERIAL_DEBUG
+    MD_TRC_VM_GFORM_DLSTREAM_EXIT();
+#endif //#ifdef VM_4G_G_SERIAL_DEBUG
+#endif //#if defined(__G_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+}
+
+void vmSet3GNetworkInfo( uint32 *l1_info, uint16 crc_result, uint16 buf_status, uint8 dl_count )
+{
+    kal_int16 tpc_SIR_lta, dpdch_SIR_lta, TFCI_max_corr, I;
+    uint32 l1Info, s_value;
+    if ( l1_info == NULL ) {
+        l1Info = 0;
+        tpc_SIR_lta = 0;
+        dpdch_SIR_lta = 0;
+        TFCI_max_corr = 0;
+        s_value = 0;
+    } else {
+        l1Info = l1_info[1];
+        tpc_SIR_lta = l1_info[4];
+        dpdch_SIR_lta = l1_info[5];
+        TFCI_max_corr = l1_info[6];
+        s_value = l1_info[3];
+    }
+    I = (uint16)(l1Info & 0xFFFF);
+    vm3GNetworkInfo[4] = I;
+
+    I = (uint16)(l1Info >> 16);
+    vm3GNetworkInfo[5] = I;
+
+    vm3GNetworkInfo[3] = crc_result;
+
+
+    vm3GNetworkInfo[6] = (uint16)((s_value >= 32767) ? 32767 : s_value); //s_value
+
+    vm3GNetworkInfo[0] = (uint16)tpc_SIR_lta;
+    vm3GNetworkInfo[1] = (uint16)dpdch_SIR_lta;
+    vm3GNetworkInfo[2] = (uint16)TFCI_max_corr;
+}
+
+static uint16 vmEPLBandSet(uint16 u2EPLBufLen, uint16 u2EPLBufShift)
+{
+    uint16 u2vmEPLBand = 0;
+    if (u2EPLBufLen == SAL_NB_PCM_SIZE)
+    {
+        u2vmEPLBand = SAL_NB;
+    }
+    else if (u2EPLBufLen == SAL_WB_PCM_SIZE)
+    {
+        u2vmEPLBand = SAL_WB;
+    }
+    else if (u2EPLBufLen == SAL_SWB_PCM_SIZE)
+    {
+        u2vmEPLBand = SAL_SWB;
+    }
+    else if (u2EPLBufLen == SAL_FB_PCM_SIZE)
+    {
+        u2vmEPLBand = SAL_FB;
+    }
+    return u2vmEPLBand << u2EPLBufShift;
+}
+
+bool VM_CodIsAMR(uint16 codec_mode)
+{
+    if ((codec_mode <= SAL_COD_AMR475 && codec_mode >= SAL_COD_AMR122) ||
+            (codec_mode >= SAL_COD_AWB660 && codec_mode <= SAL_COD_AWB2385))
+    {
+        return true;
+    }
+    return false;
+}
+
+bool VM_CodIsEVS(uint16 codec_mode)
+{
+    if ((codec_mode >= SAL_COD_EVSMIN && codec_mode <= SAL_COD_EVSMAX))
+    {
+        return true;
+    }
+    return false;
+}
+
+/* ------------------------------------------------------------------------------ */
+#if defined(__G_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+void vmFormatter_gseries(uint16 *vmBuf, Sal_VM_Frame *vmfrm)
+{
+    volatile uint16 *addr;
+    uint16 I, sc_mode, sd_mode, sc_len, sd_len;
+    uint32 J;
+
+    sc_mode = SAL_COD_AMR122;
+    sd_mode = SAL_COD_AMR122;
+
+    sc_len = AM_GetSpeechPatternLength(sc_mode);
+    //ASSERT_REBOOT( sc_len > 0 );
+    sd_len = AM_GetSpeechPatternLength(sd_mode);
+    //ASSERT_REBOOT( sd_len > 0 );
+
+    //[0:0]: UL on
+    //[6:1]: UL mode
+    //[10:7]: TX type
+    //[11:11]: (no use) SP flag
+    //[13:12]: Call mode
+    I = 0; // Tx: NO_DATA
+    vm.control_1 = (I << 7) | (sc_mode << 1) | (vm.control_1 & 1);
+
+    // if Call mode = 2G, vm.control_1 = vm.control_1 | 0x0000;
+    if (L1SP_GetState() == L1SP_STATE_4G_SPEECH_ON)
+        vm.control_1 = vm.control_1 | 0x3000; // Call mode = 4G
+    else if (SAL_3G_Mode())
+        vm.control_1 = vm.control_1 | 0x1000; // Call mode = 3G
+
+    //[0:0]: DL on
+    //[6:1]: DL mode
+    //[10:7]: RX type
+    //[15:11]: (no use) [12:11] SID flag, [13] TAF, [14] UFI, [15] BFI
+    I = 0; // Rx: NO_DATA
+    vm.control_2 = (I << 7) | (sd_mode << 1) | (vm.control_2 & 1);
+
+    kal_prompt_trace(MOD_L1SP, "vmBuf head %x", vmBuf);
+
+    *vmBuf++ = VM_VM_MAGIC_HEADER;
+    J = L1SP_GetState();
+    I = (uint16)( ( VM_VM_DBGINFO_TOTAL_SIZE << 3 ) | J);
+    *vmBuf++ = I;
+    *vmBuf++ = VM_VM_RECORD_FLAG;
+    *vmBuf++ = 0;  //reset EPL band
+    J =  fma_get_glb_ts() & 0xFFFFFFFF;
+#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
+    if ( g_bNeedExtraLog )
+        MD_TRC_VM_SP3G_VM_L1T(J);
+#endif
+    I = (uint16)(J & 0xFFFF);
+    *vmBuf++ = I;
+    I = (uint16)(J >> 16);
+    *vmBuf++ = I;
+    vm.vm_counter++;
+
+    //Chip ID
+    vm.control_3 = VM_CHIP_ID;
+
+    //[1:0]: DL frm cnt
+    //[7:2]: DL2 mode
+    //[11:8]: DL2 RX type
+    //[13:12]: Codec band
+    //[15:14]: Expert mode (By VLP)
+    vm.control_4 = (vmfrm->dec_frm_num & 0x3) | ((sd_mode & 0x3F) << 2) | ((vmfrm->dec_hdr_1 & 0xE) << 8) | ((SAL_VM_Get_CodBand() & 0x3) << 12);
+
+    //[15:0]: TS control
+    vm.control_5 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_CTRL);
+
+    //[7:0]: TS target scale
+    //[12:8]: TS max scale
+    vm.control_6 = (SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_TARGET_SCALE) & 0xFF) | ((SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_MAX_SCALE) & 0x1F) << 8);
+
+    //[10:0]: TS output size 1
+    vm.control_7 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_OUTPUT_SIZE_1);
+
+    //[10:0]: TS output size 2
+    vm.control_8 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_OUTPUT_SIZE_2);
+
+    // record vm control value
+    *vmBuf++ = vm.control_1;
+    *vmBuf++ = vm.control_2;
+    *vmBuf++ = vm.control_3;
+    *vmBuf++ = vm.control_4;
+    *vmBuf++ = vm.control_5;
+    *vmBuf++ = vm.control_6;
+    *vmBuf++ = vm.control_7;
+    *vmBuf++ = vm.control_8;
+    *vmBuf++ = vm.control_9;
+    *vmBuf++ = vm.control_10;
+
+    // record UL data
+    vm.sc_len = 0;
+    if ( vm.control_1 & 1 )
+    {
+        addr = vmfrm->enc_hb_addr;
+        for ( I = 0; I < sc_len; I++ )
+        {
+            *vmBuf++ = *addr++;
+            if (L1SP_GetState() == L1SP_STATE_2G_SPEECH_ON)
+                addr++;
+        }
+        vm.sc_len += sc_len;
+    }
+
+    // record DL data
+    vm.sd_len = 0;
+    if ( vm.control_2 & 1 )
+    {
+        addr = vmfrm->dec_hb_addr;
+        for ( I = 0; I < sd_len; I++ )
+        {
+            *vmBuf++ = *addr++;
+            if (L1SP_GetState() == L1SP_STATE_2G_SPEECH_ON)
+                addr++;
+        }
+        vm.sd_len += sd_len;
+
+        if (vmfrm->dec_frm_num == 2)
+        {
+            addr = vmfrm->dec_hb_addr_1;
+            for ( I = 0; I < sd_len; I++ )
+            {
+                *vmBuf++ = *addr++;
+                if (L1SP_GetState() == L1SP_STATE_2G_SPEECH_ON)
+                    addr++;
+            }
+            vm.sd_len += sd_len;
+        }
+    }
+
+    kal_prompt_trace(MOD_L1SP, "Formatter_GSeries SC Len= %d, SD Len= %d, Dec_Cnt= %d", vm.sc_len, vm.sd_len, vmfrm->dec_frm_num);
+
+    // Debug info
+    addr = vmfrm->dbgInfo_addr;
+    for ( I = 0; I < VM_VM_SCH_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    addr = vmfrm->enh_dbgInfo_addr;
+    for ( I = 0; I < VM_VM_ENH_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    for (I = 0; I < VM_VM_DRV_DBGINFO_SIZE; I++)
+    {
+        if (I < VM_3G_NETWORK_INFO_LEN)
+            *vmBuf++ = vm3GNetworkInfo[I];
+        else
+            *vmBuf++ = 0;
+    }
+
+    addr = vmfrm->svc_dbgInfo_addr;
+    for ( I = 0; I < VM_VM_SVC_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    kal_prompt_trace(MOD_L1SP, "vmBuf tail %x", vmBuf);
+}
+#endif //#if defined(__G_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+
+#if defined(__EVS_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+EVS_VM_ID VM_EVS_Get_Codec_ID(SP4G_Codec EVSCod)
+{
+    EVS_VM_ID VM_Codec_ID = 0;
+    switch (EVSCod)
+    {
+    case SP4G_CODEC_EVS_08K_005_9:
+    case SP4G_CODEC_EVS_16K_005_9:
+    case SP4G_CODEC_EVS_32K_005_9:
+    case SP4G_CODEC_EVS_48K_005_9:
+        VM_Codec_ID = EVS_PRI590;
+        break;
+
+    case SP4G_CODEC_EVS_AWB_06_60:
+        VM_Codec_ID = EVS_AWB660;
+        break;
+
+    case SP4G_CODEC_EVS_08K_007_2:
+    case SP4G_CODEC_EVS_16K_007_2:
+    case SP4G_CODEC_EVS_32K_007_2:
+    case SP4G_CODEC_EVS_48K_007_2:
+        VM_Codec_ID = EVS_PRI720;
+        break;
+
+    case SP4G_CODEC_EVS_08K_008_0:
+    case SP4G_CODEC_EVS_16K_008_0:
+    case SP4G_CODEC_EVS_32K_008_0:
+    case SP4G_CODEC_EVS_48K_008_0:
+        VM_Codec_ID = EVS_PRI800;
+        break;
+
+    case SP4G_CODEC_EVS_AWB_08_85:
+        VM_Codec_ID = EVS_AWB885;
+        break;
+
+    case SP4G_CODEC_EVS_08K_009_6:
+    case SP4G_CODEC_EVS_16K_009_6:
+    case SP4G_CODEC_EVS_32K_009_6:
+    case SP4G_CODEC_EVS_48K_009_6:
+        VM_Codec_ID = EVS_PRI960;
+        break;
+
+    case SP4G_CODEC_EVS_AWB_12_65:
+        VM_Codec_ID = EVS_AWB1265;
+        break;
+
+    case SP4G_CODEC_EVS_08K_013_2:
+    case SP4G_CODEC_EVS_16K_013_2:
+    case SP4G_CODEC_EVS_32K_013_2:
+    case SP4G_CODEC_EVS_48K_013_2:
+        VM_Codec_ID = EVS_PRI1320;
+        break;
+
+    case SP4G_CODEC_EVS_AWB_14_25:
+        VM_Codec_ID = EVS_AWB1425;
+        break;
+
+    case SP4G_CODEC_EVS_AWB_15_85:
+        VM_Codec_ID = EVS_AWB1585;
+        break;
+
+    case SP4G_CODEC_EVS_08K_016_4:
+    case SP4G_CODEC_EVS_16K_016_4:
+    case SP4G_CODEC_EVS_32K_016_4:
+    case SP4G_CODEC_EVS_48K_016_4:
+        VM_Codec_ID = EVS_PRI1640;
+        break;
+
+    case SP4G_CODEC_EVS_AWB_18_25:
+        VM_Codec_ID = EVS_AWB1825;
+        break;
+
+    case SP4G_CODEC_EVS_AWB_19_85:
+        VM_Codec_ID = EVS_AWB1985;
+        break;
+
+    case SP4G_CODEC_EVS_AWB_23_05:
+        VM_Codec_ID = EVS_AWB2305;
+        break;
+
+    case SP4G_CODEC_EVS_AWB_23_85:
+        VM_Codec_ID = EVS_AWB2385;
+        break;
+
+    case SP4G_CODEC_EVS_08K_024_4:
+    case SP4G_CODEC_EVS_16K_024_4:
+    case SP4G_CODEC_EVS_32K_024_4:
+    case SP4G_CODEC_EVS_48K_024_4:
+        VM_Codec_ID = EVS_PRI2440;
+        break;
+
+    case SP4G_CODEC_EVS_08K_032_0:
+    case SP4G_CODEC_EVS_16K_032_0:
+    case SP4G_CODEC_EVS_32K_032_0:
+    case SP4G_CODEC_EVS_48K_032_0:
+        VM_Codec_ID = EVS_PRI3200;
+        break;
+
+    case SP4G_CODEC_EVS_08K_048_0:
+    case SP4G_CODEC_EVS_16K_048_0:
+    case SP4G_CODEC_EVS_32K_048_0:
+    case SP4G_CODEC_EVS_48K_048_0:
+        VM_Codec_ID = EVS_PRI4800;
+        break;
+
+    case SP4G_CODEC_EVS_08K_064_0:
+    case SP4G_CODEC_EVS_16K_064_0:
+    case SP4G_CODEC_EVS_32K_064_0:
+    case SP4G_CODEC_EVS_48K_064_0:
+        VM_Codec_ID = EVS_PRI6400;
+        break;
+
+    case SP4G_CODEC_EVS_08K_096_0:
+    case SP4G_CODEC_EVS_16K_096_0:
+    case SP4G_CODEC_EVS_32K_096_0:
+    case SP4G_CODEC_EVS_48K_096_0:
+        VM_Codec_ID = EVS_PRI9600;
+        break;
+
+    case SP4G_CODEC_EVS_08K_128_0:
+    case SP4G_CODEC_EVS_16K_128_0:
+    case SP4G_CODEC_EVS_32K_128_0:
+    case SP4G_CODEC_EVS_48K_128_0:
+        VM_Codec_ID = EVS_PRI12800;
+        break;
+
+    case SP4G_CODEC_EVS_08K_002_4_SID:
+    case SP4G_CODEC_EVS_08K_000_0_REV:
+    case SP4G_CODEC_EVS_08K_000_0_LOST:
+    case SP4G_CODEC_EVS_08K_000_0_NODATA:
+
+    case SP4G_CODEC_EVS_16K_002_4_SID:
+    case SP4G_CODEC_EVS_16K_000_0_REV:
+    case SP4G_CODEC_EVS_16K_000_0_LOST:
+    case SP4G_CODEC_EVS_16K_000_0_NODATA:
+
+    case SP4G_CODEC_EVS_32K_002_4_SID:
+    case SP4G_CODEC_EVS_32K_000_0_REV:
+    case SP4G_CODEC_EVS_32K_000_0_LOST:
+    case SP4G_CODEC_EVS_32K_000_0_NODATA:
+
+    case SP4G_CODEC_EVS_48K_002_4_SID:
+    case SP4G_CODEC_EVS_48K_000_0_REV:
+    case SP4G_CODEC_EVS_48K_000_0_LOST:
+    case SP4G_CODEC_EVS_48K_000_0_NODATA:
+
+    case SP4G_CODEC_EVS_AWB_02_00_SID:
+    case SP4G_CODEC_EVS_AWB_00_00_REV0:
+    case SP4G_CODEC_EVS_AWB_00_00_REV1:
+    case SP4G_CODEC_EVS_AWB_00_00_REV2:
+    case SP4G_CODEC_EVS_AWB_00_00_REV3:
+    case SP4G_CODEC_EVS_AWB_00_00_LOST:
+    case SP4G_CODEC_EVS_AWB_00_00_NODATA:
+        VM_Codec_ID = EVS_SID_LOST_NODATA;
+        break;
+
+    default:
+        VM_Codec_ID = EVS_UNDEF;
+        break;
+    }
+    return VM_Codec_ID;
+}
+
+void vmFormatter_evs(uint16 *vmBuf, Sal_VM_Frame *vmfrm)
+{
+    volatile uint16 *addr;
+    uint16 I, sc_mode, sd_mode, sc_len, sd_len;
+    uint32 J;
+    uint16 sc_mode_invalid = 0, sd_mode_invalid = 0;
+
+    sc_mode = VM_EVS_Get_Codec_ID(SAL_EVS_Get_Codec_Mode(SAL_EVS_TX_CODEC_MODE));
+
+    if (sc_mode == EVS_UNDEF)
+    {
+        sc_mode_invalid = 1;
+        sc_mode = EVS_PRI1640;
+    }
+
+    sd_mode = VM_EVS_Get_Codec_ID(SAL_EVS_Get_Codec_Mode(SAL_EVS_RX_CODEC_MODE));
+
+    if (sd_mode == EVS_SID_LOST_NODATA) // DL only, For EVS Codec ID: REV and LOST
+    {
+        if (vm.evs_cur_sd_mode == EVS_UNDEF)
+            sd_mode = VM_EVS_Get_Codec_ID(SAL_Get_DL_CodecMode()); //Codec mode of call open
+        else
+            sd_mode = vm.evs_cur_sd_mode;
+    }
+
+    if (sd_mode == EVS_UNDEF)
+    {
+        sd_mode_invalid = 1;
+        sd_mode = EVS_PRI1640;
+    }
+
+    vm.evs_cur_sd_mode = sd_mode;
+
+    sc_len = AM_GetSpeechPatternLength(sc_mode);
+    //ASSERT_REBOOT( sc_len > 0 );
+    sd_len = AM_GetSpeechPatternLength(sd_mode);
+    //ASSERT_REBOOT( sd_len > 0 );
+
+    //[0:0]: UL on
+    //[6:1]: UL mode
+    //[10:7]: (no use) TX type
+    //[11:11]: (no use) SP flag
+    //[13:12]: Call mode
+    vm.control_1 = (sc_mode << 1) | (vm.control_1 & 1);
+    vm.control_1 = vm.control_1 | 0x3000; // Call mode = 4G
+
+    //[0:0]: DL on
+    //[6:1]: DL mode
+    //[10:7]: (no use) RX type
+    //[15:11]: (no use) [12:11] SID flag, [13] TAF, [14] UFI, [15] BFI
+    vm.control_2 = (sd_mode << 1) | (vm.control_2 & 1);
+
+    kal_prompt_trace(MOD_L1SP, "vmBuf head %x", vmBuf);
+
+    *vmBuf++ = VM_VM_MAGIC_HEADER;
+    J = L1SP_GetState();
+    I = (uint16)( ( VM_VM_DBGINFO_TOTAL_SIZE << 3 ) | J);
+    *vmBuf++ = I;
+    *vmBuf++ = VM_VM_RECORD_FLAG;
+    *vmBuf++ = 0;  //reset EPL band
+    J =  fma_get_glb_ts() & 0xFFFFFFFF;
+#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
+    if ( g_bNeedExtraLog )
+        MD_TRC_VM_SP3G_VM_L1T(J);
+#endif
+    I = (uint16)(J & 0xFFFF);
+    *vmBuf++ = I;
+    I = (uint16)(J >> 16);
+    *vmBuf++ = I;
+    vm.vm_counter++;
+
+    //Chip ID
+    vm.control_3 = VM_CHIP_ID;
+
+    //[1:0]: DL frm cnt
+    //[7:2]: DL2 mode
+    //[11:8]: DL2 RX type
+    //[13:12]: Codec band
+    //[15:14]: Expert mode (By VLP)
+    vm.control_4 = (vmfrm->dec_frm_num & 0x3) | ((sd_mode & 0x3F) << 2) | ((vmfrm->dec_hdr_1 & 0xE) << 8) | ((SAL_VM_Get_CodBand() & 0x3) << 12);
+
+    //[15:0]: TS control
+    vm.control_5 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_CTRL);
+
+    //[7:0]: TS target scale
+    //[12:8]: TS max scale
+    vm.control_6 = (SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_TARGET_SCALE) & 0xFF) | ((SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_MAX_SCALE) & 0x1F) << 8);
+
+    //[10:0]: TS output size 1
+    vm.control_7 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_OUTPUT_SIZE_1);
+
+    //[10:0]: TS output size 2
+    vm.control_8 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_OUTPUT_SIZE_2);
+
+    // record vm control value
+    *vmBuf++ = vm.control_1;
+    *vmBuf++ = vm.control_2;
+    *vmBuf++ = vm.control_3;
+    *vmBuf++ = vm.control_4;
+    *vmBuf++ = vm.control_5;
+    *vmBuf++ = vm.control_6;
+    *vmBuf++ = vm.control_7;
+    *vmBuf++ = vm.control_8;
+    *vmBuf++ = vm.control_9;
+    *vmBuf++ = vm.control_10;
+
+    // record UL data
+    vm.sc_len = 0;
+    if ( vm.control_1 & 1 )
+    {
+        if (sc_mode_invalid)
+        {
+            *vmBuf++ = SAL_EVS_SPEECH_GOOD_FRAME;
+            *vmBuf++ = 328;    //EVS 16.4 HB Len
+        }
+        else
+        {
+            *vmBuf++ = SAL_EVS_Get_Enc_BFI();
+            *vmBuf++ = SAL_EVS_Get_Enc_HBLen();
+        }
+
+        addr = vmfrm->enc_hb_addr;
+        for ( I = 0; I < (sc_len - 2); I++ )
+        {
+            if (sc_mode_invalid)
+                *vmBuf++ = 0;
+            else
+                *vmBuf++ = *addr++;
+        }
+        vm.sc_len += sc_len;
+    }
+
+    // record DL data
+    vm.sd_len = 0;
+    if ( vm.control_2 & 1 )
+    {
+        if (sd_mode_invalid)
+        {
+            *vmBuf++ = SAL_EVS_SPEECH_GOOD_FRAME;
+            *vmBuf++ = 328;    //EVS 16.4 HB Len
+        }
+        else
+        {
+            *vmBuf++ = SAL_EVS_Get_Dec_BFI(SAL_4G_RX_FIRST_FRM);
+            *vmBuf++ = SAL_EVS_Get_Dec_HBLen(SAL_4G_RX_FIRST_FRM);
+        }
+
+        addr = vmfrm->dec_hb_addr;
+        for ( I = 0; I < (sd_len - 2); I++ )
+        {
+            if (sd_mode_invalid)
+                *vmBuf++ = 0;
+            else
+                *vmBuf++ = *addr++;
+        }
+        vm.sd_len += sd_len;
+
+        if (vmfrm->dec_frm_num == 2)
+        {
+            if (sd_mode_invalid)
+            {
+                *vmBuf++ = SAL_EVS_SPEECH_GOOD_FRAME;
+                *vmBuf++ = 328;    //EVS 16.4 HB Len
+            }
+            else
+            {
+                *vmBuf++ = SAL_EVS_Get_Dec_BFI(SAL_4G_RX_SECOND_FRM);
+                *vmBuf++ = SAL_EVS_Get_Dec_HBLen(SAL_4G_RX_SECOND_FRM);
+            }
+
+            addr = vmfrm->dec_hb_addr_1;
+            for ( I = 0; I < (sd_len - 2); I++ )
+            {
+                if (sd_mode_invalid)
+                    *vmBuf++ = 0;
+                else
+                    *vmBuf++ = *addr++;
+            }
+            vm.sd_len += sd_len;
+        }
+    }
+
+    kal_prompt_trace(MOD_L1SP, "Formatter_EVS SC Len= %d, SD Len= %d, Dec_Cnt= %d", vm.sc_len, vm.sd_len, vmfrm->dec_frm_num);
+
+    // Debug info
+    // SCH Dbg Info 0
+    addr = vmfrm->dbgInfo_addr;
+    *vmBuf = (*addr) & 0xEA;
+    *vmBuf = *vmBuf | (SAL_EVS_SPEECH_BAD_FRAME == SAL_EVS_Get_Enc_BFI()) | ((SAL_EVS_SPEECH_BAD_FRAME == SAL_EVS_Get_Dec_BFI(SAL_4G_RX_FIRST_FRM)) << 2);
+    vmBuf++;
+
+    // SCH Dbg Info 1
+    *vmBuf = (SAL_EVS_Get_PCMBW()) | ((SAL_EVS_Get_PCMBW()) << 2) | ((SAL_EVS_Get_Enc_MaxRate()) << 4);
+    *vmBuf = *vmBuf | ((SAL_EVS_Get_Enc_CA_Enable()) << 6) | ((SAL_EVS_Get_Enc_CA_RF_FEC_Indicator()) << 7) | ((SAL_EVS_Get_Enc_CA_RF_FEC_Offset()) << 8);
+    *vmBuf = *vmBuf | ((SAL_EVS_Get_Dec_CA_FrmMode(SAL_4G_RX_FIRST_FRM)) << 11) | ((SAL_EVS_Get_Dec_CA_FrmMode(SAL_4G_RX_SECOND_FRM)) << 13);
+    vmBuf++;
+
+    // SCH Dbg Info 2
+    *vmBuf++ = SAL_EVS_Get_Enc_HBLen();
+
+    // SCH Dbg Info 3
+    *vmBuf++ = SAL_EVS_Get_Dec_HBLen(SAL_4G_RX_FIRST_FRM);
+
+    // SCH Dbg Info 4
+    *vmBuf++ = SAL_EVS_Get_Dec_HBLen(SAL_4G_RX_SECOND_FRM);
+
+    // SCH Dbg Info reserved
+    addr = vmfrm->dbgInfo_addr + 5;
+    for ( I = 0; I < (VM_VM_SCH_DBGINFO_SIZE - 5); I++ )
+        *vmBuf++ = *addr++;
+
+    addr = vmfrm->enh_dbgInfo_addr;
+    for ( I = 0; I < VM_VM_ENH_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    for (I = 0; I < VM_VM_DRV_DBGINFO_SIZE; I++)
+    {
+        if (I < VM_3G_NETWORK_INFO_LEN)
+            *vmBuf++ = vm3GNetworkInfo[I];
+        else
+            *vmBuf++ = 0;
+    }
+
+    addr = vmfrm->svc_dbgInfo_addr;
+    for ( I = 0; I < VM_VM_SVC_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    kal_prompt_trace(MOD_L1SP, "vmBuf tail %x", vmBuf);
+}
+#endif
+
+void vmFormatter_amr(uint16 *vmBuf, Sal_VM_Frame *vmfrm)
+{
+    volatile uint16 *addr;
+    uint16 I, sc_mode, sd_mode, sc_len, sd_len;
+    uint32 J;
+    uint16 sc_mode_invalid = 0;
+
+    sc_mode = vmfrm->enc_mode;
+    sd_mode = vmfrm->dec_mode;
+    if ((VM_CodIsAMR(sc_mode)) == false)
+    {
+        sc_mode = sd_mode;
+        sc_mode_invalid = 1;
+    }
+
+    sc_len = AM_GetSpeechPatternLength(sc_mode);
+    //ASSERT_REBOOT( sc_len > 0 );
+    sd_len = AM_GetSpeechPatternLength(sd_mode);
+    //ASSERT_REBOOT( sd_len > 0 );
+
+    //[0:0]: UL on
+    //[6:1]: UL mode
+    //[10:7]: TX type
+    //[11:11]: (no use) SP flag
+    //[13:12]: Call mode
+    if (sc_mode_invalid)
+    {
+        I = 0; // Tx: NO_DATA
+    }
+    else
+    {
+        I = vmfrm->enc_hdr & 0x3; // Tx: bit0, bit1
+    }
+    vm.control_1 = (I << 7) | (sc_mode << 1) | (vm.control_1 & 1);
+
+    // if Call mode = 2G, vm.control_1 = vm.control_1 | 0x0000;
+    if (L1SP_GetState() == L1SP_STATE_4G_SPEECH_ON)
+        vm.control_1 = vm.control_1 | 0x3000; // Call mode = 4G
+    else if (SAL_3G_Mode())
+        vm.control_1 = vm.control_1 | 0x1000; // Call mode = 3G
+
+    //[0:0]: DL on
+    //[6:1]: DL mode
+    //[10:7]: RX type
+    //[15:11]: (no use) [12:11] SID flag, [13] TAF, [14] UFI, [15] BFI
+    I = (vmfrm->dec_hdr & 0xE) >> 1; // Rx: bit1, bit2, bit3
+    vm.control_2 = (I << 7) | (sd_mode << 1) | (vm.control_2 & 1);
+
+    kal_prompt_trace(MOD_L1SP, "vmBuf head %x", vmBuf);
+
+    *vmBuf++ = VM_VM_MAGIC_HEADER;
+    J = L1SP_GetState();
+    I = (uint16)( ( VM_VM_DBGINFO_TOTAL_SIZE << 3 ) | J);
+    *vmBuf++ = I;
+    *vmBuf++ = VM_VM_RECORD_FLAG;
+    *vmBuf++ = 0;  //reset EPL band
+    J =  fma_get_glb_ts() & 0xFFFFFFFF;
+#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
+    if ( g_bNeedExtraLog )
+        MD_TRC_VM_SP3G_VM_L1T(J);
+#endif
+    I = (uint16)(J & 0xFFFF);
+    *vmBuf++ = I;
+    I = (uint16)(J >> 16);
+    *vmBuf++ = I;
+    vm.vm_counter++;
+
+    //Chip ID
+    vm.control_3 = VM_CHIP_ID;
+
+    //[1:0]: DL frm cnt
+    //[7:2]: DL2 mode
+    //[11:8]: DL2 RX type
+    //[13:12]: Codec band
+    //[15:14]: Expert mode (By VLP)
+    vm.control_4 = (vmfrm->dec_frm_num & 0x3) | ((sd_mode & 0x3F) << 2) | ((vmfrm->dec_hdr_1 & 0xE) << 8) | ((SAL_VM_Get_CodBand() & 0x3) << 12);
+
+    //[15:0]: TS control
+    vm.control_5 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_CTRL);
+
+    //[7:0]: TS target scale
+    //[12:8]: TS max scale
+    vm.control_6 = (SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_TARGET_SCALE) & 0xFF) | ((SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_MAX_SCALE) & 0x1F) << 8);
+
+    //[10:0]: TS output size 1
+    vm.control_7 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_OUTPUT_SIZE_1);
+
+    //[10:0]: TS output size 2
+    vm.control_8 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_OUTPUT_SIZE_2);
+
+    // record vm control value
+    *vmBuf++ = vm.control_1;
+    *vmBuf++ = vm.control_2;
+    *vmBuf++ = vm.control_3;
+    *vmBuf++ = vm.control_4;
+    *vmBuf++ = vm.control_5;
+    *vmBuf++ = vm.control_6;
+    *vmBuf++ = vm.control_7;
+    *vmBuf++ = vm.control_8;
+    *vmBuf++ = vm.control_9;
+    *vmBuf++ = vm.control_10;
+
+    // record UL data
+    vm.sc_len = 0;
+    if ( vm.control_1 & 1 )
+    {
+        addr = vmfrm->enc_hb_addr;
+        for ( I = 0; I < sc_len; I++ )
+        {
+            *vmBuf++ = *addr++;
+            if (L1SP_GetState() == L1SP_STATE_2G_SPEECH_ON)
+                addr++;
+        }
+        vm.sc_len += sc_len;
+    }
+
+    // record DL data
+    vm.sd_len = 0;
+    if ( vm.control_2 & 1 )
+    {
+        addr = vmfrm->dec_hb_addr;
+        for ( I = 0; I < sd_len; I++ )
+        {
+            *vmBuf++ = *addr++;
+            if (L1SP_GetState() == L1SP_STATE_2G_SPEECH_ON)
+                addr++;
+        }
+        vm.sd_len += sd_len;
+
+        if (vmfrm->dec_frm_num == 2)
+        {
+            addr = vmfrm->dec_hb_addr_1;
+            for ( I = 0; I < sd_len; I++ )
+            {
+                *vmBuf++ = *addr++;
+                if (L1SP_GetState() == L1SP_STATE_2G_SPEECH_ON)
+                    addr++;
+            }
+            vm.sd_len += sd_len;
+        }
+    }
+
+    kal_prompt_trace(MOD_L1SP, "Formatter_AMR SC Len= %d, SD Len= %d, Dec_Cnt= %d", vm.sc_len, vm.sd_len, vmfrm->dec_frm_num);
+
+    // Debug info
+    addr = vmfrm->dbgInfo_addr;
+    for ( I = 0; I < VM_VM_SCH_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    addr = vmfrm->enh_dbgInfo_addr;
+    for ( I = 0; I < VM_VM_ENH_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    for (I = 0; I < VM_VM_DRV_DBGINFO_SIZE; I++)
+    {
+        if (I < VM_3G_NETWORK_INFO_LEN)
+            *vmBuf++ = vm3GNetworkInfo[I];
+        else
+            *vmBuf++ = 0;
+    }
+
+    addr = vmfrm->svc_dbgInfo_addr;
+    for ( I = 0; I < VM_VM_SVC_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    kal_prompt_trace(MOD_L1SP, "vmBuf tail %x", vmBuf);
+}
+
+void vmFormatter_4g(uint16 *vmBuf, Sal_VM_Frame *vmfrm)
+{
+#if defined(__G_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+    if ( SP4G_IsGCodecMode() )
+    {
+        vmFormatter_gseries(vmBuf, vmfrm);
+        return;
+    }
+#endif
+
+#if defined(__EVS_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+    if (VM_CodIsEVS(vmfrm->dec_mode) == true)
+    {
+        vmFormatter_evs(vmBuf, vmfrm);
+        return;
+    }
+#endif
+
+    vmFormatter_amr(vmBuf, vmfrm);
+}
+
+void vmFormatter_c2k(uint16 *vmBuf, Sal_VM_Frame *vmfrm)
+{
+    volatile uint16 *addr;
+    uint16 I, sc_mode, sd_mode, sc_len, sd_len;
+    uint32 J;
+    uint16 sc_mode_invalid = 0;
+
+    sc_mode = vmfrm->enc_mode;
+    sd_mode = vmfrm->dec_mode;
+    if (sc_mode != sd_mode)
+    {
+        sc_mode = sd_mode;
+        sc_mode_invalid = 1;
+    }
+
+    sc_len = AM_GetSpeechPatternLength(sc_mode);
+    //ASSERT_REBOOT( sc_len > 0 );
+    sd_len = AM_GetSpeechPatternLength(sd_mode);
+    //ASSERT_REBOOT( sd_len > 0 );
+
+    //[0:0]: UL on
+    //[6:1]: UL mode
+    //[10:7]: TX type
+    //[11:11]: (no use) SP flag
+    //[13:12]: Call mode
+    if (sc_mode_invalid)
+    {
+        I = 0; // Tx: NO_DATA
+    }
+    else
+    {
+        I = vmfrm->enc_hdr; // Tx
+    }
+    vm.control_1 = (I << 7) | (sc_mode << 1) | (vm.control_1 & 1);
+    vm.control_1 = vm.control_1 | 0x2000; // Call mode = C2K
+
+    //[0:0]: DL on
+    //[6:1]: DL mode
+    //[10:7]: RX type
+    //[15:11]: (no use) [12:11] SID flag, [13] TAF, [14] UFI, [15] BFI
+    I = vmfrm->dec_hdr; // Rx
+    vm.control_2 = (I << 7) | (sd_mode << 1) | (vm.control_2 & 1);
+
+    kal_prompt_trace(MOD_L1SP, "vmBuf head %x", vmBuf);
+
+    *vmBuf++ = VM_VM_MAGIC_HEADER;
+    J = L1SP_GetState();
+    I = (uint16)( ( VM_VM_DBGINFO_TOTAL_SIZE << 3 ) | J);
+    *vmBuf++ = I;
+    *vmBuf++ = VM_VM_RECORD_FLAG;
+    *vmBuf++ = 0;  //reset EPL band
+    J =  fma_get_glb_ts() & 0xFFFFFFFF;
+#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
+    // TODO: c2k [trace]
+#endif
+    I = (uint16)(J & 0xFFFF);
+    *vmBuf++ = I;
+    I = (uint16)(J >> 16);
+    *vmBuf++ = I;
+    vm.vm_counter++;
+
+    //Chip ID
+    vm.control_3 = VM_CHIP_ID;
+
+    //[1:0]: DL frm cnt
+    //[7:2]: DL2 mode
+    //[11:8]: DL2 RX type
+    //[13:12]: Codec band
+    //[15:14]: Expert mode (By VLP)
+    vm.control_4 = (vmfrm->dec_frm_num & 0x3) | ((sd_mode & 0x3F) << 2) | ((vmfrm->dec_hdr_1 & 0xE) << 8) | ((SAL_VM_Get_CodBand() & 0x3) << 12);
+
+    //[15:0]: TS control
+    vm.control_5 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_CTRL);
+
+    //[7:0]: TS target scale
+    //[12:8]: TS max scale
+    vm.control_6 = (SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_TARGET_SCALE) & 0xFF) | ((SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_MAX_SCALE) & 0x1F) << 8);
+
+    //[10:0]: TS output size 1
+    vm.control_7 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_OUTPUT_SIZE_1);
+
+    //[10:0]: TS output size 2
+    vm.control_8 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_OUTPUT_SIZE_2);
+
+    // record vm control value
+    *vmBuf++ = vm.control_1;
+    *vmBuf++ = vm.control_2;
+    *vmBuf++ = vm.control_3;
+    *vmBuf++ = vm.control_4;
+    *vmBuf++ = vm.control_5;
+    *vmBuf++ = vm.control_6;
+    *vmBuf++ = vm.control_7;
+    *vmBuf++ = vm.control_8;
+    *vmBuf++ = vm.control_9;
+    *vmBuf++ = vm.control_10;
+
+    // record UL data
+    vm.sc_len = 0;
+    if ( vm.control_1 & 1 )
+    {
+        addr = vmfrm->enc_hb_addr;
+        for ( I = 0; I < sc_len; I++ )
+        {
+            *vmBuf++ = *addr++;
+        }
+        vm.sc_len += sc_len;
+    }
+
+    // record DL data
+    vm.sd_len = 0;
+    if ( vm.control_2 & 1 )
+    {
+        addr = vmfrm->dec_hb_addr;
+        for ( I = 0; I < sd_len; I++ )
+        {
+            *vmBuf++ = *addr++;
+        }
+        vm.sd_len += sd_len;
+
+        if (vmfrm->dec_frm_num == 2)
+        {
+            addr = vmfrm->dec_hb_addr_1;
+            for ( I = 0; I < sd_len; I++ )
+            {
+                *vmBuf++ = *addr++;
+            }
+            vm.sd_len += sd_len;
+        }
+    }
+
+    kal_prompt_trace(MOD_L1SP, "Formatter_C2K SC Len= %d, SD Len= %d, Dec_Cnt= %d", vm.sc_len, vm.sd_len, vmfrm->dec_frm_num);
+
+    // Debug info
+    addr = vmfrm->dbgInfo_addr;
+    for ( I = 0; I < VM_VM_SCH_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    addr = vmfrm->enh_dbgInfo_addr;
+    for ( I = 0; I < VM_VM_ENH_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    for (I = 0; I < VM_VM_DRV_DBGINFO_SIZE; I++)
+    {
+        if (I < VM_3G_NETWORK_INFO_LEN)
+            *vmBuf++ = vm3GNetworkInfo[I];
+        else
+            *vmBuf++ = 0;
+    }
+
+    addr = vmfrm->svc_dbgInfo_addr;
+    for ( I = 0; I < VM_VM_SVC_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    kal_prompt_trace(MOD_L1SP, "vmBuf tail %x", vmBuf);
+}
+
+void vmFormatter_standby(uint16 *vmBuf, Sal_VM_Frame *vmfrm)
+{
+    volatile uint16 *addr;
+    uint16 I, sc_mode, sd_mode, sc_len, sd_len;
+    uint32 J;
+    uint16 sc_mode_invalid = 0;
+
+    sc_mode = vmfrm->enc_mode;
+    sd_mode = vmfrm->dec_mode;
+    if ((VM_CodIsAMR(sc_mode)) == false)
+    {
+        sc_mode = sd_mode;
+        sc_mode_invalid = 1;
+    }
+
+    sc_len = AM_GetSpeechPatternLength(sc_mode);
+    //ASSERT_REBOOT( sc_len > 0 );
+    sd_len = AM_GetSpeechPatternLength(sd_mode);
+    //ASSERT_REBOOT( sd_len > 0 );
+
+    //[0:0]: UL on
+    //[6:1]: UL mode
+    //[10:7]: TX type
+    //[11:11]: (no use) SP flag
+    //[13:12]: Call mode
+    if (sc_mode_invalid)
+    {
+        I = 0; // Tx: NO_DATA
+    }
+    else
+    {
+        I = vmfrm->enc_hdr & 0x3; // Tx: bit0, bit1
+    }
+    vm.control_1 = (I << 7) | (sc_mode << 1) | (vm.control_1 & 1);
+    vm.control_1 = vm.control_1 | 0x1000; // Call mode = 3G
+
+    //[0:0]: DL on
+    //[6:1]: DL mode
+    //[10:7]: RX type
+    //[15:11]: (no use) [12:11] SID flag, [13] TAF, [14] UFI, [15] BFI
+    I = (vmfrm->dec_hdr & 0xE) >> 1; // Rx: bit1, bit2, bit3
+    vm.control_2 = (I << 7) | (sd_mode << 1) | (vm.control_2 & 1);
+
+    kal_prompt_trace(MOD_L1SP, "vmBuf head %x", vmBuf);
+
+    *vmBuf++ = VM_VM_MAGIC_HEADER;
+    J = L1SP_GetState();
+    I = (uint16)( ( VM_VM_DBGINFO_TOTAL_SIZE << 3 ) | J);
+    *vmBuf++ = I;
+    *vmBuf++ = VM_VM_RECORD_FLAG;
+    *vmBuf++ = 0;  //reset EPL band
+    J =  fma_get_glb_ts() & 0xFFFFFFFF;
+#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
+    if ( g_bNeedExtraLog )
+        MD_TRC_VM_SP3G_VM_L1T(J);
+#endif
+    I = (uint16)(J & 0xFFFF);
+    *vmBuf++ = I;
+    I = (uint16)(J >> 16);
+    *vmBuf++ = I;
+    vm.vm_counter++;
+
+    //Chip ID
+    vm.control_3 = VM_CHIP_ID;
+
+    //[1:0]: DL frm cnt
+    //[7:2]: DL2 mode
+    //[11:8]: DL2 RX type
+    //[13:12]: Codec band
+    //[15:14]: Expert mode (By VLP)
+    vm.control_4 = (vmfrm->dec_frm_num & 0x3) | ((sd_mode & 0x3F) << 2) | ((vmfrm->dec_hdr_1 & 0xE) << 8) | ((SAL_VM_Get_CodBand() & 0x3) << 12);
+
+    //[15:0]: TS control
+    vm.control_5 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_CTRL);
+
+    //[7:0]: TS target scale
+    //[12:8]: TS max scale
+    vm.control_6 = (SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_TARGET_SCALE) & 0xFF) | ((SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_MAX_SCALE) & 0x1F) << 8);
+
+    //[10:0]: TS output size 1
+    vm.control_7 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_OUTPUT_SIZE_1);
+
+    //[10:0]: TS output size 2
+    vm.control_8 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_OUTPUT_SIZE_2);
+
+    // record vm control value
+    *vmBuf++ = vm.control_1;
+    *vmBuf++ = vm.control_2;
+    *vmBuf++ = vm.control_3;
+    *vmBuf++ = vm.control_4;
+    *vmBuf++ = vm.control_5;
+    *vmBuf++ = vm.control_6;
+    *vmBuf++ = vm.control_7;
+    *vmBuf++ = vm.control_8;
+    *vmBuf++ = vm.control_9;
+    *vmBuf++ = vm.control_10;
+
+    // record UL data
+    vm.sc_len = 0;
+    if ( vm.control_1 & 1 )
+    {
+        addr = vmfrm->enc_hb_addr;
+        for ( I = 0; I < sc_len; I++ )
+        {
+            *vmBuf++ = *addr++;
+        }
+        vm.sc_len += sc_len;
+    }
+
+    // record DL data
+    vm.sd_len = 0;
+    if ( vm.control_2 & 1 )
+    {
+        addr = vmfrm->dec_hb_addr;
+        for ( I = 0; I < sd_len; I++ )
+        {
+            *vmBuf++ = *addr++;
+        }
+        vm.sd_len += sd_len;
+
+        if (vmfrm->dec_frm_num == 2)
+        {
+            addr = vmfrm->dec_hb_addr_1;
+            for ( I = 0; I < sd_len; I++ )
+            {
+                *vmBuf++ = *addr++;
+            }
+            vm.sd_len += sd_len;
+        }
+    }
+
+    kal_prompt_trace(MOD_L1SP, "Formatter_Standby SC Len= %d, SD Len= %d, Dec_Cnt= %d", vm.sc_len, vm.sd_len, vmfrm->dec_frm_num);
+
+    // Debug info
+    addr = vmfrm->dbgInfo_addr;
+    for ( I = 0; I < VM_VM_SCH_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    addr = vmfrm->enh_dbgInfo_addr;
+    for ( I = 0; I < VM_VM_ENH_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    for (I = 0; I < VM_VM_DRV_DBGINFO_SIZE; I++)
+    {
+        if (I < VM_3G_NETWORK_INFO_LEN)
+            *vmBuf++ = vm3GNetworkInfo[I];
+        else
+            *vmBuf++ = 0;
+    }
+
+    addr = vmfrm->svc_dbgInfo_addr;
+    for ( I = 0; I < VM_VM_SVC_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    kal_prompt_trace(MOD_L1SP, "vmBuf tail %x", vmBuf);
+}
+
+void vmFormatter_vm(uint16 *vmBuf, Sal_VM_Frame *vmfrm)
+{
+    volatile uint16 *addr;
+    uint16 I, sc_mode, sd_mode, sc_len, sd_len;
+    uint32 J;
+    uint16 sc_mode_invalid = 0;
+
+    sc_mode = vmfrm->enc_mode;
+    sd_mode = vmfrm->dec_mode;
+    if (sc_mode != sd_mode)
+    {
+        sc_mode = sd_mode;
+        sc_mode_invalid = 1;
+    }
+
+    sc_len = AM_GetSpeechPatternLength(sc_mode);
+    //ASSERT_REBOOT( sc_len > 0 );
+    sd_len = AM_GetSpeechPatternLength(sd_mode);
+    //ASSERT_REBOOT( sd_len > 0 );
+
+    //[0:0]: UL on
+    //[6:1]: UL mode
+    //[10:7]: (no use) TX type
+    //[11:11]: SP flag
+    //[13:12]: Call mode
+    if (sc_mode_invalid)
+    {
+        I = 0; // sp_flag: Silence
+    }
+    else
+    {
+        I = (vmfrm->enc_hdr & 0x2) >> 1; // sp_flag: bit1
+    }
+    vm.control_1 = (I << 11) | (sc_mode << 1) | (vm.control_1 & 1);
+    // if Call mode = 2G, vm.control_1 = vm.control_1 | 0x0000;
+
+    //[0:0]: DL on
+    //[6:1]: DL mode
+    //[10:7]: (no use) RX type
+    //[15:11]: [12:11] SID flag, [13] TAF, [14] UFI, [15] BFI
+    I = (vmfrm->dec_hdr & 0x3E) >> 1; // BFI, UFI, TAF, SID
+    vm.control_2 = (I << 11) | (sd_mode << 1) | (vm.control_2 & 1);
+
+    kal_prompt_trace(MOD_L1SP, "vmBuf head %x", vmBuf);
+
+    *vmBuf++ = VM_VM_MAGIC_HEADER;
+    J = L1SP_GetState();
+    I = (uint16)( ( VM_VM_DBGINFO_TOTAL_SIZE << 3 ) | J);
+    *vmBuf++ = I;
+    *vmBuf++ = VM_VM_RECORD_FLAG;
+    *vmBuf++ = 0;  //reset EPL band
+    J =  fma_get_glb_ts() & 0xFFFFFFFF;
+    I = (uint16)(J & 0xFFFF);
+    *vmBuf++ = I;
+    I = (uint16)(J >> 16);
+    *vmBuf++ = I;
+    vm.vm_counter++;
+
+    //Chip ID
+    vm.control_3 = VM_CHIP_ID;
+
+    //[1:0]: DL frm cnt
+    //[7:2]: DL2 mode
+    //[11:8]: DL2 RX type
+    //[13:12]: Codec band
+    //[15:14]: Expert mode (By VLP)
+    vm.control_4 = (vmfrm->dec_frm_num & 0x3) | ((sd_mode & 0x3F) << 2) | ((vmfrm->dec_hdr_1 & 0xE) << 8) | ((SAL_VM_Get_CodBand() & 0x3) << 12);
+
+    //[15:0]: TS control
+    vm.control_5 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_CTRL);
+
+    //[7:0]: TS target scale
+    //[12:8]: TS max scale
+    vm.control_6 = (SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_TARGET_SCALE) & 0xFF) | ((SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_MAX_SCALE) & 0x1F) << 8);
+
+    //[10:0]: TS output size 1
+    vm.control_7 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_OUTPUT_SIZE_1);
+
+    //[10:0]: TS output size 2
+    vm.control_8 = SAL_VM_Get_TS_Info(SAL_VM_TS_INFO_OUTPUT_SIZE_2);
+
+    // record vm control value
+    *vmBuf++ = vm.control_1;
+    *vmBuf++ = vm.control_2;
+    *vmBuf++ = vm.control_3;
+    *vmBuf++ = vm.control_4;
+    *vmBuf++ = vm.control_5;
+    *vmBuf++ = vm.control_6;
+    *vmBuf++ = vm.control_7;
+    *vmBuf++ = vm.control_8;
+    *vmBuf++ = vm.control_9;
+    *vmBuf++ = vm.control_10;
+
+    // record UL data
+    vm.sc_len = 0;
+    if ( vm.control_1 & 1 )
+    {
+        addr = vmfrm->enc_hb_addr;
+        for ( I = 0; I < sc_len; I++ )
+        {
+            *vmBuf++ = *addr++;
+            if (L1SP_GetState() == L1SP_STATE_2G_SPEECH_ON)
+                addr++;
+        }
+        vm.sc_len += sc_len;
+    }
+
+    // record DL data
+    vm.sd_len = 0;
+    if ( vm.control_2 & 1 )
+    {
+        addr = vmfrm->dec_hb_addr;
+        for ( I = 0; I < sd_len; I++ )
+        {
+            *vmBuf++ = *addr++;
+            if (L1SP_GetState() == L1SP_STATE_2G_SPEECH_ON)
+                addr++;
+        }
+        vm.sd_len += sd_len;
+
+        if (vmfrm->dec_frm_num == 2)
+        {
+            addr = vmfrm->dec_hb_addr_1;
+            for ( I = 0; I < sd_len; I++ )
+            {
+                *vmBuf++ = *addr++;
+                if (L1SP_GetState() == L1SP_STATE_2G_SPEECH_ON)
+                    addr++;
+            }
+            vm.sd_len += sd_len;
+        }
+    }
+
+    kal_prompt_trace(MOD_L1SP, "Formatter_VM SC Len= %d, SD Len= %d, Dec_Cnt= %d", vm.sc_len, vm.sd_len, vmfrm->dec_frm_num);
+
+    // Debug info
+    addr = vmfrm->dbgInfo_addr;
+    for ( I = 0; I < VM_VM_SCH_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    addr = vmfrm->enh_dbgInfo_addr;
+    for ( I = 0; I < VM_VM_ENH_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    for (I = 0; I < VM_VM_DRV_DBGINFO_SIZE; I++)
+    {
+        if (I < VM_3G_NETWORK_INFO_LEN)
+            *vmBuf++ = vm3GNetworkInfo[I];
+        else
+            *vmBuf++ = 0;
+    }
+
+    addr = vmfrm->svc_dbgInfo_addr;
+    for ( I = 0; I < VM_VM_SVC_DBGINFO_SIZE; I++ )
+        *vmBuf++ = *addr++;
+
+    kal_prompt_trace(MOD_L1SP, "vmBuf tail %x", vmBuf);
+}
+
+void vmFormatter_2g(uint16 *vmBuf, Sal_VM_Frame *vmfrm)
+{
+    if (VM_CodIsAMR(vmfrm->dec_mode) == true)
+    {
+        vmFormatter_amr(vmBuf, vmfrm);
+    }
+    else
+    {
+        vmFormatter_vm(vmBuf, vmfrm);
+    }
+}
+
+/* ------------------------------------------------------------------------------ */
+/**
+    @buf1: pointer to pcm buf1,
+    @len1:length of buf1, unit is word(2byte)
+    @buf2:pointer to pcm buf2
+    @len2: length of buf2. unit is word(2byte)
+*/
+void VmRec_GetReadBufs(kal_uint32 *add1, kal_uint16 *len1, kal_uint32 *add2, kal_uint16 *len2)
+{
+    if (vm.pOutputBufWrite >= vm.pOutputBufRead) // write > read, 1 buf segment
+    {
+        *add1 = (kal_uint32)(&vmRecOutputBuf[vm.pOutputBufRead]);
+        *len1 = (vm.pOutputBufWrite - vm.pOutputBufRead);
+        *add2 = 0;
+        *len2 = 0;
+    }
+    else //write < read, 2 buf segment
+    {
+        *add1 = (kal_uint32)(&vmRecOutputBuf[vm.pOutputBufRead]);
+        *len1 = (vm.outputBufSize - vm.pOutputBufRead);
+        *add2 = (kal_uint32)(vmRecOutputBuf);
+        *len2 = (vm.pOutputBufWrite);
+    }
+}
+
+/**
+    @len: unit is word
+*/
+void VmRec_ReadDataDone(uint16 len)
+{
+    vm.pOutputBufRead += len;
+    if ( vm.pOutputBufRead >= vm.outputBufSize)
+        vm.pOutputBufRead = vm.pOutputBufRead - vm.outputBufSize;
+}
+
+//use this function instead of Media_WriteDataDone to avoid media.waiting false usage
+int32 vmRec_queryOutputBufFreeSpace(void)
+{
+    int32 count;
+
+    count = vm.pOutputBufRead + vm.outputBufSize - vm.pOutputBufWrite - 1;
+
+    if ( count >= vm.outputBufSize )
+        count -= vm.outputBufSize;
+    return count;
+}
+
+void vmRec_getWriteBuffer(uint16 **buffer, uint32 *bufLen)
+{
+    int32 count;
+
+    if ( vm.pOutputBufRead > vm.pOutputBufWrite )
+        count = vm.pOutputBufRead  - vm.pOutputBufWrite - 1;
+    else if ( vm.pOutputBufRead == 0 )
+        count = vm.outputBufSize - vm.pOutputBufWrite - 1;
+    else
+        count = vm.outputBufSize - vm.pOutputBufWrite;
+
+    *buffer = &vmRecOutputBuf[vm.pOutputBufWrite];
+    *bufLen = (uint32)count;
+}
+
+static void vmRec_writeDataDone(uint32 len)
+{
+    vm.pOutputBufWrite += len;
+    if ( vm.pOutputBufWrite >= vm.outputBufSize)
+        vm.pOutputBufWrite = vm.pOutputBufWrite - vm.outputBufSize;
+}
+
+static void vocWriteVocToCatcher(uint16 vmLen, uint16 *vmBuf)
+{
+    uint32 len = vmLen * 2;
+    uint16 *buf = vmBuf;
+
+    while (len > 1000)
+    {
+        tst_vc_response(TVCI_VM_LOGGING, (const kal_uint8*)buf, 1000);
+        buf += 500;
+        len -= 1000;
+    }
+    tst_vc_response(TVCI_VM_LOGGING, (const kal_uint8*)buf, len);
+}
+
+static void vmRec_writeVmToOutputBuf(uint16 vmLen, uint16 *vmBuf) // a frame of VM must be written to MB
+{
+    uint16 *toPtr;
+    uint32 segment, I;
+
+    vmRec_getWriteBuffer( &toPtr, &segment );
+
+    if (segment > vmLen)
+        segment = vmLen;
+
+    for ( I = segment ; I > 0 ; I-- ) {
+        *toPtr++ = *vmBuf++;
+    }
+
+    vmRec_writeDataDone( segment );
+
+    // second segment
+    vmLen -= segment;    // unprocess length
+    if (vmLen > 0 )
+    {
+        vmRec_getWriteBuffer( &toPtr, &segment );
+
+        if (segment > vmLen)
+            segment = vmLen;
+
+        for ( I = segment ; I > 0 ; I-- ) {
+            *toPtr++ = *vmBuf++;
+        }
+        vmRec_writeDataDone( segment );
+    }
+    return;
+}
+
+static void voc4WayPcmRecord( volatile uint16* ul_addr, uint16 ul_len, volatile uint16* dl_addr, uint16 dl_len)
+{
+    uint16 *buf;
+
+    buf = vm.pcmBuf;
+    // header for record 1st set of UL-DL PCM data
+    *buf++ = (vm.vm_lost_count << 8) + vm.pcm_lost_count;
+    *buf++ = vm.vm_counter ;
+
+    // make it interleave
+    // Uplink
+    EMI_ReadFromDSP((uint16*)buf, ul_addr, ul_len);
+    buf += ul_len;
+
+    // Downlink
+    EMI_ReadFromDSP((uint16*)buf, dl_addr, dl_len);
+
+    buf = vm.pcmBuf;
+
+    vocWriteVocToCatcher(ul_len + dl_len + 2, buf);
+}
+
+static void vm4WayPcmRecord(volatile uint16 *ul_addr, uint16 ul_len, volatile uint16 *dl_addr, uint16 dl_len)
+{
+    uint32 I, tmp = 0;
+    uint16 *buf, *mBuf;
+    uint16 logsize;
+
+    logsize = ul_len + dl_len + 2;
+
+    buf = vm.pcmBuf;
+    // header for record 1st set of UL-DL PCM data
+    *buf++ = (vm.vm_lost_count << 8) + vm.pcm_lost_count;
+    *buf++ = vm.vm_counter ;
+
+    // Uplink
+    EMI_ReadFromDSP((uint16*)buf, ul_addr, ul_len);
+    buf += ul_len;
+
+    // Downlink
+    EMI_ReadFromDSP((uint16*)buf, dl_addr, dl_len);
+
+    buf = vm.pcmBuf;
+
+    vmRec_getWriteBuffer( &mBuf, &tmp );
+    if ( tmp > logsize )
+        tmp = logsize;
+    //for( I = tmp ; I > 0 ; I-- ) {
+    //   *mBuf++ = *buf++;
+    //}
+    kal_mem_cpy(mBuf, buf, tmp << 1);
+    buf += tmp;
+    mBuf += tmp;
+
+    vmRec_writeDataDone(tmp);
+
+    tmp = logsize - tmp; // tmp is size did not write to Buffer
+    if ( (int32)tmp > 0 )
+    {
+        vmRec_getWriteBuffer( &mBuf, &I );
+
+        if (I >= tmp)
+        {
+            //for( I = tmp ; I > 0 ; I--) {
+            //     *mBuf++ = *buf++;
+            //}
+            kal_mem_cpy(mBuf, buf, tmp << 1);
+            buf += tmp;
+            mBuf += tmp;
+
+            vmRec_writeDataDone( tmp );
+        }
+        else
+        {
+            MD_TRC_VM_REC_HISR_PCM_DATA_LOST(0);
+        }
+    }
+}
+
+static void vmRefMic_AGC_PcmRecord( bool isToVoc, volatile uint16 *addr, uint16 len )
+{
+    uint32 I, tmp = 0;
+    uint16 *buf, *mBuf;
+    uint16 logsize;
+
+    logsize = len + 2 + 2;
+
+    buf = vm.pcmBuf;
+    *buf++ = (vm.vm_lost_count << 8) + vm.pcm_lost_count;
+    *buf++ = vm.vm_counter ;
+
+    {   //RefMic
+        EMI_ReadFromDSP((uint16*)buf, addr, len);
+        buf += len;
+        *buf++ = SAL_AGC_GetSWGain(0);
+        *buf = SAL_AGC_GetSWGain(1);
+    }
+
+    buf = vm.pcmBuf;
+
+    if (isToVoc)
+    {
+        vocWriteVocToCatcher(logsize, buf);
+    }
+    else // normal vm process
+    {
+        vmRec_getWriteBuffer( &mBuf, &tmp );
+        if ( tmp > logsize )
+            tmp = logsize;
+        kal_mem_cpy(mBuf, buf, tmp << 1);
+        buf += tmp;
+        mBuf += tmp;
+
+        vmRec_writeDataDone(tmp);
+
+        tmp = logsize - tmp;
+        if ( (int32)tmp > 0 )
+        {
+            vmRec_getWriteBuffer( &mBuf, &I );
+            if (I >= tmp)
+            {
+                kal_mem_cpy(mBuf, buf, tmp << 1);
+                buf += tmp;
+                mBuf += tmp;
+                vmRec_writeDataDone(tmp);
+            }
+            else
+            {
+                MD_TRC_VM_REC_HISR_PCM_DATA_LOST(0);
+            }
+        }
+    }
+}
+
+static void vmEchoRefPcmRecord( bool isToVoc, volatile uint16 *addr, uint16 len )
+{
+    uint32 I, tmp = 0;
+    uint16 *buf, *mBuf;
+    uint16 logsize;
+
+    logsize = len + 2;
+
+    buf = vm.pcmBuf;
+    *buf++ = (vm.vm_lost_count << 8) + vm.pcm_lost_count;
+    *buf++ = vm.vm_counter ;
+
+    EMI_ReadFromDSP((uint16*)buf, addr, len);
+    buf = vm.pcmBuf;
+
+    if (isToVoc)
+    {
+        vocWriteVocToCatcher(logsize, buf);
+    }
+    else // normal vm process
+    {
+        vmRec_getWriteBuffer( &mBuf, &tmp );
+        if ( tmp > logsize )
+            tmp = logsize;
+        kal_mem_cpy(mBuf, buf, tmp << 1);
+        buf += tmp;
+        mBuf += tmp;
+
+        vmRec_writeDataDone(tmp);
+
+        tmp = logsize - tmp;
+        if ( (int32)tmp > 0 )
+        {
+            vmRec_getWriteBuffer( &mBuf, &I );
+            if (I >= tmp)
+            {
+                kal_mem_cpy(mBuf, buf, tmp << 1);
+                buf += tmp;
+                mBuf += tmp;
+                vmRec_writeDataDone(tmp);
+            }
+            else
+            {
+                MD_TRC_VM_REC_HISR_PCM_DATA_LOST(0);
+            }
+        }
+    }
+}
+
+/* ------------------------------------------------------------------------------ */
+void vmTchPcmRecordHisr(void *param)
+{
+    uint16 u2VM_total_size;   // VM + EPL_PCM + EPL_dummy
+    uint16 u2VM_buffer_size;  // VM
+    uint16 u2VM_size;         // Dbg Info size + EPL PCM size
+    uint16 u2EPL_PCM_size = 0;
+    uint16 u2EPL_dummy_size = 0;
+    uint16 *buf;
+    Sal_EPL_Frame eplfrm_t;
+
+    if (KAL_SPINLOCK_NOT_AVAILABLE == kal_take_spinlock(vm.lockId, KAL_NO_WAIT))
+    {
+        MD_TRC_VM_HISR_LOCK_NOT_AVALIABLE(2);
+        goto leaveEplHisr;
+    }
+
+    // dsp status check
+    if ( vm.state != VM_STATE_RECORD )
+    {
+        goto leaveEplProc;
+    }
+
+    // application status check
+    if ( (false == vm.isVocOn) && (false == vm.isVmLOn))
+    {
+        goto leaveEplProc;
+    }
+
+    SAL_EPL_GetFrame(&eplfrm_t);
+
+    if (vm.record_info & VM_EPL_1STSET_RECORD_FLAG) {
+        u2EPL_PCM_size += eplfrm_t.ul_pre_len + eplfrm_t.dl_pre_len;
+        u2EPL_dummy_size += 2;
+    }
+    if (vm.record_info & VM_EPL_2NDSET_RECORD_FLAG) {
+        u2EPL_PCM_size += eplfrm_t.ul_pos_len + eplfrm_t.dl_pos_len;
+        u2EPL_dummy_size += 2;
+    }
+    if (vm.record_info & VM_EPL_REFMIC_RECORD_FLAG) {
+        u2EPL_PCM_size += eplfrm_t.ul2_pos_len;
+        u2EPL_dummy_size += 4;
+    }
+    if (vm.record_info & VM_EPL_ECHOREF_RECORD_FLAG) {
+        u2EPL_PCM_size += eplfrm_t.ul4_pos_len;
+        u2EPL_dummy_size += 2;
+    }
+    if (vm.record_info & VM_EPL_3RDMIC_RECORD_FLAG) {
+        u2EPL_PCM_size += eplfrm_t.ul3_pos_len;
+        u2EPL_dummy_size += 2;
+    }
+    if (vm.record_info & VM_EPL_2NDECHOREF_RECORD_FLAG) {
+        u2EPL_PCM_size += eplfrm_t.ul5_pos_len;
+        u2EPL_dummy_size += 2;
+    }
+
+    // handing the total size u2VM_total_size (vm + pcm buffer) in word(2byte)
+    buf = vm.vmBuf;
+
+    if (buf[0] == VM_VM_MAGIC_HEADER)  //already buffer VM, (normal case)
+    {
+        u2VM_size = VM_VM_DBGINFO_TOTAL_SIZE + u2EPL_PCM_size;
+        u2VM_buffer_size = VM_VM_HEADER_SIZE + VM_VM_CONTROL_SIZE + vm.sc_len + vm.sd_len + VM_VM_DBGINFO_TOTAL_SIZE;
+        kal_prompt_trace(MOD_L1SP, "TchPcmRecordHisr SC Len= %d, SD Len= %d", vm.sc_len, vm.sd_len);
+    }
+    else   // case when previous vmbufer is missing! Save the pcm data with empty vm
+    {
+        u2VM_size = u2EPL_PCM_size;
+        u2VM_buffer_size = VM_VM_HEADER_SIZE;
+    }
+    u2VM_total_size = u2VM_buffer_size + u2EPL_PCM_size + u2EPL_dummy_size;
+
+    buf[3] |= vmEPLBandSet(eplfrm_t.ul_pre_len,  VM_EPL_BAND_UL0_SHIFT);
+    buf[3] |= vmEPLBandSet(eplfrm_t.ul_pos_len,  VM_EPL_BAND_UL1_SHIFT);
+    buf[3] |= vmEPLBandSet(eplfrm_t.dl_pre_len,  VM_EPL_BAND_DL0_SHIFT);
+    buf[3] |= vmEPLBandSet(eplfrm_t.dl_pos_len,  VM_EPL_BAND_DL1_SHIFT);
+    buf[3] |= vmEPLBandSet(eplfrm_t.ul2_pos_len, VM_EPL_BAND_UL2_SHIFT);
+    buf[3] |= vmEPLBandSet(eplfrm_t.ul4_pos_len, VM_EPL_BAND_UL4_SHIFT);
+    buf[3] |= vmEPLBandSet(eplfrm_t.ul3_pos_len, VM_EPL_BAND_UL3_SHIFT);
+    buf[3] |= vmEPLBandSet(eplfrm_t.ul5_pos_len, VM_EPL_BAND_UL5_SHIFT);
+
+    kal_prompt_trace(MOD_L1SP, "UL_PRE %d, UL_POS %d, DL_PRE %d, DL_POS %d, UL2 %d, UL3 %d, UL4 %d, UL5 %d", eplfrm_t.ul_pre_len, eplfrm_t.ul_pos_len, eplfrm_t.dl_pre_len, eplfrm_t.dl_pos_len, eplfrm_t.ul2_pos_len, eplfrm_t.ul3_pos_len, eplfrm_t.ul4_pos_len, eplfrm_t.ul5_pos_len);
+    kal_prompt_trace(MOD_L1SP, "Band %x", buf[3]);
+
+    //when vm logging and VOC are both on, only send the data to vm logging to reduce log size
+    if (vm.isVmLOn)
+    {
+        if (vmRec_queryOutputBufFreeSpace() < u2VM_total_size)
+        {
+            // drop this log and add counter
+            vm.pcm_lost_count++;
+            MD_TRC_VM_REC_HISR_VM_DATA_LOST(vm.vm_lost_count, 1);
+            goto leaveEplProc;
+        }
+        else
+        {
+            uint32 timestamp;
+            buf[0] = VM_VM_MAGIC_HEADER;
+            buf[1] = (u2VM_size << 3) | (L1SP_GetState()) ;
+            buf[2] |= (vm.record_info & VM_EPL_ALL_RECORD_FLAG);
+            // buf[3] is set in previous
+            timestamp =  fma_get_glb_ts() & 0xFFFFFFFF;
+            buf[4] = (uint16)(timestamp & 0xFFFF); // Lo
+            buf[5] = (uint16)(timestamp >> 16);    // High
+
+            vmRec_writeVmToOutputBuf(u2VM_buffer_size, buf);
+
+            //pcm bufs
+            if (vm.record_info & VM_EPL_1STSET_RECORD_FLAG)
+                vm4WayPcmRecord(eplfrm_t.ul_pre_buf, eplfrm_t.ul_pre_len, eplfrm_t.dl_pre_buf, eplfrm_t.dl_pre_len);
+
+            if (vm.record_info & VM_EPL_2NDSET_RECORD_FLAG)
+                vm4WayPcmRecord(eplfrm_t.ul_pos_buf, eplfrm_t.ul_pos_len, eplfrm_t.dl_pos_buf, eplfrm_t.dl_pos_len);
+
+            if (vm.record_info & VM_EPL_REFMIC_RECORD_FLAG)
+                vmRefMic_AGC_PcmRecord(false, eplfrm_t.ul2_pos_buf, eplfrm_t.ul2_pos_len);
+
+            if (vm.record_info & VM_EPL_ECHOREF_RECORD_FLAG)
+                vmEchoRefPcmRecord(false, eplfrm_t.ul4_pos_buf, eplfrm_t.ul4_pos_len);
+
+            if (vm.record_info & VM_EPL_3RDMIC_RECORD_FLAG)
+                vmEchoRefPcmRecord(false, eplfrm_t.ul3_pos_buf, eplfrm_t.ul3_pos_len);
+
+            if (vm.record_info & VM_EPL_2NDECHOREF_RECORD_FLAG)
+                vmEchoRefPcmRecord(false, eplfrm_t.ul5_pos_buf, eplfrm_t.ul5_pos_len);
+        }
+    }
+    else // VOC
+    {
+        // fill vm buffer header
+        uint32 timestamp;
+        buf[0] = VM_VM_MAGIC_HEADER;
+        buf[1] = (u2VM_size << 3) | (L1SP_GetState()) ;
+        buf[2] |= (vm.record_info & VM_EPL_ALL_RECORD_FLAG);
+        // buf[3] is set in previous
+        timestamp =  fma_get_glb_ts() & 0xFFFFFFFF;
+        buf[4] = (uint16)(timestamp & 0xFFFF); // Lo
+        buf[5] = (uint16)(timestamp >> 16);    // High
+
+        vocWriteVocToCatcher(u2VM_buffer_size, buf);
+
+        if (vm.record_info & VM_EPL_1STSET_RECORD_FLAG)
+            voc4WayPcmRecord(eplfrm_t.ul_pre_buf, eplfrm_t.ul_pre_len, eplfrm_t.dl_pre_buf, eplfrm_t.dl_pre_len);
+
+        if (vm.record_info & VM_EPL_2NDSET_RECORD_FLAG)
+            voc4WayPcmRecord(eplfrm_t.ul_pos_buf, eplfrm_t.ul_pos_len, eplfrm_t.dl_pos_buf, eplfrm_t.dl_pos_len);
+
+        if (vm.record_info & VM_EPL_REFMIC_RECORD_FLAG)
+            vmRefMic_AGC_PcmRecord(true, eplfrm_t.ul2_pos_buf, eplfrm_t.ul2_pos_len);
+
+        if (vm.record_info & VM_EPL_ECHOREF_RECORD_FLAG)
+            vmEchoRefPcmRecord(true, eplfrm_t.ul4_pos_buf, eplfrm_t.ul4_pos_len);
+
+        if (vm.record_info & VM_EPL_3RDMIC_RECORD_FLAG)
+            vmEchoRefPcmRecord(true, eplfrm_t.ul3_pos_buf, eplfrm_t.ul3_pos_len);
+
+        if (vm.record_info & VM_EPL_2NDECHOREF_RECORD_FLAG)
+            vmEchoRefPcmRecord(true, eplfrm_t.ul5_pos_buf, eplfrm_t.ul5_pos_len);
+    }
+
+    vm.pcm_lost_count = 0;
+    buf[0] = 0;
+    buf[1] = 0;
+    buf[2] = 0;
+    buf[3] = 0;
+
+leaveEplProc:
+    kal_give_spinlock(vm.lockId);
+
+    if (vm.vm_hdlr) {
+        vm.vm_hdlr();
+    }
+
+leaveEplHisr:
+    return;
+}
+
+void vmTchRecordHisr(void *param)
+{
+    uint16  u2VM_buffer_size;
+    uint16  *vmBuf;
+    uint8   sp_state = L1SP_GetState();
+
+    if (KAL_SPINLOCK_NOT_AVAILABLE == kal_take_spinlock(vm.lockId, KAL_NO_WAIT))
+    {
+        MD_TRC_VM_HISR_LOCK_NOT_AVALIABLE(1);
+        goto leaveHisr;
+    }
+
+    // check dsp status
+    if ( vm.state != VM_STATE_RECORD )
+    {
+        goto leaveProc;
+    }
+
+    // check application status
+    if ( (false == vm.isVocOn) && (false == vm.isVmLOn))
+    {
+        goto leaveProc;
+    }
+
+    // just logging
+#if defined(__MA_L1__)
+    if (!(L1SP_GetState() == L1SP_STATE_3G_SPEECH_ON || L1SP_GetState() == L1SP_STATE_3G324M_SPEECH_ON))
+    {
+        uint8 rx_type, tx_type, BFI;
+        uint16 rx_debug;
+        rx_debug = *DSP_RX_TCH_S(0, 0);
+        tx_type = *DSP_RX_TCH_S(0, 0) & 0x3;
+        rx_type = (rx_debug >> 1) & 0x7;
+        BFI = (rx_debug >> 5) & 0x1;     //speechBFI
+        if ( rx_type < 3 ) //non-amr
+            rx_type = 8 + (rx_type << 1) + BFI;
+        BFI = (rx_debug >> 8) & 0xFF;  //BER
+        MD_TRC_L1Audio_Msg_SPEECH_FRAME( L1SP_Speech_TX_Type(tx_type), L1SP_Speech_RX_Type(rx_type), BFI);
+        MD_TRC_L1Audio_Msg_VM_DEBUG( DP2_3G_debug_info0, DP2_3G_debug_info1, DP2_3G_debug_info7 );
+    }
+#endif
+
+    // process previous buffer
+    vmBuf = vm.vmBuf;
+
+    if (vmBuf[0] == VM_VM_MAGIC_HEADER) //already buffer VM
+    {
+        u2VM_buffer_size = VM_VM_HEADER_SIZE + VM_VM_CONTROL_SIZE + vm.sc_len + vm.sd_len + VM_VM_DBGINFO_TOTAL_SIZE;
+        kal_prompt_trace(MOD_L1SP, "TchRecordHisr SC Len= %d, SD Len= %d", vm.sc_len, vm.sd_len);
+
+        //when vm logging and VOC are both on, only send the data to vm logging to reduce log size
+        if (vm.isVmLOn)
+        {
+            if (vmRec_queryOutputBufFreeSpace() < u2VM_buffer_size)
+            {
+                // drop this log and add counter
+                vm.vm_lost_count++;
+                MD_TRC_VM_REC_HISR_VM_DATA_LOST(vm.vm_lost_count, 2);
+                goto leaveProc;
+            }
+            else
+            {
+                vmRec_writeVmToOutputBuf(u2VM_buffer_size, vmBuf);
+            }
+        }
+        else
+        {
+            vocWriteVocToCatcher(u2VM_buffer_size, vmBuf);
+        }
+
+        vm.vm_lost_count = 0;
+        vmBuf[0] = 0;
+        vmBuf[1] = 0;
+        vmBuf[2] = 0;
+        vmBuf[3] = 0;
+    }
+
+    // formatting
+    Sal_VM_Frame vmfrm_t;
+
+    switch (sp_state)
+    {
+    case L1SP_STATE_4G_SPEECH_ON:
+        SAL_VM_GetFrame3G(&vmfrm_t);
+        vmFormatter_4g(vmBuf, &vmfrm_t);
+        break;
+    case L1SP_STATE_3G_SPEECH_ON:
+    case L1SP_STATE_3G324M_SPEECH_ON:
+        SAL_VM_GetFrame3G(&vmfrm_t);
+        vmFormatter_amr(vmBuf, &vmfrm_t);
+        break;
+    case L1SP_STATE_C2K_SPEECH_ON:
+        SAL_VM_GetFrameC2K(&vmfrm_t);
+        vmFormatter_c2k(vmBuf, &vmfrm_t);
+        break;
+    default:
+        if (L1SP_Get_isStandByMode() || pcmEx_isRunInIdleMode())
+        {
+            SAL_VM_GetFrame3G(&vmfrm_t);
+            vmFormatter_standby(vmBuf, &vmfrm_t);
+        }
+        else
+        {
+            SAL_VM_GetFrame2G(&vmfrm_t);
+            vmFormatter_2g(vmBuf, &vmfrm_t);
+        }
+        break;
+    }
+
+leaveProc:
+    kal_give_spinlock(vm.lockId);
+
+    if (vm.vm_hdlr)
+    {
+        vm.vm_hdlr();
+    }
+
+leaveHisr:
+	SP_updateEmCodecEvent();
+    return;
+}
+
+void VM_Init(void)
+{
+    vm.lockId = kal_create_spinlock("VM_LOCK");
+}
+
+void VMREC_ConfigEpl(void)
+{
+    // only support phone call VM record dynamic change from AP side
+    if (vm.isVocOn || vm.isVmLOn)
+    {
+        kal_uint16 recordInfo = L1Audio_GetDebugInfo(VM_DEBUG_INFO);
+
+        if (ChkL1ClsFltr_L1Audio_VoC_TRACE_EPL())
+        {
+            recordInfo |= (VM_EPL_1STSET_RECORD_FLAG + VM_EPL_2NDSET_RECORD_FLAG);
+            recordInfo |= VM_EPL_REFMIC_RECORD_FLAG;
+            recordInfo |= VM_EPL_ECHOREF_RECORD_FLAG;
+            recordInfo |= VM_EPL_3RDMIC_RECORD_FLAG;
+            recordInfo |= VM_EPL_2NDECHOREF_RECORD_FLAG;
+        }
+
+        MD_TRC_VM_REC_DEBUG_INFO(recordInfo);
+
+        // config to open, and did not open yet
+        if (((recordInfo & (VM_EPL_1STSET_RECORD_FLAG + VM_EPL_2NDSET_RECORD_FLAG)) != 0)
+                && ((vm.record_info & (VM_EPL_1STSET_RECORD_FLAG + VM_EPL_2NDSET_RECORD_FLAG)) == 0))
+        {
+            //EPL open
+            recordInfo |= VM_EPL_REFMIC_RECORD_FLAG;
+            recordInfo |= VM_EPL_ECHOREF_RECORD_FLAG;
+            recordInfo |= VM_EPL_3RDMIC_RECORD_FLAG;
+            recordInfo |= VM_EPL_2NDECHOREF_RECORD_FLAG;
+
+            // Initial
+            vm.record_info = recordInfo;
+            vm.vm_lost_count = 0;
+            vm.pcm_lost_count = 0;
+            vm.vm_counter = 0;
+
+            vm.pcmBuf = vmEPLPCMInputBuf;
+            memset(vmEPLPCMInputBuf, 0, sizeof(uint16)*VM_EPL_PCM_BUFFER_SIZE);
+
+            // Enable EPL
+            L1Audio_HookHisrHandler(DP_D2C_VMEPL_REC_INT, (L1Audio_EventHandler)vmTchPcmRecordHisr, 0);
+            AM_PCM8K_RecordOn(AM_PCM8KREC_APP_TYPE_VMEPL, 0);
+        }
+    }
+}
+
+/**
+    @vm_hdlr: handler
+    @isVoc: is call from vm over catcher.
+*/
+void VMREC_Start(void (*vm_hdlr)(void), bool isVoc)
+{
+    if (AM_IsAmInSpeechState())
+    {
+        //decide the open
+        bool isAlreadyOn = (vm.isVocOn || vm.isVmLOn);
+
+        if (isVoc)
+        {
+            //ASSERT(!vm.isVocOn); // prevent re-entry
+            vm.isVocOn = true;
+        }
+        else  // normal vm
+        {
+            //ASSERT(!vm.isVmLOn); // prevent re-entry
+            vm.isVmLOn = true;
+            vm.vm_hdlr = vm_hdlr;
+        }
+
+#ifdef __SENSITIVE_DATA_MOSAIC__
+        if (dhl_mask_sensitive_trace_on())
+        {
+            vm.isMosaic = true;
+            return;
+        }
+        else
+        {
+            vm.isMosaic = false;
+        }
+#endif
+
+        //already on
+        if (isAlreadyOn)
+        {
+            VMREC_ConfigEpl();
+            return;
+        }
+        else
+        {
+            // Initial
+            vm.audId = L1Audio_GetAudioID();
+            L1Audio_SetFlag(vm.audId); //Be careful.Before Locking SleepMode, to access DSP sherrif tasks much time. So access DSP must be after SetFlag
+
+            vm.state = VM_STATE_RECORD;
+
+            vm.control_1  = VM_VM_CTRL_UL_ON;
+            vm.control_2  = VM_VM_CTRL_DL_ON;
+            vm.control_3  = VM_CHIP_ID;
+            vm.control_4  = 0;
+            vm.control_5  = 0;
+            vm.control_6  = 0;
+            vm.control_7  = 0;
+            vm.control_8  = 0;
+            vm.control_9  = 0;
+            vm.control_10 = 0;
+
+            vm.evs_cur_sd_mode = EVS_UNDEF;
+            vm.sc_len = 0;
+            vm.sd_len = 0;
+
+            //vm buffer initital
+            vm.vmBuf = vmBuffer;
+            memset(vm.vmBuf, 0, sizeof(uint16)*VM_VM_BUFFER_SIZE);
+
+            // output buffer initial
+            vm.pOutputBufWrite = 0;
+            vm.pOutputBufRead = 0;
+            vm.outputBufSize = VMREC_OUTPUT_BUF_SIZE;
+            memset(vmRecOutputBuf, 0, sizeof(uint16)*VMREC_OUTPUT_BUF_SIZE);
+
+            VMREC_ConfigEpl();
+
+#if defined(__G_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+            //G-serial codec buffer initial
+            {
+                vmInitGCodecULBuf();
+                vmInitGCodecDLBuf();
+            }
+#endif
+
+#if defined(__UMTS_RAT__)
+#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
+            //TDD load need to reduce trace
+            if (SP_3G_SIM_FDD_ACTIVE == L1SP_GetSIMStatus() &&
+                    (((int)L1Audio_GetDebugInfo(SPH_DEBUGINFO))& SPH_DEBUGINFO12_BIT1))
+            {
+                g_bNeedExtraLog = KAL_TRUE;
+            }
+#endif
+#endif
+            // enalbe normal VM record
+            L1Audio_HookHisrHandler(DP_D2C_VM_REC_INT, (L1Audio_EventHandler)vmTchRecordHisr, 0);
+            AM_VMRecordOn();
+        }
+    }
+}
+
+/**
+    @isVoc: is call from voice over cater. true is yes; false is no.
+*/
+void VMREC_Stop( bool isVoc)
+{
+    // check voc & vm are both closed.
+    if (AM_IsAmInSpeechState())
+    {
+        if (isVoc)
+        {
+            //ASSERT(vm.isVocOn == true);
+            kal_take_spinlock(vm.lockId, KAL_INFINITE_WAIT);
+            vm.isVocOn = false;
+            kal_give_spinlock(vm.lockId);
+
+            if (vm.isVmLOn) //still another need vm
+            {
+                return;
+            }
+        }
+        else //record vm from media
+        {
+            //ASSERT(vm.isVmLOn == true);
+            kal_take_spinlock(vm.lockId, KAL_INFINITE_WAIT);
+            vm.isVmLOn = false;
+            vm.vm_hdlr = NULL;
+            kal_give_spinlock(vm.lockId);
+
+            if (vm.isVocOn) //still another need vm
+            {
+                return;
+            }
+        }
+
+#ifdef __SENSITIVE_DATA_MOSAIC__
+        {
+            if (vm.isMosaic)
+            {
+                return;
+            }
+        }
+#endif
+
+        if (VM_STATE_RECORD == vm.state)
+        {
+            kal_take_spinlock(vm.lockId, KAL_INFINITE_WAIT);
+            vm.state = VM_STATE_RECORD_STOP;
+            kal_give_spinlock(vm.lockId);
+
+            if (vm.record_info & (VM_EPL_1STSET_RECORD_FLAG + VM_EPL_2NDSET_RECORD_FLAG))
+            {
+                AM_PCM8K_RecordOff(false, AM_PCM8KREC_APP_TYPE_VMEPL);
+                L1Audio_UnhookHisrHandler(DP_D2C_VMEPL_REC_INT);    // EPL record unhook
+
+                vm.pcmBuf = NULL;
+            }
+
+            AM_VMRecordOff();
+            L1Audio_UnhookHisrHandler(DP_D2C_VM_REC_INT);    // vm record unhook
+
+            vm.vmBuf = NULL;
+            vm.state = VM_STATE_STOP;
+            vm.record_info = 0;
+
+            // output buffer clean
+            vm.pOutputBufWrite = 0;
+            vm.pOutputBufRead  = 0;
+            vm.outputBufSize   = 0;
+            memset(vmRecOutputBuf, 0, sizeof(uint16)*VMREC_OUTPUT_BUF_SIZE);
+
+#if defined(__G_CODEC_SUPPORT__) && defined(__VOLTE_SUPPORT__)
+            //G-serial codec buffer initial
+            {
+                vmInitGCodecULBuf();
+                vmInitGCodecDLBuf();
+            }
+#endif
+
+            // release sleep mode
+            L1Audio_ClearFlag(vm.audId);
+            L1Audio_FreeAudioID(vm.audId);
+        }
+    }
+}