[Feature]merge MTK MR3.0 release

Change-Id: I877d3bbcdacfa7d2ab902e6c4c8e740a67069038
diff --git a/src/multimedia/audio-misc/libmodem-afe-ctrl/LICENSE b/src/multimedia/audio-misc/libmodem-afe-ctrl/LICENSE
new file mode 100644
index 0000000..77f59ed
--- /dev/null
+++ b/src/multimedia/audio-misc/libmodem-afe-ctrl/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+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 RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'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 RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
diff --git a/src/multimedia/audio-misc/libmodem-afe-ctrl/Makefile b/src/multimedia/audio-misc/libmodem-afe-ctrl/Makefile
new file mode 100644
index 0000000..670173d
--- /dev/null
+++ b/src/multimedia/audio-misc/libmodem-afe-ctrl/Makefile
@@ -0,0 +1,34 @@
+#SPDX-License-Identifier: MediaTekProprietary
+$(warning !!!!! target platform=$(TARGET_PLATFORM) !!!!!)
+ifeq ($(strip $(TARGET_PLATFORM)), )
+	DIR_MAKEFILE = mt2635
+else
+	DIR_MAKEFILE = $(TARGET_PLATFORM)
+endif
+
+build:
+	$(warning ########## build libmodem ##########)
+	for i in $(DIR_MAKEFILE); do			\
+		(cd $$i && make);			\
+		if [ $$? != 0 ]; then		\
+			exit 1;					\
+		fi							\
+	done
+
+install:
+	$(warning ########## install libmodem ##########)
+	for i in $(DIR_MAKEFILE); do			\
+		(cd $$i && make install);			\
+		if [ $$? != 0 ]; then		\
+			exit 1;					\
+		fi							\
+	done
+
+clean:
+	for i in $(DIR_MAKEFILE); do			\
+		(cd $$i && make clean);			\
+		if [ $$? != 0 ]; then		\
+			exit 1;					\
+		fi							\
+	done
+
diff --git a/src/multimedia/audio-misc/libmodem-afe-ctrl/mt2735/LICENSE b/src/multimedia/audio-misc/libmodem-afe-ctrl/mt2735/LICENSE
new file mode 100644
index 0000000..77f59ed
--- /dev/null
+++ b/src/multimedia/audio-misc/libmodem-afe-ctrl/mt2735/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+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 RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'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 RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
diff --git a/src/multimedia/audio-misc/libmodem-afe-ctrl/mt2735/Makefile b/src/multimedia/audio-misc/libmodem-afe-ctrl/mt2735/Makefile
new file mode 100644
index 0000000..423882f
--- /dev/null
+++ b/src/multimedia/audio-misc/libmodem-afe-ctrl/mt2735/Makefile
@@ -0,0 +1,43 @@
+#SPDX-License-Identifier: MediaTekProprietary
+PREFIX   = ../install
+NAME     = modemafectrl
+COMPILER = GNU
+CROSS    = arm-linux-
+CROSS_SUP= arm-linux- arm-none-eabi- aarch64-linux-
+GCC         = $(CROSS)gcc
+CC          = $(GCC)
+CXX         = $(CROSS)g++
+OBJDUMP     = $(CROSS)objdump
+OBJCOPY     = $(CROSS)objcopy
+AR          = $(CROSS)ar
+
+OFLAGS      ?= -g -O0 -fPIC -Wno-missing-braces
+
+ifeq ($(strip $(CROSS)), arm-linux-)
+	CFLAGS = -mthumb-interwork
+endif
+
+INIT 	   = syss_init
+LDFLAGS  = $(BB_LDFLAGS_ADD) -Wl,--hash-style=gnu -L. -L $(ROOT)/lib
+LOCAL_PATH   = .
+
+
+all: libmodemafectrl.so
+	
+INCLUDE = -Iinclude
+
+libmodemafectrl.so: pcm_ctrl.o
+	$(CC) $(OFLAGS) $(INCLUDE) ${LDFLAGS} -lasound -lmtk_audio_mixer_ctrl -shared -o $@ pcm_ctrl.o
+
+pcm_ctrl.o: include/
+	$(CC) $(OFLAGS) $(INCLUDE) ${CFLAGS} -c src/pcm_ctrl.c -o $@
+
+install:
+	mkdir -p ../include
+	cp -af include/* ../include/
+
+	mkdir -p $(ROOT)/${base_libdir}/
+	cp lib$(NAME).so $(ROOT)/${base_libdir}/
+	
+clean:
+	rm -f libmodemafectrl.so
diff --git a/src/multimedia/audio-misc/libmodem-afe-ctrl/mt2735/include/dev_string.h b/src/multimedia/audio-misc/libmodem-afe-ctrl/mt2735/include/dev_string.h
new file mode 100644
index 0000000..d3541a3
--- /dev/null
+++ b/src/multimedia/audio-misc/libmodem-afe-ctrl/mt2735/include/dev_string.h
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: MediaTekProprietary
+#ifndef _DEV_STRING_H_
+#define _DEV_STRING_H_
+
+/* modem device name*/
+#define MODEM_DEV_NAME "hw:0,18" //"hw:0,15"
+#define MODEM_BT_DEV_NAME "hw:0,18"
+
+#endif
diff --git a/src/multimedia/audio-misc/libmodem-afe-ctrl/mt2735/include/modem_afe_ctrl.h b/src/multimedia/audio-misc/libmodem-afe-ctrl/mt2735/include/modem_afe_ctrl.h
new file mode 100644
index 0000000..f67a164
--- /dev/null
+++ b/src/multimedia/audio-misc/libmodem-afe-ctrl/mt2735/include/modem_afe_ctrl.h
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: MediaTekProprietary
+/*
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2016. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+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 RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'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 RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+
+Auther: Garlic Tseng <garlic.tseng@mediatek.com>
+*/
+
+/*
+usage:
+1. call get_default_device to get the system default phonecall device
+2. call enable_phone_call_AFE_path when phone call is enabled
+   (may or may not use default device)
+3. call disable_phone_call_AFE_path when phone call is disabled
+*/
+
+#ifndef _MODEM_ALSA_LIB_H_
+#define _MODEM_ALSA_LIB_H_
+
+typedef enum {
+	DEV_SPK,
+	DEV_SPK_EX,
+	DEV_DIRECT,
+	DEV_DIRECT_LO,
+	DEV_HP,
+	DEV_BT,
+	DEV_DEFAULT,
+	DEV_NUM = DEV_DEFAULT,
+	DEV_INVALID = -1,
+} Audio_device;
+
+/***********************************************
+ * The API below will make request to server.  *
+ ***********************************************/
+
+//enable audio path for modem.
+//return value: 0 if success, or negitive error number
+int enable_phone_call_AFE_path(int audio_device);
+
+//close audio path for modem
+//return value: 0 if success, or negitive error number
+int disable_phone_call_AFE_path(void);
+
+//get default device.
+//return value: default device setting
+int get_default_device(void);
+
+//set UL analog gain
+//return value: 0 if success, or negitive error number
+int set_UL_analog_gain(int dB);
+
+//set DL analog gain
+//return value: 0 if success, or negitive error number
+int set_DL_analog_gain(int dB);
+
+//set BT WB on
+//return value: 0 if success, or negitive error number
+int set_BT_WB(int on);
+
+//change device when the phone call is enabled
+//return value: 0 if success, or negitive error number
+int dynamic_switch_phone_call_path(int audio_device);
+
+//set phonecall sample rate
+//return value: 0 if success, or negitive error number
+int set_phonecall_rate(int rate);
+
+
+/***********************************************
+ * IPC define.                                 *
+ ***********************************************/
+
+#define FUNC_ENABLE_PHONE_CALL_AFE_PATH 0
+#define FUNC_DISABLE_PHONE_CALL_AFE_PATH 1
+#define FUNC_GET_DEFAULT_VALUE 2
+#define FUNC_SET_UL_ANALOG_GAIN 3
+#define FUNC_SET_DL_ANALOG_GAIN 4
+#define FUNC_SET_BT_WB 5
+#define FUNC_DYNAMIC_SWITCH_PHONE_CALL_PATH 6
+#define FUNC_SET_PHONE_CALL_SAMPLERATE 7
+
+/***********************************************
+ * default parameter                           *
+ ***********************************************/
+
+#define FUNC_SET_BT_WB_default 0 //default off
+
+/******************************************************************************
+ * The API below is for service to call. Please use API defined above if you  *
+ * are not service.                                                           *
+ ******************************************************************************/
+int set_BT_wb(int on);
+int set_phonecall_rate_for_service(int rate);
+
+//enable audio path for modem.
+//return value: 0 if success, or negitive error number
+int enable_phone_call_AFE_path_for_service(int audio_device);
+
+//close audio path for modem
+//return value: 0 if success, or negitive error number
+int disable_phone_call_AFE_path_for_service(void);
+
+//get default device.
+//return value: default device setting
+int get_default_device_for_service(void);
+
+//set UL analog gain
+int set_UL_analog_gain_for_service(int dB);
+
+//set DL analog gain
+int set_DL_analog_gain_for_service(int dB);
+
+//change device when the phone call is enabled
+int dynamic_switch_phone_call_path_for_service(int audio_device);
+
+#endif //_MODEM_ALSA_LIB_H_
+
diff --git a/src/multimedia/audio-misc/libmodem-afe-ctrl/mt2735/src/pcm_ctrl.c b/src/multimedia/audio-misc/libmodem-afe-ctrl/mt2735/src/pcm_ctrl.c
new file mode 100644
index 0000000..cedf569
--- /dev/null
+++ b/src/multimedia/audio-misc/libmodem-afe-ctrl/mt2735/src/pcm_ctrl.c
@@ -0,0 +1,1053 @@
+// SPDX-License-Identifier: MediaTekProprietary
+/*
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2016. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+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 RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'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 RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+
+Auther: Garlic Tseng <garlic.tseng@mediatek.com>
+*/
+#include <pthread.h>
+#include <error.h>
+#include <signal.h>
+#include <stdio.h>
+#include <alsa/asoundlib.h>
+#include <semaphore.h>
+#include "modem_afe_ctrl.h"
+#include "mixer_ctrl.h"
+#include "dev_string.h"
+
+#include <syslog.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "phonecall_pcm"
+
+#define STR_SIZE 128
+#define ARRAY_SIZE(x)  (sizeof(x) / sizeof((x)[0]))
+//#define USE_MIC_0
+
+static int g_device = DEV_DEFAULT;
+static int g_afe_enabled;
+
+/* prevent disable when enable (or vice versa) */
+static pthread_mutex_t g_afe_enabled_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static snd_pcm_t *g_pcm_playback_handle;
+static snd_pcm_t *g_pcm_capture_handle;
+
+static snd_pcm_t *g_pcm_playback_handle_bt;
+
+static int do_enable_AFE_l(void);
+static int do_disable_AFE_l(void);
+
+static int open_start_pcm(void);
+static void close_pcm(void);
+
+static int open_start_bt_pcm(void);
+static void close_bt_pcm(void);
+
+static void store_AFE_original_setting();
+static void restore_AFE_original_setting();
+
+static void do_AFE_open_sequence(int dev);
+static void do_AFE_close_sequence(int dev);
+static void do_bt_open_sequence(void);
+static void do_bt_close_sequence(void);
+static void do_internal_codec_open_sequence(int dev);
+static void do_internal_codec_close_sequence(int dev);
+static void do_ext_codec_open_sequence(int dev);
+static void do_ext_codec_close_sequence(int dev);
+static int is_using_internal_codec(void);
+
+static int do_IPC_call(const char* cmd);
+
+
+typedef enum {
+	MixerName,
+	MixerValue,
+	MixerPairSize,
+} MixerCtrlPair;
+
+typedef char Mixer_pair[MixerPairSize][STR_SIZE];
+typedef char String[STR_SIZE];
+
+/*now we fix playback & record to hs.*/
+/*will remove the constrain after codec reflection finish.*/
+static const String MIXER_BACKUP_LIST_NAME[] = {
+	"I2S0_HD_Mux",
+	"I2S3_HD_Mux",
+	"I2S3_Out_Mux",
+	"OUT1 MUX",
+	"AIN MUX",
+};
+
+static int MIXER_BACKUP_LIST_VALUE[ARRAY_SIZE(MIXER_BACKUP_LIST_NAME)];
+
+static const String INTERCONN_BACKUP_LIST_NAME[] = {
+	/*{mixer name, option name}*/
+	"PCM_2_PB_CH1 I2S0_CH1",
+	"I2S3_CH1 PCM_2_CAP_CH1",
+	"I2S3_CH2 PCM_2_CAP_CH2",
+	"I2S3_CH1 DL1_CH1",
+	"I2S3_CH2 DL1_CH2",
+	"UL2_CH1 I2S0_CH1",
+	"UL2_CH2 I2S0_CH2",
+};
+
+static int INTERCONN_BACKUP_LIST_VALUE[ARRAY_SIZE(INTERCONN_BACKUP_LIST_NAME)];
+
+static const Mixer_pair SPK_ENABLE_SEQ[] = {
+	/*{mixer name, option name}*/
+	{"I2S0_HD_Mux", "Low_Jitter"},
+	{"I2S3_HD_Mux", "Low_Jitter"},
+	{"I2S3_Out_Mux", "Output_Widget"},
+	{"OUT1 MUX", "DAC"},
+	{"Lineout Type", "Differential"},
+	{"BICK Frequency", "32fs"},
+	{"ADC Input Type", "Single-end"},
+	{"AIN MUX", "AIN1"},
+};
+
+static const Mixer_pair HP_ENABLE_SEQ[] = {
+	/*{mixer name, option name}*/
+	{"ETDM_HD_Mux", "Normal"},
+	{"ETDM_PCM1_MUX", "PCM"},
+};
+
+static const Mixer_pair DIRECT_ENABLE_SEQ[] = {
+	/*{mixer name, option name}*/
+	{"ETDM_HD_Mux", "Normal"},
+	{"ETDM_PCM1_MUX", "PCM"},
+};
+
+static const Mixer_pair DIRECT_LO_ENABLE_SEQ[] = {
+	{"ETDM_HD_Mux", "Normal"},
+	{"ETDM_PCM1_MUX", "PCM"},
+};
+
+//TBD
+static const Mixer_pair BT_ENABLE_SEQ[] = {
+	/*{mixer name, option name}*/
+	{"ETDM_HD_Mux", "Normal"},
+};
+
+static const Mixer_pair SPK_DISABLE_SEQ[] = {
+	/*{mixer name, option name}*/
+	{"I2S3_HD_Mux", "Normal"},
+	{"I2S0_HD_Mux", "Normal"},
+	{"I2S3_Out_Mux", "Normal"},
+	{"OUT1 MUX", "VCOM"},
+	{"Lineout Type", "Single-end"},
+};
+
+static const Mixer_pair HP_DISABLE_SEQ[] = {
+	/*{mixer name, option name}*/
+	{"ETDM_HD_Mux", "Normal"},
+	{"ETDM_PCM1_MUX", "PCM"},
+};
+
+static const Mixer_pair DIRECT_DISABLE_SEQ[] = {
+	/*{mixer name, option name}*/
+	{"ETDM_HD_Mux", "Normal"},
+	{"ETDM_PCM1_MUX", "PCM"},
+};
+
+static const Mixer_pair DIRECT_LO_DISABLE_SEQ[] = {
+	/*{mixer name, option name}*/
+	{"ETDM_HD_Mux", "Normal"},
+	{"ETDM_PCM1_MUX", "PCM"},
+};
+
+//TBD
+static const Mixer_pair BT_DISABLE_SEQ[] = {
+	/*{mixer name, option name}*/
+	{"ETDM_HD_Mux", "Normal"},
+};
+
+static const Mixer_pair INT_CODEC_INTERCONN_SEQ[] = {
+    /*{mixer name, option name}*/
+	{"PCM_2_PB_CH1 I2S0_CH1", "1"},
+	{"I2S3_CH1 PCM_2_CAP_CH1", "1"},
+	{"I2S3_CH2 PCM_2_CAP_CH1", "1"},
+};
+
+
+static const Mixer_pair BT_INTERCONN_SEQ[] = {
+	/*{mixer name, option name}*/
+};
+
+/*external codec seq, should modify if new codec applied*/
+static const Mixer_pair EXT_CODEC_ENABLE_SEQ[] = {
+    /*{mixer name, option name}*/
+	{"ETDM_PCM1_MUX", "PCM"},
+};
+
+static const Mixer_pair EXT_CODEC_DISABLE_SEQ[] = {
+	/*{mixer name, option name}*/
+	{"ETDM_HD_Mux", "Normal"},
+	{"ETDM_PCM1_MUX", "PCM"},
+};
+
+static const Mixer_pair EXT_CODEC_INTERCONN_SEQ[] = {
+	/*{mixer name, option name}*/
+	{"Ext_Speaker_Amp", "1"},
+	{"ETDM_PB_CH1 DL1_CH1", "1"},
+	{"ETDM_PB_CH1 DL1_CH2", "1"},
+	{"UL1_CH1 ETDM_CAP_CH1", "1"},
+	{"UL1_CH2 ETDM_CAP_CH1", "1"},
+};
+
+/*external codec seq end*/
+
+/* for BT WB */
+static pthread_mutex_t g_BT_WB_on_lock = PTHREAD_MUTEX_INITIALIZER;
+static int g_BT_WB_on = FUNC_SET_BT_WB_default;
+int set_BT_wb(int on){
+    pthread_mutex_lock(&g_BT_WB_on_lock);
+    g_BT_WB_on = !!on;
+    pthread_mutex_unlock(&g_BT_WB_on_lock);
+    return 0;
+}
+/* for BT WB end*/
+
+static int phonecall_rate = 16000;
+
+int set_phonecall_rate_for_service(int rate)
+{
+	phonecall_rate = rate;
+	return 0;
+}
+
+int enable_phone_call_AFE_path_for_service(int audio_device)
+{
+	int ret;
+
+	pthread_mutex_lock(&g_afe_enabled_lock);
+	if (g_afe_enabled) {
+		printf("%s, modem path already opened.\n", __func__);
+		pthread_mutex_unlock(&g_afe_enabled_lock);
+		return -EBUSY;
+	}
+	printf("%s.YR\n", __func__);
+
+	g_device = audio_device;
+	if (audio_device == DEV_DEFAULT)
+		g_device = get_default_device_for_service();
+
+	ret = do_enable_AFE_l();
+
+	if (ret)
+		printf("%s, pthread_create failed: %d\n", __func__, ret);
+
+	pthread_mutex_unlock(&g_afe_enabled_lock);
+
+	return ret;
+}
+
+int disable_phone_call_AFE_path_for_service(void)
+{
+	int ret;
+
+	pthread_mutex_lock(&g_afe_enabled_lock);
+	if (!g_afe_enabled) {
+		printf("%s, modem path not opened.\n", __func__);
+		pthread_mutex_unlock(&g_afe_enabled_lock);
+		return 0;
+	}
+
+	ret = do_disable_AFE_l();
+	if (ret)
+		printf("%s, do_disable_AFE_l failed: %d\n", __func__, ret);
+
+	pthread_mutex_unlock(&g_afe_enabled_lock);
+	return ret;
+}
+
+/*do enable sequence, need lock outside*/
+static int do_enable_AFE_l(void)
+{
+	int device;
+	int ret;
+
+	device = g_device;
+	do_AFE_open_sequence(device);
+	//ret = open_start_pcm(); //Garlic!!! tmp test BT
+	if (device != DEV_BT)
+		ret = open_start_pcm();
+	else
+		ret = open_start_bt_pcm();
+	if (ret) {
+		printf("%s, open_start_pcm failed: %d\n", __func__, ret);
+		close_pcm();
+		return ret;
+	}
+
+	g_afe_enabled = 1;
+
+	return 0;
+}
+
+/*do disable sequence, need lock outside*/
+static int do_disable_AFE_l(void){
+	int device;
+	device = g_device;
+
+	g_afe_enabled = 0;
+	//close_pcm(); //Garlic!!! tmp test BT
+	if (device != DEV_BT)
+		close_pcm();
+	else
+		close_bt_pcm();
+
+	do_AFE_close_sequence(device);
+	return 0;
+}
+
+int get_default_device_for_service(void)
+{
+	int mix_value;
+
+	mix_value = get_mixer_ctrl_interconn_value("Ext_Speaker_Amp");
+
+	printf("%s, mix_value %d\n", __func__, mix_value);
+
+	if (mix_value==1)
+		return DEV_SPK;
+	else if (mix_value < 0)
+		printf("get_mixer_ctrl_value_int for LOL Mux error!\n");
+
+	/* TODO: add BT device support */
+	printf("no available device, use spk for default\n");
+	return DEV_SPK;
+}
+
+static int open_start_pcm(void)
+{
+	int ret = 0;
+	snd_pcm_hw_params_t *hw_params = NULL;
+	snd_pcm_hw_params_t *hw_params_c = NULL;
+
+	/*pcm interface create*/
+	if ((ret = snd_pcm_open(&g_pcm_playback_handle, MODEM_DEV_NAME,
+				SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
+		printf ("cannot open audio device %s (%s)\n",
+			 MODEM_DEV_NAME, snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_open(&g_pcm_capture_handle, MODEM_DEV_NAME,
+				SND_PCM_STREAM_CAPTURE, 0)) < 0) {
+		printf ("cannot open audio device %s (%s)\n",
+			 MODEM_DEV_NAME, snd_strerror(ret));
+		return ret;
+	}
+
+	snd_pcm_hw_params_alloca(&hw_params);
+	if (hw_params == NULL) {
+		printf ("cannot allocate hardware parameter structure (%s)\n",
+			 snd_strerror(ret));
+		return ret;
+	}
+
+	snd_pcm_hw_params_alloca(&hw_params_c);
+	if (hw_params_c == NULL) {
+		printf ("cannot allocate hardware parameter structure (%s)\n",
+			 snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params_any(g_pcm_playback_handle, hw_params)) < 0) {
+		printf ("cannot initialize hardware parameter structure (%s)\n",
+			 snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params_any(g_pcm_capture_handle, hw_params_c)) < 0) {
+		printf ("cannot initialize hardware parameter structure (%s)\n",
+			 snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params_set_access(g_pcm_playback_handle, hw_params,
+						SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+		printf ("cannot set access type (%s)\n", snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params_set_access(g_pcm_capture_handle, hw_params_c,
+						SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+		printf ("cannot set access type (%s)\n", snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params_set_format(g_pcm_playback_handle, hw_params,
+						SND_PCM_FORMAT_S16_LE)) < 0) {
+		printf ("cannot set sample format (%s)\n", snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params_set_format(g_pcm_capture_handle, hw_params_c,
+						SND_PCM_FORMAT_S16_LE)) < 0) {
+		printf ("cannot set sample format (%s)\n", snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params_set_rate(g_pcm_playback_handle, hw_params, phonecall_rate, 0)) < 0) {
+		printf ("cannot set sample rate (%s)\n", snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params_set_rate(g_pcm_capture_handle, hw_params_c, phonecall_rate, 0)) < 0) {
+		printf ("cannot set sample rate (%s)\n", snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params_set_channels(g_pcm_playback_handle, hw_params, 2)) < 0) {
+		printf ("cannot set channel count (%s)\n", snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params_set_channels(g_pcm_capture_handle, hw_params_c, 2)) < 0) {
+		printf ("cannot set channel count (%s)\n", snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params (g_pcm_playback_handle, hw_params)) < 0) {
+		printf ("cannot set parameters(%s)\n", snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params (g_pcm_capture_handle, hw_params_c)) < 0) {
+		printf ("cannot set parameters(%s)\n", snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_prepare(g_pcm_playback_handle)) < 0) {
+		printf ("cannot prepare audio interface for use (%s)\n",
+			 snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_prepare(g_pcm_capture_handle)) < 0) {
+		printf ("cannot prepare audio interface for use (%s)\n",
+			 snd_strerror(ret));
+		return ret;
+	}
+
+	snd_pcm_start(g_pcm_playback_handle);
+	snd_pcm_start(g_pcm_capture_handle);
+
+	return ret;
+}
+
+
+static int open_start_bt_pcm(void)
+{
+	int ret;
+	snd_pcm_hw_params_t *hw_params = NULL;
+
+        pthread_mutex_lock(&g_BT_WB_on_lock);
+	/*pcm interface create*/
+	if ((ret = snd_pcm_open(&g_pcm_playback_handle_bt, MODEM_BT_DEV_NAME,
+				SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
+		printf ("cannot open audio device %s (%s)\n",
+			 MODEM_BT_DEV_NAME, snd_strerror(ret));
+		return ret;
+	}
+
+	snd_pcm_hw_params_alloca(&hw_params);
+	if (hw_params == NULL) {
+		printf ("cannot allocate hardware parameter structure (%s)\n",
+			 snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params_any(g_pcm_playback_handle_bt, hw_params)) < 0) {
+		printf ("cannot initialize hardware parameter structure (%s)\n",
+			 snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params_set_access(g_pcm_playback_handle_bt, hw_params,
+						SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+		printf ("cannot set access type (%s)\n", snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params_set_format(g_pcm_playback_handle_bt, hw_params,
+						SND_PCM_FORMAT_S16_LE)) < 0) {
+		printf ("cannot set sample format (%s)\n", snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params_set_rate(g_pcm_playback_handle_bt,
+	                                      hw_params,
+	                                      g_BT_WB_on? 16000: 8000, 0)) < 0) {
+		printf ("cannot set sample rate (%s)\n", snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params_set_channels(g_pcm_playback_handle_bt, hw_params, 1)) < 0) {
+		printf ("cannot set channel count (%s)\n", snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_hw_params (g_pcm_playback_handle_bt, hw_params)) < 0) {
+		printf ("cannot set parameters(%s)\n", snd_strerror(ret));
+		return ret;
+	}
+
+	if ((ret = snd_pcm_prepare(g_pcm_playback_handle_bt)) < 0) {
+		printf ("cannot prepare audio interface for use (%s)\n",
+			 snd_strerror(ret));
+		return ret;
+	}
+
+	snd_pcm_start(g_pcm_playback_handle_bt);
+        pthread_mutex_unlock(&g_BT_WB_on_lock);
+
+	return ret;
+}
+
+
+static void close_pcm(void)
+{
+	if (g_pcm_playback_handle != NULL) {
+		snd_pcm_close(g_pcm_playback_handle);
+		g_pcm_playback_handle = NULL;
+	}
+	if (g_pcm_capture_handle != NULL) {
+		snd_pcm_close(g_pcm_capture_handle);
+		g_pcm_capture_handle = NULL;
+	}
+}
+
+static void close_bt_pcm(void)
+{
+	if (g_pcm_playback_handle_bt != NULL) {
+		snd_pcm_close(g_pcm_playback_handle_bt);
+		g_pcm_playback_handle_bt = NULL;
+	}
+}
+
+static void store_AFE_original_setting()
+{
+	int i;
+
+	for(i = 0;i < ARRAY_SIZE(INTERCONN_BACKUP_LIST_NAME); i++)
+		INTERCONN_BACKUP_LIST_VALUE[i] =
+			get_mixer_ctrl_interconn_value(INTERCONN_BACKUP_LIST_NAME[i]);
+
+	for(i = 0;i < ARRAY_SIZE(MIXER_BACKUP_LIST_NAME); i++)
+		MIXER_BACKUP_LIST_VALUE[i] =
+			get_mixer_ctrl_value_int(MIXER_BACKUP_LIST_NAME[i]);
+}
+
+
+
+static void restore_AFE_original_setting()
+{
+	int i, ret;
+	int device;
+
+	for(i = 0;i < ARRAY_SIZE(MIXER_BACKUP_LIST_NAME); i++) {
+		ret = set_mixer_ctrl_value_int(MIXER_BACKUP_LIST_NAME[i],
+					       MIXER_BACKUP_LIST_VALUE[i]);
+		if(ret)
+			printf("%s, restore_AFE_original_setting error %d, %s, %d\n",
+				__func__, ret,
+				MIXER_BACKUP_LIST_NAME[i],
+				MIXER_BACKUP_LIST_VALUE[i]);
+	}
+
+	for(i = 0;i < ARRAY_SIZE(INTERCONN_BACKUP_LIST_NAME); i++) {
+		ret = set_mixer_ctrl_interconn_value(INTERCONN_BACKUP_LIST_NAME[i],
+					       INTERCONN_BACKUP_LIST_VALUE[i]);
+		if(ret)
+			printf("%s, restore_AFE_original_setting error %d, %s, %d\n",
+				__func__, ret,
+				INTERCONN_BACKUP_LIST_NAME[i],
+				INTERCONN_BACKUP_LIST_VALUE[i]);
+	}
+}
+
+static void do_AFE_open_sequence(int dev)
+{
+	printf("YR %s, dev: %d\n", __func__, dev);
+
+	if (dev == DEV_BT) {
+		do_bt_open_sequence();
+	} else if (is_using_internal_codec()) {
+		store_AFE_original_setting();
+		do_internal_codec_open_sequence(dev);
+	} else {
+		do_ext_codec_open_sequence(dev);
+	}
+}
+
+static void do_AFE_close_sequence(int dev)
+{
+	if (dev == DEV_BT) {
+		do_bt_close_sequence();
+	} else if (is_using_internal_codec()) {
+		do_internal_codec_close_sequence(dev);
+		restore_AFE_original_setting();
+	} else {
+		do_ext_codec_close_sequence(dev);
+	}
+}
+
+static void do_bt_open_sequence(void)
+{
+	int i, ret;
+
+	for(i = 0;i < ARRAY_SIZE(BT_ENABLE_SEQ); i++){
+		ret = set_mixer_ctrl_value_string(BT_ENABLE_SEQ[i][MixerName],
+				     BT_ENABLE_SEQ[i][MixerValue]);
+		if(ret)
+			printf("%s, set_mixer_ctrl_value_string error %d, %s, %s\n",
+				__func__, ret,
+				BT_ENABLE_SEQ[i][MixerName],
+				BT_ENABLE_SEQ[i][MixerValue]);
+	}
+
+	for(i = 0;i < ARRAY_SIZE(BT_INTERCONN_SEQ); i++){
+		ret = set_mixer_ctrl_interconn_value(BT_INTERCONN_SEQ[i][MixerName],
+					 atoi(BT_INTERCONN_SEQ[i][MixerValue]));
+		if(ret)
+			printf("%s, set_mixer_ctrl_interconn_value error %d, %s, %s\n",
+				__func__, ret,
+				BT_INTERCONN_SEQ[i][MixerName],
+				BT_INTERCONN_SEQ[i][MixerValue]);
+	}
+}
+
+static void do_bt_close_sequence(void)
+{
+	int i, ret;
+
+	for(i = 0;i < ARRAY_SIZE(BT_INTERCONN_SEQ); i++){
+		ret = set_mixer_ctrl_interconn_value(BT_INTERCONN_SEQ[i][MixerName], 0);
+		if(ret)
+			printf("%s, set_mixer_ctrl_interconn_value error %d, %s, 0\n",
+				__func__, ret,
+				BT_INTERCONN_SEQ[i][MixerName]);
+	}
+
+	for(i = 0;i < ARRAY_SIZE(BT_DISABLE_SEQ); i++){
+		ret = set_mixer_ctrl_value_string(BT_DISABLE_SEQ[i][MixerName],
+				     BT_DISABLE_SEQ[i][MixerValue]);
+		if(ret)
+			printf("%s, set_mixer_ctrl_value_string error %d, %s, %s\n",
+				__func__, ret,
+				BT_DISABLE_SEQ[i][MixerName],
+				BT_DISABLE_SEQ[i][MixerValue]);
+	}
+}
+
+static void do_internal_codec_open_sequence(int dev)
+{
+	int i, ret;
+	printf("YR %s, dev: %d\n", __func__, dev);
+
+	/*TODO: make it simpler*/
+	switch(dev) {
+	case DEV_SPK:
+		for(i = 0;i < ARRAY_SIZE(SPK_ENABLE_SEQ); i++){
+			ret = set_mixer_ctrl_value_string(SPK_ENABLE_SEQ[i][MixerName],
+					     SPK_ENABLE_SEQ[i][MixerValue]);
+			//if(ret)
+				printf("%s,YR set_mixer_ctrl_value_string error %d, %s, %s\n",
+					__func__, ret,
+					SPK_ENABLE_SEQ[i][MixerName],
+					SPK_ENABLE_SEQ[i][MixerValue]);
+		}
+
+		for(i = 0;i < ARRAY_SIZE(INT_CODEC_INTERCONN_SEQ); i++){
+			ret = set_mixer_ctrl_interconn_value(INT_CODEC_INTERCONN_SEQ[i][MixerName],
+						 atoi(INT_CODEC_INTERCONN_SEQ[i][MixerValue]));
+			//if(ret)
+				printf("%s,YR set_mixer_ctrl_interconn_value error %d, %s, %s\n",
+					__func__, ret,
+					INT_CODEC_INTERCONN_SEQ[i][MixerName],
+					INT_CODEC_INTERCONN_SEQ[i][MixerValue]);
+		}
+		break;
+	case DEV_HP:
+		for(i = 0;i < ARRAY_SIZE(HP_ENABLE_SEQ); i++){
+			ret = set_mixer_ctrl_value_string(HP_ENABLE_SEQ[i][MixerName],
+					     HP_ENABLE_SEQ[i][MixerValue]);
+			if(ret)
+				printf("%s, set_mixer_ctrl_value_string error %d, %s, %s\n",
+					__func__, ret,
+					HP_ENABLE_SEQ[i][MixerName],
+					HP_ENABLE_SEQ[i][MixerValue]);
+		}
+		break;
+	case DEV_DIRECT:
+		for(i = 0;i < ARRAY_SIZE(DIRECT_ENABLE_SEQ); i++){
+			ret = set_mixer_ctrl_value_string(DIRECT_ENABLE_SEQ[i][MixerName],
+					     DIRECT_ENABLE_SEQ[i][MixerValue]);
+			if(ret)
+				printf("%s, set_mixer_ctrl_value_string error %d, %s, %s\n",
+					__func__, ret,
+					DIRECT_ENABLE_SEQ[i][MixerName],
+					DIRECT_ENABLE_SEQ[i][MixerValue]);
+		}
+		break;
+	case DEV_DIRECT_LO:
+		for(i = 0;i < ARRAY_SIZE(DIRECT_LO_ENABLE_SEQ); i++){
+			ret = set_mixer_ctrl_value_string(DIRECT_LO_ENABLE_SEQ[i][MixerName],
+					     DIRECT_LO_ENABLE_SEQ[i][MixerValue]);
+			if(ret)
+				printf("%s, set_mixer_ctrl_value_string error %d, %s, %s\n",
+					__func__, ret,
+					DIRECT_LO_ENABLE_SEQ[i][MixerName],
+					DIRECT_LO_ENABLE_SEQ[i][MixerValue]);
+		}
+		break;
+	default:
+		printf("%s, device error, device: %d", __func__, dev);
+		break;
+	}
+}
+
+static void do_internal_codec_close_sequence(int dev)
+{
+	int i, ret;
+
+	/*TODO: make it simpler*/
+	switch(dev) {
+	case DEV_SPK:
+		for(i = 0;i < ARRAY_SIZE(SPK_DISABLE_SEQ); i++){
+			ret = set_mixer_ctrl_value_string(SPK_DISABLE_SEQ[i][MixerName],
+					     SPK_DISABLE_SEQ[i][MixerValue]);
+			if(ret)
+				printf("%s, set_mixer_ctrl_value_string error %d, %s, %s\n",
+					__func__, ret,
+					SPK_DISABLE_SEQ[i][MixerName],
+					SPK_DISABLE_SEQ[i][MixerValue]);
+		}
+
+		for(i = 0;i < ARRAY_SIZE(INT_CODEC_INTERCONN_SEQ); i++){
+			ret = set_mixer_ctrl_interconn_value(INT_CODEC_INTERCONN_SEQ[i][MixerName], 0);
+			if(ret)
+				printf("%s, set_mixer_ctrl_interconn_value error %d, %s, 0\n",
+					__func__, ret,
+					INT_CODEC_INTERCONN_SEQ[i][MixerName]);
+		}
+		break;
+	case DEV_HP:
+		for(i = 0;i < ARRAY_SIZE(HP_DISABLE_SEQ); i++){
+			ret = set_mixer_ctrl_value_string(HP_DISABLE_SEQ[i][MixerName],
+					     HP_DISABLE_SEQ[i][MixerValue]);
+			if(ret)
+				printf("%s, set_mixer_ctrl_value_string error %d, %s, %s\n",
+					__func__, ret,
+					HP_DISABLE_SEQ[i][MixerName],
+					HP_DISABLE_SEQ[i][MixerValue]);
+		}
+		break;
+	case DEV_DIRECT:
+		for(i = 0;i < ARRAY_SIZE(DIRECT_DISABLE_SEQ); i++){
+			ret = set_mixer_ctrl_value_string(DIRECT_DISABLE_SEQ[i][MixerName],
+					     DIRECT_DISABLE_SEQ[i][MixerValue]);
+			if(ret)
+				printf("%s, set_mixer_ctrl_value_string error %d, %s, %s\n",
+					__func__, ret,
+					DIRECT_DISABLE_SEQ[i][MixerName],
+					DIRECT_DISABLE_SEQ[i][MixerValue]);
+		}
+		break;
+	case DEV_DIRECT_LO:
+		for(i = 0;i < ARRAY_SIZE(DIRECT_LO_DISABLE_SEQ); i++){
+			ret = set_mixer_ctrl_value_string(DIRECT_LO_DISABLE_SEQ[i][MixerName],
+					     DIRECT_LO_DISABLE_SEQ[i][MixerValue]);
+			if(ret)
+				printf("%s, set_mixer_ctrl_value_string error %d, %s, %s\n",
+					__func__, ret,
+					DIRECT_LO_DISABLE_SEQ[i][MixerName],
+					DIRECT_LO_DISABLE_SEQ[i][MixerValue]);
+		}
+		break;
+
+	default:
+		printf("%s, device error, device: %d", __func__, dev);
+		break;
+	}
+}
+
+static void do_ext_codec_open_sequence(int dev)
+{
+	int i, ret;
+
+	for(i = 0;i < ARRAY_SIZE(EXT_CODEC_INTERCONN_SEQ); i++){
+		ret = set_mixer_ctrl_interconn_value(EXT_CODEC_INTERCONN_SEQ[i][MixerName],
+					 atoi(EXT_CODEC_INTERCONN_SEQ[i][MixerValue]));
+		if(ret)
+			printf("%s, set_mixer_ctrl_interconn_value error %d, %s, %s\n",
+				__func__, ret,
+				EXT_CODEC_INTERCONN_SEQ[i][MixerName],
+				EXT_CODEC_INTERCONN_SEQ[i][MixerValue]);
+	}
+
+	for(i = 0;i < ARRAY_SIZE(EXT_CODEC_ENABLE_SEQ); i++){
+		ret = set_mixer_ctrl_value_string(EXT_CODEC_ENABLE_SEQ[i][MixerName],
+				     EXT_CODEC_ENABLE_SEQ[i][MixerValue]);
+		if(ret)
+			printf("%s, set_mixer_ctrl_value_string error %d, %s, %s\n",
+				__func__, ret,
+				EXT_CODEC_ENABLE_SEQ[i][MixerName],
+				EXT_CODEC_ENABLE_SEQ[i][MixerValue]);
+	}
+}
+
+static void do_ext_codec_close_sequence(int dev)
+{
+	int i, ret;
+
+	for(i = 0;i < ARRAY_SIZE(EXT_CODEC_INTERCONN_SEQ); i++){
+		ret = set_mixer_ctrl_interconn_value(EXT_CODEC_INTERCONN_SEQ[i][MixerName], 0);
+		if(ret)
+			printf("%s, set_mixer_ctrl_interconn_value error %d, %s, 0\n",
+				__func__, ret,
+				EXT_CODEC_INTERCONN_SEQ[i][MixerName]);
+	}
+
+	for(i = 0;i < ARRAY_SIZE(EXT_CODEC_DISABLE_SEQ); i++){
+		ret = set_mixer_ctrl_value_string(EXT_CODEC_DISABLE_SEQ[i][MixerName],
+				     EXT_CODEC_DISABLE_SEQ[i][MixerValue]);
+		if(ret)
+			printf("%s, set_mixer_ctrl_value_string error %d, %s, %s\n",
+				__func__, ret,
+				EXT_CODEC_DISABLE_SEQ[i][MixerName],
+				EXT_CODEC_DISABLE_SEQ[i][MixerValue]);
+	}
+}
+
+static int is_using_internal_codec(void)
+{
+	int use_int_codec = get_mixer_ctrl_interconn_value("Ext_Speaker_Amp");
+
+	printf("%s, use_int_codec = %d\n",
+		   __func__, use_int_codec);
+
+	return use_int_codec;
+}
+
+int set_UL_analog_gain_for_service(int dB)
+{
+	char ul_gain_char[16];
+
+	pthread_mutex_lock(&g_afe_enabled_lock);
+	if(!g_afe_enabled) {
+		printf("%s, phone call not start!\n", __func__);
+		pthread_mutex_unlock(&g_afe_enabled_lock);
+		return -EPERM;
+	}
+	sprintf(ul_gain_char, "%dDb", dB);
+	/* set_mixer_ctrl_value_string("Audio_PGA1_Setting", ul_gain_char); */
+	/* set_mixer_ctrl_value_string("Audio_PGA2_Setting", ul_gain_char); */
+	pthread_mutex_unlock(&g_afe_enabled_lock);
+
+	return 0;
+}
+
+int set_DL_analog_gain_for_service(int dB)
+{
+	char dl_gain_char[16];
+
+	pthread_mutex_lock(&g_afe_enabled_lock);
+	if(!g_afe_enabled) {
+		printf("%s, phone call not start!\n", __func__);
+		pthread_mutex_unlock(&g_afe_enabled_lock);
+		return -EPERM;
+	}
+	/* set spk gain (-9~8dB)*/
+	sprintf(dl_gain_char, "%dDb", dB-9);
+	/* set_mixer_ctrl_value_string("Lineout_PGAL_GAIN", dl_gain_char); */
+	/* set_mixer_ctrl_value_string("Lineout_PGAR_GAIN", dl_gain_char); */
+
+	/* set hp gain (-9~8dB)*/
+	/* we set hp gain for tuning purpose, not really use them */
+	sprintf(dl_gain_char, "%dDb", dB-9);
+	/* set_mixer_ctrl_value_string("Headset_PGAL_GAIN", dl_gain_char); */
+	/* set_mixer_ctrl_value_string("Headset_PGAR_GAIN", dl_gain_char); */
+	pthread_mutex_unlock(&g_afe_enabled_lock);
+
+	return 0;
+}
+
+int dynamic_switch_phone_call_path_for_service(int audio_device)
+{
+	int ret;
+
+	if (!g_afe_enabled) {
+		printf("%s, phone call not start! no device switch~\n", __func__);
+		return 0;
+	}
+
+	if (audio_device == DEV_DEFAULT) {
+		audio_device = get_default_device_for_service();
+	}
+
+	if (g_device == audio_device) {
+		printf("%s, device not change!\n", __func__);
+		return 0;
+	}
+
+	disable_phone_call_AFE_path_for_service();
+	ret = enable_phone_call_AFE_path_for_service(audio_device);
+	return ret;
+}
+
+/* for client calling */
+//enable audio path for modem.
+//return value: 0 if success, or negitive error number
+int enable_phone_call_AFE_path(int audio_device)
+{
+	char buf[256];
+
+	sprintf(buf, "%d,%d", FUNC_ENABLE_PHONE_CALL_AFE_PATH, audio_device);
+	return do_IPC_call(buf);
+}
+
+//close audio path for modem
+//return value: 0 if success, or negitive error number
+int disable_phone_call_AFE_path(void)
+{
+	char buf[256];
+
+	sprintf(buf, "%d", FUNC_DISABLE_PHONE_CALL_AFE_PATH);
+	return do_IPC_call(buf);
+}
+
+//get default device.
+//return value: default device setting
+int get_default_device(void)
+{
+	char buf[256];
+
+	sprintf(buf, "%d", FUNC_GET_DEFAULT_VALUE);
+	return do_IPC_call(buf);
+}
+
+//set UL analog gain
+//return value: 0 if success, or negitive error number
+int set_UL_analog_gain(int dB)
+{
+	char buf[256];
+	sprintf(buf, "%d,%d", FUNC_SET_UL_ANALOG_GAIN, dB);
+	return do_IPC_call(buf);
+}
+
+//set DL analog gain
+//return value: 0 if success, or negitive error number
+int set_DL_analog_gain(int dB)
+{
+	char buf[256];
+
+	sprintf(buf, "%d,%d", FUNC_SET_DL_ANALOG_GAIN, dB);
+	return do_IPC_call(buf);
+}
+
+//set BT WB on
+//return value: 0 if success, or negitive error number
+int set_BT_WB(int on)
+{
+	char buf[256];
+	sprintf(buf, "%d,%d", FUNC_SET_BT_WB, on);
+	return do_IPC_call(buf);
+}
+
+//change device when the phone call is enabled
+//return value: 0 if success, or negitive error number
+int dynamic_switch_phone_call_path(int audio_device)
+{
+	char buf[256];
+
+	sprintf(buf, "%d,%d", FUNC_DYNAMIC_SWITCH_PHONE_CALL_PATH, audio_device);
+	return do_IPC_call(buf);
+}
+
+//set phonecall sample rate
+//return value: 0 if success, or negitive error number
+int set_phonecall_rate(int rate)
+{
+	char buf[256];
+
+	sprintf(buf, "%d,%d", FUNC_SET_PHONE_CALL_SAMPLERATE, rate);
+	return do_IPC_call(buf);
+}
+
+#define LIBMODEM_AFE_CTRL_IPC_SEM "LIBMODEM_AFE_CTRL_IPC_SEM"
+static int do_IPC_call(const char* cmd)
+{
+	static char *send_cmd_node = "/tmp/libmodem-afe-ctrl/server_rcv";
+	static char *receive_cmd_node = "/tmp/libmodem-afe-ctrl/server_send";
+	int send_cmd_handler;
+	int receive_cmd_handler;
+	int read_size, call_result;
+	sem_t *sem_ipc;
+	char buf[256];
+
+#ifdef IPC_SEQ_DEBUG
+	int cmd_int;
+
+	cmd_int = atoi(cmd);
+	printf("%s_libmodem, cmd_int: %d\n", __func__, cmd_int);
+	fflush(stdout);
+#endif
+
+	sem_ipc = sem_open(LIBMODEM_AFE_CTRL_IPC_SEM, O_CREAT, 0644, 1);
+	if (sem_ipc == SEM_FAILED) {
+		printf("%s sem_open failed, WTF = = \n", __func__);
+		return errno;
+	}
+	sem_wait(sem_ipc);
+
+	send_cmd_handler = open(send_cmd_node, O_WRONLY);
+	receive_cmd_handler = open(receive_cmd_node, O_RDONLY);
+
+	write(send_cmd_handler, cmd, strlen(cmd));
+	read_size = read(receive_cmd_handler, buf, 256);
+
+	buf[read_size] = '\0';
+	call_result = atoi(buf);
+
+	close(send_cmd_handler);
+	close(receive_cmd_handler);
+
+	sem_post(sem_ipc);
+	return call_result;
+}
+