[Feature][ZXW-33]merge ZXW 0428 version

Change-Id: I11f167edfea428d9fab198ff00ff1364932d1b0b
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/sanechips/Kconfig b/ap/os/linux/linux-3.4.x/sound/soc/sanechips/Kconfig
index ba6a099..b481212 100644
--- a/ap/os/linux/linux-3.4.x/sound/soc/sanechips/Kconfig
+++ b/ap/os/linux/linux-3.4.x/sound/soc/sanechips/Kconfig
@@ -20,6 +20,9 @@
 config SND_SOC_ZX297520V3_ES8312
 	tristate "SoC I2S Audio support for ZX297520V3 - ES8312"	
 	select SND_SOC_ES8312 if I2C
+config SND_SOC_ZX297520V3_DUMMY
+	tristate "SoC I2S Audio support for ZX297520V3 - DUMMY"	
+		select SND_SOC_DUMMY
 config SND_SOC_ZX_VOICE
 	tristate "SoC 2/3G Voice support"	
 	
@@ -49,3 +52,6 @@
 config SND_EXTRA_CTRL
 	tristate "Soc add extra snd controls"			
 
+config SND_SOC_DUMMY
+	tristate "Soc dummy codec"	
+
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/sanechips/Makefile b/ap/os/linux/linux-3.4.x/sound/soc/sanechips/Makefile
index 71daf42..b509eb0 100644
--- a/ap/os/linux/linux-3.4.x/sound/soc/sanechips/Makefile
+++ b/ap/os/linux/linux-3.4.x/sound/soc/sanechips/Makefile
@@ -17,5 +17,7 @@
 obj-$(CONFIG_SND_SOC_ZX297520V3_ES8374) += snd-soc-zx297520v3-es8374.o
 snd-soc-zx297520v3-es8312-objs := zx297520v3_es8312.o
 obj-$(CONFIG_SND_SOC_ZX297520V3_ES8312) += snd-soc-zx297520v3-es8312.o
