Baseline update from LYNQ_SDK_ASR_T108_V05.03.01.00(kernel build error.)

Change-Id: I56fc72cd096e82c589920026553170e5cb9692eb
diff --git a/marvell/linux/drivers/mfd/tlv320aic3x.c b/marvell/linux/drivers/mfd/tlv320aic3x.c
new file mode 100755
index 0000000..5378989
--- /dev/null
+++ b/marvell/linux/drivers/mfd/tlv320aic3x.c
@@ -0,0 +1,3141 @@
+/*
+ * Base driver for ASR tlv320aic3x 
+ *
+ * Copyright (C) 2019 ASR.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/88pm80x.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/of_device.h>
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <linux/gpio.h>
+//#include <plat/mfp.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <asm/io.h>
+#include <linux/interrupt.h>
+#include <linux/cputype.h>
+#include <soc/asr/addr-map.h>
+#include "tlv320aic3x.h"
+#include <linux/clk.h>
+
+#ifndef APB_VIRT_BASE
+#define APB_VIRT_BASE		IOMEM(0xfe000000)
+#endif
+
+#define SSP1_I2S_CLOCK_REG_ADDR     (0xD4050044)
+
+#ifdef Kestrel_Z2
+//Kestrel Z2
+static void __iomem *VCXO_OUT_MFPR_reg = APB_VIRT_BASE + 0x1E000 + 0x208;/* 0xD401E000+0x208 */
+static void __iomem *PM_MN_CLK_reg = APB_VIRT_BASE + 0x51000 + 0xA4;/* 0xD4051000+0xA4 */
+static void __iomem *GPCR_reg = APB_VIRT_BASE + 0x50000 + 0x30;/* 0xD4050030 */
+#else
+//Kestrel A0
+static void __iomem *MCLK_CLK_CTRL_reg = NULL;/* 0xD6800000+0x4C */
+static void __iomem *MCLK_MN_DIV_reg = NULL;/* 0xD6800000+0x50 */
+#endif
+
+//NezhaC/Falcon
+static void __iomem *SSP1_I2S_CLOCK_reg = APB_VIRT_BASE + 0x50000 + 0x44;/* 0xD4050000+0x44 */
+
+#if defined(CONFIG_CODEC_PCM_NB)
+/* Narrowband */
+char Audio_Codec_Fsync_Rate = 0;
+#elif defined(CONFIG_CODEC_PCM_WB)
+/* Wideband */
+char Audio_Codec_Fsync_Rate = 1;
+#elif defined(CONFIG_CODEC_PCM_32KHz)
+/* 32KHz */
+char Audio_Codec_Fsync_Rate = 2;
+#elif defined(CONFIG_CODEC_PCM_48KHz)
+/* 48KHz */
+char Audio_Codec_Fsync_Rate = 3;
+#else
+/* Narrowband */
+char Audio_Codec_Fsync_Rate = 0;
+#endif
+
+#ifdef CONFIG_CODEC_PCM_MASTER
+/* CODEC is master, GSSP is slave. */
+
+char G_AudioModemMaster = 0;
+#else
+/* CODEC PCM config is slave in config/defconfig_asr1802sp201
+   CODEC is slave, GSSP is master. */
+
+char G_AudioModemMaster = 1;
+#endif
+
+static const struct i2c_device_id tlv320aic3x_dt_table[] = {
+    {"tlv320aic3x", 0},
+    {} /* NULL terminated */
+};
+MODULE_DEVICE_TABLE(i2c, tlv320aic3x_dt_table);
+
+static const struct of_device_id tlv320aic3x_dt_ids[] = {
+    { .compatible = "ti,tlv320aic3104", },
+    {},
+};
+MODULE_DEVICE_TABLE(of, tlv320aic3x_dt_ids);
+
+static struct i2c_client  *g_tlv320aic3x_client = NULL;
+static struct pinctrl *g_tlv320aic3x_pinctrl = NULL;
+static struct device_node *g_tlv320aic3x_node = NULL;
+static void __iomem *i2s_clk_reg = NULL;
+
+static int gpio_tds_dio10 = 0;       /* GPIO[78]  */   
+static int gpio_vcxo_out = 0;        /* GPIO[126] */
+static int gpio_31_CODEC_1V8_EN = 0; /* GPIO[31]  */
+static int gpio_32_CODEC_3V3_EN = 0; /* GPIO[32]  */
+
+static int g_reset_gpio = -1;
+static struct regulator *tlv320aic3x_regulator_vdd_1v8 = NULL;
+static struct regulator *tlv320aic3x_regulator_vdd_3v3 = NULL;
+
+#ifdef HEADSET_DETECTION
+static int gpio_CODEC_IRQ = 0; /* GPIO[1] */
+static int irq_codec;
+#endif
+
+//#define HEADSET_DETECTION
+//#define TLV320AIC3X_DEBUG
+//#define TLV320AIC3X_DEBUG_CLOSE
+
+#define tlv320aic3x_reg_NUM 0xFF
+/* base functions */
+
+static unsigned short tlv320aic3x_readable_register(unsigned int reg)
+{
+    switch (reg) {
+        case TLV320AIC3X_RESET_REG00:
+        case TLV320AIC3X_CLK_MANAGER_REG01:
+        case TLV320AIC3X_CLK_MANAGER_REG02:
+        case TLV320AIC3X_CLK_MANAGER_REG03:
+        case TLV320AIC3X_CLK_MANAGER_REG04:
+        case TLV320AIC3X_CLK_MANAGER_REG05:
+        case TLV320AIC3X_CLK_MANAGER_REG06:
+        case TLV320AIC3X_CLK_MANAGER_REG07:
+        case TLV320AIC3X_CLK_MANAGER_REG08:
+        case TLV320AIC3X_SDPIN_REG09:
+        case TLV320AIC3X_SDPOUT_REG0A:
+        case TLV320AIC3X_SYSTEM_REG0B:
+        case TLV320AIC3X_SYSTEM_REG0C:
+        case TLV320AIC3X_SYSTEM_REG0D:
+        case TLV320AIC3X_SYSTEM_REG0E:
+        case TLV320AIC3X_SYSTEM_REG0F:
+        case TLV320AIC3X_SYSTEM_REG10:
+        case TLV320AIC3X_SYSTEM_REG11:
+        case TLV320AIC3X_SYSTEM_REG12:
+        case TLV320AIC3X_SYSTEM_REG13:
+        case TLV320AIC3X_SYSTEM_REG14:
+        case TLV320AIC3X_ADC_REG15:
+        case TLV320AIC3X_ADC_REG16:
+        case TLV320AIC3X_ADC_REG17:
+        case TLV320AIC3X_ADC_REG18:
+        case TLV320AIC3X_ADC_REG19:
+        case TLV320AIC3X_ADC_REG1A:
+        case TLV320AIC3X_ADC_REG1B:
+        case TLV320AIC3X_ADC_REG1C:
+        case TLV320AIC3X_ADC_REG1E:
+        case TLV320AIC3X_DAC_REG31:
+        case TLV320AIC3X_DAC_REG32:
+        case TLV320AIC3X_DAC_REG33:
+        case TLV320AIC3X_PRIV_INDEX:
+        case TLV320AIC3X_PRIV_DATA:
+        case TLV320AIC3X_DAC_REG34:
+        case TLV320AIC3X_DAC_REG35:
+        case TLV320AIC3X_DAC_REG37:
+        case TLV320AIC3X_GPIO_REG44:
+        case TLV320AIC3X_GP_REG45:
+        case TLV320AIC3X_CHD1_REGFD:
+        case TLV320AIC3X_CHD2_REGFE:
+        case TLV320AIC3X_CHVER_REGFF:
+            return 1;
+        default:
+            return 0;
+    }
+}
+
+/******************************************************************************
+ * Function     : tlv320aic3x_reg_read
+ *******************************************************************************
+ *
+ * Description  :  
+ *
+ * Parameters   : char RegAddr
+ * Parameters   : unsigned short *value
+ *
+ * Output Param   : None.
+ *
+ * Return value   :  
+ *
+ * Notes         : 
+ *******************************************************************************/
+static int tlv320aic3x_reg_read(struct i2c_client *client, unsigned char reg)
+{  
+    unsigned char data[1] = {0};
+    int value = 0x0;
+
+    data[0] = reg & 0xFF;
+
+    if (data[0] > 0x00)
+    {
+        data[0] -= 1;
+    }
+
+    if(i2c_master_send(client, data, 1) == 1) {
+        i2c_master_recv(client, data, 1);
+        value = data[0];
+#ifdef TLV320AIC3X_DEBUG
+        printk(KERN_INFO"%s: tlv320aic3x read reg:[0x%02x]=0x%02x\n", __FUNCTION__, reg, value);
+#endif
+        return value;
+    } else {
+        printk(KERN_INFO"%s: tlv320aic3x read failed.\n", __FUNCTION__);
+        return -EIO;
+    }
+}
+
+
+static int tlv320aic3x_read(unsigned char reg, unsigned short *oValue)
+{
+    int value;
+
+    value = tlv320aic3x_reg_read(g_tlv320aic3x_client, reg);
+
+    if (value < 0)
+    {
+        printk(KERN_INFO"%s: tlv320aic3x_reg read failed.\n", __FUNCTION__);
+
+        *oValue = 0x00;
+        return -EIO;
+    }
+
+    *oValue = value & 0xFF;
+
+    return 0;
+}
+/******************************************************************************
+ * Function     : tlv320aic3x_write
+ *******************************************************************************
+ *
+ * Description  :  
+ *
+ * Parameters   : char RegAddr
+ * Parameters   : unsigned short RegData
+ *
+ * Output Param   : None.
+ *
+ * Return value   :  
+ *
+ * Notes         : 
+ *******************************************************************************/
+static int tlv320aic3x_reg_write(struct i2c_client *client, char reg, unsigned short value)
+{  
+    char data[3] = {0};
+
+    data[0] = reg & 0xFF;
+   // data[1] = (char)((value >> 8) & 0xFF);
+    data[1] = (char)(value & 0xFF);
+
+    if (i2c_master_send(client, data, 2) == 2) {
+#ifdef TLV320AIC3X_DEBUG
+        printk(KERN_INFO"%s=> reg:0x%02x,value:0x%02x success\n", __FUNCTION__, reg, value);
+#endif
+        return 0;
+    } else {
+        printk(KERN_INFO"%s=> reg:0x%02x,value:0x%02x error\n", __FUNCTION__, reg, value);
+        return -1;
+    }
+}
+
+static int tlv320aic3x_write(unsigned char reg, unsigned short value)
+{
+    int ret;
+
+#ifdef TLV320AIC3X_DEBUG_CLOSE
+    unsigned short read_value;
+#endif
+
+    ret = tlv320aic3x_reg_write(g_tlv320aic3x_client, reg, value);
+    if (ret < 0)
+    {
+        printk(KERN_INFO"%s:L%d: tlv320aic3x_write() error.\n", __FUNCTION__, __LINE__);
+    }
+
+#ifdef TLV320AIC3X_DEBUG_CLOSE
+    //for check whether write is OK or not.
+    ret = tlv320aic3x_read(reg, &read_value);
+    if (ret < 0)
+    {
+        printk(KERN_INFO"%s:L%d: tlv320aic3x_read() error.\n", __FUNCTION__, __LINE__);
+    }
+
+    printk(KERN_INFO"%s:L%d: reg=0x%02x, value=0x%04x, read_value=0x%04x. Please check it:%s.\n",
+            __FUNCTION__, __LINE__, reg, value, read_value, (value == read_value)?"OK":"FAIL");
+#endif
+    return ret;
+}
+
+static int tlv320aic3x_update_bit(unsigned char reg, unsigned short mask, unsigned short value)
+{
+    int status = 0;
+    unsigned short orig = 0;
+    unsigned short tmp = 0;
+
+    status = tlv320aic3x_read(reg, &orig);
+    if (status < 0)
+    {
+        printk(KERN_INFO"%s:L%d: tlv320aic3x_read() error.\n", __FUNCTION__, __LINE__);
+        return status;
+    }
+    else
+    {
+        tmp = orig & (~mask);
+        tmp |= (value & mask);
+
+        if (tmp != orig)
+        {
+            status = tlv320aic3x_write(reg, tmp);
+            if (status < 0)
+            {
+                printk(KERN_INFO"%s:L%d: tlv320aic3x_write() error.\n", __FUNCTION__, __LINE__);
+                return status;
+            }
+        }
+    }
+
+#ifdef TLV320AIC3X_DEBUG_CLOSE
+    printk(KERN_INFO"%s:L%d: reg=0x%02x, mask=0x%02x, value=0x%04x, orig=0x%04x, last_value=0x%04x, please check it:%s.\n",
+            __FUNCTION__, __LINE__, reg, mask, value, orig, tmp, (orig == tmp)?"EQUAL":"UNEQUAL");
+#endif
+
+    return status;
+}
+
+static int tlv320aic3x_index_read(unsigned char RegAddr, unsigned short *value)
+{
+    int status = -1;
+
+    status = tlv320aic3x_write(TLV320AIC3X_PRIV_INDEX, RegAddr);
+    if (status != 0)
+    {
+        printk(KERN_INFO"status: %d, RegAddr: 0x%04x\n", status, RegAddr);
+        return status;
+    }
+
+    status = tlv320aic3x_read(TLV320AIC3X_PRIV_DATA, value);
+    if (status != 0)
+    {
+        printk(KERN_INFO"status: %d, RegAddr: 0x%04x\n", status, RegAddr);
+        return status;
+    }
+
+    return status;
+}
+
+static int tlv320aic3x_index_write(char RegAddr, unsigned short value)
+{
+    int status = -1;
+
+    status = tlv320aic3x_write(TLV320AIC3X_PRIV_INDEX, RegAddr);
+    if (status != 0)
+    {
+        printk(KERN_INFO"status: %d, RegAddr: 0x%04x\n", status, RegAddr);
+        return status;
+    }
+
+    status = tlv320aic3x_write(TLV320AIC3X_PRIV_DATA, value);
+    if (status != 0)
+    {
+        printk(KERN_INFO"status: %d, RegAddr: 0x%04x\n", status, RegAddr);
+        return status;
+    }
+
+    return status;
+}
+
+static int tlv320aic3x_index_update_bits(char RegAddr, unsigned short mask, unsigned short value)
+{
+    int status = -1;
+    unsigned short orig;
+    unsigned short tmp;
+
+    status = tlv320aic3x_index_read(RegAddr, &orig);
+    if (status != 0)
+    {
+        printk(KERN_INFO"status: %d, RegAddr: 0x%04x\n", status, RegAddr);
+    }
+    else
+    {
+        tmp = orig & (~mask);
+        tmp |= (value & mask);;
+
+        if (tmp != orig)
+        {
+            status = tlv320aic3x_index_write(RegAddr, tmp);
+            if (status != 0)
+            {
+                printk(KERN_INFO"status: %d, RegAddr: 0x%04x\n", status, RegAddr);
+            }
+        }
+    }
+
+    return status;
+}
+
+
+#define TLV320AIC3X_STATE_OFF 0x00  
+
+static char tlv320aic3x_init_ok = 0;
+static char connect_TLV320AIC3X = 0;
+static char TLV320AIC3X_work_state = TLV320AIC3X_STATE_OFF;
+
+static char l_connect_tlv320aic3x = 0;
+
+int tlv320aic3x_is_connect(void)
+{
+    return l_connect_tlv320aic3x;
+}
+
+int codec_tlv320aic3x_init(void)
+{
+    static char tlv320aic3x_init_ok = 0;
+    short value = 0;
+
+    if(0 == tlv320aic3x_init_ok){
+        //codec_tlv320aic3x_enable_mfpr();
+        /* check if has codec tlv320aic3x*/
+        tlv320aic3x_read(0xFE, &value);
+
+        if (0x10EC == value) {
+            tlv320aic3x_write(0x00, 0x00);
+            tlv320aic3x_init_ok = 1;
+            l_connect_tlv320aic3x = 1;
+
+            tlv320aic3x_init_ok = 1;
+            connect_TLV320AIC3X = 1;
+        }
+    }
+
+    printk(KERN_INFO"%s:L%d: tlv320aic3x_init_ok=%d, l_connect_tlv320aic3x =%d.\n",
+            __FUNCTION__, __LINE__, tlv320aic3x_init_ok, l_connect_tlv320aic3x);
+
+    return !tlv320aic3x_init_ok;
+}
+
+static int g_tlv320aic3x_mclk_type = 1;    /* 0: use bitclk,  1: use i2s_mclk,  2, use bitclk and turn on i2s_mclk */
+static int g_tlv320aic3xmainmic_type = 0; /* 0: differential mode,  1: single mode */
+
+/***********************************************************************
+  INTCBind() could only use one lisr for ***all*** GPIOs, 
+  So, headset detection is disabled by default on ASR1802S EVB.
+
+  So, we need to set g_tlv320aic3xheadset_plugged=1 by default;
+  thus user just need to plugin headset and no other operation/command is needed.
+ ************************************************************************/
+static int g_tlv320aic3xheadset_plugged = 1;	/* 0: headset plug out, 1: headset plug in */
+static int g_tlv320aic3xheadset_mic = 0; /* 0: without HS_MIC, 1: with HS_MIC */
+
+/***********************************************************************
+  When we enable headset detection, could not power off codec
+  i.e could not call codec_tlv320aic3x_power_on/codec_tlv320aic3x_power_off
+ ************************************************************************/
+int g_tlv320aic3xheadset_detection_enabled = 0; /* 0: disable, 1: enable */
+
+#define is_speaker_on()                 (TLV320AIC3X_work_state & 0x01)
+#define is_headphone_on()               (TLV320AIC3X_work_state & 0x02)
+#define is_main_mic_on()                (TLV320AIC3X_work_state & 0x04)
+#define is_headset_mic_on()             (TLV320AIC3X_work_state & 0x08)
+
+struct reg_value_group {
+    char reg;
+    unsigned short mask;
+    unsigned short value;
+};
+
+void disable_tlv320aic3x_MClock(void);
+void enable_tlv320aic3x_MClock(void);
+
+static int disableTLV320AIC3X = 0;
+static int disableTLV320AIC3XHsMic = 0;
+void disableCodecTLV320AIC3X(void)
+{
+    disableTLV320AIC3X = 1;
+}
+
+static int disableTLV320AIC3XDefaultPower = 0;
+void disableCodecTLV320AIC3XPower(void)
+{
+    disableTLV320AIC3XDefaultPower = 1;
+}
+
+void disableCodecTLV320AIC3XHsMic(void)
+{
+    disableTLV320AIC3XHsMic = 1;
+}
+
+int codec_tlv320aic3x_is_connect(void)
+{
+    return connect_TLV320AIC3X;
+}
+
+static void TLV320AIC3X_set_work_state(char device, char onoff)
+{
+    if (device == TLV320AIC3X_OUTPUT_DEVICE_SPEAKER)
+    {
+        if (onoff == TLV320AIC3X_DEVICE_OFF)
+        {
+            TLV320AIC3X_work_state &= 0xFE;
+        }
+        else if (onoff == TLV320AIC3X_DEVICE_ON)
+        {
+            TLV320AIC3X_work_state |= 0x01;
+        }
+    }
+    else if (device == TLV320AIC3X_OUTPUT_DEVICE_HEADPHONE)
+    {
+        if (onoff == TLV320AIC3X_DEVICE_OFF)
+        {
+            TLV320AIC3X_work_state &= 0xFD;
+        }
+        else if (onoff == TLV320AIC3X_DEVICE_ON)
+        {
+            TLV320AIC3X_work_state |= 0x02;
+        }
+    }
+    else if (device == TLV320AIC3X_INPUT_DEVICE_MAIN_MIC)
+    {
+        if (onoff == TLV320AIC3X_DEVICE_OFF)
+        {
+            TLV320AIC3X_work_state &= 0xFB;
+        }
+        else if (onoff == TLV320AIC3X_DEVICE_ON)
+        {
+            TLV320AIC3X_work_state |= 0x04;
+        }
+    }
+    else if (device == TLV320AIC3X_INPUT_DEVICE_HEADSET_MIC)
+    {
+        if (onoff == TLV320AIC3X_DEVICE_OFF)
+        {
+            TLV320AIC3X_work_state &= 0xF7;
+        }
+        else if (onoff == TLV320AIC3X_DEVICE_ON)
+        {
+            TLV320AIC3X_work_state |= 0x08;
+        }
+    }
+}
+
+/* audio control functions */
+static void tlv320aic3x_speaker_on(void)
+{
+#if 1
+    tlv320aic3x_index_write(0x3D, 0x3600);                        /*DAC Clock1 Generator Enable*/
+    tlv320aic3x_write(0x63, 0xf8de);                              /*LOUTMIX Power On*/
+    tlv320aic3x_write(0x61, 0x9804);                              /*DACL1 Power On*/
+    tlv320aic3x_write(0x62, 0x8800);                              /*Stereo1 DAC Digital Filter Power On*/
+    tlv320aic3x_write(0x65, 0xc800);                              /*OUTMIXL Power On*/
+    tlv320aic3x_write(0x66, 0x3000);                              /*OUTVOLL Power On*/
+    tlv320aic3x_write(0x8F, 0x3100);                              /*HP Deop Mode mode 2*/
+    tlv320aic3x_write(0x2A, 0x1250);                              /*DACL1 to Stereo DAC left Mixer*/
+    tlv320aic3x_write(0x4F, 0x0278);                              /*DACL1 to OUTMIXL*/
+    tlv320aic3x_write(0x52, 0x0278);                              /*DACR1 to OUTMIXR*/
+    tlv320aic3x_write(0x53, 0xc000);                              /*OUTVOLL to LOUTMIX Unmute*/
+    tlv320aic3x_write(0x03, 0x0808);                              /*LOUTL Unmute*/
+    tlv320aic3x_write(0x73, 0x0102);                              /*Stereo DAC sample Rate 128 FS*/
+    tlv320aic3x_write(0x05, 0x8000);                              /*enable Differential Line Output*/
+#else
+    tlv320aic3x_index_update_bits(0x3D, 1 << 10, 1 << 10);        /*DAC Clock1 Generator Enable*/
+    tlv320aic3x_index_update_bits(0x3D, 1 << 9,  1 << 9);         /*DAC Clock2 Generator Enable*/
+    tlv320aic3x_update_bit(0x63, 1 << 12, 1 << 12);               /*LOUTMIX Power On*/
+    tlv320aic3x_update_bit(0x61, 1 << 12, 1 << 12);               /*DACL1 Power On*/
+    tlv320aic3x_update_bit(0x61, 1 << 11, 1 << 11);               /*DACR1 Power On*/
+    tlv320aic3x_update_bit(0x62, 1 << 11, 1 << 11);               /*Stereo1 DAC Digital Filter Power On*/
+    tlv320aic3x_update_bit(0x65, 1 << 15, 1 << 15);               /*OUTMIXL Power On*/
+    tlv320aic3x_update_bit(0x65, 1 << 14, 1 << 14);               /*OUTMIXR Power On*/
+    tlv320aic3x_update_bit(0x66, 1 << 13, 1 << 13);               /*OUTVOLL Power On*/
+    tlv320aic3x_update_bit(0x66, 1 << 12, 1 << 12);               /*OUTVOLR Power On*/
+    tlv320aic3x_update_bit(0x8F, 1 << 13, 1 << 13);               /*HP Deop Mode mode 2*/
+    tlv320aic3x_update_bit(0x2A, 1 << 14, 0);                     /*DACL1 to Stereo DAC left Mixer*/
+    tlv320aic3x_update_bit(0x2A, 1 << 1,  0);                     /*DACL1 to Stereo DAC Right Mixer*/
+    tlv320aic3x_update_bit(0x4F, 1,       0);                     /*DACL1 to OUTMIXL*/
+    tlv320aic3x_update_bit(0x52, 1,       0);                     /*DACR1 to OUTMIXR*/
+    tlv320aic3x_update_bit(0x53, 1 << 13, 0);                     /*OUTVOLL to LOUTMIX Unmute*/
+    tlv320aic3x_update_bit(0x53, 1 << 12, 0);                     /*OUTVOLR to LOUTMIX Unmute*/
+    tlv320aic3x_update_bit(0x03, 1 << 15, 0);                     /*LOUTL Unmute*/
+    tlv320aic3x_update_bit(0x03, 1 << 14, 0);                     /*OUTVOLL Unmute*/
+    tlv320aic3x_update_bit(0x03, 1 << 7,  0);                     /*LOUTR Unmute*/
+    tlv320aic3x_update_bit(0x03, 1 << 6,  0);                     /*OUTVOLR Unmute*/
+    tlv320aic3x_update_bit(0x73, 3 << 2,  0 << 2);                /*Stereo DAC sample Rate 128 FS*/
+    tlv320aic3x_update_bit(0x05, 1 << 15,  1 << 15);              /*enable Differential Line Output*/
+#endif
+}
+
+static void tlv320aic3x_speaker_off(void)
+{
+#if 1
+    tlv320aic3x_index_write(0x3D, 0x2000);                        /*DAC Clock1 Generator Enable*/
+    tlv320aic3x_write(0x63, 0xe8de);                              /*LOUTMIX Power Off*/
+    tlv320aic3x_write(0x61, 0x8000);                              /*DACL1 Power On*/
+    tlv320aic3x_write(0x62, 0x0000);                              /*Stereo1 DAC Digital Filter Power On*/
+    tlv320aic3x_write(0x65, 0x0000);                              /*OUTMIXL Power On*/
+    tlv320aic3x_write(0x66, 0x0000);                              /*OUTVOLL Power On*/
+    tlv320aic3x_write(0x8F, 0x1100);                              /*HP Deop Mode mode 2*/
+    tlv320aic3x_write(0x2A, 0x5250);                              /*DACL1 to Stereo DAC left Mixer*/
+    tlv320aic3x_write(0x4F, 0x0279);                              /*DACL1 to OUTMIXL*/
+    tlv320aic3x_write(0x52, 0x0279);                              /*DACR1 to OUTMIXR*/
+    tlv320aic3x_write(0x53, 0xf000);                              /*OUTVOLL to LOUTMIX Unmute*/
+    tlv320aic3x_write(0x03, 0xc8c8);                              /*LOUTL Unmute*/
+    tlv320aic3x_write(0x73, 0x0102);                              /*Stereo DAC sample Rate 128 FS*/
+    tlv320aic3x_write(0x05, 0x0000);                              /*disable Differential Line Output*/
+#else
+    tlv320aic3x_index_update_bits(0x3D, 1 << 10, 0);              /*DAC Clock1 Generator Enable*/
+    tlv320aic3x_index_update_bits(0x3D, 1 << 9,  0);              /*DAC Clock2 Generator Enable*/
+    tlv320aic3x_update_bit(0x63, 1 << 12, 0);                     /*LOUTMIX Power Off*/
+    tlv320aic3x_update_bit(0x61, 1 << 12, 0);                     /*DACL1 Power On*/
+    tlv320aic3x_update_bit(0x61, 1 << 11, 0);                     /*DACR1 Power On*/
+    tlv320aic3x_update_bit(0x62, 1 << 11, 0);                     /*Stereo1 DAC Digital Filter Power On*/
+    tlv320aic3x_update_bit(0x65, 1 << 15, 0);                     /*OUTMIXL Power On*/
+    tlv320aic3x_update_bit(0x65, 1 << 14, 0);                     /*OUTMIXR Power On*/
+    tlv320aic3x_update_bit(0x66, 1 << 13, 0);                     /*OUTVOLL Power On*/
+    tlv320aic3x_update_bit(0x66, 1 << 12, 0);                     /*OUTVOLR Power On*/
+    tlv320aic3x_update_bit(0x8F, 1 << 13, 0);                     /*HP Deop Mode mode 2*/
+    tlv320aic3x_update_bit(0x2A, 1 << 14, 1 << 14);               /*DACL1 to Stereo DAC left Mixer*/
+    tlv320aic3x_update_bit(0x2A, 1 << 6,  1 << 6);                /*DACR1 to Stereo DAC Right Mixer*/
+    tlv320aic3x_update_bit(0x4F, 1,       1);                     /*DACL1 to OUTMIXL*/
+    tlv320aic3x_update_bit(0x52, 1,       1);                     /*DACR1 to OUTMIXR*/
+    tlv320aic3x_update_bit(0x53, 1 << 13, 1 << 13);               /*OUTVOLL to LOUTMIX Unmute*/
+    tlv320aic3x_update_bit(0x53, 1 << 12, 1 << 12);               /*OUTVOLR to LOUTMIX Unmute*/
+    tlv320aic3x_update_bit(0x03, 1 << 15, 1 << 15);               /*LOUTL Unmute*/
+    tlv320aic3x_update_bit(0x03, 1 << 14, 1 << 14);               /*OUTVOLL Unmute*/
+    tlv320aic3x_update_bit(0x03, 1 << 7,  1 << 7);                /*LOUTR Unmute*/
+    tlv320aic3x_update_bit(0x03, 1 << 6,  1 << 6);                /*OUTVOLR Unmute*/
+    tlv320aic3x_update_bit(0x73, 3 << 2,  0 << 2);                /*Stereo DAC sample Rate 128 FS*/
+    tlv320aic3x_update_bit(0x05, 1 << 15,  0 << 15);              /*disable Differential Line Output*/
+#endif
+}
+
+static void tlv320aic3x_headphone_on(void)
+{
+#if 1
+    tlv320aic3x_index_write(0x3D, 0x3600);                        /*DAC Clock1 Generator Enable*/
+    tlv320aic3x_write(0x61, 0x9804);                              /*DACL1 Power On*/
+    tlv320aic3x_write(0x62, 0x8800);                              /*Stereo1 DAC Digital Filter Power On*/
+    tlv320aic3x_write(0x65, 0xcc00);                              /*OUTMIXL Power On*/
+    tlv320aic3x_write(0x66, 0x0c00);                              /*HPOVOLL Power On*/
+    tlv320aic3x_write(0x8E, 0x001d);                              /*Enable Headphone Output*/
+    tlv320aic3x_write(0x8F, 0x3100);                              /*HP Deop Mode mode 2*/
+    tlv320aic3x_write(0x2A, 0x1250);                              /*DACL1 to Stereo DAC left Mixer*/
+    tlv320aic3x_write(0x4F, 0x0278);                              /*DACL1 to OUTMIXL*/
+    tlv320aic3x_write(0x52, 0x0278);                              /*DACR1 to OUTMIXR*/
+    tlv320aic3x_write(0x45, 0x5000);                              /*HPOVOL to HPOMIX Unmute*/
+    tlv320aic3x_write(0x02, 0x0808);                              /*HPOL UnMute*/
+    tlv320aic3x_write(0x73, 0x0102);                              /*Stereo DAC sample Rate 128 FS*/
+
+#else
+    tlv320aic3x_index_update_bits(0x3D, 1 << 10, 1 << 10);        /*DAC Clock1 Generator Enable*/
+    tlv320aic3x_index_update_bits(0x3D, 1 << 9,  1 << 9);         /*DAC Clock2 Generator Enable*/
+    tlv320aic3x_update_bit(0x61, 1 << 12, 1 << 12);               /*DACL1 Power On*/
+    tlv320aic3x_update_bit(0x61, 1 << 11, 1 << 11);               /*DACR1 Power On*/
+    tlv320aic3x_update_bit(0x62, 1 << 11, 1 << 11);               /*Stereo1 DAC Digital Filter Power On*/
+    tlv320aic3x_update_bit(0x65, 1 << 15, 1 << 15);               /*OUTMIXL Power On*/
+    tlv320aic3x_update_bit(0x65, 1 << 14, 1 << 14);               /*OUTMIXR Power On*/
+    tlv320aic3x_update_bit(0x66, 1 << 11, 1 << 11);               /*HPOVOLL Power On*/
+    tlv320aic3x_update_bit(0x66, 1 << 10, 1 << 10);               /*HPOVOLR Power On*/
+    tlv320aic3x_update_bit(0x8E, 1 << 4,  1 << 4);                /*Enable Headphone Output*/
+    tlv320aic3x_update_bit(0x8E, 1,       1);                     /*HP Amp All Power On*/
+    tlv320aic3x_update_bit(0x8F, 1 << 13, 1 << 13);               /*HP Deop Mode mode 2*/
+    tlv320aic3x_update_bit(0x2A, 1 << 14, 0);                     /*DACL1 to Stereo DAC left Mixer*/
+    tlv320aic3x_update_bit(0x2A, 1 << 1,  0);                     /*DACL1 to Stereo DAC Right Mixer*/
+    tlv320aic3x_update_bit(0x4F, 1,       0);                     /*DACL1 to OUTMIXL*/
+    tlv320aic3x_update_bit(0x52, 1,       0);                     /*DACR1 to OUTMIXR*/
+    tlv320aic3x_update_bit(0x45, 1 << 13, 0);                     /*HPOVOL to HPOMIX Unmute*/
+    tlv320aic3x_update_bit(0x02, 1 << 15, 0);                     /*HPOL UnMute*/
+    tlv320aic3x_update_bit(0x02, 1 << 14, 0);                     /*HPOVOLL Unmute*/
+    tlv320aic3x_update_bit(0x02, 1 << 7,  0);                     /*HPOR UnMute*/
+    tlv320aic3x_update_bit(0x02, 1 << 6,  0);                     /*HPOVOLR Unmute*/
+    tlv320aic3x_update_bit(0x73, 3 << 2,  0 << 2);                /*Stereo DAC sample Rate 128 FS*/
+
+#endif
+}
+
+static void tlv320aic3x_headphone_off(void)
+{
+#if 1
+    tlv320aic3x_index_write(0x3D, 0x2000);                        /*DAC Clock1 Generator Enable*/
+    tlv320aic3x_write(0x61, 0x8000);                              /*DACL1 Power On*/
+    tlv320aic3x_write(0x62, 0x0000);                              /*Stereo1 DAC Digital Filter Power On*/
+    tlv320aic3x_write(0x65, 0x0000);                              /*OUTMIXL Power On*/
+    tlv320aic3x_write(0x66, 0x0000);                              /*HPOVOLL Power On*/
+    tlv320aic3x_write(0x8E, 0x000c);                              /*Enable Headphone Output*/
+    tlv320aic3x_write(0x8F, 0x1100);                              /*HP Deop Mode mode 2*/
+    tlv320aic3x_write(0x2A, 0x5252);                              /*DACR1 to Stereo DAC left Mixer*/
+    tlv320aic3x_write(0x4F, 0x0279);                              /*DACL1 to OUTMIXL*/
+    tlv320aic3x_write(0x52, 0x0279);                              /*DACR1 to OUTMIXR*/
+    tlv320aic3x_write(0x45, 0x7000);                              /*HPOVOL to HPOMIX Unmute*/
+    tlv320aic3x_write(0x02, 0xc8c8);                              /*HPOL UnMute*/
+    tlv320aic3x_write(0x73, 0x0102);                              /*Stereo DAC sample Rate 128 FS*/
+#else
+    tlv320aic3x_index_update_bits(0x3D, 1 << 10, 0);              /*DAC Clock1 Generator Enable*/
+    tlv320aic3x_index_update_bits(0x3D, 1 << 9,  0);              /*DAC Clock2 Generator Enable*/
+    tlv320aic3x_update_bit(0x61, 1 << 12, 0);                     /*DACL1 Power On*/
+    tlv320aic3x_update_bit(0x61, 1 << 11, 0);                     /*DACR1 Power On*/
+    tlv320aic3x_update_bit(0x62, 1 << 11, 0);                     /*Stereo1 DAC Digital Filter Power On*/
+    tlv320aic3x_update_bit(0x65, 1 << 15, 0);                     /*OUTMIXL Power On*/
+    tlv320aic3x_update_bit(0x65, 1 << 14, 0);                     /*OUTMIXR Power On*/
+    tlv320aic3x_update_bit(0x66, 1 << 11, 0);                     /*HPOVOLL Power On*/
+    tlv320aic3x_update_bit(0x66, 1 << 10, 0);                     /*HPOVOLR Power On*/
+    tlv320aic3x_update_bit(0x8E, 1 << 4,  0);                     /*Enable Headphone Output*/
+    tlv320aic3x_update_bit(0x8E, 1,       0);                     /*HP Amp All Power On*/
+    tlv320aic3x_update_bit(0x8F, 1 << 13, 0);                     /*HP Deop Mode mode 2*/
+    tlv320aic3x_update_bit(0x2A, 1 << 14, 1 << 14);               /*DACR1 to Stereo DAC left Mixer*/
+    tlv320aic3x_update_bit(0x2A, 1 << 1,  1 << 1);                /*DACL1 to Stereo DAC Right Mixer*/
+    tlv320aic3x_update_bit(0x4F, 1,       1);                     /*DACL1 to OUTMIXL*/
+    tlv320aic3x_update_bit(0x52, 1,       1);                     /*DACR1 to OUTMIXR*/
+    tlv320aic3x_update_bit(0x45, 1 << 13, 1 << 13);               /*HPOVOL to HPOMIX Unmute*/
+    tlv320aic3x_update_bit(0x02, 1 << 15, 1 << 15);               /*HPOL UnMute*/
+    tlv320aic3x_update_bit(0x02, 1 << 14, 1 << 14);               /*HPOVOLL Unmute*/
+    tlv320aic3x_update_bit(0x02, 1 << 7,  1 << 7);                /*HPOR UnMute*/
+    tlv320aic3x_update_bit(0x02, 1 << 6,  1 << 6);                /*HPOVOLR Unmute*/
+    tlv320aic3x_update_bit(0x73, 3 << 2,  0 << 2);                /*Stereo DAC sample Rate 128 FS*/
+#endif
+}
+
+static void tlv320aic3x_main_mic_on(void)
+{
+#if 1
+    tlv320aic3x_index_write(0x3D, 0x3600);                        /*ADC Clock Genaral Enable*/
+    tlv320aic3x_write(0x65, 0xc800);                              /*RECMIXL Power On*/
+    tlv320aic3x_write(0x61, 0x9804);                              /*ADCL Power On*/
+    tlv320aic3x_write(0x62, 0x8800);                              /*Stereo ADC Digital Filter Power On*/
+    tlv320aic3x_write(0x64, 0x4a00);                              /*BST2 Power On*/
+    tlv320aic3x_write(0x0D, 0x0540);                              /*IN2 Boost Control +40dB*/
+    tlv320aic3x_write(0x73, 0x0102);                              /*Stereo ADC Over Sample Rate 32 Fs*/
+    tlv320aic3x_write(0x3C, 0x006b);                              /*BST2 to RECMIXL Unmute*/
+    tlv320aic3x_write(0x3E, 0x006b);                              /*BST1 to RECMIXR Unmute*/
+    tlv320aic3x_write(0x27, 0x3860);                              /*Stereo ADC1 Left Channel Unmute*/
+#else
+    tlv320aic3x_index_update_bits(0x3D, 1 << 12,  1 << 12);       /*ADC Clock Genaral Enable*/
+    tlv320aic3x_update_bit(0x65, 1 << 11, 1 << 11);               /*RECMIXL Power On*/
+    tlv320aic3x_update_bit(0x61, 1 << 2,  1 << 2);                /*ADCL Power On*/
+    tlv320aic3x_update_bit(0x62, 1 << 15, 1 << 15);               /*Stereo ADC Digital Filter Power On*/
+    tlv320aic3x_update_bit(0x64, 1 << 14, 1 << 14);               /*BST2 Power On*/
+    tlv320aic3x_update_bit(0x0D, 0xF << 8, 5 << 8);               /*IN2 Boost Control +40dB*/
+    tlv320aic3x_update_bit(0x0D, 1 << 6,  1 << 6);                /*IN2 Differential Mode*/
+    tlv320aic3x_update_bit(0x73, 3,       2);                     /*Stereo ADC Over Sample Rate 32 Fs*/
+    tlv320aic3x_update_bit(0x3C, 1 << 2,  0);                     /*BST2 to RECMIXL Unmute*/
+    tlv320aic3x_update_bit(0x3E, 1 << 2,  0);                     /*BST1 to RECMIXR Unmute*/
+    tlv320aic3x_update_bit(0x27, 1 << 14, 0);                     /*Stereo ADC1 Left Channel Unmute*/
+#endif
+}
+
+static void tlv320aic3x_main_mic_off(void)
+{
+#if 1
+    tlv320aic3x_index_write(0x3D, 0x2000);                        /*ADC Clock Genaral Enable*/
+    tlv320aic3x_write(0x65, 0x0000);                              /*RECMIXL Power On*/
+    tlv320aic3x_write(0x61, 0x8000);                              /*ADCL Power On*/
+    tlv320aic3x_write(0x62, 0x0000);                              /*Stereo ADC Digital Filter Power On*/
+    tlv320aic3x_write(0x64, 0x0a00);                              /*BST2 Power On*/
+    tlv320aic3x_write(0x0D, 0x0000);                              /*IN2 Boost Control +40dB*/
+    tlv320aic3x_write(0x73, 0x0102);                              /*Stereo ADC Over Sample Rate 128 Fs*/
+    tlv320aic3x_write(0x3C, 0x006f);                              /*BST2 to RECMIXL Unmute*/
+    tlv320aic3x_write(0x3E, 0x006f);                              /*BST2 to RECMIXL Unmute*/
+    tlv320aic3x_write(0x27, 0x7860);                              /*Stereo ADC1 Left Channel Unmute*/
+#else
+    tlv320aic3x_index_update_bits(0x3D, 1 << 12,  0);             /*ADC Clock Genaral Enable*/
+    tlv320aic3x_update_bit(0x65, 1 << 11, 0);                     /*RECMIXL Power On*/
+    tlv320aic3x_update_bit(0x61, 1 << 2,  0);                     /*ADCL Power On*/
+    tlv320aic3x_update_bit(0x62, 1 << 15, 0);                     /*Stereo ADC Digital Filter Power On*/
+    tlv320aic3x_update_bit(0x64, 1 << 14, 0);                     /*BST2 Power On*/
+    tlv320aic3x_update_bit(0x0D, 0xF << 8, 0);                    /*IN2 Boost Control +40dB*/
+    tlv320aic3x_update_bit(0x0D, 1 << 6,  0);                     /*IN2 Differential Mode*/
+    tlv320aic3x_update_bit(0x73, 3,       2);                     /*Stereo ADC Over Sample Rate 128 Fs*/
+    tlv320aic3x_update_bit(0x3C, 1 << 2,  1 << 2);                /*BST2 to RECMIXL Unmute*/
+    tlv320aic3x_update_bit(0x3E, 1 << 2,  1 << 2);                /*BST2 to RECMIXL Unmute*/
+    tlv320aic3x_update_bit(0x27, 1 << 14, 1 << 14);               /*Stereo ADC1 Left Channel Unmute*/
+#endif
+}
+
+static void tlv320aic3x_headset_mic_on(void)
+{
+#if 1
+    tlv320aic3x_index_write(0x3D, 0x3600);                        /*ADC Clock Genaral Enable*/
+    tlv320aic3x_write(0x65, 0xcc00);                              /*RECMIXL Power On*/
+    tlv320aic3x_write(0x61, 0x9804);                              /*ADCL Power On*/
+    tlv320aic3x_write(0x62, 0x8800);                              /*Stereo ADC Digital Filter Power On*/
+    tlv320aic3x_write(0x0D, 0x5000);                              /*IN1 Boost Control +40dB*/
+    tlv320aic3x_write(0x64, 0x4a04);                              /*BST1 Power On*/
+    tlv320aic3x_write(0x73, 0x0102);                              /*Stereo ADC Over Sample Rate 128 Fs*/
+    tlv320aic3x_write(0x3C, 0x006D);                              /*BST1 to RECMIXL Unmute*/
+    tlv320aic3x_write(0x3E, 0x006D);                              /*BST1 to RECMIXR Unmute*/
+    tlv320aic3x_write(0x27, 0x3820);                              /*Stereo ADC1 Left Channel Unmute*/
+#else
+    tlv320aic3x_index_update_bits(0x3D, 1 << 12, 1 << 12);        /*ADC Clock Genaral Enable*/
+    tlv320aic3x_update_bit(0x65, 1 << 11, 1 << 11);               /*RECMIXL Power On*/
+    tlv320aic3x_update_bit(0x65, 1 << 10, 1 << 10);               /*RECMIXR Power On*/
+    tlv320aic3x_update_bit(0x61, 1 << 2,  1 << 2);                /*ADCL Power On*/
+    tlv320aic3x_update_bit(0x61, 1 << 1,  1 << 1);                /*ADCR Power On*/
+    tlv320aic3x_update_bit(0x62, 1 << 15, 1 << 15);               /*Stereo ADC Digital Filter Power On*/
+    tlv320aic3x_update_bit(0x0D, 0xF << 12, 5 << 12);             /*IN1 Boost Control +40dB*/
+    tlv320aic3x_update_bit(0x64, 1 << 15, 0 << 15);               /*BST1 Power On*/
+    tlv320aic3x_update_bit(0x64, 1 << 4,  1 << 4);                /*MIC2 SE Mode single-end mode*/
+    tlv320aic3x_update_bit(0x73, 3,       2);                     /*Stereo ADC Over Sample Rate 128 Fs*/
+    tlv320aic3x_update_bit(0x3C, 1 << 1,  0);                     /*BST1 to RECMIXL Unmute*/
+    tlv320aic3x_update_bit(0x3E, 1 << 1,  0);                     /*BST1 to RECMIXR Unmute*/
+    tlv320aic3x_update_bit(0x27, 1 << 14, 0);                     /*Stereo ADC1 Left Channel Unmute*/
+    tlv320aic3x_update_bit(0x27, 1 << 6, 0);                      /*Stereo ADC1 Right Channel Unmute*/
+#endif
+}
+
+static void tlv320aic3x_headset_mic_off(void)
+{
+#if 1
+    tlv320aic3x_index_write(0x3D, 0x2000);                        /*ADC Clock Genaral Enable*/
+    tlv320aic3x_write(0x65, 0x0000);                              /*recmixl power on*/
+    tlv320aic3x_write(0x61, 0x8000);                              /*adcl power on*/
+    tlv320aic3x_write(0x62, 0x0000);                              /*stereo adc digital filter power on*/
+    tlv320aic3x_write(0x0d, 0x0540);                              /*in1 boost control +40db*/
+    tlv320aic3x_write(0x64, 0x4a00);                              /*bst1 power on*/
+    tlv320aic3x_write(0x73, 0x0102);                              /*stereo adc over sample rate 128 fs*/
+    tlv320aic3x_write(0x3c, 0x006b);                              /*bst1 to recmixl unmute*/
+    tlv320aic3x_write(0x3e, 0x006b);                              /*bst1 to recmixr unmute*/
+    tlv320aic3x_write(0x27, 0x7860);                              /*stereo adc1 left channel unmute*/
+#else
+    tlv320aic3x_index_update_bits(0x3D, 1 << 12,  0);            /*ADC Clock Genaral Enable*/
+    tlv320aic3x_update_bit(0x65, 1 << 11, 0);                    /*RECMIXL Power On*/
+    tlv320aic3x_update_bit(0x65, 1 << 10, 0);                    /*RECMIXR Power On*/
+    tlv320aic3x_update_bit(0x61, 1 << 2,  0);                    /*ADCL Power On*/
+    tlv320aic3x_update_bit(0x61, 1 << 1,  0);                    /*ADCR Power On*/
+    tlv320aic3x_update_bit(0x62, 1 << 15, 0);                    /*Stereo ADC Digital Filter Power On*/
+    tlv320aic3x_update_bit(0x0D, 0xF << 12, 0);                  /*IN1 Boost Control +40dB*/
+    tlv320aic3x_update_bit(0x64, 1 << 15, 0);                    /*BST1 Power On*/
+    tlv320aic3x_update_bit(0x64, 1 << 4,  0);                    /*MIC2 SE Mode single-end mode*/
+    tlv320aic3x_update_bit(0x73, 3,       2);                    /*Stereo ADC Over Sample Rate 128 Fs*/
+    tlv320aic3x_update_bit(0x3C, 1 << 1,  1 << 1);               /*BST1 to RECMIXL Unmute*/
+    tlv320aic3x_update_bit(0x3E, 1 << 1,  1 << 1);               /*BST1 to RECMIXR Unmute*/
+    tlv320aic3x_update_bit(0x27, 1 << 14, 1 << 14);              /*Stereo ADC1 Left Channel Unmute*/
+    tlv320aic3x_update_bit(0x27, 1 << 6, 1 << 6);                /*Stereo ADC1 Right Channel Unmute*/
+#endif
+}
+
+void tlv320aic3x_mute_mic(int mute)
+{
+#if 1
+    if (mute) {
+        tlv320aic3x_write(0x1c, 0xafaf);
+    } else {
+        tlv320aic3x_write(0x1c, 0x2f2f);
+    }
+#else
+    if (mute) {
+        tlv320aic3x_update_bit(0x1c, (1 << 15), (1 << 15));
+        tlv320aic3x_update_bit(0x1c, (1 << 7), (1 << 7));
+    } else {
+        tlv320aic3x_update_bit(0x1c, (1 << 15), (0 << 15));
+        tlv320aic3x_update_bit(0x1c, (1 << 7), (0 << 7));
+    }
+#endif
+    return;
+}
+             /*volume level:   0,     1,      2,      3,      4,      5,      6,      7,      8,      9,     10 */
+int gain_output_ctrl[11] = { 0x0A,   0x09,   0x08,   0x07,   0x06,   0x05,   0x04,   0x03,   0x02,   0x01,   0x00};
+int gain_digital_vol[11] = { 0xAFAF, 0xB7B7, 0xBFBF, 0xC7C7, 0xCFCF, 0xD7D7, 0xDDDD, 0xE5E5, 0xEDED, 0xF5F5, 0xFFFF};
+
+void tlv320aic3x_adjust_gain(int gain)
+{
+    /* gain is within 0~10 */
+#if 1
+    tlv320aic3x_update_bit(0x02, (0x3F << 8), (gain_output_ctrl[gain] << 8));/* Headphone output control */
+    tlv320aic3x_update_bit(0x02, (0x3F << 0), (gain_output_ctrl[gain] << 0));
+
+    tlv320aic3x_update_bit(0x03, (0x3F << 8), (gain_output_ctrl[gain] << 8));/* Line Output Control 1 */
+    tlv320aic3x_update_bit(0x03, (0x3F << 0), (gain_output_ctrl[gain] << 0));
+
+    tlv320aic3x_write(0x19, gain_digital_vol[gain]); /* DACL1/R1 Digital Volume */
+#else
+    tlv320aic3x_update_bit(0x02, (0x3F << 8), (gain_output_ctrl[gain] << 8));/* Headphone output control */
+    tlv320aic3x_update_bit(0x02, (0x3F << 0), (gain_output_ctrl[gain] << 0));
+
+    tlv320aic3x_update_bit(0x03, (0x3F << 8), (gain_output_ctrl[gain] << 8));/* Line Output Control 1 */
+    tlv320aic3x_update_bit(0x03, (0x3F << 0), (gain_output_ctrl[gain] << 0));
+
+    tlv320aic3x_write(0x19, gain_digital_vol[gain]); /* DACL1/R1 Digital Volume */
+#endif
+    return;
+}
+
+void tlv320aic3x_check_HS_mic(void)
+{
+    /* Enable MICBIAS1 Short Current Detector, Threshold:1500uA */
+    tlv320aic3x_update_bit(0x93, (7 << 9), (5 << 9));
+    return;
+}
+
+#define tlv320aic3x_speaker_on_REG_GROUP_NUM 23
+static struct reg_value_group tlv320aic3x_speaker_on_reg_group[] = {
+    {0x3D, 1 << 10, 1 << 10},               /*DAC Clock1 Generator Enable*/
+    {0x3D, 1 << 9,  1 << 9},                /*DAC Clock2 Generator Enable*/
+    {0x63, 1 << 12, 1 << 12},               /*LOUTMIX Power On*/
+    {0x61, 1 << 12, 1 << 12},               /*DACL1 Power On*/
+    {0x61, 1 << 11, 1 << 11},               /*DACR1 Power On*/
+    {0x62, 1 << 11, 1 << 11},               /*Stereo1 DAC Digital Filter Power On*/
+    {0x65, 1 << 15, 1 << 15},               /*OUTMIXL Power On*/
+    {0x65, 1 << 14, 1 << 14},               /*OUTMIXR Power On*/
+    {0x66, 1 << 13, 1 << 13},               /*OUTVOLL Power On*/
+    {0x66, 1 << 12, 1 << 12},               /*OUTVOLR Power On*/
+    {0x8F, 1 << 13, 1 << 13},               /*HP Deop Mode mode 2*/
+    {0x2A, 1 << 14, 0},                     /*DACL1 to Stereo DAC left Mixer*/
+    {0x2A, 1 << 1,  0},                     /*DACL1 to Stereo DAC Right Mixer*/
+    {0x4F, 1,       0},                     /*DACL1 to OUTMIXL*/
+    {0x52, 1,       0},                     /*DACR1 to OUTMIXR*/
+    {0x53, 1 << 13, 0},                     /*OUTVOLL to LOUTMIX Unmute*/
+    {0x53, 1 << 12, 0},                     /*OUTVOLR to LOUTMIX Unmute*/
+    {0x03, 1 << 15, 0},                     /*LOUTL Unmute*/
+    {0x03, 1 << 14, 0},                     /*OUTVOLL Unmute*/
+    {0x03, 1 << 7,  0},                     /*LOUTR Unmute*/
+    {0x03, 1 << 6,  0},                     /*OUTVOLR Unmute*/
+    {0x73, 3 << 2,  0 << 2},                /*Stereo DAC sample Rate 128 FS*/
+    {0x05, 1 << 15,  1 << 15},              /*enable Differential Line Output*/
+};
+
+#define TLV320AIC3X_SPEAKER_OFF_REG_GROUP_NUM 23
+static struct reg_value_group TLV320AIC3X_speaker_off_reg_group[] = {
+    {0x3D, 1 << 10, 0},                     /*DAC Clock1 Generator Enable*/
+    {0x3D, 1 << 9,  0},                     /*DAC Clock2 Generator Enable*/
+    {0x63, 1 << 12, 0},                     /*LOUTMIX Power Off*/
+    {0x61, 1 << 12, 0},                     /*DACL1 Power On*/
+    {0x61, 1 << 11, 0},                     /*DACR1 Power On*/
+    {0x62, 1 << 11, 0},                     /*Stereo1 DAC Digital Filter Power On*/
+    {0x65, 1 << 15, 0},                     /*OUTMIXL Power On*/
+    {0x65, 1 << 14, 0},                     /*OUTMIXR Power On*/
+    {0x66, 1 << 13, 0},                     /*OUTVOLL Power On*/
+    {0x66, 1 << 12, 0},                     /*OUTVOLR Power On*/
+    {0x8F, 1 << 13, 0},                     /*HP Deop Mode mode 2*/
+    {0x2A, 1 << 14, 1 << 14},               /*DACL1 to Stereo DAC left Mixer*/
+    {0x2A, 1 << 6,  1 << 6},                /*DACR1 to Stereo DAC Right Mixer*/
+    {0x4F, 1,       1},                     /*DACL1 to OUTMIXL*/
+    {0x52, 1,       1},                     /*DACR1 to OUTMIXR*/
+    {0x53, 1 << 13, 1 << 13},               /*OUTVOLL to LOUTMIX Unmute*/
+    {0x53, 1 << 12, 1 << 12},               /*OUTVOLR to LOUTMIX Unmute*/
+    {0x03, 1 << 15, 1 << 15},               /*LOUTL Unmute*/
+    {0x03, 1 << 14, 1 << 14},               /*OUTVOLL Unmute*/
+    {0x03, 1 << 7,  1 << 7},                /*LOUTR Unmute*/
+    {0x03, 1 << 6,  1 << 6},                /*OUTVOLR Unmute*/
+    {0x73, 3 << 2,  0 << 2},                /*Stereo DAC sample Rate 128 FS*/
+    {0x05, 1 << 15,  0 << 15},              /*disable Differential Line Output*/
+};
+
+#define tlv320aic3x_headphone_on_REG_GROUP_NUM 22
+static struct reg_value_group tlv320aic3x_headphone_on_reg_group[] = {
+    {0x3D, 1 << 10, 1 << 10},               /*DAC Clock1 Generator Enable*/
+    {0x3D, 1 << 9,  1 << 9},                /*DAC Clock2 Generator Enable*/
+    {0x61, 1 << 12, 1 << 12},               /*DACL1 Power On*/
+    {0x61, 1 << 11, 1 << 11},               /*DACR1 Power On*/
+    {0x62, 1 << 11, 1 << 11},               /*Stereo1 DAC Digital Filter Power On*/
+    {0x65, 1 << 15, 1 << 15},               /*OUTMIXL Power On*/
+    {0x65, 1 << 14, 1 << 14},               /*OUTMIXR Power On*/
+    {0x66, 1 << 11, 1 << 11},               /*HPOVOLL Power On*/
+    {0x66, 1 << 10, 1 << 10},               /*HPOVOLR Power On*/
+    {0x8E, 1 << 4,  1 << 4},                /*Enable Headphone Output*/
+    {0x8E, 1,       1},                     /*HP Amp All Power On*/
+    {0x8F, 1 << 13, 1 << 13},               /*HP Deop Mode mode 2*/
+    {0x2A, 1 << 14, 0},                     /*DACL1 to Stereo DAC left Mixer*/
+    {0x2A, 1 << 1,  0},                     /*DACL1 to Stereo DAC Right Mixer*/
+    {0x4F, 1,       0},                     /*DACL1 to OUTMIXL*/
+    {0x52, 1,       0},                     /*DACR1 to OUTMIXR*/
+    {0x45, 1 << 13, 0},                     /*HPOVOL to HPOMIX Unmute*/
+    {0x02, 1 << 15, 0},                     /*HPOL UnMute*/
+    {0x02, 1 << 14, 0},                     /*HPOVOLL Unmute*/
+    {0x02, 1 << 7,  0},                     /*HPOR UnMute*/
+    {0x02, 1 << 6,  0},                     /*HPOVOLR Unmute*/
+    {0x73, 3 << 2,  0 << 2},                /*Stereo DAC sample Rate 128 FS*/
+};
+
+#define TLV320AIC3X_HEADPHONE_OFF_REG_GROUP_NUM 22
+static struct reg_value_group TLV320AIC3X_headphone_off_reg_group[] = {
+    {0x3D, 1 << 10, 0},                     /*DAC Clock1 Generator Enable*/
+    {0x3D, 1 << 9,  0},                     /*DAC Clock2 Generator Enable*/
+    {0x61, 1 << 12, 0},                     /*DACL1 Power On*/
+    {0x61, 1 << 11, 0},                     /*DACR1 Power On*/
+    {0x62, 1 << 11, 0},                     /*Stereo1 DAC Digital Filter Power On*/
+    {0x65, 1 << 15, 0},                     /*OUTMIXL Power On*/
+    {0x65, 1 << 14, 0},                     /*OUTMIXR Power On*/
+    {0x66, 1 << 11, 0},                     /*HPOVOLL Power On*/
+    {0x66, 1 << 10, 0},                     /*HPOVOLR Power On*/
+    {0x8E, 1 << 4,  0},                     /*Enable Headphone Output*/
+    {0x8E, 1,       0},                     /*HP Amp All Power On*/
+    {0x8F, 1 << 13, 0},                     /*HP Deop Mode mode 2*/
+    {0x2A, 1 << 14, 1 << 14},               /*DACR1 to Stereo DAC left Mixer*/
+    {0x2A, 1 << 1,  1 << 1},                /*DACL1 to Stereo DAC Right Mixer*/
+    {0x4F, 1,       1},                     /*DACL1 to OUTMIXL*/
+    {0x52, 1,       1},                     /*DACR1 to OUTMIXR*/
+    {0x45, 1 << 13, 1 << 13},               /*HPOVOL to HPOMIX Unmute*/
+    {0x02, 1 << 15, 1 << 15},               /*HPOL UnMute*/
+    {0x02, 1 << 14, 1 << 14},               /*HPOVOLL Unmute*/
+    {0x02, 1 << 7,  1 << 7},                /*HPOR UnMute*/
+    {0x02, 1 << 6,  1 << 6},                /*HPOVOLR Unmute*/
+    {0x73, 3 << 2,  0 << 2},                /*Stereo DAC sample Rate 128 FS*/
+};
+
+#define tlv320aic3x_main_mic_on_REG_GROUP_NUM 11
+static struct reg_value_group tlv320aic3x_main_mic_on_reg_group[] = {
+    {0x3D, 1 << 12,  1 << 12},              /*ADC Clock Genaral Enable*/
+    {0x65, 1 << 11, 1 << 11},               /*RECMIXL Power On*/
+    {0x61, 1 << 2,  1 << 2},                /*ADCL Power On*/
+    {0x62, 1 << 15, 1 << 15},               /*Stereo ADC Digital Filter Power On*/
+    {0x64, 1 << 14, 1 << 14},               /*BST2 Power On*/
+    {0x0D, 0xF << 8, 5 << 8},               /*IN2 Boost Control +40dB*/
+    {0x0D, 1 << 6,  1 << 6},                /*IN2 Differential Mode*/
+    {0x73, 3,       2},                     /*Stereo ADC Over Sample Rate 32 Fs*/
+    {0x3C, 1 << 2,  0},                     /*BST2 to RECMIXL Unmute*/
+    {0x3E, 1 << 2,  0},                     /*BST1 to RECMIXR Unmute*/
+    {0x27, 1 << 14, 0},                     /*Stereo ADC1 Left Channel Unmute*/
+};
+static struct reg_value_group tlv320aic3x_main_mic_on_reg_group_singlemode[] = {
+    {0x3D, 1 << 12,  1 << 12},              /*ADC Clock Genaral Enable*/
+    {0x65, 1 << 11, 1 << 11},               /*RECMIXL Power On*/
+    {0x61, 1 << 2,  1 << 2},                /*ADCL Power On*/
+    {0x62, 1 << 15, 1 << 15},               /*Stereo ADC Digital Filter Power On*/
+    {0x64, 1 << 14, 1 << 14},               /*BST2 Power On*/
+    {0x0D, 0xF << 8, 5 << 8},               /*IN2 Boost Control +40dB*/
+    {0x0D, 1 << 6,  0},                		/*IN2 Single Mode*/
+    {0x73, 3,       2},                     /*Stereo ADC Over Sample Rate 32 Fs*/
+    {0x3C, 1 << 2,  0},                     /*BST2 to RECMIXL Unmute*/
+    {0x3E, 1 << 2,  0},                     /*BST1 to RECMIXR Unmute*/
+    {0x27, 1 << 14, 0},                     /*Stereo ADC1 Left Channel Unmute*/
+};
+
+
+
+#define TLV320AIC3X_MAIN_MIC_OFF_REG_GROUP_NUM 11
+static struct reg_value_group TLV320AIC3X_main_mic_off_reg_group[] = {
+    {0x3D, 1 << 12,  0},                    /*ADC Clock Genaral Enable*/
+    {0x65, 1 << 11, 0},                     /*RECMIXL Power On*/
+    {0x61, 1 << 2,  0},                     /*ADCL Power On*/
+    {0x62, 1 << 15, 0},                     /*Stereo ADC Digital Filter Power On*/
+    {0x64, 1 << 14, 0},                     /*BST2 Power On*/
+    {0x0D, 0xF << 8, 0},                    /*IN2 Boost Control +40dB*/
+    {0x0D, 1 << 6,  0},                     /*IN2 Differential Mode*/
+    {0x73, 3,       2},                     /*Stereo ADC Over Sample Rate 128 Fs*/
+    {0x3C, 1 << 2,  1 << 2},                /*BST2 to RECMIXL Unmute*/
+    {0x3E, 1 << 2,  1 << 2},                /*BST2 to RECMIXL Unmute*/
+    {0x27, 1 << 14, 1 << 14},               /*Stereo ADC1 Left Channel Unmute*/
+};
+
+#define tlv320aic3x_headset_mic_on_REG_GROUP_NUM 14
+static struct reg_value_group tlv320aic3x_headset_mic_on_reg_group[] = {
+    {0x3D, 1 << 12, 1 << 12},               /*ADC Clock Genaral Enable*/
+    {0x65, 1 << 11, 1 << 11},               /*RECMIXL Power On*/
+    {0x65, 1 << 10, 1 << 10},               /*RECMIXR Power On*/
+    {0x61, 1 << 2,  1 << 2},                /*ADCL Power On*/
+    {0x61, 1 << 1,  1 << 1},                /*ADCR Power On*/
+    {0x62, 1 << 15, 1 << 15},               /*Stereo ADC Digital Filter Power On*/
+    {0x0D, 0xF << 12, 5 << 12},             /*IN1 Boost Control +40dB*/
+    {0x64, 1 << 15, 0 << 15},               /*BST1 Power On*/
+    {0x64, 1 << 4,  1 << 4},                /*MIC2 SE Mode single-end mode*/
+    {0x73, 3,       2},                     /*Stereo ADC Over Sample Rate 128 Fs*/
+    {0x3C, 1 << 1,  0},                     /*BST1 to RECMIXL Unmute*/
+    {0x3E, 1 << 1,  0},                     /*BST1 to RECMIXR Unmute*/
+    {0x27, 1 << 14, 0},                     /*Stereo ADC1 Left Channel Unmute*/
+    {0x27, 1 << 6, 0},                      /*Stereo ADC1 Right Channel Unmute*/
+};
+
+#define TLV320AIC3X_HEADSET_MIC_OFF_REG_GROUP_NUM 14
+static struct reg_value_group TLV320AIC3X_headset_mic_off_reg_group[] = {
+    {0x3D, 1 << 12,  0},                   /*ADC Clock Genaral Enable*/
+    {0x65, 1 << 11, 0},                    /*RECMIXL Power On*/
+    {0x65, 1 << 10, 0},                    /*RECMIXR Power On*/
+    {0x61, 1 << 2,  0},                    /*ADCL Power On*/
+    {0x61, 1 << 1,  0},                    /*ADCR Power On*/
+    {0x62, 1 << 15, 0},                    /*Stereo ADC Digital Filter Power On*/
+    {0x0D, 0xF << 12, 0},                  /*IN1 Boost Control +40dB*/
+    {0x64, 1 << 15, 0},                    /*BST1 Power On*/
+    {0x64, 1 << 4,  0},                    /*MIC2 SE Mode single-end mode*/
+    {0x73, 3,       2},                    /*Stereo ADC Over Sample Rate 128 Fs*/
+    {0x3C, 1 << 1,  1 << 1},               /*BST1 to RECMIXL Unmute*/
+    {0x3E, 1 << 1,  1 << 1},               /*BST1 to RECMIXR Unmute*/
+    {0x27, 1 << 14, 1 << 14},              /*Stereo ADC1 Left Channel Unmute*/
+    {0x27, 1 << 6, 1 << 6},                /*Stereo ADC1 Right Channel Unmute*/
+};
+/////////////////////////////////////////////////////////////////////////////////
+
+#define TLV320AIC3X_HEADSET_DETECT_ON_REG_GROUP_NUM 3
+static struct reg_value_group TLV320AIC3X_headset_detect_on_reg_group[] = {
+    {0x64, 1 << 2,  1 << 2},               /*JD1 Multilevel Power on*/
+    {0xC0, 1 << 15, 1 << 15},              /*GPIO1 Pin as IRQ output*/
+    {0xBD, 7 << 7,  4 << 7},               /*jd1_1, jd1_1_stricky disable, Polarity Normal*/
+};
+
+#define TLV320AIC3X_HEADSET_DETECT_OFF_REG_GROUP_NUM 3
+static struct reg_value_group TLV320AIC3X_headset_detect_off_reg_group[] = {
+    {0x64, 1 << 2,  0 << 2},               /*JD1 Multilevel Power off*/
+    {0xC0, 1 << 15, 0 << 15},              /*GPIO1 Pin as IRQ output*/
+    {0xBD, 7 << 7,  0 << 7},               /*jd1_1, jd1_1_stricky disable, Polarity Normal*/
+};
+
+
+int tlv320aic3x_reg_dump(void)
+{
+    unsigned char index;
+    unsigned short value;
+    int status = -1;
+
+    printk(KERN_INFO"tlv320aic3x_reg_dump_enter\n");
+    for (index = 0; index < 0xFF; index++)
+    {
+       // if (tlv320aic3x_readable_register(index))
+      //  {
+            status = tlv320aic3x_read(index, &value);
+            if (status != 0)
+            {
+                printk(KERN_INFO"status: 0x%x\n", status);
+                return -1;
+            }
+            printk(KERN_INFO"index: 0x%x, value: 0x%x\n", index, value);
+       // }
+    }
+
+    return 0;
+}
+
+/*
+   I2S1 BCLK Polarity Invert
+   I2S1 PCM Mode A
+ */
+static void TLV320AIC3X_set_dai_fmt(char enable)
+{
+#if 0
+    if (TLV320AIC3X_DEVICE_ON == enable)
+    {
+        if(0 == G_AudioModemMaster){
+            /* GSSP is slave, tlv320aic3x is master */
+            tlv320aic3x_write(0x70, 0x0082);
+        } else {
+            /* GSSP is master, tlv320aic3x is slave */
+            tlv320aic3x_write(0x70, 0x8082);
+        }
+    }
+    else if (TLV320AIC3X_DEVICE_OFF == enable)
+    {
+        if(0 == G_AudioModemMaster){
+            /* GSSP is slave, tlv320aic3x is master */
+            tlv320aic3x_write(0x70, 0x0000);
+        } else {
+            /* GSSP is master, tlv320aic3x is slave */
+            tlv320aic3x_write(0x70, 0x8000);
+        }
+    }
+#else
+    if (TLV320AIC3X_DEVICE_ON == enable)
+    {
+        tlv320aic3x_update_bit(0x70, (1 << 7) | 3, (1 << 7) | 2);
+        if(0 == G_AudioModemMaster){// gssp slave, tlv320aic3x master
+            tlv320aic3x_update_bit(0x70, (1 << 15) , (0 << 15) );// set tlv320aic3x master
+        }
+    }
+    else if (TLV320AIC3X_DEVICE_OFF == enable)
+    {
+        tlv320aic3x_update_bit(0x70, (1 << 7) | 3, 0);
+    }
+#endif
+}
+
+/*FS = bitrate = 8K
+  BCLK = 512K = 64FS , 0x73
+  FOUT = (sysclk * (N + 2)) / ((M + 2) / (K + 2))
+  SYSCLK = PLL = 26M
+  FOUT = (26 * 34) / (9 * 4) = 24.555
+  CLK = FOUT / 12 = 2048K = 256 * FS
+ */
+static void tlv320aic3x_set_sysclk(char enable)
+{
+#if 1
+    if (TLV320AIC3X_DEVICE_ON == enable)
+    {
+        tlv320aic3x_write(0xFA, 0x0001);                    /*Enable MCLK Input*/
+        tlv320aic3x_write(0x73, 0x0002);                    /*DAC Over Sample Rate: 128Fs, ADC Over Sample Rate: 32Fs*/
+        if (3 == Audio_Codec_Fsync_Rate)
+        {
+            printk(KERN_INFO"%s, sys clock comes from PLL when Fsync = 48K.\n", __FUNCTION__);
+            tlv320aic3x_update_bit(0x64, 1 << 9, 1 << 9);   /*PLL Power On*/
+            tlv320aic3x_update_bit(0x73, 7 << 12, 1 << 12); /*sel_i2s_pre_div1 = 1/2*/
+        }
+    }
+    else if (TLV320AIC3X_DEVICE_OFF == enable)
+    {
+        tlv320aic3x_write(0xFA, 0x0000);                    /*Disable MCLK Input*/
+        if (3 == Audio_Codec_Fsync_Rate)
+        {
+            printk(KERN_INFO"%s, sys clock comes from PLL when Fsync = 48K.\n", __FUNCTION__);
+            tlv320aic3x_update_bit(0x64, 1 << 9, 0);        /*PLL Power Off*/
+        }
+    }
+#else
+    int bclk_type = BCLK_256_FS;
+
+    if (TLV320AIC3X_DEVICE_ON == enable)
+    {
+        tlv320aic3x_update_bit(0xFA, 1, 1);                              /*Enable MCLK Input*/
+        tlv320aic3x_update_bit(0x64, 1 << 9, 1 << 9);                    /*PLL Power On*/
+
+        tlv320aic3x_update_bit(0x73, 3 << 2, 0 << 2);    /*128Fs*/
+        tlv320aic3x_update_bit(0x73, 3, 2);              /*32Fs*/
+
+        if(1 == g_tlv320aic3x_mclk_type){/*use I2S_SYSCLK  as  MCLK ,  2.048M/4.096M*/
+            tlv320aic3x_update_bit(0x73, 7 << 12, 0 << 12);  /*I2S Clock Pre-Divider = 0 for divide 1*/
+        }
+        else if(0 == g_tlv320aic3x_mclk_type){//using bitclk as tlv320aic3x mclk
+            tlv320aic3x_update_bit(0x73, 7 << 12, 0 << 12);  /*I2S Clock Pre-Divider = 0 for divide 1*/
+            tlv320aic3x_update_bit(0x80, 3 << 14, 1 << 14);                  /*System Clock from PLL*/
+            tlv320aic3x_update_bit(0x80, 3 << 12, 1 << 12);                  /*PLL from bclk*/
+            tlv320aic3x_update_bit(0x82, 1 << 11, 1 << 11);           /*PLL M bypass */
+
+            if(BCLK_64_FS == bclk_type){ // 64fs
+                tlv320aic3x_update_bit(0x81, 0x1FF << 7 , 6 << 7);/*PLL K = 0,PLL N = 6*/
+            }
+            else if(BCLK_128_FS == bclk_type){// 128fs
+                tlv320aic3x_update_bit(0x81, 0x1FF << 7 , 2 << 7);/*PLL K = 0,PLL N = 2*/
+            }
+            else if(BCLK_256_FS == bclk_type){// 256fs
+                tlv320aic3x_update_bit(0x81, 0x1FF << 7 , 0 << 7);/*PLL K = 0,PLL N = 0*/
+            }
+            else if(BCLK_32_FS == bclk_type){// 32fs
+                tlv320aic3x_update_bit(0x81, 0x1FF << 7 , 14 << 7);/*PLL K = 0,PLL N = 14*/
+            }
+
+        }
+    }
+    else if (TLV320AIC3X_DEVICE_OFF == enable)
+    {
+        tlv320aic3x_update_bit(0xFA, 1, 0);                              /*disable MCLK Input*/
+        tlv320aic3x_update_bit(0x64, 1 << 9, 0);                         /*PLL Power off*/
+    }
+#endif
+}
+
+static void TLV320AIC3X_set_sys_power(char enable)
+{
+    if (TLV320AIC3X_DEVICE_ON == enable)
+    {
+        tlv320aic3x_update_bit(0x63, 1 << 11, 1 << 11);              /*MICBIAS Bandgap Power On*/
+        tlv320aic3x_update_bit(0x63, 1 << 15, 1 << 15);              /*VREF1 Power On*/
+        tlv320aic3x_update_bit(0x63, 1 << 14, 1 << 14);              /*VREF Slow*/
+        tlv320aic3x_update_bit(0x63, 1 << 4,  1 << 4);              /*VREF2 Power On*/
+        tlv320aic3x_update_bit(0x63, 1 << 3,  1 << 3);              /*VREF2 Slow*/
+        tlv320aic3x_update_bit(0x63, 1 << 13, 1 << 13);              /*MBIAS Power On*/
+        tlv320aic3x_update_bit(0x61, 1 << 15, 1 << 15);              /*I2S Power On*/
+        tlv320aic3x_update_bit(0x8E, 1 << 3,  1 << 3);               /*Charge Pump Power On*/
+        tlv320aic3x_update_bit(0x64, 1 << 11, 1 << 11);              /*MICBIAS1 Power On*/
+    }
+    else if (TLV320AIC3X_DEVICE_OFF == enable)
+    {
+        tlv320aic3x_update_bit(0x63, 1 << 11, 0);              /*MICBIAS Bandgap Power Off*/
+        tlv320aic3x_update_bit(0x63, 1 << 15, 0);              /*VREF1 Power Off*/
+        tlv320aic3x_update_bit(0x63, 1 << 14, 0);              /*VREF Slow*/
+        tlv320aic3x_update_bit(0x63, 1 << 4,  0);              /*VREF2 Power Off*/
+        tlv320aic3x_update_bit(0x63, 1 << 3,  0);              /*VREF2 Slow*/
+        tlv320aic3x_update_bit(0x63, 1 << 13, 0);              /*MBIAS Power Off*/
+        tlv320aic3x_update_bit(0x61, 1 << 15, 0);              /*I2S Power Off*/
+        tlv320aic3x_update_bit(0x8E, 1 << 3,  0);               /*Charge Pump Power Off*/
+        tlv320aic3x_update_bit(0x64, 1 << 11, 0);              /*MICBIAS1 Power Off*/
+    }
+}
+
+static void TLV320AIC3X_device_enable(char device, char enable)
+{
+    int length;
+    int index;
+    struct reg_value_group *reg_group = NULL;
+
+    if ((device == TLV320AIC3X_OUTPUT_DEVICE_SPEAKER) && (enable == TLV320AIC3X_DEVICE_ON))
+    {
+        reg_group = tlv320aic3x_speaker_on_reg_group;
+        length = tlv320aic3x_speaker_on_REG_GROUP_NUM;
+    }
+    else if ((device == TLV320AIC3X_OUTPUT_DEVICE_SPEAKER) && (enable == TLV320AIC3X_DEVICE_OFF))
+    {
+        reg_group = TLV320AIC3X_speaker_off_reg_group;
+        length = TLV320AIC3X_SPEAKER_OFF_REG_GROUP_NUM;
+    }
+    else if ((device == TLV320AIC3X_OUTPUT_DEVICE_HEADPHONE) && (enable == TLV320AIC3X_DEVICE_ON))
+    {
+        reg_group = tlv320aic3x_headphone_on_reg_group;
+        length = tlv320aic3x_headphone_on_REG_GROUP_NUM;
+    }
+    else if ((device == TLV320AIC3X_OUTPUT_DEVICE_HEADPHONE) && (enable == TLV320AIC3X_DEVICE_OFF))
+    {
+        reg_group = TLV320AIC3X_headphone_off_reg_group;
+        length = TLV320AIC3X_HEADPHONE_OFF_REG_GROUP_NUM;
+    }
+    else if ((device == TLV320AIC3X_INPUT_DEVICE_MAIN_MIC) && (enable == TLV320AIC3X_DEVICE_ON))
+    {
+        if(g_tlv320aic3xmainmic_type == 0)
+            reg_group = tlv320aic3x_main_mic_on_reg_group;
+        else
+            reg_group = tlv320aic3x_main_mic_on_reg_group_singlemode;
+        length = tlv320aic3x_main_mic_on_REG_GROUP_NUM;
+    }
+    else if ((device == TLV320AIC3X_INPUT_DEVICE_MAIN_MIC) && (enable == TLV320AIC3X_DEVICE_OFF))
+    {
+        reg_group = TLV320AIC3X_main_mic_off_reg_group;
+        length = TLV320AIC3X_MAIN_MIC_OFF_REG_GROUP_NUM;
+    }
+    else if ((device == TLV320AIC3X_INPUT_DEVICE_HEADSET_MIC) && (enable == TLV320AIC3X_DEVICE_ON))
+    {
+        reg_group = tlv320aic3x_headset_mic_on_reg_group;
+        length = tlv320aic3x_headset_mic_on_REG_GROUP_NUM;
+    }
+    else if ((device == TLV320AIC3X_INPUT_DEVICE_HEADSET_MIC) && (enable == TLV320AIC3X_DEVICE_OFF))
+    {
+        reg_group = TLV320AIC3X_headset_mic_off_reg_group;
+        length = TLV320AIC3X_HEADSET_MIC_OFF_REG_GROUP_NUM;
+    }
+    else if ((device == TLV320AIC3X_INPUT_DEVICE_HEADSET_DETECT) && (enable == TLV320AIC3X_DEVICE_ON))
+    {
+        reg_group = TLV320AIC3X_headset_detect_on_reg_group;
+        length = TLV320AIC3X_HEADSET_DETECT_ON_REG_GROUP_NUM;
+    }
+    else if ((device == TLV320AIC3X_INPUT_DEVICE_HEADSET_DETECT) && (enable == TLV320AIC3X_DEVICE_OFF))
+    {
+        reg_group = TLV320AIC3X_headset_detect_off_reg_group;
+        length = TLV320AIC3X_HEADSET_DETECT_OFF_REG_GROUP_NUM;
+    }
+
+    if (reg_group == NULL)
+        return;
+
+    if (enable == TLV320AIC3X_DEVICE_ON)
+    {
+        for (index = 0; index < length; index++)
+        {
+            if (reg_group[index].reg != 0x3D)
+                tlv320aic3x_update_bit(reg_group[index].reg, reg_group[index].mask, reg_group[index].value);
+            else
+                tlv320aic3x_index_update_bits(reg_group[index].reg, reg_group[index].mask, reg_group[index].value);
+        }
+        TLV320AIC3X_set_work_state(device, enable);
+        //printk(KERN_INFO"device enabled:%e{TLV320AIC3X_DEVICE}", device);
+    }
+    else if (enable == TLV320AIC3X_DEVICE_OFF)
+    {
+        for (index = 0; index < length; index++)
+        {
+            if (reg_group[index].reg != 0x3D)
+                tlv320aic3x_update_bit(reg_group[index].reg, reg_group[index].mask, reg_group[index].value);
+            else
+                tlv320aic3x_index_update_bits(reg_group[index].reg, reg_group[index].mask, reg_group[index].value);
+        }
+        TLV320AIC3X_set_work_state(device, enable);
+        //printk(KERN_INFO"device disabled:%e{TLV320AIC3X_DEVICE}", device);
+    }
+}
+
+static void TLV320AIC3X_speaker_enable(char enable)
+{
+#ifdef RECONFIGURE_POWER_INCALL
+    TLV320AIC3X_set_dai_fmt(enable);
+    tlv320aic3x_set_sysclk(enable);
+    TLV320AIC3X_set_sys_power(enable);
+#endif
+    TLV320AIC3X_device_enable(TLV320AIC3X_OUTPUT_DEVICE_SPEAKER, enable);
+    return;
+}
+
+static void TLV320AIC3X_headphone_enable(char enable)
+{
+#ifdef RECONFIGURE_POWER_INCALL
+    TLV320AIC3X_set_dai_fmt(enable);
+    tlv320aic3x_set_sysclk(enable);
+    TLV320AIC3X_set_sys_power(enable);
+#endif
+
+    TLV320AIC3X_device_enable(TLV320AIC3X_OUTPUT_DEVICE_HEADPHONE, enable);
+    return;
+}
+
+static void TLV320AIC3X_main_mic_enable(char enable)
+{
+#ifdef RECONFIGURE_POWER_INCALL
+    TLV320AIC3X_set_dai_fmt(enable);
+    tlv320aic3x_set_sysclk(enable);
+    TLV320AIC3X_set_sys_power(enable);
+#endif
+
+    TLV320AIC3X_device_enable(TLV320AIC3X_INPUT_DEVICE_MAIN_MIC, enable);
+    return;
+}
+
+static void TLV320AIC3X_headset_mic_enable(char enable)
+{
+#ifdef RECONFIGURE_POWER_INCALL
+    TLV320AIC3X_set_dai_fmt(enable);
+    tlv320aic3x_set_sysclk(enable);
+    TLV320AIC3X_set_sys_power(enable);
+#endif
+
+    TLV320AIC3X_device_enable(TLV320AIC3X_INPUT_DEVICE_HEADSET_MIC, enable);
+    return;
+}
+
+static void TLV320AIC3X_device_select(char device, char onoff)
+{
+    if (tlv320aic3x_init_ok == 0)
+    {   
+        printk(KERN_INFO"TLV320AIC3X not init\n");
+        return;
+    }
+    switch (onoff)
+    {
+        case TLV320AIC3X_DEVICE_ON:
+            if (device == TLV320AIC3X_OUTPUT_DEVICE_SPEAKER)
+            {
+                if (is_speaker_on())
+                {
+                    printk(KERN_INFO"already enabled\n");
+                    return;
+                }
+                else
+                {
+                    if (is_headphone_on())
+                    {
+                        TLV320AIC3X_headphone_enable(TLV320AIC3X_DEVICE_OFF);
+                    }
+                    TLV320AIC3X_speaker_enable(TLV320AIC3X_DEVICE_ON);
+                }
+            }
+            else if (device == TLV320AIC3X_OUTPUT_DEVICE_HEADPHONE)
+            {
+                if (is_headphone_on())
+                {
+                    printk(KERN_INFO"already enabled\n");
+                    return;
+                }
+                else
+                {
+                    if (is_speaker_on())
+                    {
+                        TLV320AIC3X_speaker_enable(TLV320AIC3X_DEVICE_OFF);
+                    }
+                    TLV320AIC3X_headphone_enable(TLV320AIC3X_DEVICE_ON);
+                }
+            }
+            else if (device == TLV320AIC3X_INPUT_DEVICE_MAIN_MIC)
+            {
+                if (is_main_mic_on())
+                {
+                    printk(KERN_INFO"already enabled\n");
+                    return;
+                }
+                else
+                {
+                    if (is_headset_mic_on())
+                    {
+                        TLV320AIC3X_headset_mic_enable(TLV320AIC3X_DEVICE_OFF);
+                    }
+                    TLV320AIC3X_main_mic_enable(TLV320AIC3X_DEVICE_ON);
+                }
+            }
+            else if (device == TLV320AIC3X_INPUT_DEVICE_HEADSET_MIC)
+            {
+                if (is_headset_mic_on())
+                {
+                    printk(KERN_INFO"already enabled\n");
+                    return;
+                }
+                else
+                {
+                    if (is_main_mic_on())
+                    {
+                        TLV320AIC3X_main_mic_enable(TLV320AIC3X_DEVICE_OFF);
+                    }
+                    TLV320AIC3X_headset_mic_enable(TLV320AIC3X_DEVICE_ON);
+                }
+            }
+            break;
+
+        case TLV320AIC3X_DEVICE_OFF:
+            if (device == TLV320AIC3X_OUTPUT_DEVICE_SPEAKER)
+            {
+                if (!is_speaker_on())
+                {
+                    printk(KERN_INFO"already disabled\n");
+                    return;
+                }
+                else
+                {
+                    TLV320AIC3X_speaker_enable(TLV320AIC3X_DEVICE_OFF);
+                }
+            }
+            else if (device == TLV320AIC3X_OUTPUT_DEVICE_HEADPHONE)
+            {
+                if (!is_headphone_on())
+                {
+                    printk(KERN_INFO"already disabled\n");
+                    return;
+                }
+                else
+                {
+                    TLV320AIC3X_headphone_enable(TLV320AIC3X_DEVICE_OFF);
+                }
+            }
+            else if (device == TLV320AIC3X_INPUT_DEVICE_MAIN_MIC)
+            {
+                if (!is_main_mic_on())
+                {
+                    printk(KERN_INFO"already disabled\n");
+                    return;
+                }
+                else
+                {
+                    TLV320AIC3X_main_mic_enable(TLV320AIC3X_DEVICE_OFF);
+                }
+            }
+            else if (device == TLV320AIC3X_INPUT_DEVICE_HEADSET_MIC)
+            {
+                if (!is_headset_mic_on())
+                {
+                    printk(KERN_INFO"already disabled\n");
+                    return;
+                }
+                else
+                {
+                    TLV320AIC3X_headset_mic_enable(TLV320AIC3X_DEVICE_OFF);
+                }
+            }
+
+            if (is_speaker_on())
+                TLV320AIC3X_speaker_enable(TLV320AIC3X_DEVICE_ON);
+            if (is_headphone_on())
+                TLV320AIC3X_headphone_enable(TLV320AIC3X_DEVICE_ON);
+            if (is_main_mic_on())
+                TLV320AIC3X_main_mic_enable(TLV320AIC3X_DEVICE_ON);
+            if (is_headset_mic_on())
+                TLV320AIC3X_headset_mic_enable(TLV320AIC3X_DEVICE_ON);
+            break;
+
+        default:
+            break;
+    }
+}
+
+
+void codec_tlv320aic3x_set_headphone_gain(void)
+{
+#if 0 
+    // -6db
+    tlv320aic3x_update_bit(0x45, (1 << 12), (1 << 12));
+
+#else
+
+    tlv320aic3x_write(0x45, 0x5000);
+#endif
+
+    return;
+}
+
+void codec_tlv320aic3x_set_headphone_mic_gain(void)
+{
+#if 0 
+    // +24db
+    tlv320aic3x_update_bit(0x1c, (0x7F << 8), (0x6F << 8));
+    tlv320aic3x_update_bit(0x1c, (0x7F << 0), (0x6F << 0));
+
+    // +24db: Boost will cause something like white noise in background, so just remove it.
+    //tlv320aic3x_update_bit(0x1E, (3 << 14), (2 << 14));
+    //tlv320aic3x_update_bit(0x1E, (3 << 12), (2 << 12));
+#else
+    tlv320aic3x_write(0x1c, 0x6f6f);
+#endif
+    return;
+}
+
+void codec_TLV320AIC3X_mute_headphone(int mute)
+{
+    if(mute){
+        tlv320aic3x_update_bit(0x02, (1 << 15), (1 << 15));
+        tlv320aic3x_update_bit(0x02, (1 << 7), (1 << 7));
+    }
+    else{
+        tlv320aic3x_update_bit(0x02, (1 << 15), (0 << 15));
+        tlv320aic3x_update_bit(0x02, (1 << 7), (0 << 7));
+    }
+    return;
+}
+
+void codec_TLV320AIC3X_mute_speaker(int mute)
+{
+    if(mute){
+        tlv320aic3x_update_bit(0x03, (1 << 15), (1 << 15));
+        tlv320aic3x_update_bit(0x03, (1 << 7), (1 << 7));
+    }
+    else{
+        tlv320aic3x_update_bit(0x03, (1 << 15), (0 << 15));
+        tlv320aic3x_update_bit(0x03, (1 << 7), (0 << 7));
+    }
+    return;
+}
+
+void codec_TLV320AIC3X_set_speaker_mic_gain(void)
+{
+    // +0db
+    tlv320aic3x_update_bit(0x1c, (0x7F << 8), (0x2F << 8));
+    tlv320aic3x_update_bit(0x1c, (0x7F << 0), (0x2F << 0));
+
+    return;
+}
+
+
+void codec_tlv320aic3x_enable_headphone_main_mic(void)
+{
+    if(!codec_tlv320aic3x_is_connect()) {return;}
+
+    printk(KERN_INFO"codec_tlv320aic3x_enable_headphone_main_mic\n");
+
+#ifdef RECONFIGURE_POWER_INCALL  
+    enable_tlv320aic3x_MClock();
+#endif	
+    TLV320AIC3X_device_select(TLV320AIC3X_OUTPUT_DEVICE_HEADPHONE, TLV320AIC3X_DEVICE_ON);
+    TLV320AIC3X_device_select(TLV320AIC3X_INPUT_DEVICE_MAIN_MIC, TLV320AIC3X_DEVICE_ON);    
+    codec_tlv320aic3x_set_headphone_gain();
+    return;
+}
+
+void codec_TLV320AIC3X_enable_headphone(void)
+{
+    if(disableTLV320AIC3XHsMic){
+        return codec_tlv320aic3x_enable_headphone_main_mic();
+    }
+
+    if(!codec_tlv320aic3x_is_connect()) {return;}
+
+    printk(KERN_INFO"codec_TLV320AIC3X_enable_headphone\n");
+#ifdef RECONFIGURE_POWER_INCALL  
+    enable_tlv320aic3x_MClock();
+#endif
+    TLV320AIC3X_device_select(TLV320AIC3X_OUTPUT_DEVICE_HEADPHONE, TLV320AIC3X_DEVICE_ON);
+    TLV320AIC3X_device_select(TLV320AIC3X_INPUT_DEVICE_HEADSET_MIC, TLV320AIC3X_DEVICE_ON);
+
+    codec_tlv320aic3x_set_headphone_gain();
+    codec_tlv320aic3x_set_headphone_mic_gain();
+    return;
+}
+
+void codec_TLV320AIC3X_enable_headphone_only(void)
+{
+    if(!codec_tlv320aic3x_is_connect()) {return;}
+
+    printk(KERN_INFO"codec_TLV320AIC3X_enable_headphone_only\n");
+#ifdef RECONFIGURE_POWER_INCALL  
+    enable_tlv320aic3x_MClock();
+#endif
+    TLV320AIC3X_device_select(TLV320AIC3X_OUTPUT_DEVICE_HEADPHONE, TLV320AIC3X_DEVICE_ON);
+    return;
+}
+
+void codec_TLV320AIC3X_enable_main_mic_only(void)
+{
+    if(!codec_tlv320aic3x_is_connect()) {return;}
+
+    printk(KERN_INFO"codec_TLV320AIC3X_enable_main_mic_only\n");
+#ifdef RECONFIGURE_POWER_INCALL  
+    enable_tlv320aic3x_MClock();
+#endif
+    TLV320AIC3X_device_select(TLV320AIC3X_INPUT_DEVICE_HEADSET_MIC, TLV320AIC3X_DEVICE_ON);
+    return;
+}
+
+void codec_TLV320AIC3X_enable_speaker(void)
+{
+    if(!codec_tlv320aic3x_is_connect()) {return;}
+
+    printk(KERN_INFO"codec_TLV320AIC3X_enable_speaker\n");
+#ifdef RECONFIGURE_POWER_INCALL    
+    enable_tlv320aic3x_MClock();
+#endif
+    TLV320AIC3X_device_select(TLV320AIC3X_OUTPUT_DEVICE_SPEAKER, TLV320AIC3X_DEVICE_ON);
+    TLV320AIC3X_device_select(TLV320AIC3X_INPUT_DEVICE_MAIN_MIC, TLV320AIC3X_DEVICE_ON);
+
+    codec_TLV320AIC3X_set_speaker_mic_gain();
+    return;
+}
+
+void codec_TLV320AIC3X_enable_speaker_only(void)
+{
+    if(!codec_tlv320aic3x_is_connect()) {return;}
+
+    printk(KERN_INFO"codec_TLV320AIC3X_enable_speaker_only\n");
+    TLV320AIC3X_device_select(TLV320AIC3X_OUTPUT_DEVICE_SPEAKER, TLV320AIC3X_DEVICE_ON);
+    return;
+}
+
+void codec_TLV320AIC3X_disable_path(void)
+{
+    if(!codec_tlv320aic3x_is_connect()) {return;}
+
+    printk(KERN_INFO"codec_TLV320AIC3X_disable_path\n");
+
+    if(is_speaker_on()){
+        TLV320AIC3X_device_select(TLV320AIC3X_OUTPUT_DEVICE_SPEAKER, TLV320AIC3X_DEVICE_OFF);
+    }
+    if(is_headphone_on()){
+        TLV320AIC3X_device_select(TLV320AIC3X_OUTPUT_DEVICE_HEADPHONE, TLV320AIC3X_DEVICE_OFF);
+    }
+    if(is_main_mic_on()){
+        TLV320AIC3X_device_select(TLV320AIC3X_INPUT_DEVICE_MAIN_MIC, TLV320AIC3X_DEVICE_OFF);
+    }
+    if(is_headset_mic_on()){
+        TLV320AIC3X_device_select(TLV320AIC3X_INPUT_DEVICE_HEADSET_MIC, TLV320AIC3X_DEVICE_OFF);
+    }
+
+#ifdef RECONFIGURE_POWER_INCALL
+    disable_tlv320aic3x_MClock();
+#endif
+    return;
+}
+
+//Kestrel/Falcon/NezhaC
+void disable_tlv320aic3x_MClock(void)
+{
+    printk(KERN_INFO"disable_tlv320aic3x_MClock, g_tlv320aic3x_mclk_type=%d\n", g_tlv320aic3x_mclk_type);
+
+#if 0 //yjg
+    if(g_tlv320aic3x_mclk_type){
+        /*GPIO-20 function 0 (default),   GPIO-20*/
+        /* *(volatile unsigned long *)(SSP1_I2S_CLOCK_REG_ADDR) = 0x7820130B; *//*8k, sysclk_en = 0*/
+        /* *(volatile unsigned long *)(MFPRX_GPIO_20) = 0xB0C0; */
+        iounmap(i2s_clk_reg); 
+        release_mem_region(SSP1_I2S_CLOCK_REG_ADDR, 4);
+    }
+#endif
+    return;
+}
+
+extern char * get_MCLK_start_addr(void);
+#ifdef CONFIG_CPU_ASR1901
+extern int enable_pmu_audio_clk(void);
+#endif
+//Kestrel/Flacon/NezhaC
+void enable_tlv320aic3x_MClock(void)
+{
+#ifdef TLV320AIC3X_DEBUG_CLOSE
+    int reg_value = 0;
+
+    printk(KERN_INFO"enable_tlv320aic3x_MClock, g_tlv320aic3x_mclk_type=%d, Audio_Codec_Fsync_Rate=%d\n", g_tlv320aic3x_mclk_type, Audio_Codec_Fsync_Rate);
+  printk("enable_tlv320aic3x_MClock, g_tlv320aic3x_mclk_type=%d, Audio_Codec_Fsync_Rate=%d\n", g_tlv320aic3x_mclk_type, Audio_Codec_Fsync_Rate);
+    if (cpu_is_asr1803()) {
+        printk(KERN_INFO"%s, platform is Falcon.\n", __FUNCTION__);
+    } else if (cpu_is_asr1806()) {
+        printk(KERN_INFO"%s, platform is Falcon-T.\n", __FUNCTION__);
+    } else if (cpu_is_asr1901() || cpu_is_asr1906()) {
+        printk(KERN_INFO"%s, platform is Kestrel.\n", __FUNCTION__);
+    } else if (cpu_is_asr1903()) {
+        printk(KERN_INFO"%s, platform is Lapwing.\n", __FUNCTION__);
+    } else {
+        printk(KERN_INFO"%s, platform is Nezhac or Nezha3.\n", __FUNCTION__);
+    }
+#endif
+
+    if (cpu_is_asr1901() || cpu_is_asr1906()) {
+        printk(KERN_INFO"%s, platform is kestrel.\n", __FUNCTION__);
+#ifdef Kestrel_Z2
+        __raw_writel(0x1043, VCXO_OUT_MFPR_reg);
+        __raw_writel(0x3, PM_MN_CLK_reg);
+
+        if(0 == Audio_Codec_Fsync_Rate){
+            /* config 2.048MHz MCLK for 8KHz Fsync of PCM */
+            __raw_writel(0x00980001, GPCR_reg);
+        } else {
+            /* config 4.096MHz MCLK for 16KHz Fsync of PCM */
+            __raw_writel(0x004c0001, GPCR_reg);
+        }
+
+        printk(KERN_INFO"%s, VCXO_OUT_MFPR_reg is 0x%0x, PM_MN_CLK_reg is 0x%0x, GPCR_reg is 0x%0x.\n",
+            __FUNCTION__, *(unsigned int *)VCXO_OUT_MFPR_reg, *(unsigned int *)PM_MN_CLK_reg, *(unsigned int *)GPCR_reg);
+
+#else
+        MCLK_CLK_CTRL_reg = get_MCLK_start_addr();
+        if (NULL ==  MCLK_CLK_CTRL_reg) {
+            printk(KERN_INFO"%s, MCLK_CLK_CTRL_reg is NULL.\n", __FUNCTION__, MCLK_CLK_CTRL_reg);
+            return;
+        }
+
+        MCLK_MN_DIV_reg = (char *)MCLK_CLK_CTRL_reg + 4;
+
+        __raw_writel(0x3, MCLK_CLK_CTRL_reg);
+
+        if(0 == Audio_Codec_Fsync_Rate){
+            /* config 2.048MHz MCLK for 8KHz Fsync of PCM */
+            printk("--->%s%d\n", __FUNCTION__, __LINE__);
+            __raw_writel(0x004b0004, MCLK_MN_DIV_reg);
+        } else if (1 == Audio_Codec_Fsync_Rate){
+            /* config 4.096MHz MCLK for 16KHz Fsync of PCM */
+            __raw_writel(0x004b0008, MCLK_MN_DIV_reg);
+        } else if (3 == Audio_Codec_Fsync_Rate) {
+            /* config 12.288MHz MCLK for 48KHz Fsync of PCM */
+            //__raw_writel(0x004b0018, MCLK_MN_DIV_reg);//1.MCLK 12.288MHz direct connection
+
+            __raw_writel(0x000a0001, MCLK_MN_DIV_reg);//MCLK 3.84MHz for PLL and for HP detection
+
+            tlv320aic3x_write(0x73, 0x1002);
+            tlv320aic3x_write(0x80, 0x4000);//2.MCLK 3.84MHz for PLL
+            //tlv320aic3x_write(0x80, 0x5000);//3.BCLK 3.84MHz for PLL
+            tlv320aic3x_write(0x81, 0x3F02);
+            tlv320aic3x_write(0x82, 0x3000);
+        } else {
+            printk(KERN_INFO"%s, please check Audio_Codec_Fsync_Rate = %d.\n",__FUNCTION__, Audio_Codec_Fsync_Rate);
+        }
+        
+        printk(KERN_INFO"%s, Audio_Codec_Fsync_Rate = %d.\n",__FUNCTION__, Audio_Codec_Fsync_Rate);
+        printk(KERN_INFO"%s, MCLK_CLK_CTRL_reg is 0x%0x, MCLK_MN_DIV_reg is 0x%0x.\n",
+            __FUNCTION__, *(unsigned int *)MCLK_CLK_CTRL_reg, *(unsigned int *)MCLK_MN_DIV_reg);
+#endif
+    } else {
+        printk(KERN_INFO"%s, platform is NezhaC, Falcon, .etc.\n", __FUNCTION__);
+        printk("--->%s%d\n", __FUNCTION__, __LINE__);
+        struct clk * mclk = devm_clk_get(&g_tlv320aic3x_client->dev, "i2s_sys_clk");
+        if(IS_ERR(mclk)){
+            printk(KERN_INFO"mclk get failed\n");
+            return;
+        }
+
+        int ret = clk_prepare_enable(mclk);
+        if(ret){
+            printk(KERN_INFO"mclk prepare enable failed");
+            return;
+        }
+
+        if(g_tlv320aic3x_mclk_type){
+printk("--->%s%d\n", __FUNCTION__, __LINE__);
+            if(0 == Audio_Codec_Fsync_Rate){
+                /*i2s_sysclk = 2M for 8k*/
+
+#ifdef TLV320AIC3X_DEBUG_CLOSE
+                reg_value = ioread32(SSP1_I2S_CLOCK_reg);
+                //reg_value = *(volatile int*)(i2s_clk_reg);
+                printk(KERN_INFO"read: reg_value=0x%x\n", reg_value);
+                //printk(KERN_INFO"read: *register_address = 0x%x, reg_value=0x%x\n",
+                //*(unsigned int *)i2s_clk_reg, reg_value);
+#endif
+                printk("--->%s%d\n", __FUNCTION__, __LINE__);
+                clk_set_rate(mclk, 2048000);
+               // clk_set_rate(mclk, 10000000);
+                int rate = clk_get_rate(mclk);
+                printk(KERN_INFO"mclk rate is %d", rate);
+                printk("--->%s%d mclk rate is  %d\n", __FUNCTION__, __LINE__, rate);
+                /* write value to register */
+                //*(volatile unsigned int *)i2s_clk_reg = 0xF820130B;
+
+#ifdef TLV320AIC3X_DEBUG_CLOSE
+                /* read value from register */
+                printk(KERN_INFO"NB, write:0xF820130B(Nezhac, Nezha3),0xE0C472D8(Falcon),*register_address = 0x%x\n", *(unsigned int *)SSP1_I2S_CLOCK_reg);
+#endif
+            }
+            else{
+                /*i2s_sysclk = 4M for 16k*/
+
+#ifdef TLV320AIC3X_DEBUG_CLOSE
+                reg_value = ioread32(SSP1_I2S_CLOCK_reg);
+                printk(KERN_INFO"read: reg_value=0x%x\n", reg_value);
+                //printk(KERN_INFO"read: *register_address = %x\n", *(unsigned int *)i2s_clk_reg);
+
+                //reg_value = *(volatile int*)(i2s_clk_reg);
+                //printk(KERN_INFO"read: *register_address = 0x%x, reg_value=0x%x\n",
+                //*(unsigned int *)i2s_clk_reg, reg_value);
+#endif
+                clk_set_rate(mclk, 4096000);
+                int rate = clk_get_rate(mclk);
+                printk(KERN_INFO"mclk rate is %d", rate);
+#ifdef TLV320AIC3X_DEBUG_CLOSE
+                /* write value to register */
+                //*(volatile unsigned int *)i2s_clk_reg = 0xF840130B;
+
+                /* read value from register */
+                printk(KERN_INFO"WB, write: 0xF840130B(Nezhac, Nezha3),0xE18872D8(Falcon), *register_address = %x\n", *(unsigned int *)SSP1_I2S_CLOCK_reg);
+#endif
+            }
+        }
+    }
+    return;
+}
+EXPORT_SYMBOL_GPL(enable_tlv320aic3x_MClock);
+
+void codec_tlv320aic3x_power_on(void)
+{
+    printk(KERN_INFO"codec_tlv320aic3x_power_on\n");
+
+    enable_tlv320aic3x_MClock();
+    TLV320AIC3X_set_dai_fmt(1);
+    tlv320aic3x_set_sysclk(1);
+    TLV320AIC3X_set_sys_power(1);
+}
+
+void codec_tlv320aic3x_power_off(void)
+{
+    printk(KERN_INFO"codec_tlv320aic3x_power_off\n");
+
+    TLV320AIC3X_set_dai_fmt(0);
+    tlv320aic3x_set_sysclk(0);
+    TLV320AIC3X_set_sys_power(0);
+    disable_tlv320aic3x_MClock();
+}
+
+void codec_tlv320aic3x_enable_headset_detect(void)
+{
+    if(!codec_tlv320aic3x_is_connect()) {return;}
+
+    printk(KERN_INFO"codec_tlv320aic3x_enable_headset_detect\n");
+
+    g_tlv320aic3xheadset_detection_enabled = 1;
+    g_tlv320aic3xheadset_plugged = 0;
+
+    TLV320AIC3X_device_enable(TLV320AIC3X_INPUT_DEVICE_HEADSET_DETECT, 1);
+
+    return;
+}
+
+void codec_tlv320aic3x_disable_headset_detect(void)
+{
+    if(!codec_tlv320aic3x_is_connect()) {return;}
+
+    printk(KERN_INFO"codec_tlv320aic3x_disable_headset_detect\n");
+
+    TLV320AIC3X_device_enable(TLV320AIC3X_INPUT_DEVICE_HEADSET_DETECT, 0);
+
+    g_tlv320aic3xheadset_detection_enabled = 0;
+    return;
+}
+
+/* HS Detection */
+static struct mfd_cell headset_devs_tlv320aic3x[] = {
+    {
+        .name = "tlv320aic3x-headset",
+        .id = -1,
+    },
+};
+
+static void tlv320aic3x_headset_detection_init(struct i2c_client *client)
+{
+    int ret = 0;
+
+    headset_devs_tlv320aic3x[0].platform_data = client;
+    headset_devs_tlv320aic3x[0].pdata_size = sizeof(struct i2c_client);
+
+    ret = mfd_add_devices(&client->dev, 0, &headset_devs_tlv320aic3x[0],
+            ARRAY_SIZE(headset_devs_tlv320aic3x), NULL,
+            0,
+            NULL);
+    if (ret) {
+        printk(KERN_INFO"Failed to add headset subdev\n");
+        return;
+    }
+
+    return;
+}
+
+
+void codec_tlv320aic3x_switch_headset(char on)
+{
+    if(on == 1)
+    {
+        //codec_TLV320AIC3X_disable_path();
+        //msleep(10);
+        //ACMSetMSAVoicePath(ATC_HEADSET);
+
+        codec_TLV320AIC3X_enable_headphone();
+    }
+    else
+    {
+        //codec_TLV320AIC3X_disable_path();
+        //msleep(10);
+
+        //ACMSetMSAVoicePath(ATC_HANDSET);
+        codec_TLV320AIC3X_enable_speaker();
+    }
+
+    return;
+}
+
+/* Headset function and report to userspace for ACM */
+
+void tlv320aic3x_get_headset_status(void)
+{
+    unsigned short value = 0;
+    int status = -1;
+
+    if(!codec_tlv320aic3x_is_connect()) {return;}
+
+    status = tlv320aic3x_read(0xBF, &value);
+    if(0 != status)
+    {
+        printk(KERN_INFO"%s: Read register [0xBF] error = 0x%x\n", __FUNCTION__, status);
+        return;
+    }
+
+    if((value & 0x3000) == 0)
+    {/* headset plug in: bit 12 & 13 is 1 */
+        g_tlv320aic3xheadset_plugged = 1;
+
+        /* Enable MICBIAS1 Short Current Detector, Threshold:1500uA */
+        tlv320aic3x_update_bit(0x93, (7 << 9), (5 << 9));
+
+        /* wait mic bias stable*/
+        mdelay(100);
+
+        value = 0;
+        status = tlv320aic3x_read(0xBE, &value);
+        if(0 != status)
+        {
+            printk(KERN_INFO"%s: Read register [0xBE] error = 0x%x\n", __FUNCTION__, status);
+            return;
+        }
+
+        /* MICBIAS1 Over Current status */
+        if((1 == g_tlv320aic3xheadset_plugged) && ((value & (1 << 3)) == 0))
+        {
+            /* Headset with mic */
+            g_tlv320aic3xheadset_mic = 1;
+            printk(KERN_INFO"Headset(with mic) plugin!\n");
+        }
+        else if((1 == g_tlv320aic3xheadset_plugged) && ((value & (1 << 3)) != 0))
+        {
+            /* Headset without mic */
+            g_tlv320aic3xheadset_mic = 0;
+            printk(KERN_INFO"Headset(without mic) plugin!\n");
+        }
+    }
+    else if((value & 0x3000) == 0x3000)
+    {/* headset plug out: bit 12 & 13 is 0 */
+        g_tlv320aic3xheadset_plugged = 0;
+        g_tlv320aic3xheadset_mic = 0;
+
+        /* Disable MICBIAS1 Short Current Detector */
+        tlv320aic3x_update_bit(0x93, (7 << 9), (0 << 9));
+
+        printk(KERN_INFO"Headset plugout!\n");
+    }
+
+    return;
+}
+
+
+int tlv320aic3x_get_headset_mic_status(void)
+{
+    return g_tlv320aic3xheadset_mic;
+}
+EXPORT_SYMBOL_GPL(tlv320aic3x_get_headset_mic_status);
+
+int tlv320aic3x_get_headset_plugged_status(void)
+{
+    return g_tlv320aic3xheadset_plugged;
+}
+EXPORT_SYMBOL_GPL(tlv320aic3x_get_headset_plugged_status);
+
+void codec_tlv320aic3x_clear_headset_status(void)
+{
+    if(!codec_tlv320aic3x_is_connect()) {return;}
+
+    printk(KERN_INFO"codec_tlv320aic3x_clear_headset_status\n");
+
+    tlv320aic3x_write(0xBF, 0);
+    return;
+}
+
+void codec_tlv320aic3x_use_bitclk(void)
+{    
+    printk(KERN_INFO"codec_tlv320aic3x_use_bitclk\n");
+    g_tlv320aic3x_mclk_type = 0;   
+    return;
+}
+
+void codec_tlv320aic3x_use_bitclk_with_mclk_on(void)
+{    
+    printk(KERN_INFO"codec_tlv320aic3x_use_bitclk_with_mclk_on\n");
+    g_tlv320aic3x_mclk_type = 2;
+    return;
+}
+
+void codec_tlv320aic3x_set_mainmic_singlemode(void)
+{
+    printk(KERN_INFO"codec_tlv320aic3x_set_mainmic_singlemode\n");
+    g_tlv320aic3xmainmic_type = 1;
+    return;
+}
+
+void tlv320aic3x_Enable_Headsetdetection(void)
+{
+    /* Init headset detection for tlv320aic3x */
+    if(codec_tlv320aic3x_is_connect() && (g_tlv320aic3xheadset_detection_enabled == 0))
+    {
+        codec_tlv320aic3x_enable_headset_detect();
+    }
+}
+EXPORT_SYMBOL_GPL(tlv320aic3x_Enable_Headsetdetection);
+
+void tlv320aic3x_Disable_Headsetdetection(void)
+{
+    /* Init headset detection for tlv320aic3x */
+    if(codec_tlv320aic3x_is_connect() && (g_tlv320aic3xheadset_detection_enabled == 1))
+    {
+        codec_tlv320aic3x_disable_headset_detect();
+    }
+}
+EXPORT_SYMBOL_GPL(tlv320aic3x_Disable_Headsetdetection);
+
+void codec_tlv320aic3x_dump(void)
+{
+    tlv320aic3x_reg_dump();
+}
+
+/* debug fs for tlv320aic3x register interface of read and write. */
+static int reg_tlv320aic3x = 0xffff;
+struct dentry *tlv320aic3x_dump_reg = NULL;
+
+static ssize_t tlv320aic3x_dump_read(struct file *file, char __user *user_buf,
+        size_t count, loff_t *ppos)
+{
+    unsigned short reg_val = 0;
+    unsigned short out_val = 0;
+    int i;
+    int len = 0;
+   unsigned char str[255] = {0};
+
+    if (reg_tlv320aic3x == 0xffff) 
+    {
+        len = snprintf(str, sizeof(str) - 1, "%s\n",
+                "tlv320aic3x: register dump:");
+        for (i = 0; i < tlv320aic3x_reg_NUM; i++) 
+        {
+
+            reg_val = tlv320aic3x_read(i, &out_val); 
+            pr_info("%s: [0x%02x]=0x%02x\n", __FUNCTION__, i, out_val);
+        }        
+
+    } 
+    else
+    {
+        reg_val = tlv320aic3x_read(reg_tlv320aic3x, &out_val);
+        len = snprintf(str, sizeof(str), "reg_tlv320aic3x=0x%02x, val=0x%04x\n",
+                    reg_tlv320aic3x, out_val);
+        printk(KERN_INFO"%s:%s\n", __FUNCTION__, str);
+   
+    }
+
+    return 0;
+}
+
+/*
+   read example: 
+   echo 0x90 > /sys/kernel/debug/tlv320aic3x_reg
+   cat /sys/kernel/debug/tlv320aic3x_reg
+   read all register:
+   echo + > /sys/kernel/debug/tlv320aic3x_reg
+   cat /sys/kernel/debug/tlv320aic3x_reg
+   write example: echo 0x90 0x10 > /sys/kernel/debug/tlv320aic3x_reg
+
+   read register example:
+   echo 0x3F > /sys/kernel/debug/tlv320aic3x_reg
+   cat /sys/kernel/debug/tlv320aic3x_reg
+
+   read all registers example:
+   echo + > /sys/kernel/debug/tlv320aic3x_reg
+   cat /sys/kernel/debug/tlv320aic3x_reg
+
+   config Gain example:
+   echo 0xFF 0x00 > /sys/kernel/debug/tlv320aic3x_reg
+   echo 0xFF 0x01 > /sys/kernel/debug/tlv320aic3x_reg
+   echo 0xFF 0x02 > /sys/kernel/debug/tlv320aic3x_reg
+   echo 0xFF 0x03 > /sys/kernel/debug/tlv320aic3x_reg
+   echo 0xFF 0x04 > /sys/kernel/debug/tlv320aic3x_reg
+   echo 0xFF 0x05 > /sys/kernel/debug/tlv320aic3x_reg
+   echo 0xFF 0x06 > /sys/kernel/debug/tlv320aic3x_reg
+   echo 0xFF 0x07 > /sys/kernel/debug/tlv320aic3x_reg
+   cat /sys/kernel/debug/tlv320aic3x_reg
+
+   write the register example:
+   echo 0x2C 0x01 > /sys/kernel/debug/tlv320aic3x_reg
+   cat /sys/kernel/debug/tlv320aic3x_reg
+ */
+static ssize_t tlv320aic3x_dump_write(struct file *file,
+        const char __user *user_buf,
+        size_t count, loff_t *ppos)
+{
+    int reg_val;
+    //struct pm80x_chip *chip = file->private_data;
+    int i = 0;
+    int ret;
+
+    char messages[20];
+    memset(messages, '\0', 20);
+
+    if (copy_from_user(messages, user_buf, count))
+        return -EFAULT;
+
+    if ('+' == messages[0]) {
+        /* enable to get all the reg value */
+        reg_tlv320aic3x = 0xffff;
+        pr_info("%s: read all reg enabled!\n", __FUNCTION__);
+    } else {
+        if (messages[1] != 'x') {
+            pr_err("Right format: 0x[addr]\n");
+            return -EINVAL;
+        }
+
+        if (strlen(messages) > 5) {
+            while (messages[i] != ' ')
+                i++;
+            messages[i] = '\0';
+            if (kstrtouint(messages, 16, &reg_tlv320aic3x) < 0)
+                return -EINVAL;
+            i++;
+            if (kstrtouint(messages + i, 16, &reg_val) < 0)
+                return -EINVAL;
+
+            {
+                /* config the registers */
+                ret = tlv320aic3x_write(reg_tlv320aic3x, reg_val & 0xffff);
+                if (ret < 0) {
+                    pr_err("write reg error!\n");
+                    return -EINVAL;
+                }
+
+                printk(KERN_INFO"%s/L%d: addr=0x%02x, val=0x%04x.\n", __FUNCTION__, __LINE__, reg_tlv320aic3x, reg_val);
+
+            }
+
+        } else {
+            /* point out the register address for read. */
+            if (kstrtouint(messages, 16, &reg_tlv320aic3x) < 0)
+                return -EINVAL;
+        }
+    }
+
+    return count;
+}
+
+static const struct file_operations tlv320aic3x_dump_ops = {
+    .open		= simple_open,
+    .read		= tlv320aic3x_dump_read,
+    .write		= tlv320aic3x_dump_write,
+};
+
+static inline int tlv320aic3x_dump_debugfs_init(struct pm80x_chip *chip)
+{
+
+    tlv320aic3x_dump_reg = debugfs_create_file("tlv320aic3x_dump_reg", S_IRUGO | S_IFREG,
+            NULL, NULL, &tlv320aic3x_dump_ops);
+
+    if (tlv320aic3x_dump_reg == NULL) {
+        pr_err("create tlv320aic3x debugfs error!\n");
+        return -ENOENT;
+    } else if (tlv320aic3x_dump_reg == ERR_PTR(-ENODEV)) {
+        pr_err("CONFIG_DEBUG_FS is not enabled!\n");
+        return -ENOENT;
+    }
+
+    return 0;
+}
+
+static void tlv320aic3x_dump_debugfs_remove(struct pm80x_chip *chip)
+{
+    if (NULL != tlv320aic3x_dump_reg){
+        debugfs_remove_recursive(tlv320aic3x_dump_reg);
+    }
+
+    return;
+}
+
+
+
+/* debug fs for tlv320aic3x audio control of Earphone, speaker or HS... */
+
+struct dentry *tlv320aic3x_audio_control = NULL;
+
+static ssize_t tlv320aic3x_audio_read(struct file *file, char __user *user_buf,
+        size_t count, loff_t *ppos)
+{
+
+#ifdef TLV320AIC3X_DEBUG
+    printk(KERN_INFO"%s/L%d.\n", __FUNCTION__, __LINE__);
+#endif
+    return 0;
+
+}
+
+/*
+1:enable earphone, enable MIC1
+2:disable earphone, enable MIC1
+
+3:enable speaker, enable MIC1
+4:disable speaker, enable MIC1
+
+5:enable Headphone, enable HSMIC
+6:disable Headphone, enable HSMIC
+control command:
+enable earphone and MIC1:    echo 1 > /sys/kernel/debug/tlv320aic3x_audio
+disable earphone and MIC1:   echo 2 > /sys/kernel/debug/tlv320aic3x_audio
+
+enable speaker and MIC1:     echo 3 > /sys/kernel/debug/tlv320aic3x_audio
+disable speaker and MIC1:    echo 4 > /sys/kernel/debug/tlv320aic3x_audio
+
+enable Headphone and HSMIC   echo 5 > /sys/kernel/debug/tlv320aic3x_audio
+disable Headphone and HSMIC  echo 6 > /sys/kernel/debug/tlv320aic3x_audio
+ */
+static char msg[10];
+
+static ssize_t tlv320aic3x_audio_write(struct file *file,
+        const char __user *user_buf,
+        size_t count, loff_t *ppos)
+{
+    int ret = 0;
+    size_t tmp_count = 0;
+
+    printk(KERN_INFO"%s/L%d.\n", __FUNCTION__, __LINE__);
+
+    memset(msg, 0x00, sizeof(msg));
+    tmp_count = count;
+
+    if (tmp_count >= sizeof(msg)){
+        tmp_count = sizeof(msg) - 1;
+    }
+
+    /* copy the content from user space to kernel space */
+    ret = copy_from_user(msg, user_buf, tmp_count);
+    if (ret){
+        printk(KERN_ALERT"copy from user fail \n");
+        return -EFAULT;
+    }
+
+    switch (msg[0]){
+        case '1':/* input command# echo 1 > /sys/kernel/debug/tlv320aic3x_audio */
+            printk(KERN_INFO "input %c. \n", msg[0]);
+            tlv320aic3x_check_HS_mic();
+            break;
+
+        case '2':/* input command# echo 2 > /sys/kernel/debug/tlv320aic3x_audio */
+            printk(KERN_INFO "input %c. \n", msg[0]);
+            enable_tlv320aic3x_MClock();
+            tlv320aic3x_speaker_off();
+            tlv320aic3x_main_mic_off();
+            break;
+
+        case '3':/* input command# echo 3 > /sys/kernel/debug/tlv320aic3x_audio */
+            printk(KERN_INFO "input %c. \n", msg[0]);
+            enable_tlv320aic3x_MClock();
+            tlv320aic3x_headphone_on();
+            tlv320aic3x_headset_mic_on();
+            break;
+
+        case '4':/* input command# echo 4 > /sys/kernel/debug/tlv320aic3x_audio */
+            printk(KERN_INFO "input %c. \n", msg[0]);
+            codec_tlv320aic3x_enable_headset_detect();
+            break;
+
+        case '5':/* input command# echo 5 > /sys/kernel/debug/tlv320aic3x_audio */
+            printk(KERN_INFO "input %c. \n", msg[0]);
+            enable_tlv320aic3x_MClock();
+            tlv320aic3x_headphone_off();
+            tlv320aic3x_headset_mic_off();
+            break;
+
+        case '6':/* input command# echo 6 > /sys/kernel/debug/tlv320aic3x_audio */
+            printk(KERN_INFO "input %c. \n", msg[0]);
+            tlv320aic3x_mute_mic(1);
+            break;
+
+        case '7':/* input command# echo 7 > /sys/kernel/debug/tlv320aic3x_audio */
+            enable_tlv320aic3x_MClock();
+            tlv320aic3x_speaker_on();
+            tlv320aic3x_main_mic_on();
+            break;
+
+        case '8':/* input command# echo 8 > /sys/kernel/debug/tlv320aic3x_audio */
+            enable_tlv320aic3x_MClock();
+            tlv320aic3x_speaker_off();
+            tlv320aic3x_main_mic_off();
+            break;
+
+        case '9':/* input command# echo 9 > /sys/kernel/debug/tlv320aic3x_audio */
+            enable_tlv320aic3x_MClock();
+            codec_tlv320aic3x_enable_headphone_main_mic();
+            break;
+
+        default:/* input command#  */
+            printk(KERN_INFO "input invalid. \n");
+            break;
+    }
+
+    return tmp_count;
+}
+
+static const struct file_operations tlv320aic3x_audio_ops = {
+    .open		= simple_open,
+    .read		= tlv320aic3x_audio_read,
+    .write		= tlv320aic3x_audio_write,
+};
+
+static inline int tlv320aic3x_audio_debugfs_init(struct pm80x_chip *chip)
+{
+
+    tlv320aic3x_audio_control = debugfs_create_file("tlv320aic3x_audio", S_IRUGO | S_IFREG,
+            NULL, NULL, &tlv320aic3x_audio_ops);
+
+    if (tlv320aic3x_audio_control == NULL) {
+        pr_err("create tlv320aic3x debugfs error!\n");
+        return -ENOENT;
+    } else if (tlv320aic3x_audio_control == ERR_PTR(-ENODEV)) {
+        pr_err("CONFIG_DEBUG_FS is not enabled!\n");
+        return -ENOENT;
+    }
+
+    return 0;
+}
+
+static void tlv320aic3x_audio_debugfs_remove(struct pm80x_chip *chip)
+{
+    if (NULL != tlv320aic3x_audio_control){
+        debugfs_remove_recursive(tlv320aic3x_audio_control);
+    }
+
+    return;
+};
+
+/* register codec to ALSA. */
+static const struct snd_kcontrol_new tlv320aic3x_snd_controls[] = {
+
+    SOC_SINGLE("Reset Register",       TLV320AIC3X_RESET_REG00, 0, 0xff, 0),             //0x00
+    
+    SOC_SINGLE("Clock Manager 1",      TLV320AIC3X_CLK_MANAGER_REG01, 0, 0xff, 0),       //0x01
+    SOC_SINGLE("Clock Manager 2",      TLV320AIC3X_CLK_MANAGER_REG02, 0, 0xff, 0),       //0x02
+    SOC_SINGLE("Clock Manager 3",      TLV320AIC3X_CLK_MANAGER_REG03, 0, 0xff, 0),       //0x03
+    SOC_SINGLE("Clock Manager 4",      TLV320AIC3X_CLK_MANAGER_REG04, 0, 0xff, 0),       //0x04
+    SOC_SINGLE("Clock Manager 5",      TLV320AIC3X_CLK_MANAGER_REG05, 0, 0xff, 0),       //0x05
+    SOC_SINGLE("Clock Manager 6",      TLV320AIC3X_CLK_MANAGER_REG06, 0, 0xff, 0),       //0x06
+    SOC_SINGLE("Clock Manager 7",      TLV320AIC3X_CLK_MANAGER_REG07, 0, 0xff, 0),       //0x07
+    SOC_SINGLE("Clock Manager 8",      TLV320AIC3X_CLK_MANAGER_REG08, 0, 0xff, 0),       //0x08
+
+    SOC_SINGLE("ADC SDP Register",     TLV320AIC3X_SDPIN_REG09, 0, 0xff, 0),             //0x09
+    SOC_SINGLE("DAC SDP Register",     TLV320AIC3X_SDPOUT_REG0A, 0, 0xff, 0),            //0x0A
+    
+    SOC_SINGLE("System Manager 1",     TLV320AIC3X_SYSTEM_REG0B, 0, 0xff, 0),            //0x0B
+    SOC_SINGLE("System Manager 2",     TLV320AIC3X_SYSTEM_REG0C, 0, 0xff, 0),            //0x0C
+    SOC_SINGLE("System Manager 3",     TLV320AIC3X_SYSTEM_REG0D, 0, 0xff, 0),            //0x0D
+    SOC_SINGLE("System Manager 4",     TLV320AIC3X_SYSTEM_REG0E, 0, 0xff, 0),            //0x0E
+    SOC_SINGLE("System Manager 5",     TLV320AIC3X_SYSTEM_REG0F, 0, 0xff, 0),            //0x0F
+    SOC_SINGLE("System Manager 6",     TLV320AIC3X_SYSTEM_REG10, 0, 0xff, 0),            //0x10
+    SOC_SINGLE("System Manager 7",     TLV320AIC3X_SYSTEM_REG11, 0, 0xff, 0),            //0x11
+    SOC_SINGLE("System Manager 8",     TLV320AIC3X_SYSTEM_REG12, 0, 0xff, 0),            //0x12
+    SOC_SINGLE("System Manager 9",     TLV320AIC3X_SYSTEM_REG13, 0, 0xff, 0),            //0x13
+    SOC_SINGLE("System Manager 10",    TLV320AIC3X_SYSTEM_REG14, 0, 0xff, 0),            //0x14
+    
+    SOC_SINGLE("ADC RAMP Register",    TLV320AIC3X_ADC_REG15, 0, 0xff, 0),               //0x15
+    SOC_SINGLE("ADC Register",         TLV320AIC3X_ADC_REG16, 0, 0xff, 0),               //0x16
+    SOC_SINGLE("ADC Volume Register",  TLV320AIC3X_ADC_REG17, 0, 0xff, 0),               //0x17
+    SOC_SINGLE("ADC ALC Register1",    TLV320AIC3X_ADC_REG18, 0, 0xff, 0),               //0x18
+    SOC_SINGLE("ADC ALC Register2",    TLV320AIC3X_ADC_REG19, 0, 0xff, 0),               //0x19
+    SOC_SINGLE("ADC Mute Register1",   TLV320AIC3X_ADC_REG1A, 0, 0xff, 0),               //0x1A
+    SOC_SINGLE("ADC Mute Register2",   TLV320AIC3X_ADC_REG1B, 0, 0xff, 0),               //0x1B
+    SOC_SINGLE("ADC EQ Register1",     TLV320AIC3X_ADC_REG1C, 0, 0xff, 0),               //0x1C
+    SOC_SINGLE("ADC EQ Register2",     TLV320AIC3X_ADC_REG1E, 0, 0xff, 0),               //0x1E
+
+    SOC_SINGLE("DAC Mute Register",    TLV320AIC3X_DAC_REG31, 0, 0xff, 0),               //0x31
+    SOC_SINGLE("DAC Volume Register",  TLV320AIC3X_DAC_REG32, 0, 0xff, 0),               //0x32
+    SOC_SINGLE("DAC Offset Register",  TLV320AIC3X_DAC_REG33, 0, 0xff, 0),               //0x33
+    SOC_SINGLE("DAC DRC Register1",    TLV320AIC3X_DAC_REG34, 0, 0xff, 0),               //0x34
+    SOC_SINGLE("DAC DRC Register2",    TLV320AIC3X_DAC_REG35, 0, 0xff, 0),               //0x35
+    SOC_SINGLE("DAC RAMP Register",    TLV320AIC3X_DAC_REG37, 0, 0xff, 0),               //0x37
+
+    SOC_SINGLE("GPIO AFSEL Register",  TLV320AIC3X_GPIO_REG44, 0, 0xff, 0),              //0x44
+    SOC_SINGLE("GPIO CTL Register",    TLV320AIC3X_GP_REG45, 0, 0xff, 0),                //0x45
+ 
+};
+
+void tlv320aic3x_register_init(void)
+{
+
+        tlv320aic3x_write( 0x00, 0x00);
+        tlv320aic3x_write( 0x01, 0x80);
+        tlv320aic3x_write( 0x07, 0x02);
+        tlv320aic3x_write( 0x65, 0x00);
+
+        tlv320aic3x_write( 0x02, 0xaa);
+        tlv320aic3x_write( 0x03, 0x91);
+        tlv320aic3x_write( 0x04, 0xc0);
+        tlv320aic3x_write( 0x05, 0x00);
+
+        tlv320aic3x_write( 0x06, 0x00);
+        tlv320aic3x_write( 0x0b, 0x01);
+        tlv320aic3x_write( 0x09, 0xc0);
+        tlv320aic3x_write( 0x10, 0x00);
+
+        tlv320aic3x_write( 0x15, 0xf8);
+        tlv320aic3x_write( 0x16, 0xb4);
+        tlv320aic3x_write( 0x25, 0xc0);
+        tlv320aic3x_write( 0x2c, 0x00);
+
+        tlv320aic3x_write( 0x5c, 0x80);
+        tlv320aic3x_write( 0x5d, 0x01);
+        tlv320aic3x_write( 0x5d, 0x09);
+        tlv320aic3x_write( 0x2c, 0x32);
+
+}
+
+static int tlv320aic3x_codec_probe(struct snd_soc_component *component)
+{
+#ifdef TLV320AIC3X_DEBUG
+    printk(KERN_INFO"%s/L%d.\n", __FUNCTION__, __LINE__);
+#endif
+
+   // tlv320aic3x_write(TLV320AIC3X_RESET_REG00, 0x1f);
+   // tlv320aic3x_write(TLV320AIC3X_RESET_REG00, 0x80);
+
+    printk("%s, wait for codec internal init\n", __func__);
+    msleep(5);
+
+    tlv320aic3x_register_init();
+    
+  //  tlv320aic3x_write(TLV320AIC3X_SYSTEM_REG0D, 0x01);    
+  //  tlv320aic3x_write(TLV320AIC3X_RESET_REG00, 0x1f);
+    enable_tlv320aic3x_MClock();
+    snd_soc_add_component_controls(component, tlv320aic3x_snd_controls, ARRAY_SIZE(tlv320aic3x_snd_controls));
+
+    return 0;
+}
+
+static unsigned int tlv320aic3x_codec_read(struct snd_soc_component *component, unsigned int reg)
+{
+    unsigned short out_val = 0;
+    int ret;
+
+    ret = tlv320aic3x_read(reg, &out_val);
+
+    if(ret)
+    {
+        printk("%s, read reg[0x%02x] fail\n", __func__, reg);
+        return -EIO;
+    }
+
+    out_val = out_val & 0xff;
+
+#ifdef TLV320AIC3X_DEBUG
+    printk(KERN_INFO"%s/L%d.[0x%02x]=[0x%04x]\n", __FUNCTION__, __LINE__, reg, out_val);
+#endif
+
+    return out_val;
+}
+
+static int tlv320aic3x_codec_write(struct snd_soc_component *component,
+        unsigned int reg, unsigned int value)
+{
+    int ret = 0;
+
+#ifdef TLV320AIC3X_DEBUG
+    printk(KERN_INFO"%s/L%d.[0x%02x]=[0x%04x]\n", __FUNCTION__, __LINE__, reg, value);
+#endif
+
+    ret = tlv320aic3x_write(reg, value & 0xFFFF);
+
+    return ret;
+}
+
+/* tlv320aic3x_dai_ops */
+
+static int tlv320aic3x_digital_mute(struct snd_soc_dai *codec_dai, int mute)
+{
+#ifdef TLV320AIC3X_DEBUG
+    printk(KERN_INFO"%s/L%d.\n", __FUNCTION__, __LINE__);
+#endif
+
+    return 0;
+}
+
+static int tlv320aic3x_hw_params(struct snd_pcm_substream *substream,
+        struct snd_pcm_hw_params *params,
+        struct snd_soc_dai *dai)
+{
+#ifdef TLV320AIC3X_DEBUG
+    printk(KERN_INFO"%s/L%d.\n", __FUNCTION__, __LINE__);
+#endif
+
+    return 0;
+}
+
+static int tlv320aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+#ifdef TLV320AIC3X_DEBUG
+    printk(KERN_INFO"%s/L%d.\n", __FUNCTION__, __LINE__);
+#endif
+
+    return 0;
+}
+
+static int tlv320aic3x_set_dai_sysclk(struct snd_soc_dai *dai,
+        int clk_id, unsigned int freq, int dir)
+{
+#ifdef TLV320AIC3X_DEBUG
+    printk(KERN_INFO"%s/L%d.\n", __FUNCTION__, __LINE__);
+#endif
+
+    return 0;
+}
+
+static const struct snd_soc_component_driver soc_component_dev_tlv320aic3x = {
+    .probe =        tlv320aic3x_codec_probe,
+    .read =         tlv320aic3x_codec_read,
+    .write =        tlv320aic3x_codec_write,
+#if 0
+    .suspend_bias_off       = 1,
+    .idle_bias_on           = 1,
+    .use_pmdown_time        = 1,
+    .endianness             = 1,
+    .non_legacy_dai_naming  = 1,
+#endif
+};
+
+static struct snd_soc_dai_ops tlv320aic3x_dai_ops = {
+    .digital_mute = tlv320aic3x_digital_mute,
+    .hw_params = tlv320aic3x_hw_params,
+    .set_fmt = tlv320aic3x_set_dai_fmt,
+    .set_sysclk = tlv320aic3x_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_driver tlv320aic3x_dai[] ={
+    {
+        /* DAI I2S(SAI1) */
+        .name   = "tlv320aic3x-i2s",
+        .id = 1,
+        .playback = {
+            .stream_name    = "I2S Playback",
+            .channels_min   = 2,
+            .channels_max   = 2,
+            .rates      = SNDRV_PCM_RATE_8000_48000,
+            .formats    = SNDRV_PCM_FORMAT_S16_LE | \
+                          SNDRV_PCM_FORMAT_S18_3LE,
+        },
+        .capture = {
+            .stream_name    = "I2S Capture",
+            .channels_min   = 2,
+            .channels_max   = 2,
+            .rates      = SNDRV_PCM_RATE_8000_48000,
+            .formats    = SNDRV_PCM_FORMAT_S16_LE | \
+                          SNDRV_PCM_FORMAT_S18_3LE,
+        },
+        .ops    = &tlv320aic3x_dai_ops,
+    }, {
+        /* DAI PCM(SAI2) */
+        .name   = "tlv320aic3x-pcm",
+            .id = 2,
+            .playback = {
+                .stream_name    = "PCM Playback",
+                .channels_min   = 1,
+                .channels_max   = 2,
+                .rates      = SNDRV_PCM_RATE_8000_48000,
+                .formats    = SNDRV_PCM_FORMAT_S8|      \
+                              SNDRV_PCM_FORMAT_S16_LE | \
+                              SNDRV_PCM_FORMAT_S20_3LE |    \
+                              SNDRV_PCM_FORMAT_S24,
+            },
+            .capture = {
+                .stream_name    = "PCM Capture",
+                .channels_min   = 1,
+                .channels_max   = 2,
+                .rates      = SNDRV_PCM_RATE_8000_48000,
+                .formats    = SNDRV_PCM_FORMAT_S8|      \
+                              SNDRV_PCM_FORMAT_S16_LE | \
+                              SNDRV_PCM_FORMAT_S20_3LE |    \
+                              SNDRV_PCM_FORMAT_S24,
+            },
+            .ops    = &tlv320aic3x_dai_ops,
+    },
+};
+
+#ifdef HEADSET_DETECTION
+irqreturn_t codec_irq_handler(int irq, void *dev_id)
+{
+    printk(KERN_INFO"%s/L%d.\n", __FUNCTION__, __LINE__);
+
+    /* check the headset plug in/out */
+    tlv320aic3x_get_headset_status();
+
+    return IRQ_HANDLED;
+}
+#endif
+
+//Kestrel
+void audio_set_codec_vdd(int on_off)
+{
+    struct regulator *vdd_1v8 = NULL;
+    struct regulator *vdd_3v3 = NULL;
+    static int codec_on_off = 0;
+
+    printk(KERN_INFO"%s: codec now:%d, to be:%d\n", __FUNCTION__, codec_on_off, on_off);
+
+    if (!(cpu_is_asr1901() || cpu_is_asr1906()) || codec_on_off == on_off)
+    {
+        return;
+    }
+
+    if(on_off) {
+        /* 1V8 */
+        vdd_1v8 = regulator_get(&g_tlv320aic3x_client->dev, "vdd18");
+        if (IS_ERR_OR_NULL(vdd_1v8)) {
+            if (PTR_ERR(vdd_1v8) < 0) {
+                printk(KERN_INFO"%s: the regulator for vdd_1v8 not found.\n", __FUNCTION__);
+            }
+        } else {
+            tlv320aic3x_regulator_vdd_1v8 = vdd_1v8;
+            printk(KERN_INFO"%s: the regulator for vdd_1v8 is OK.\n", __FUNCTION__);
+        }
+
+        if (tlv320aic3x_regulator_vdd_1v8 > 0) {
+            if (regulator_set_voltage(tlv320aic3x_regulator_vdd_1v8, 1800000, 1800000))
+                printk(KERN_INFO"fail to set regulator with 1.8v.\n");
+            if (regulator_enable(tlv320aic3x_regulator_vdd_1v8))
+                printk(KERN_INFO"fail to enable regulator vdd_1v8.\n");
+        }
+
+        /* 3V3 */
+        vdd_3v3 = regulator_get(&g_tlv320aic3x_client->dev, "vdd33");
+        if (IS_ERR_OR_NULL(vdd_3v3)) {
+            if (PTR_ERR(vdd_3v3) < 0) {
+                printk(KERN_INFO"%s: the regulator for vdd_3v3 not found.\n", __FUNCTION__);
+            }
+        } else {
+            tlv320aic3x_regulator_vdd_3v3 = vdd_3v3;
+            printk(KERN_INFO"%s: the regulator for vdd_3v3 is OK.\n", __FUNCTION__);
+        }
+
+        if (tlv320aic3x_regulator_vdd_3v3 > 0) {
+            if (regulator_set_voltage(tlv320aic3x_regulator_vdd_3v3, 3300000, 3300000))
+                printk(KERN_INFO"fail to set regulator with 3.3v.\n");
+            if (regulator_enable(tlv320aic3x_regulator_vdd_3v3))
+                printk(KERN_INFO"fail to enable regulator vdd_3v3.\n");
+        }
+
+        codec_on_off = 1;
+    }
+    else {
+        if (tlv320aic3x_regulator_vdd_1v8 > 0) {
+            if (regulator_disable(tlv320aic3x_regulator_vdd_1v8))
+                printk(KERN_INFO"fail to disable regulator vdd_1v8\n");
+        }
+
+        if (tlv320aic3x_regulator_vdd_3v3 > 0) {
+            if (regulator_disable(tlv320aic3x_regulator_vdd_3v3))
+                printk(KERN_INFO"fail to disable regulator vdd_3v3\n");
+        }
+
+        codec_on_off = 0;
+    }
+}
+EXPORT_SYMBOL_GPL(audio_set_codec_vdd);
+
+
+//Kestrel/NezhaC/Falcon
+static void tlv320aic3x_config_init(void)
+{
+    struct pinctrl_state *pin_AUDIO = NULL;
+    int gpio_1V8 = 0;
+    int gpio_3V3 = 0;
+#ifdef HEADSET_DETECTION
+    int ret = -1;
+#endif
+
+#ifdef TLV320AIC3X_DEBUG
+    printk(KERN_INFO"%s/L%d.\n", __FUNCTION__, __LINE__);
+#endif
+
+    if (cpu_is_asr1803()) {
+        printk(KERN_INFO"%s, platform is Falcon.\n", __FUNCTION__);
+    } else if (cpu_is_asr1806()) {
+        printk(KERN_INFO"%s, platform is Falcon-T.\n", __FUNCTION__);
+    } else if (cpu_is_asr1901() || cpu_is_asr1906()) {
+        printk(KERN_INFO"%s, platform is Kestrel.\n", __FUNCTION__);
+    } else if (cpu_is_asr1903()) {
+        printk(KERN_INFO"%s, platform is Lapwing.\n", __FUNCTION__);
+    }  else if (cpu_is_asr1802s()) {
+        printk(KERN_INFO"%s, platform is Nezhac.\n", __FUNCTION__);
+    } else {
+        printk(KERN_INFO"%s, please check the platform.\n", __FUNCTION__);
+    }
+
+    /* 
+       NezhaC AUDIO_PIN_CTRL = TDS_DIO10 = function 1 , GPIO-78
+       Config MPFR in arch/arm/boot/dts/asr1802s-p201.dts 
+    */
+    pin_AUDIO = pinctrl_lookup_state(g_tlv320aic3x_pinctrl, "default");
+
+    pinctrl_select_state(g_tlv320aic3x_pinctrl, pin_AUDIO);
+
+    /* config MPFR of device node "asrmicro,tlv320aic3x" */
+    if (cpu_is_asr1802s()) {
+        gpio_tds_dio10 = of_get_named_gpio(g_tlv320aic3x_node, "tds_dio10-gpio", 0);/* GPIO[78] */
+        gpio_vcxo_out = of_get_named_gpio(g_tlv320aic3x_node, "vcxo_out-gpio", 0);/* GPIO[126] */
+    }
+
+    printk(KERN_INFO"%s/L%d, gpio_tds_dio10 = %d, gpio_vcxo_out = %d\n", __FUNCTION__, __LINE__, gpio_tds_dio10, gpio_vcxo_out);
+
+    /* TDS_DIO10 */
+    //gpio_request(gpio_tds_dio10, "TDS_DIO10");
+    //gpio_direction_output(gpio_tds_dio10, 0);
+
+    /* VCXO_OUT */
+    if (cpu_is_asr1802s()) {
+        gpio_request(gpio_vcxo_out, "VCXO_OUT");
+        gpio_direction_input(gpio_vcxo_out);
+    }
+
+    /* config VDD */
+    if (cpu_is_asr1802s()) {
+        gpio_1V8 = of_get_named_gpio(g_tlv320aic3x_node, "1V8-gpio", 0);
+    }
+
+    gpio_3V3 = of_get_named_gpio(g_tlv320aic3x_node, "3V3-gpio", 0);
+
+    printk(KERN_INFO"%s/L%d, gpio_1V8=%d, gpio_3V3=%d.\n", __FUNCTION__, __LINE__, gpio_1V8, gpio_3V3);
+
+    /* GPIO_31 for CODEC_1V8_EN.
+       GPIO_32 for CODEC_3V3_EN. */
+    //gpio_31_CODEC_1V8_EN = mfp_to_gpio(MFP_PIN_GPIO31);
+    //gpio_32_CODEC_3V3_EN = mfp_to_gpio(MFP_PIN_GPIO32);
+
+    if (cpu_is_asr1802s()) {
+        gpio_31_CODEC_1V8_EN = gpio_1V8;
+    }
+
+    gpio_32_CODEC_3V3_EN = gpio_3V3;
+
+    if (cpu_is_asr1802s()) {
+        if (gpio_31_CODEC_1V8_EN) {
+            if (gpio_request(gpio_31_CODEC_1V8_EN, "power on/off 1V8")) {
+                gpio_31_CODEC_1V8_EN = 0;
+            } else {
+                gpio_direction_output(gpio_31_CODEC_1V8_EN, 0);
+            }
+        }
+    }
+
+    if (gpio_32_CODEC_3V3_EN >= 0) {
+        if (gpio_request(gpio_32_CODEC_3V3_EN, "power on/off 3V3")) {
+            gpio_32_CODEC_3V3_EN = 0;
+        } else {
+            gpio_direction_output(gpio_32_CODEC_3V3_EN, 0);
+        }
+    }
+
+    if (cpu_is_asr1802s()) {
+        gpio_direction_output(gpio_31_CODEC_1V8_EN, 1);
+    }
+
+    if (gpio_32_CODEC_3V3_EN >= 0) {
+        gpio_direction_output(gpio_32_CODEC_3V3_EN, 1);
+    }
+
+    /* Power on for ASR1901 kestrel */
+    audio_set_codec_vdd(1);
+
+#ifdef HEADSET_DETECTION
+    /* CODEC_IRQ */
+    gpio_CODEC_IRQ = of_get_named_gpio(g_tlv320aic3x_node, "irq-gpio", 0); //GPIO[1]
+    printk(KERN_INFO"%s/L%d, gpio_CODEC_IRQ=%d.\n", __FUNCTION__, __LINE__, gpio_CODEC_IRQ);
+
+    gpio_request(gpio_CODEC_IRQ, "CODEC_IRQ");
+    gpio_direction_input(gpio_CODEC_IRQ);
+
+    irq_codec = gpio_to_irq(gpio_CODEC_IRQ);
+    printk(KERN_INFO"%s/L%d, irq_codec=%d.\n", __FUNCTION__, __LINE__, irq_codec);
+
+    /* request irq */
+    ret = request_threaded_irq(irq_codec, NULL, codec_irq_handler,
+            IRQF_SHARED | IRQF_TRIGGER_RISING |
+            IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "tlv320aic3x-headset_detection",
+            g_tlv320aic3x_client);
+    if (ret < 0) {
+        printk(KERN_INFO"%s: request irq failed!\n",__FUNCTION__);
+    }
+#endif
+
+#if 0 //The vdds should be supplied
+    /* Power off for ASR1901 kestrel */
+    audio_set_codec_vdd(0);
+#endif
+
+    return;
+}
+
+static int g_fsync_rate = 0;
+static ssize_t tlv320aic3x_switch_rate_show(struct device *dev, struct device_attribute *attr,
+        char *buf)
+{
+    int s = 0;
+
+    s += sprintf(buf, "%d", g_fsync_rate);
+    return s;
+}
+
+static ssize_t tlv320aic3x_switch_rate_set(struct device *dev,
+        struct device_attribute *attr,
+        const char *buf, size_t count)
+{
+    int ret;
+
+    ret = kstrtoint(buf, 10, &g_fsync_rate);
+    if (ret)
+        return ret;
+
+    Audio_Codec_Fsync_Rate = g_fsync_rate;
+    enable_tlv320aic3x_MClock();
+    printk(KERN_INFO"%s, Audio_Codec_Fsync_Rate=%d\n", __FUNCTION__, Audio_Codec_Fsync_Rate);
+
+    return count;
+}
+static DEVICE_ATTR(tlv320aic3x_switch_rate, 0644, tlv320aic3x_switch_rate_show, tlv320aic3x_switch_rate_set);
+
+
+
+
+
+
+
+
+
+
+/* i2c driver */
+static int tlv320aic3x_probe(struct i2c_client *client,
+        const struct i2c_device_id *id)
+{
+    int ret = 0;
+
+    printk(KERN_INFO"[tlv320aic3x codec-dai probe: begin] %s/L%d.\n", __FUNCTION__, __LINE__);
+    printk("--->%s/L%d\n", __FUNCTION__, __LINE__);
+    if (NULL == client) {
+        printk(KERN_INFO"Please check codec input parameter for client.\n");
+        return 0;
+    }
+
+    g_tlv320aic3x_client = client;
+
+    g_tlv320aic3x_pinctrl = devm_pinctrl_get(&client->dev);
+    if (NULL == g_tlv320aic3x_pinctrl){
+        printk(KERN_INFO"Please check codec input parameter for g_tlv320aic3x_pinctrl.\n");
+        return 0;
+    }
+
+    g_tlv320aic3x_node = client->dev.of_node;
+    if (NULL == g_tlv320aic3x_node){
+        printk(KERN_INFO"Please check codec input parameter for g_tlv320aic3x_node.\n");
+        return 0;
+    }
+
+
+    g_reset_gpio = of_get_named_gpio(g_tlv320aic3x_node, "reset-gpio", 0);/* GPIO[120] */
+    if (unlikely(g_reset_gpio < 0)) {
+        printk("g_reset_gpio undefined\n");
+      
+    } 
+    else 
+    {  
+        printk("g_reset_gpio get success \n");
+        gpio_request(g_reset_gpio, "g_eth_0v9_pin");
+        gpio_direction_output(g_reset_gpio, 1);
+        mdelay(50);
+        gpio_direction_output(g_reset_gpio, 0);
+        mdelay(50);
+        gpio_direction_output(g_reset_gpio, 1);   
+       
+    }                                        
+   
+
+    tlv320aic3x_dump_debugfs_init(NULL);
+
+
+   // tlv320aic3x_audio_debugfs_init(NULL);
+
+    /* Power on the tlv320aic3x. */
+    //tlv320aic3x_config_init();
+
+    /* initiate the TLV320AIC3X codec. */
+ //   codec_tlv320aic3x_init();
+
+   // if (!tlv320aic3x_is_connect()) {
+   //     printk(KERN_INFO"Please check codec tlv320aic3x OK or not.\n");
+     //   return 0;
+ //   }
+
+#ifdef CONFIG_CPU_ASR1901
+    if(!enable_pmu_audio_clk())
+    {
+#endif
+    //    enable_tlv320aic3x_MClock();
+    //    tlv320aic3x_set_sysclk(1);
+#ifdef CONFIG_CPU_ASR1901
+    }
+#endif
+
+#if 0
+    /* if debug the codec in kernel, could open the procedure */
+
+    /* enable the path. */
+    codec_tlv320aic3x_power_on();
+
+    //codec_tlv320aic3x_enable_headphone_main_mic();
+    //codec_tlv320aic3x_switch_headset(1);
+
+    tlv320aic3x_headphone_on();
+    tlv320aic3x_headset_mic_on();
+
+    codec_tlv320aic3x_set_headphone_gain();
+    codec_tlv320aic3x_set_headphone_mic_gain();
+#endif
+
+#if 0
+    /* if debug the codec in kernel, could open the procedure for spk */
+
+    /* enable the path. */
+    codec_tlv320aic3x_power_on();
+
+    tlv320aic3x_speaker_on();
+    tlv320aic3x_main_mic_on();
+    /* Enable the speaker path using the command:echo 7 > /sys/kernel/debug/tlv320aic3x_audio */
+    /* Enable PA from CP or Enable PA using the command:echo 0 > /sys/kernel/debug/tlv320aic3x_audio */
+#endif
+    /*
+       create the platform device, and platform driver will register codec to ALSA.
+       which will be for device node, such as /dev/snd/timer, control0, ...
+       snd_soc_register_codec(&client->dev, &soc_codec_dev_tlv320aic3x,
+       tlv320aic3x_dai, ARRAY_SIZE(tlv320aic3x_dai));
+       int snd_soc_register_card(struct snd_soc_card *card)
+     */
+    ret = devm_snd_soc_register_component(&client->dev, &soc_component_dev_tlv320aic3x,
+            tlv320aic3x_dai, ARRAY_SIZE(tlv320aic3x_dai));
+
+    if (ret < 0) {
+        printk(KERN_INFO"Failed to register codec tlv320aic3x: %d.\n", ret);
+        return ret;
+    }
+
+    /* Headset detection platform device */
+    //tlv320aic3x_headset_detection_init(client);
+
+    /* create the interface for audio_if command "config_pcm" */
+    ret = device_create_file(&client->dev, &dev_attr_tlv320aic3x_switch_rate);
+    if (ret < 0) {
+        printk(KERN_INFO"attr tlv320aic3x_switch_rate create fail: %d.\n", ret);
+        return ret;
+
+    printk(KERN_INFO"[tlvv320aic3x codec-dai probe: end] %s/L%d.\n", __FUNCTION__, __LINE__);
+    }
+
+
+    return 0;
+}
+
+static int tlv320aic3x_remove(struct i2c_client *client)
+{
+#ifdef TLV320AIC3X_DEBUG
+    printk(KERN_INFO"%s/L%d.\n", __FUNCTION__, __LINE__);
+#endif
+
+    tlv320aic3x_dump_debugfs_remove(NULL);
+
+  //  tlv320aic3x_audio_debugfs_remove(NULL);
+
+    /* free gpio resource. */
+    //gpio_free(gpio_tds_dio10);
+    if (cpu_is_asr1802s()) {
+        gpio_free(gpio_vcxo_out);
+    }
+
+    if (cpu_is_asr1802s()) {
+        gpio_free(gpio_31_CODEC_1V8_EN);
+    }
+
+    if (gpio_32_CODEC_3V3_EN >= 0) {
+        gpio_free(gpio_32_CODEC_3V3_EN);
+    }
+
+    /* Power off for ASR1901 kestrel */
+    audio_set_codec_vdd(0);
+
+#ifdef HEADSET_DETECTION
+    gpio_free(gpio_CODEC_IRQ);
+    free_irq(irq_codec, g_tlv320aic3x_client);
+#endif
+    /* disable the path. */
+    //codec_tlv320aic3x_disable_path();
+    //codec_tlv320aic3x_disable_path_app();
+
+    codec_tlv320aic3x_power_off();
+
+    g_tlv320aic3x_client = NULL;
+
+    mfd_remove_devices(&client->dev); 
+    return 0;
+}
+
+void tlv320aic3x_shutdown(struct i2c_client *client)
+{
+#ifdef TLV320AIC3X_DEBUG
+    printk(KERN_INFO"%s/L%d.\n", __FUNCTION__, __LINE__);
+#endif
+
+    return;
+}
+
+static struct i2c_driver tlv320aic3x_driver = {
+    .driver = {
+        .name = "tlv320aic3x",
+        .of_match_table	= of_match_ptr(tlv320aic3x_dt_ids),
+    },
+    .probe = tlv320aic3x_probe,
+    .remove = tlv320aic3x_remove,
+    //.shutdown = tlv320aic3x_shutdown,
+    .id_table = tlv320aic3x_dt_table,
+};
+
+static int tlv320aic3x_i2c_init(void)
+{
+    return i2c_add_driver(&tlv320aic3x_driver);
+}
+module_init(tlv320aic3x_i2c_init);
+
+static void tlv320aic3x_i2c_exit(void)
+{
+    i2c_del_driver(&tlv320aic3x_driver);
+}
+module_exit(tlv320aic3x_i2c_exit);
+
+MODULE_DESCRIPTION("Driver for tlv320aic3x");
+MODULE_AUTHOR("wenchen@asrmicro.com");
+MODULE_LICENSE("GPL");