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, ®_tlv320aic3x) < 0)
+ return -EINVAL;
+ i++;
+ if (kstrtouint(messages + i, 16, ®_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, ®_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");