+snd-soc-zx297520v3-dummy-objs := zx297520v3_dummy.o
+obj-$(CONFIG_SND_SOC_ZX297520V3_DUMMY) += snd-soc-zx297520v3-dummy.o
 
 ccflags-y += -I/$(CP_ROOT_DIR)/ps/driver/inc/misc
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/sanechips/zx297520v3_dummy.c b/ap/os/linux/linux-3.4.x/sound/soc/sanechips/zx297520v3_dummy.c
new file mode 100755
index 0000000..0124154
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/sanechips/zx297520v3_dummy.c
@@ -0,0 +1,629 @@
+/*
+ * zx297520v3_dummy.c  --  ZX297520v3_dummy ALSA SoC Audio board driver
+ *
+ * Copyright (C) 2017, ZTE Corporation.
+ *
+ * Based on smdk_wm8994.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <sound/tlv.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/zx29_snd_platform.h>
+#include <mach/iomap.h>
+#include <mach/board.h>
+#include "../codecs/tlv320aic31xx.h"
+#include <sound/pcm_params.h>
+#include "i2s.h"
+
+#define  AIC31XX_MCLK  26000000
+
+#define AON_WIFI_BT_CLK_CFG2  ((volatile unsigned int *)(ZX_TOP_CRM_BASE + 0x94))
+
+static struct platform_device *zx297520v3_dummy_snd_device;
+#if (defined CONFIG_SND_EXTRA_CTRL) || (defined CONFIG_SND_EXTRA_CTRL_MODULE)
+extern  const struct snd_kcontrol_new voice_process_controls[];
+extern int vp_controls_size;
+int new_ctrls_add_flag = 1; 
+#endif
+/*
+static const struct snd_kcontrol_new controls[] = {
+	SOC_DAPM_PIN_SWITCH("Main Speaker"),
+	SOC_DAPM_PIN_SWITCH("Main Mic"),
+};
+*/
+
+#ifdef CONFIG_PREEMPT_RT_FULL
+extern int zDrv_Audio_Printf(void *pFormat, ...);
+extern int zDrvVp_GetVol_Wrap(void);
+extern int zDrvVp_SetVol_Wrap(int volume);
+extern int zDrvVp_GetPath_Wrap(void);
+extern int zDrvVp_SetPath_Wrap(int path);
+extern int zDrvVp_SetMute_Wrap(bool enable);
+extern bool zDrvVp_GetMute_Wrap(void);
+extern int zDrvVp_SetTone_Wrap(int toneNum);
+ extern int zDrvVp_SetRxMute_Wrap(bool enable);
+ extern int zDrvVp_GetRxMute_Wrap(void);
+ extern int zDrvVp_GetTxVol_Wrap(void); 
+ extern int zDrvVp_SetTxVol_Wrap(int volume);
+
+static int vp_GetPath(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+static int vp_SetPath(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+static int vp_SetVol(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+static int vp_GetVol(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+static int vp_SetMute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+static int vp_GetMute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+static int vp_SetTone(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+static int vp_getTone(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+
+static int audio_GetPath(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+static int audio_SetPath(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+static int vp_GetTxVol(struct snd_kcontrol *kcontrol,struct snd_ctl_elem_value *ucontrol);
+static int vp_SetTxVol(struct snd_kcontrol *kcontrol,struct snd_ctl_elem_value *ucontrol);
+static int vp_SetRxMute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); 
+static int vp_GetRxMute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+
+ 								
+
+static const DECLARE_TLV_DB_SCALE(vp_path_tlv, 0, 300, 0);
+
+static const char * const vpath_in_text[] = {
+	"handset", "speak", "headset", "bluetooth",
+};
+
+static const char *tone_class[] = {
+	"Lowpower", "Sms", "Callstd", "Alarm", "Calltime",
+};
+
+static const struct soc_enum vpath_in_enum =	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(vpath_in_text), vpath_in_text); 
+
+static const struct soc_enum tone_class_enum[] = {
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tone_class),	tone_class),
+};
+
+static const struct snd_kcontrol_new vp_snd_controls[] = {	
+	SOC_ENUM_EXT("voice processing path select",vpath_in_enum,vp_GetPath,vp_SetPath),
+	SOC_SINGLE_EXT_TLV("voice processing path Volume",0, 5, 5, 0,vp_GetVol, vp_SetVol,vp_path_tlv),	
+	//SOC_SINGLE_EXT("voice processing path Volume",0, 5, 5, 0,vp_GetVol, vp_SetVol),
+	SOC_SINGLE_EXT("voice processing tx path Volume",0, 5, 5, 0,vp_GetTxVol, vp_SetTxVol),	
+	SOC_SINGLE_EXT("voice uplink mute", 0, 1, 1, 0,vp_GetMute, vp_SetMute),
+	SOC_SINGLE_EXT("voice downlink mute", 0, 1, 1, 0,vp_GetRxMute, vp_SetRxMute),	
+	SOC_ENUM_EXT("voice tone sel", tone_class_enum[0], vp_getTone, vp_SetTone),
+	SOC_ENUM_EXT("audio path select",vpath_in_enum,audio_GetPath,audio_SetPath),
+};
+
+static int curtonetype = 0;
+static int vp_getTone(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = curtonetype;
+	return 0;
+}
+
+static int vp_SetTone(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+	int vol = 0,ret = 0, tonenum;
+	tonenum = ucontrol->value.integer.value[0];
+	curtonetype = tonenum;
+	//printk("Alsa vp_SetTone tonenum=%d\n", tonenum);
+	ret = CPPS_FUNC(cpps_callbacks, zDrvVp_SetTone_Wrap)(tonenum);
+	if(ret < 0)
+	{
+		printk(KERN_ERR "vp_SetTone fail = %d\n", tonenum);
+		return ret;
+	}
+	return 0;
+}
+
+static int vp_SetMute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+	int enable = 0,ret = 0;
+	enable = ucontrol->value.integer.value[0];
+	ret = CPPS_FUNC(cpps_callbacks, zDrvVp_SetMute_Wrap)(enable);
+	if(ret < 0)
+	{
+	  printk(KERN_ERR "vp_SetMute fail = %d\n",enable);
+	  return ret;
+	}
+	return 0;
+}
+
+static int vp_GetMute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{       
+       ucontrol->value.integer.value[0] = CPPS_FUNC(cpps_callbacks, zDrvVp_GetMute_Wrap)();
+       return 0;
+}
+ static int vp_SetRxMute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+ {
+	 int enable = 0,ret = 0;
+	 enable = ucontrol->value.integer.value[0];
+	 ret = CPPS_FUNC(cpps_callbacks, zDrvVp_SetRxMute_Wrap)(enable);
+	 
+	 if(ret < 0)
+	 {
+	   printk(KERN_ERR "vp_SetRxMute fail = %d\n",enable);
+	   return ret;
+	 }
+	 return 0;
+ }
+ 
+ static int vp_GetRxMute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+ {		 
+		ucontrol->value.integer.value[0] =  CPPS_FUNC(cpps_callbacks, zDrvVp_GetRxMute_Wrap)();
+		return 0;
+ }
+  
+static int vp_SetVol(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{
+	   int vol = 0,ret = 0;
+	   vol = ucontrol->value.integer.value[0];
+	   ret = CPPS_FUNC(cpps_callbacks, zDrvVp_SetVol_Wrap)(vol);
+	   if(ret < 0)
+	   {
+		  printk(KERN_ERR "vp_SetVol fail = %d\n",vol);
+		  return ret;
+	  }
+	return 0;
+}
+static int vp_GetVol(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{       
+       ucontrol->value.integer.value[0] = CPPS_FUNC(cpps_callbacks, zDrvVp_GetVol_Wrap)();
+       return 0;
+}
+static int vp_SetTxVol(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{
+	   int vol = 0,ret = 0;
+	   vol = ucontrol->value.integer.value[0];
+	   ret = CPPS_FUNC(cpps_callbacks, zDrvVp_SetTxVol_Wrap)(vol);
+	   if(ret < 0)
+	   {
+		  printk(KERN_ERR "vp_SetTxVol fail = %d\n",vol);
+		  return ret;
+	  }
+	return 0;
+}
+static int vp_GetTxVol(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{       
+       ucontrol->value.integer.value[0] = CPPS_FUNC(cpps_callbacks, zDrvVp_GetTxVol_Wrap)();
+       return 0;
+}							   
+static int vp_GetPath(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{	
+	ucontrol->value.enumerated.item[0] = CPPS_FUNC(cpps_callbacks, zDrvVp_GetPath_Wrap)();
+	return 0;
+}
+static int vp_SetPath(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	int ret = 0,path = 0;
+	
+	path = ucontrol->value.enumerated.item[0];
+	ret = CPPS_FUNC(cpps_callbacks, zDrvVp_SetPath_Wrap)(path);
+	if(ret < 0)
+	{
+	  printk(KERN_ERR "vp_SetPath fail = %d\n",path);
+	  return ret;
+	}
+	return 0;
+}
+
+static int curpath = 0;
+static int audio_GetPath(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{	
+	ucontrol->value.enumerated.item[0] = curpath;
+	return 0;
+}
+
+static int audio_SetPath(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	int ret = 0,path = 0;
+	
+	path = ucontrol->value.enumerated.item[0];
+	curpath = path;
+#if 0
+	switch (path) {
+	case 0:
+		break;
+	case 1:
+		break;
+	case 2:
+		break;
+	case 3:
+		break;
+	default
+		break;
+	}
+#endif
+	return 0;
+}
+
+
+typedef enum
+{
+    VP_PATH_HANDSET    =0,     
+    VP_PATH_SPEAKER,  		
+    VP_PATH_HEADSET,                     
+    VP_PATH_BLUETOOTH,                    
+    VP_PATH_BLUETOOTH_NO_NR,                    
+    VP_PATH_HSANDSPK,
+    
+    VP_PATH_OFF = 255,					
+    
+    MAX_VP_PATH = VP_PATH_OFF               
+}T_ZDrv_VpPath;
+
+extern int zDrvVp_Loop(T_ZDrv_VpPath path);
+int zx297520v3_dummy_prepare2(struct snd_pcm_substream *substream)
+{
+	int path, ret;
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		ret = CPPS_FUNC(cpps_callbacks, zDrvVp_Loop)(VP_PATH_SPEAKER);
+		if (ret < 0)
+			return -1;
+	}
+	
+	return 0;
+}
+
+#endif
+
+
+static int zx297520v3_dummy_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+//	print_audio("Alsa Entered func %s\n", __func__);
+	CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa: zx297520v3_dummy_startup device=%d,stream=%d\n", substream->pcm->device, substream->stream);
+
+	struct snd_pcm *pcmC0D0p = snd_lookup_minor_data(16, SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
+	struct snd_pcm *pcmC0D1p = snd_lookup_minor_data(17, SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
+	struct snd_pcm *pcmC0D2p = snd_lookup_minor_data(18, SNDRV_DEVICE_TYPE_PCM_PLAYBACK);   
+	struct snd_pcm *pcmC0D3p = snd_lookup_minor_data(19, SNDRV_DEVICE_TYPE_PCM_PLAYBACK);  
+	if ((pcmC0D0p == NULL) || (pcmC0D1p == NULL) || (pcmC0D2p == NULL) || (pcmC0D3p == NULL))
+		return  -EINVAL;  
+	if ((pcmC0D0p->streams[0].substream_opened && pcmC0D1p->streams[0].substream_opened) || 
+		(pcmC0D0p->streams[0].substream_opened && pcmC0D2p->streams[0].substream_opened) || 
+		(pcmC0D0p->streams[0].substream_opened && pcmC0D3p->streams[0].substream_opened) || 
+		(pcmC0D1p->streams[0].substream_opened && pcmC0D2p->streams[0].substream_opened) ||
+		(pcmC0D1p->streams[0].substream_opened && pcmC0D3p->streams[0].substream_opened) ||
+		(pcmC0D2p->streams[0].substream_opened && pcmC0D3p->streams[0].substream_opened))
+		BUG();
+
+#ifdef _USE_7520V3_PHONE_TYPE_FWP
+	unsigned int  armRegBit = 0;
+	armRegBit = zx_read_reg(AON_WIFI_BT_CLK_CFG2);
+	armRegBit &= 0xfffffffe;
+	armRegBit |= 0x1;
+	zx_write_reg(AON_WIFI_BT_CLK_CFG2, armRegBit);
+#endif	
+	return ret;
+}
+
+static void zx297520v3_dummy_shutdown(struct snd_pcm_substream *substream)
+{
+	CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa: zx297520v3_dummy_shutdown device=%d, stream=%d\n", substream->pcm->device, substream->stream);
+
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+//	print_audio("Alsa Entered func %s\n", __func__);
+
+	if (rtd->cpu_dai->active)
+		return;
+	
+#ifdef _USE_7520V3_PHONE_TYPE_FWP
+	unsigned int  armRegBit = 0;
+	armRegBit = zx_read_reg(AON_WIFI_BT_CLK_CFG2);
+	armRegBit &= 0xfffffffe;
+	armRegBit |= 0x0;
+	zx_write_reg(AON_WIFI_BT_CLK_CFG2, armRegBit);
+#endif	
+//	snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS");
+}
+
+static void zx297520v3_dummy_shutdown2(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa: zx297520v3_dummy_shutdown2 device=%d, stream=%d\n", substream->pcm->device, substream->stream);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+#ifdef CONFIG_PREEMPT_RT_FULL
+		CPPS_FUNC(cpps_callbacks, zDrvVp_Loop)(VP_PATH_OFF);
+#endif
+	}
+#ifdef _USE_7520V3_PHONE_TYPE_FWP
+	unsigned int  armRegBit = 0;
+	armRegBit = zx_read_reg(AON_WIFI_BT_CLK_CFG2);
+	armRegBit &= 0xfffffffe;
+	armRegBit |= 0x0;
+	zx_write_reg(AON_WIFI_BT_CLK_CFG2, armRegBit);
+#endif	
+
+}
+
+static int zx297520v3_dummy_init_paiftx(struct snd_soc_pcm_runtime *rtd)
+{
+	int ret = 0;
+
+	/* Other pins NC */
+//	snd_soc_dapm_nc_pin(dapm, "HPOUT2P");
+#if (defined CONFIG_SND_EXTRA_CTRL) || (defined CONFIG_SND_EXTRA_CTRL_MODULE)
+
+	/* add voice process specific controls */
+	if(new_ctrls_add_flag == 1){
+	ret = snd_soc_add_card_controls(rtd->card, voice_process_controls,vp_controls_size);
+	if (ret)
+		return ret;
+	  new_ctrls_add_flag = 0;
+	}
+#endif	
+
+	return ret;
+}
+static int zx297520v3_dummy_hw_params(struct snd_pcm_substream *substream,
+                                       struct snd_pcm_hw_params *params)
+{
+//	print_audio("Alsa Entered func %s\n", __func__);
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret;
+#if 0
+	/* Set the Codec DAI configuration */
+	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
+	                          | SND_SOC_DAIFMT_NB_NF
+	                          | SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	/* Set the AP DAI configuration */
+	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
+	                          | SND_SOC_DAIFMT_NB_NF
+	                          | SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, AIC31XX_PLL_CLKIN_MCLK,
+	                             AIC31XX_MCLK, SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_dai_set_sysclk(cpu_dai, ZX29_I2S_WCLK_SEL,
+	                             ZX29_I2S_WCLK_FREQ_26M, SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+#endif
+	
+	return 0;
+}
+
+static int zx297520v3_dummy_hw_params1(struct snd_pcm_substream *substream,
+                                        struct snd_pcm_hw_params *params)
+{
+//	print_audio("Alsa Entered func %s\n", __func__);
+
+
+
+
+	return 0;
+}
+static void zx29_i2s_top_reg_cfg(void)
+{
+	unsigned int i2s_top_reg;
+	int ret = 0;
+
+#ifdef CONFIG_USE_PIN_I2S0
+	ret = gpio_request(PIN_I2S0_WS, "i2s0_ws");
+	if (ret < 0)
+		BUG();
+	ret = gpio_request(PIN_I2S0_CLK, "i2s0_clk");
+	if (ret < 0)
+		BUG();
+	ret = gpio_request(PIN_I2S0_DIN, "i2s0_din");
+	if (ret < 0)
+		BUG();
+	ret = gpio_request(PIN_I2S0_DOUT, "i2s0_dout");
+	if (ret < 0)
+		BUG();
+	zx29_gpio_config(PIN_I2S0_WS, FUN_I2S0_WS);
+	zx29_gpio_config(PIN_I2S0_CLK, FUN_I2S0_CLK);
+	zx29_gpio_config(PIN_I2S0_DIN, FUN_I2S0_DIN);
+	zx29_gpio_config(PIN_I2S0_DOUT, FUN_I2S0_DOUT);
+	
+	//top i2s1 cfg
+	i2s_top_reg = zx_read_reg(ZX29_I2S_LOOP_CFG);
+	i2s_top_reg &= 0xfffffff8;
+	i2s_top_reg |= 0x00000001; //  inter arm_i2s1--top i2s1
+	zx_write_reg(ZX29_I2S_LOOP_CFG, i2s_top_reg);
+#elif defined (CONFIG_USE_PIN_I2S1)
+	ret = gpio_request(PIN_I2S1_WS,"i2s1_ws");
+	if(ret < 0)
+		BUG();
+	ret = gpio_request(PIN_I2S1_CLK,"i2s1_clk");
+	if(ret < 0)
+		BUG();
+	ret = gpio_request(PIN_I2S1_DIN,"i2s1_din");
+	if(ret < 0)
+		BUG();
+	ret = gpio_request(PIN_I2S1_DOUT,"i2s1_dout");
+	if(ret < 0)
+		BUG();
+	zx29_gpio_config(PIN_I2S1_WS, FUN_I2S1_WS);
+	zx29_gpio_config(PIN_I2S1_CLK, FUN_I2S1_CLK);
+	zx29_gpio_config(PIN_I2S1_DIN, FUN_I2S1_DIN);
+	zx29_gpio_config(PIN_I2S1_DOUT, FUN_I2S1_DOUT);
+		
+	//top i2s2 cfg
+	i2s_top_reg = zx_read_reg(ZX29_I2S_LOOP_CFG);
+	i2s_top_reg &= 0xfff8ffff;
+	i2s_top_reg |= 0x00010000; //  inter arm_i2s1--top i2s2
+	zx_write_reg(ZX29_I2S_LOOP_CFG, i2s_top_reg);
+#endif
+
+	// inter loop
+    i2s_top_reg = zx_read_reg(ZX29_I2S_LOOP_CFG);
+    i2s_top_reg &= 0xfffffe07;
+    i2s_top_reg |= 0x000000a8; //  inter arm_i2s2--afe i2s
+    zx_write_reg(ZX29_I2S_LOOP_CFG, i2s_top_reg);
+	
+//	print_audio("Alsa %s i2s loop cfg reg=%x\n",__func__, zx_read_reg(ZX29_I2S_LOOP_CFG));	
+}
+
+
+
+static struct snd_soc_ops zx297520v3_dummy_ops = {
+	.startup = zx297520v3_dummy_startup,
+	.shutdown = zx297520v3_dummy_shutdown,
+	.hw_params = zx297520v3_dummy_hw_params,
+};
+
+static struct snd_soc_ops zx297520v3_dummy_ops1 = {
+	.startup = zx297520v3_dummy_startup,
+	.shutdown = zx297520v3_dummy_shutdown,
+	.hw_params = zx297520v3_dummy_hw_params1,
+};
+
+static struct snd_soc_ops zx297520v3_dummy_ops2 = {
+	.startup = zx297520v3_dummy_startup,
+	.shutdown = zx297520v3_dummy_shutdown2,
+	.hw_params = zx297520v3_dummy_hw_params1,
+	.prepare = zx297520v3_dummy_prepare2,
+};
+
+static struct snd_soc_dai_link zx297520v3_dummy_dai_link[] = {
+	{
+		.name = "dummy_Media",
+		.stream_name = "MultiMedia",
+		.codec_name = "snd-soc-dummy",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.cpu_dai_name = "snd-soc-dummy-dai", //"zx29_i2s.0"
+		.ops = &zx297520v3_dummy_ops,
+		.init = zx297520v3_dummy_init_paiftx,
+		.platform_name	= "snd-soc-dummy",
+	},
+	{
+		.name = "voice_call",
+		.stream_name = "voice",
+		.codec_name = "snd-soc-dummy",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.cpu_dai_name = "snd-soc-dummy-dai", //"snd-soc-dummy-dai",
+		.platform_name	= "snd-soc-dummy",
+		.init = zx297520v3_dummy_init_paiftx,
+		.ops = &zx297520v3_dummy_ops1,
+	},
+#ifdef CONFIG_PREEMPT_RT_FULL
+	{
+		.name = "2&3g_voice",
+		.stream_name = "2_3g_voice",
+		.codec_name = "snd-soc-dummy",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.cpu_dai_name = "voice", //"snd-soc-dummy-dai",
+		.platform_name	= "voice_audio",
+		.init = zx297520v3_dummy_init_paiftx,
+		.ops = &zx297520v3_dummy_ops1,
+	},
+	{
+		.name = "loop_test",
+		.stream_name = "loop_voice",
+		.codec_name = "snd-soc-dummy",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.cpu_dai_name = "snd-soc-dummy-dai", //"snd-soc-dummy-dai",
+		.platform_name	= "snd-soc-dummy",
+		.init = zx297520v3_dummy_init_paiftx,
+		.ops = &zx297520v3_dummy_ops2,
+	},
+	{
+		.name = "3g_voice", // 3g nb,wb
+		.stream_name = "3g_voice",
+		.codec_name = "snd-soc-dummy",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.cpu_dai_name = "voice", //"snd-soc-dummy-dai",
+		.platform_name	= "voice_audio",
+		.init = zx297520v3_dummy_init_paiftx,
+		.ops = &zx297520v3_dummy_ops1,
+	},
+#endif
+};
+
+static struct snd_soc_card snd_soc_zx297520v3_dummy = {
+	.name = "zx297520v3_dummy",
+	.owner = THIS_MODULE,
+	.dai_link = &zx297520v3_dummy_dai_link,
+	.num_links = ARRAY_SIZE(zx297520v3_dummy_dai_link),
+#ifdef CONFIG_PREEMPT_RT_FULL
+	.controls = vp_snd_controls,
+	.num_controls = ARRAY_SIZE(vp_snd_controls),
+#endif
+	//.dapm_widgets = widgets,
+	//.num_dapm_widgets = ARRAY_SIZE(widgets),
+	//.dapm_routes = audio_paths,
+	//.num_dapm_routes = ARRAY_SIZE(audio_paths),
+	.fully_routed = true,
+};
+
+static struct zx297520v3_dummy_platform_data *zx297520v3_dummy_pow_pins;
+
+
+
+static int zx297520v3_dummy_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	print_audio("Alsa zx297520v3_dummy SoC Audio driver\n");
+
+#ifndef	_ALSA_CODEC_IN_CAP
+	zx29_i2s_top_reg_cfg();
+#endif
+	zx297520v3_dummy_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!zx297520v3_dummy_snd_device) {
+		printk(KERN_ERR "Alsa zx297520v3_dummy SoC Audio: Unable to register\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(zx297520v3_dummy_snd_device,
+	                     &snd_soc_zx297520v3_dummy);
+//	platform_device_add_data(zx29xx_dummy_snd_device, &zx29xx_dummy, sizeof(zx29xx_dummy));
+	ret = platform_device_add(zx297520v3_dummy_snd_device);
+	if (ret) {
+		printk(KERN_ERR "Alsa zx297520v3_dummy SoC Audio: Unable to add\n");
+		platform_device_put(zx297520v3_dummy_snd_device);
+	}
+
+	return ret;
+}
+
+static int zx297520v3_dummy_remove(struct platform_device *pdev)
+{
+
+	platform_device_unregister(zx297520v3_dummy_snd_device);
+	return 0;
+}
+
+static struct platform_driver zx297520v3_dummy_driver = {
+	.probe  = zx297520v3_dummy_probe,
+	.remove = zx297520v3_dummy_remove,
+	.driver = {
+		.name = "zx29_snd_machine",
+		.owner = THIS_MODULE,
+	},
+};
+
+module_platform_driver(zx297520v3_dummy_driver);
+
+MODULE_DESCRIPTION("ZX297520V3_dummy ALSA SoC audio driver");
+MODULE_LICENSE("GPL");
+
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/sanechips/zx29_voice.c b/ap/os/linux/linux-3.4.x/sound/soc/sanechips/zx29_voice.c
index 1d961e5..4546eed 100644
--- a/ap/os/linux/linux-3.4.x/sound/soc/sanechips/zx29_voice.c
+++ b/ap/os/linux/linux-3.4.x/sound/soc/sanechips/zx29_voice.c
@@ -21,6 +21,8 @@
 #include <linux/cp_types.h>

 #include "drvs_volte.h"

 #endif

+#include <linux/wakelock.h>

+#include <linux/soc/zte/pm/drv_idle.h>

 

 #ifdef  CONFIG_PREEMPT_RT_FULL

 typedef enum {

@@ -117,6 +119,14 @@
 //extern T_DrvVoice_3G_Opt  gDrvVoice_3G_Obj;

 #endif

 

+struct zx29_voice {

+

+	struct mutex         mutex;

+	struct wake_lock     pm_lock;

+

+};

+

+static struct zx29_voice voice = {0};

 

 static const struct snd_pcm_hardware dma_hardware = {

 	.info			= SNDRV_PCM_INFO_INTERLEAVED |

@@ -227,15 +237,21 @@
 	int ret = 0;

 //	print_audio("Alsa Entered func %s, cmd=%d\n", __func__, cmd);

 	struct snd_soc_pcm_runtime *rtd = substream->private_data;

+	CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa: %s start,rtd->dai_link->name=%s,cmd=%d\n", __func__, rtd->dai_link->name,cmd);

+

 	if (rtd->dai_link->name != NULL && (!strcmp(rtd->dai_link->name, "3g_voice"))) {

 

 		print_audio("Alsa Entered func %s  3g soft amr !\n", __func__);

-		return 0;

+		//return 0;

 	}

 	switch (cmd) {

 	case SNDRV_PCM_TRIGGER_START:

+		zx_cpuidle_set_busy(IDLE_FLAG_VOICE);

+		wake_lock(&voice.pm_lock);

 		break;

 	case SNDRV_PCM_TRIGGER_STOP:

+		zx_cpuidle_set_free(IDLE_FLAG_VOICE);

+		wake_unlock(&voice.pm_lock);

 		break;

 	default:

 		ret = -EINVAL;

@@ -251,6 +267,7 @@
 	int ret = 0;

 	struct snd_soc_pcm_runtime *rtd = substream->private_data;

 	snd_soc_set_runtime_hwparams(substream, &dma_hardware);

+	CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa: %s start,rtd->dai_link->name=%s\n", __func__, rtd->dai_link->name);

 

 #ifdef CONFIG_PREEMPT_RT_FULL

 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {

@@ -259,14 +276,19 @@
 

 			ret = CPPS_FUNC(cpps_callbacks, halVoice_Open3G)();

 			print_audio("Alsa Entered func %s  3g soft amr  ret=%d!\n", __func__, ret);

+		    CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa Entered func %s  3g soft amr  ret=%d!\n", __func__, ret);

+		

 

 		} else {

 			ret = CPPS_FUNC(cpps_callbacks, halVoice_Open)();

 			print_audio("Alsa Entered func %s  2/3G teaklit  ret=%d!\n", __func__, ret);

+		    CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa Entered func %s  2/3G teaklit  ret=%d!\n", __func__, ret);

 

 		}

 	}

 #endif

+	CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa: %s end,rtd->dai_link->name=%s\n", __func__, rtd->dai_link->name);

+

 	return ret;

 }

 

@@ -276,23 +298,34 @@
 //	print_audio("Alsa Entered func %s\n", __func__);

 	int ret = 0;

 	struct snd_soc_pcm_runtime *rtd = substream->private_data;

+	CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa: %s start,rtd->dai_link->name=%s\n", __func__, rtd->dai_link->name);

+

+	//dump_stack();	

+	WARN_ON(1);

 #ifdef CONFIG_PREEMPT_RT_FULL

 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {

 		if ((rtd->dai_link->name != NULL) && (!strcmp(rtd->dai_link->name, "3g_voice"))) {

 			ret = CPPS_FUNC(cpps_callbacks, halVoice_Close3G)();

 			print_audio("Alsa Entered func %s  3g soft amr  ret=%d!\n", __func__, ret);

+			CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa Entered func %s  3g soft amr  ret=%d!\n", __func__, ret);

 

 		} else {

 

 			ret = CPPS_FUNC(cpps_callbacks, halVoice_Disable)();

-			if (ret < 0)

-				print_audio("Alsa Entered func %s  2/3G teakl err ret=%d\n", __func__, ret);

+			if (ret < 0){

+				print_audio("Alsa Entered func %s  2/3G teakl disable err ret=%d\n", __func__, ret);

+				

+		   		CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa Entered func %s  2/3G teakl disable err ret=%d\n", __func__, ret);

+			}

 			ret += CPPS_FUNC(cpps_callbacks, halVoice_Close)();

+			

+		    CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa Entered func %s  2/3G teaklit close end ret=%d!\n", __func__, ret);

 		}

 

 

 	}

 #endif

+	CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa: %s end,rtd->dai_link->name=%s\n", __func__, rtd->dai_link->name);

 

 	return ret;

 }

@@ -316,6 +349,9 @@
 static int __devinit voice_asoc_platform_probe(struct platform_device *pdev)

 {

 //	print_audio("Alsa voice_asoc_platform_probe start\n");

+	mutex_init(&voice.mutex);

+	wake_lock_init(&voice.pm_lock, WAKE_LOCK_SUSPEND, "zx29-voice");

+

 	return snd_soc_register_platform(&pdev->dev, &voice_asoc_platform);

 }

 

diff --git a/ap/os/linux/linux-3.4.x/sound/soc/soc-utils.c b/ap/os/linux/linux-3.4.x/sound/soc/soc-utils.c
index 6005370..37f4872 100644
--- a/ap/os/linux/linux-3.4.x/sound/soc/soc-utils.c
+++ b/ap/os/linux/linux-3.4.x/sound/soc/soc-utils.c
@@ -89,9 +89,35 @@
 	.ops = &dummy_dma_ops,
 };
 
+#define ZX29_I2S_RATES \
+				(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
+				 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+				 SNDRV_PCM_RATE_48000)
+			
+#define ZX29_I2S_FMTBIT \
+				(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \
+				SNDRV_PCM_FMTBIT_S32_LE)
+
+
 static struct snd_soc_codec_driver dummy_codec;
 static struct snd_soc_dai_driver dummy_dai = {
 	.name = "snd-soc-dummy-dai",
+#ifdef _USE_VEHICLE_DC	
+	.playback = {
+		.stream_name	= "Playback",
+		.channels_min	= 1,
+		.channels_max	= 384,
+		.rates		= ZX29_I2S_RATES,
+		.formats	= ZX29_I2S_FMTBIT,
+	},
+	.capture = {
+		.stream_name	= "Capture",
+		.channels_min	= 1,
+		.channels_max	= 384,
+		.rates		= ZX29_I2S_RATES,
+		.formats	= ZX29_I2S_FMTBIT,
+	 },	
+#endif	 
 };
 
 static __devinit int snd_soc_dummy_probe(struct platform_device *pdev)