diff --git a/drivers/mfd/ac200.c b/drivers/mfd/ac200.c
index 570573790..5d759eb1e 100644
--- a/drivers/mfd/ac200.c
+++ b/drivers/mfd/ac200.c
@@ -41,6 +41,7 @@ static const struct regmap_range_cfg ac200_range_cfg[] = {
 };
 
 static const struct regmap_config ac200_regmap_config = {
+	.name = "ac200",
 	.reg_bits	= 8,
 	.val_bits	= 16,
 	.ranges		= ac200_range_cfg,
@@ -75,6 +76,10 @@ static const struct mfd_cell ac200_cells[] = {
 		.resources	= ephy_resource,
 		.of_compatible	= "x-powers,ac200-ephy",
 	},
+	{
+		.name = "acx00-codec",
+		.of_compatible	= "x-powers,ac200-codec",
+	},
 };
 
 static int ac200_i2c_probe(struct i2c_client *i2c,
diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
index 0ad261ffa..7a654de46 100644
--- a/drivers/pwm/pwm-sun4i.c
+++ b/drivers/pwm/pwm-sun4i.c
@@ -175,7 +175,7 @@ static int sun4i_pwm_calculate(struct sun4i_pwm_chip *sun4i_pwm,
 	clk_rate = clk_get_rate(sun4i_pwm->clk);
 
 	*bypass = sun4i_pwm->data->has_direct_mod_clk_output &&
-		  state->enabled &&
+//		  state->enabled &&
 		  (state->period * clk_rate >= NSEC_PER_SEC) &&
 		  (state->period * clk_rate < 2 * NSEC_PER_SEC) &&
 		  (state->duty_cycle * clk_rate * 2 >= NSEC_PER_SEC);
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 20d99b44d..09ac9c747 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1787,4 +1787,12 @@ config SND_SOC_TPA6130A2
 	tristate "Texas Instruments TPA6130A2 headphone amplifier"
 	depends on I2C
 
+config SND_SOC_ACX00
+	tristate "ACX00 Codec"
+	select MFD_ACX00
+	default n
+	help
+		ACX00 now used as SUN50IW6 internal Codec, Connect Through I2S0.
+		Say Y or M if you want to add support internal audio codec.
+
 endmenu
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index cfdeed716..e6c378f71 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -306,6 +306,7 @@ snd-soc-tpa6130a2-objs := tpa6130a2.o
 snd-soc-tas2552-objs := tas2552.o
 snd-soc-tas2562-objs := tas2562.o
 snd-soc-tas2764-objs := tas2764.o
+snd-soc-acx00-objs := acx00.o
 
 obj-$(CONFIG_SND_SOC_88PM860X)	+= snd-soc-88pm860x.o
 obj-$(CONFIG_SND_SOC_AB8500_CODEC)	+= snd-soc-ab8500-codec.o
@@ -615,3 +616,4 @@ obj-$(CONFIG_SND_SOC_MAX9877)	+= snd-soc-max9877.o
 obj-$(CONFIG_SND_SOC_MAX98504)	+= snd-soc-max98504.o
 obj-$(CONFIG_SND_SOC_SIMPLE_AMPLIFIER)	+= snd-soc-simple-amplifier.o
 obj-$(CONFIG_SND_SOC_TPA6130A2)	+= snd-soc-tpa6130a2.o
+obj-$(CONFIG_SND_SOC_ACX00)	+= snd-soc-acx00.o
\ No newline at end of file
diff --git a/sound/soc/codecs/acx00.c b/sound/soc/codecs/acx00.c
new file mode 100644
index 000000000..afa072353
--- /dev/null
+++ b/sound/soc/codecs/acx00.c
@@ -0,0 +1,1372 @@
+/*
+ * acx00.c  --  ACX00 ALSA Soc Audio Codec driver
+ *
+ * (C) Copyright 2010-2016 Allwinnertech Technology., Ltd.
+ *
+ * Author: Wolfgang Huang <huangjinhui@allwinner.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/mfd/ac200.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <linux/workqueue.h>
+
+#include "acx00.h"
+
+
+#define ACX00_DEF_VOL		0x9F9F
+#undef ACX00_DAPM_LINEOUT
+
+struct acx00_priv {
+	struct ac200_dev *acx00;	/* parent mfd device struct */
+	struct snd_soc_component *component;
+	struct clk *clk;
+	unsigned int sample_rate;
+	unsigned int fmt;
+	unsigned int enable;
+	unsigned int spk_gpio;
+	unsigned int switch_gpio;
+	bool spk_gpio_used;
+	struct mutex mutex;
+	struct delayed_work spk_work;
+	struct delayed_work resume_work;
+};
+
+struct sample_rate {
+	unsigned int samplerate;
+	unsigned int rate_bit;
+};
+
+static const struct sample_rate sample_rate_conv[] = {
+	{44100, 7},
+	{48000, 8},
+	{8000, 0},
+	{32000, 6},
+	{22050, 4},
+	{24000, 5},
+	{16000, 3},
+	{11025, 1},
+	{12000, 2},
+	{192000, 10},
+	{96000, 9},
+};
+
+void __iomem *io_stat_addr;
+
+static const DECLARE_TLV_DB_SCALE(i2s_mixer_adc_tlv, -600, 600, 1);
+static const DECLARE_TLV_DB_SCALE(i2s_mixer_dac_tlv, -600, 600, 1);
+static const DECLARE_TLV_DB_SCALE(dac_mixer_adc_tlv, -600, 600, 1);
+static const DECLARE_TLV_DB_SCALE(dac_mixer_dac_tlv, -600, 600, 1);
+static const DECLARE_TLV_DB_SCALE(line_out_tlv, -450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(mic_out_tlv, -450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(phoneout_tlv, -450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(adc_input_tlv, -450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(lineout_tlv, -4800, 150, 1);
+static const unsigned int mic_boost_tlv[] = {
+	TLV_DB_RANGE_HEAD(2),
+	0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+	1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0),
+};
+
+static const struct snd_kcontrol_new acx00_codec_controls[] = {
+	SOC_DOUBLE_TLV("I2S Mixer ADC Volume", AC_I2S_MIXER_GAIN,
+			I2S_MIXERL_GAIN_ADC, I2S_MIXERR_GAIN_ADC,
+			0x1, 0, i2s_mixer_adc_tlv),
+	SOC_DOUBLE_TLV("I2S Mixer DAC Volume", AC_I2S_MIXER_GAIN,
+			I2S_MIXERL_GAIN_DAC, I2S_MIXERR_GAIN_DAC,
+			0x1, 0, i2s_mixer_dac_tlv),
+	SOC_DOUBLE_TLV("DAC Mixer ADC Volume", AC_DAC_MIXER_GAIN,
+			DAC_MIXERL_GAIN_ADC, DAC_MIXERR_GAIN_ADC,
+			0x1, 0, dac_mixer_adc_tlv),
+	SOC_DOUBLE_TLV("DAC Mxier DAC Volume", AC_DAC_MIXER_GAIN,
+			DAC_MIXERL_GAIN_DAC, DAC_MIXERR_GAIN_DAC,
+			0x1, 0, dac_mixer_dac_tlv),
+	SOC_SINGLE_TLV("Line Out Mixer Volume", AC_OUT_MIXER_CTL,
+			OUT_MIXER_LINE_VOL, 0x7, 0, line_out_tlv),
+	SOC_DOUBLE_TLV("MIC Out Mixer Volume", AC_OUT_MIXER_CTL,
+			OUT_MIXER_MIC1_VOL, OUT_MIXER_MIC2_VOL,
+			0x7, 0, mic_out_tlv),
+	SOC_SINGLE_TLV("ADC Input Volume", AC_ADC_MIC_CTL,
+			ADC_GAIN, 0x07, 0, adc_input_tlv),
+	SOC_SINGLE_TLV("Master Volume", AC_LINEOUT_CTL,
+			LINEOUT_VOL, 0x1f, 0, lineout_tlv),
+	SOC_SINGLE_TLV("MIC1 Boost Volume", AC_ADC_MIC_CTL,
+			MIC1_BOOST, 0x07, 0, mic_boost_tlv),
+	SOC_SINGLE_TLV("MIC2 Boost Volume", AC_ADC_MIC_CTL,
+			MIC2_BOOST, 0x07, 0, mic_boost_tlv),
+};
+
+/* Enable I2S & DAC clk, then enable the DAC digital part */
+static int acx00_playback_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *k, int event)
+{
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+
+	switch (event) {
+	case	SND_SOC_DAPM_POST_PMU:
+		snd_soc_component_update_bits(component, AC_SYS_CLK_CTL,
+				(0x1<<SYS_CLK_DAC), (0x1<<SYS_CLK_DAC));
+		snd_soc_component_update_bits(component, AC_SYS_MOD_RST,
+				(0x1<<MOD_RST_DAC), (0x1<<MOD_RST_DAC));
+		snd_soc_component_update_bits(component, AC_DAC_CTL,
+				(0x1<<DAC_CTL_DAC_EN), (0x1<<DAC_CTL_DAC_EN));
+		break;
+	case	SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component, AC_SYS_CLK_CTL,
+				(0x1<<SYS_CLK_DAC), (0x0<<SYS_CLK_DAC));
+		snd_soc_component_update_bits(component, AC_SYS_MOD_RST,
+				(0x1<<MOD_RST_DAC), (0x0<<MOD_RST_DAC));
+		snd_soc_component_update_bits(component, AC_DAC_CTL,
+				(0x1<<DAC_CTL_DAC_EN), (0x0<<DAC_CTL_DAC_EN));
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+/* Enable I2S & ADC clk, then enable the ADC digital part */
+static int acx00_capture_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *k, int event)
+{
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+
+	switch (event) {
+	case	SND_SOC_DAPM_POST_PMU:
+		snd_soc_component_update_bits(component, AC_SYS_CLK_CTL,
+				(0x1<<SYS_CLK_ADC), (0x1<<SYS_CLK_ADC));
+		snd_soc_component_update_bits(component, AC_SYS_MOD_RST,
+				(0x1<<MOD_RST_ADC), (0x1<<MOD_RST_ADC));
+		snd_soc_component_update_bits(component, AC_ADC_CTL,
+				(0x1<<ADC_EN), (0x1<<ADC_EN));
+		break;
+	case	SND_SOC_DAPM_POST_PMD:
+		snd_soc_component_update_bits(component, AC_SYS_CLK_CTL,
+				(0x1<<SYS_CLK_ADC), (0x0<<SYS_CLK_ADC));
+		snd_soc_component_update_bits(component, AC_SYS_MOD_RST,
+				(0x1<<MOD_RST_ADC), (0x0<<MOD_RST_ADC));
+		snd_soc_component_update_bits(component, AC_ADC_CTL,
+				(0x1<<ADC_EN), (0x0<<ADC_EN));
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+/*
+ * we used for three scene:
+ * 1. No external Spker & DAPM LINEOUT used, we just enable the LINEOUT in the
+ * ALSA codec probe(acx00_codec_probe) and resume, and we shutdown the LINEOUT
+ * in device shutdown or suspend.
+ * 2. No external Spker, but DAPM LINEOUT used, we just using the LINEOUT
+ * enable or disable throught the DAPM control.
+ * 3. External Spker & DAPM LINEOUT used, we just using the LINEOUT and
+ * External Spker control GPIO enable or disable through DAPM control.
+ */
+static unsigned int spk_delay = 100;
+module_param(spk_delay, int, 0644);
+MODULE_PARM_DESC(spk_delay, "ACX00-Codec spk mute delay time");
+
+static void acx00_spk_enable(struct work_struct *work)
+{
+	struct acx00_priv *priv = container_of(work,
+			struct acx00_priv, spk_work.work);
+	gpio_set_value(priv->spk_gpio, 1);
+}
+
+static int acx00_lineout_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *k, int event)
+{
+	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+	struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
+
+	switch (event) {
+	case	SND_SOC_DAPM_POST_PMU:
+		if (!priv->enable) {
+			snd_soc_component_update_bits(priv->component, AC_LINEOUT_CTL,
+					(1<<LINEL_SRC_EN), (1<<LINEL_SRC_EN));
+			snd_soc_component_update_bits(priv->component, AC_LINEOUT_CTL,
+					(1<<LINER_SRC_EN), (1<<LINER_SRC_EN));
+			msleep(100);
+			priv->enable = 1;
+		}
+#ifdef ACX00_DAPM_LINEOUT
+		snd_soc_component_update_bits(component, AC_LINEOUT_CTL,
+				(1<<LINEOUT_EN), (1<<LINEOUT_EN));
+		mdelay(50);
+#endif
+		if (priv->spk_gpio_used) {
+			if (spk_delay == 0) {
+				gpio_set_value(priv->spk_gpio, 1);
+				/*
+				* time delay to wait spk pa work fine,
+				* general setting 50ms
+				*/
+				mdelay(50);
+			} else
+				schedule_delayed_work(&priv->spk_work,
+					msecs_to_jiffies(spk_delay));
+		}
+		break;
+	case	SND_SOC_DAPM_PRE_PMD:
+		mdelay(50);
+		if (priv->spk_gpio_used) {
+			gpio_set_value(priv->spk_gpio, 0);
+			msleep(50);
+		}
+#ifdef ACX00_DAPM_LINEOUT
+		snd_soc_component_update_bits(component, AC_LINEOUT_CTL,
+				(1<<LINEOUT_EN), (0<<LINEOUT_EN));
+#endif
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+/* AC_I2S_MIXER_SRC : 0x2114 */
+static const struct snd_kcontrol_new i2sl_mixer_src[] = {
+	SOC_DAPM_SINGLE("I2SDACL Switch", AC_I2S_MIXER_SRC,
+			I2S_MIXERL_SRC_DAC, 1, 0),
+	SOC_DAPM_SINGLE("ADCL Switch", AC_I2S_MIXER_SRC,
+			I2S_MIXERL_SRC_ADC, 1, 0),
+};
+
+static const struct snd_kcontrol_new i2sr_mixer_src[] = {
+	SOC_DAPM_SINGLE("I2SDACR Switch", AC_I2S_MIXER_SRC,
+			I2S_MIXERR_SRC_DAC, 1, 0),
+	SOC_DAPM_SINGLE("ADCR Switch", AC_I2S_MIXER_SRC,
+			I2S_MIXERR_SRC_ADC, 1, 0),
+};
+
+/* AC_DAC_MIXER_SRC : 0x2202 */
+static const struct snd_kcontrol_new dacl_mixer_src[] = {
+	SOC_DAPM_SINGLE("I2SDACL Switch", AC_DAC_MIXER_SRC,
+			DAC_MIXERL_SRC_DAC, 1, 0),
+	SOC_DAPM_SINGLE("ADCL Switch", AC_DAC_MIXER_SRC,
+			DAC_MIXERL_SRC_ADC, 1, 0),
+};
+
+static const struct snd_kcontrol_new dacr_mixer_src[] = {
+	SOC_DAPM_SINGLE("I2SDACR Switch", AC_DAC_MIXER_SRC,
+			DAC_MIXERR_SRC_DAC, 1, 0),
+	SOC_DAPM_SINGLE("ADCR Switch", AC_DAC_MIXER_SRC,
+			DAC_MIXERR_SRC_ADC, 1, 0),
+};
+
+/* AC_OUT_MIXER_SRC : 0x2222 */
+static const struct snd_kcontrol_new left_output_mixer[] = {
+	SOC_DAPM_SINGLE("MIC1 Switch", AC_OUT_MIXER_SRC,
+			OUT_MIXERL_SRC_MIC1, 1, 0),
+	SOC_DAPM_SINGLE("MIC2 Switch", AC_OUT_MIXER_SRC,
+			OUT_MIXERL_SRC_MIC2, 1, 0),
+	SOC_DAPM_SINGLE("PhonePN Switch", AC_OUT_MIXER_SRC,
+			OUT_MIXERL_SRC_PHPN, 1, 0),
+	SOC_DAPM_SINGLE("PhoneN Switch", AC_OUT_MIXER_SRC,
+			OUT_MIXERL_SRC_PHN, 1, 0),
+	SOC_DAPM_SINGLE("LINEINL Switch", AC_OUT_MIXER_SRC,
+			OUT_MIXERL_SRC_LINEL, 1, 0),
+	SOC_DAPM_SINGLE("DACL Switch", AC_OUT_MIXER_SRC,
+			OUT_MIXERL_SRC_DACL, 1, 0),
+	SOC_DAPM_SINGLE("DACR Switch", AC_OUT_MIXER_SRC,
+			OUT_MIXERL_SRC_DACR, 1, 0),
+};
+
+static const struct snd_kcontrol_new right_output_mixer[] = {
+	SOC_DAPM_SINGLE("MIC1 Switch", AC_OUT_MIXER_SRC,
+			OUT_MIXERR_SRC_MIC1, 1, 0),
+	SOC_DAPM_SINGLE("MIC2 Switch", AC_OUT_MIXER_SRC,
+			OUT_MIXERR_SRC_MIC2, 1, 0),
+	SOC_DAPM_SINGLE("PhonePN Switch", AC_OUT_MIXER_SRC,
+			OUT_MIXERR_SRC_PHPN, 1, 0),
+	SOC_DAPM_SINGLE("PhoneP Switch", AC_OUT_MIXER_SRC,
+			OUT_MIXERR_SRC_PHP, 1, 0),
+	SOC_DAPM_SINGLE("LINEINR Switch", AC_OUT_MIXER_SRC,
+			OUT_MIXERR_SRC_LINER, 1, 0),
+	SOC_DAPM_SINGLE("DACR Switch", AC_OUT_MIXER_SRC,
+			OUT_MIXERR_SRC_DACR, 1, 0),
+	SOC_DAPM_SINGLE("DACL Switch", AC_OUT_MIXER_SRC,
+			OUT_MIXERR_SRC_DACL, 1, 0),
+};
+
+/* AC_LINEOUT_CTL : 0x2224 */
+const char * const left_lineout_text[] = {
+	"Left OMixer", "LR OMixer",
+};
+
+static const struct soc_enum left_lineout_enum =
+	SOC_ENUM_SINGLE(AC_LINEOUT_CTL, LINEL_SRC,
+		ARRAY_SIZE(left_lineout_text), left_lineout_text);
+
+static const struct snd_kcontrol_new left_lineout_mux =
+	SOC_DAPM_ENUM("Left LINEOUT Mux", left_lineout_enum);
+
+const char * const right_lineout_text[] = {
+	"Right OMixer", "LR OMixer",
+};
+
+static const struct soc_enum right_lineout_enum =
+	SOC_ENUM_SINGLE(AC_LINEOUT_CTL, LINER_SRC,
+		ARRAY_SIZE(right_lineout_text), right_lineout_text);
+
+static const struct snd_kcontrol_new right_lineout_mux =
+	SOC_DAPM_ENUM("Right LINEOUT Mux", right_lineout_enum);
+
+/* AC_ADC_MIXER_SRC : 0x2322 */
+static const struct snd_kcontrol_new left_input_mixer[] = {
+	SOC_DAPM_SINGLE("MIC1 Switch", AC_ADC_MIXER_SRC,
+			ADC_MIXERL_MIC1, 1, 0),
+	SOC_DAPM_SINGLE("MIC2 Switch", AC_ADC_MIXER_SRC,
+			ADC_MIXERL_MIC2, 1, 0),
+	SOC_DAPM_SINGLE("PhonePN Switch", AC_ADC_MIXER_SRC,
+			ADC_MIXERL_PHPN, 1, 0),
+	SOC_DAPM_SINGLE("PhoneN Switch", AC_ADC_MIXER_SRC,
+			ADC_MIXERL_PHN, 1, 0),
+	SOC_DAPM_SINGLE("LINEINL Switch", AC_ADC_MIXER_SRC,
+			ADC_MIXERL_LINEL, 1, 0),
+	SOC_DAPM_SINGLE("OMixerL Switch", AC_ADC_MIXER_SRC,
+			ADC_MIXERL_MIXL, 1, 0),
+	SOC_DAPM_SINGLE("OMixerR Switch", AC_ADC_MIXER_SRC,
+			ADC_MIXERL_MIXR, 1, 0),
+};
+
+static const struct snd_kcontrol_new right_input_mixer[] = {
+	SOC_DAPM_SINGLE("MIC1 Switch", AC_ADC_MIXER_SRC,
+			ADC_MIXERR_MIC1, 1, 0),
+	SOC_DAPM_SINGLE("MIC2 Switch", AC_ADC_MIXER_SRC,
+			ADC_MIXERR_MIC2, 1, 0),
+	SOC_DAPM_SINGLE("PhonePN Switch", AC_ADC_MIXER_SRC,
+			ADC_MIXERR_PHPN, 1, 0),
+	SOC_DAPM_SINGLE("PhoneP Switch", AC_ADC_MIXER_SRC,
+			ADC_MIXERR_PHP, 1, 0),
+	SOC_DAPM_SINGLE("LINEINR Switch", AC_ADC_MIXER_SRC,
+			ADC_MIXERR_LINER, 1, 0),
+	SOC_DAPM_SINGLE("OMixerR Switch", AC_ADC_MIXER_SRC,
+			ADC_MIXERR_MIXR, 1, 0),
+	SOC_DAPM_SINGLE("OMixerL Switch", AC_ADC_MIXER_SRC,
+			ADC_MIXERR_MIXL, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget acx00_codec_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_IN_E("DACL", "Playback", 0, AC_DAC_CTL,
+			OUT_MIXER_DACL_EN, 0,
+			acx00_playback_event,
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_AIF_IN_E("DACR", "Playback", 0,
+			AC_DAC_CTL, OUT_MIXER_DACR_EN, 0,
+			acx00_playback_event,
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("ADCL", "Capture", 0,
+			AC_ADC_MIC_CTL, ADCL_EN, 0,
+			acx00_capture_event,
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_AIF_OUT_E("ADCR", "Capture", 0,
+			AC_ADC_MIC_CTL, ADCR_EN, 0,
+			acx00_capture_event,
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER("Left Output Mixer", AC_OUT_MIXER_CTL,
+			OUT_MIXER_LMIX_EN, 0,
+			left_output_mixer, ARRAY_SIZE(left_output_mixer)),
+
+	SND_SOC_DAPM_MIXER("Right Output Mixer", AC_OUT_MIXER_CTL,
+			OUT_MIXER_RMIX_EN, 0, right_output_mixer,
+			ARRAY_SIZE(right_output_mixer)),
+
+	SND_SOC_DAPM_MIXER("Left Input Mixer", SND_SOC_NOPM, 0, 0,
+			left_input_mixer, ARRAY_SIZE(left_input_mixer)),
+	SND_SOC_DAPM_MIXER("Right Input Mixer", SND_SOC_NOPM, 0, 0,
+			right_input_mixer, ARRAY_SIZE(right_input_mixer)),
+
+	SND_SOC_DAPM_MIXER("Left DAC Mixer", AC_OUT_MIXER_CTL,
+			OUT_MIXER_DACL_EN, 0, dacl_mixer_src,
+			ARRAY_SIZE(dacl_mixer_src)),
+	SND_SOC_DAPM_MIXER("Right DAC Mixer", AC_OUT_MIXER_CTL,
+			OUT_MIXER_DACR_EN, 0, dacr_mixer_src,
+			ARRAY_SIZE(dacr_mixer_src)),
+
+	SND_SOC_DAPM_MIXER("Left I2S Mixer", SND_SOC_NOPM,
+			0, 0, i2sl_mixer_src, ARRAY_SIZE(i2sl_mixer_src)),
+	SND_SOC_DAPM_MIXER("Right I2S Mixer", SND_SOC_NOPM,
+			0, 0, i2sr_mixer_src, ARRAY_SIZE(i2sr_mixer_src)),
+
+	SND_SOC_DAPM_MUX("Left LINEOUT Mux", SND_SOC_NOPM,
+			0, 0, &left_lineout_mux),
+	SND_SOC_DAPM_MUX("Right LINEOUT Mux", SND_SOC_NOPM,
+			0, 0, &right_lineout_mux),
+
+	SND_SOC_DAPM_PGA("MIC1 PGA", AC_ADC_MIC_CTL,
+			MIC1_GAIN_EN, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("MIC2 PGA", AC_ADC_MIC_CTL,
+			MIC2_GAIN_EN, 0, NULL, 0),
+
+	SND_SOC_DAPM_MICBIAS("MIC Bias", AC_MICBIAS_CTL,
+			MMBIAS_EN, 0),
+
+	/* PHONEIN & PHONEOUT not enable in pin assign */
+	SND_SOC_DAPM_INPUT("PHONEINP"),
+	SND_SOC_DAPM_INPUT("PHONEINN"),
+	SND_SOC_DAPM_INPUT("PHONEINPN"),
+
+	/* endpoint define */
+	SND_SOC_DAPM_LINE("LINEIN", NULL),
+	SND_SOC_DAPM_LINE("LINEOUT", acx00_lineout_event),
+	SND_SOC_DAPM_MIC("MIC1", NULL),
+	SND_SOC_DAPM_MIC("MIC2", NULL),
+};
+
+static const struct snd_soc_dapm_route acx00_codec_dapm_routes[] = {
+	{"Left Output Mixer", "MIC1 Switch", "MIC1 PGA"},
+	{"Left Output Mixer", "MIC2 Switch", "MIC2 PGA"},
+	{"Left Output Mixer", "PhonePN Switch", "PHONEINPN"},
+	{"Left Output Mixer", "PhoneN Switch", "PHONEINN"},
+	{"Left Output Mixer", "LINEINL Switch", "LINEIN"},
+	{"Left Output Mixer", "DACR Switch", "Right DAC Mixer"},
+	{"Left Output Mixer", "DACL Switch", "Left DAC Mixer"},
+
+	{"Right Output Mixer", "MIC1 Switch", "MIC1 PGA"},
+	{"Right Output Mixer", "MIC2 Switch", "MIC2 PGA"},
+	{"Right Output Mixer", "PhonePN Switch", "PHONEINPN"},
+	{"Right Output Mixer", "PhoneP Switch", "PHONEINP"},
+	{"Right Output Mixer", "LINEINR Switch", "LINEIN"},
+	{"Right Output Mixer", "DACR Switch", "Right DAC Mixer"},
+	{"Right Output Mixer", "DACL Switch", "Left DAC Mixer"},
+
+	{"Left LINEOUT Mux", NULL, "Left Output Mixer"},
+	{"Left LINEOUT Mux", "LR OMixer", "Right Output Mixer"},
+	{"Right LINEOUT Mux", NULL, "Right Output Mixer"},
+	{"Right LINEOUT Mux", "LR OMixer", "Left Output Mixer"},
+
+	{"Left Input Mixer", "MIC1 Switch", "MIC1 PGA"},
+	{"Left Input Mixer", "MIC2 Switch", "MIC2 PGA"},
+	{"Left Input Mixer", "PhonePN Switch", "PHONEINPN"},
+	{"Left Input Mixer", "PhoneN Switch", "PHONEINN"},
+	{"Left Input Mixer", "LINEINL Switch", "LINEIN"},
+	{"Left Input Mixer", "OMixerL Switch", "Left Output Mixer"},
+	{"Left Input Mixer", "OMixerR Switch", "Right Output Mixer"},
+
+	{"Right Input Mixer", "MIC1 Switch", "MIC1 PGA"},
+	{"Right Input Mixer", "MIC2 Switch", "MIC2 PGA"},
+	{"Right Input Mixer", "PhonePN Switch", "PHONEINPN"},
+	{"Right Input Mixer", "PhoneP Switch", "PHONEINP"},
+	{"Right Input Mixer", "LINEINR Switch", "LINEIN"},
+	{"Right Input Mixer", "OMixerR Switch", "Right Output Mixer"},
+	{"Right Input Mixer", "OMixerL Switch", "Left Output Mixer"},
+
+	{"Left I2S Mixer", "I2SDACL Switch", "DACL"},
+	{"Left I2S Mixer", "ADCL Switch", "Left Input Mixer"},
+
+	{"Right I2S Mixer", "I2SDACR Switch", "DACR"},
+	{"Right I2S Mixer", "ADCR Switch", "Right Input Mixer"},
+
+	{"Left DAC Mixer", "I2SDACL Switch", "DACL"},
+	{"Left DAC Mixer", "ADCL Switch", "Left Input Mixer"},
+
+	{"Right DAC Mixer", "I2SDACR Switch", "DACR"},
+	{"Right DAC Mixer", "ADCR Switch", "Right Input Mixer"},
+
+	{"ADCL", NULL, "Left I2S Mixer"},
+	{"ADCR", NULL, "Right I2S Mixer"},
+
+	{"LINEOUT", NULL, "Left LINEOUT Mux"},
+	{"LINEOUT", NULL, "Right LINEOUT Mux"},
+
+	{"MIC Bias", NULL, "MIC1"},
+	{"MIC Bias", NULL, "MIC2"},
+	{"MIC1 PGA", NULL, "MIC Bias"},
+	{"MIC2 PGA", NULL, "MIC Bias"},
+};
+
+static void acx00_codec_txctrl_enable(struct snd_soc_component *component,
+					int enable)
+{
+	pr_debug("Enter %s, enable %d\n", __func__, enable);
+	if (enable) {
+		snd_soc_component_update_bits(component, AC_I2S_CTL,
+					(1<<I2S_RX_EN), (1<<I2S_RX_EN));
+	} else {
+		snd_soc_component_update_bits(component, AC_I2S_CTL,
+					(1<<I2S_RX_EN), (0<<I2S_RX_EN));
+	}
+	pr_debug("End %s, enable %d\n", __func__, enable);
+}
+
+static void acx00_codec_rxctrl_enable(struct snd_soc_component *component,
+					int enable)
+{
+	pr_debug("Enter %s, enable %d\n", __func__, enable);
+	if (enable) {
+		snd_soc_component_update_bits(component, AC_I2S_CTL,
+					(1<<I2S_TX_EN), (1<<I2S_TX_EN));
+	} else {
+		snd_soc_component_update_bits(component, AC_I2S_CTL,
+					(1<<I2S_TX_EN), (0<<I2S_TX_EN));
+	}
+	pr_debug("End %s, enable %d\n", __func__, enable);
+}
+
+int acx00_reg_read(struct ac200_dev *acx00, unsigned short reg)
+{
+        unsigned int val;
+        int ret;
+
+        ret = regmap_read(acx00->regmap, reg, &val);
+
+        if (ret < 0)
+                return ret;
+        else
+                return val;
+}
+
+int acx00_reg_write(struct ac200_dev *acx00, unsigned short reg, unsigned short val)
+{
+	return regmap_write(acx00->regmap, reg, val);
+}
+
+static void acx00_codec_init(struct snd_soc_component *component)
+{
+	struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
+
+	acx00_reg_write(priv->acx00, 0x50, 0x82b1);
+	acx00_reg_write(priv->acx00, 0xc, 0xce01);
+
+	/* acx00_codec sysctl init */
+	acx00_reg_write(priv->acx00, 0x0010, 0x03);
+	acx00_reg_write(priv->acx00, 0x0012, 0x01);
+
+	/* The bit3 need to setup to 1 for bias current. */
+	snd_soc_component_update_bits(component, AC_MICBIAS_CTL,
+			(0x1 << ADDA_BIAS_CUR), (0x1 << ADDA_BIAS_CUR));
+
+	/* enable the output & global enable bit */
+	snd_soc_component_update_bits(component, AC_I2S_CTL,
+			(1<<I2S_SDO0_EN), (1<<I2S_SDO0_EN));
+	snd_soc_component_update_bits(component, AC_I2S_CTL, (1<<I2S_GEN), (1<<I2S_GEN));
+
+	/* Default setting slot width as 32 bit for I2S */
+	snd_soc_component_update_bits(component, AC_I2S_FMT0,
+			(7<<I2S_FMT_SLOT_WIDTH), (7<<I2S_FMT_SLOT_WIDTH));
+
+	/* default setting 0xA0A0 for ADC & DAC Volume */
+	snd_soc_component_write(component, AC_I2S_DAC_VOL, ACX00_DEF_VOL);
+	snd_soc_component_write(component, AC_I2S_ADC_VOL, ACX00_DEF_VOL);
+
+	/* Enable HPF for high pass filter */
+	snd_soc_component_update_bits(component, AC_DAC_CTL,
+			(1<<DAC_CTL_HPF_EN), (1<<DAC_CTL_HPF_EN));
+
+	/* LINEOUT ANTI POP & Click noise */
+	snd_soc_component_update_bits(component, AC_LINEOUT_CTL,
+			(0x7<<LINE_ANTI_TIME), (0x3<<LINE_ANTI_TIME));
+	snd_soc_component_update_bits(component, AC_LINEOUT_CTL,
+			(0x3<<LINE_SLOPE_SEL), (0x3<<LINE_SLOPE_SEL));
+
+	/* enable & setting adc convert delay time */
+	snd_soc_component_update_bits(component, AC_ADC_CTL, (0x3<<ADC_DELAY_TIME),
+			(0x3<<ADC_DELAY_TIME));
+	snd_soc_component_update_bits(component, AC_ADC_CTL, (1<<ADC_DELAY_EN),
+			(1<<ADC_DELAY_EN));
+
+	if (priv->spk_gpio_used) {
+		snd_soc_component_update_bits(priv->component, AC_LINEOUT_CTL,
+					(1<<LINEL_SRC_EN), (1<<LINEL_SRC_EN));
+		snd_soc_component_update_bits(priv->component, AC_LINEOUT_CTL,
+					(1<<LINER_SRC_EN), (1<<LINER_SRC_EN));
+		priv->enable = 1;
+	}
+#ifndef ACX00_DAPM_LINEOUT
+	snd_soc_component_update_bits(component, AC_LINEOUT_CTL, (1<<LINEOUT_EN),
+			(1<<LINEOUT_EN));
+#endif
+
+	snd_soc_component_update_bits(component, AC_LINEOUT_CTL, 0x1f, 0x0f);
+	snd_soc_component_write(component, AC_DAC_MIXER_SRC, 0x2200);
+	snd_soc_component_write(component, AC_OUT_MIXER_SRC, 0x0202);
+}
+
+static int acx00_codec_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	struct snd_soc_component *component = dai->component;
+	int i;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+			(7<<I2S_FMT_SAMPLE), (3<<I2S_FMT_SAMPLE));
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+			(7<<I2S_FMT_SAMPLE), (5<<I2S_FMT_SAMPLE));
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+			(7<<I2S_FMT_SAMPLE), (7<<I2S_FMT_SAMPLE));
+		break;
+	default:
+		dev_err(component->dev, "unrecognized format support\n");
+		break;
+	}
+	for (i = 0; i < ARRAY_SIZE(sample_rate_conv); i++) {
+		if (sample_rate_conv[i].samplerate == params_rate(params)) {
+			snd_soc_component_update_bits(component, AC_SYS_SR_CTL,
+				(SYS_SR_MASK<<SYS_SR_BIT),
+				(sample_rate_conv[i].rate_bit<<SYS_SR_BIT));
+		}
+	}
+
+	return 0;
+}
+
+static int acx00_codec_dai_set_sysclk(struct snd_soc_dai *codec_dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	return 0;
+}
+
+static int acx00_codec_dai_set_fmt(struct snd_soc_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct acx00_priv *priv = snd_soc_dai_get_drvdata(codec_dai);
+	struct snd_soc_component *component = priv->component;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	/* codec clk & FRM master */
+	case SND_SOC_DAIFMT_CBM_CFM:
+		snd_soc_component_update_bits(component, AC_I2S_CLK,
+				(0x1<<I2S_BCLK_OUT), (0x1<<I2S_BCLK_OUT));
+		snd_soc_component_update_bits(component, AC_I2S_CLK,
+				(0x1<<I2S_LRCK_OUT), (0x1<<I2S_LRCK_OUT));
+		break;
+	/* codec clk & FRM slave */
+	case SND_SOC_DAIFMT_CBS_CFS:
+		snd_soc_component_update_bits(component, AC_I2S_CLK,
+				(0x1<<I2S_BCLK_OUT), 0x0<<I2S_BCLK_OUT);
+		snd_soc_component_update_bits(component, AC_I2S_CLK,
+				(0x1<<I2S_LRCK_OUT), 0x0<<I2S_LRCK_OUT);
+		break;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		snd_soc_component_update_bits(component, AC_I2S_CLK,
+				(0x3FF<<I2S_LRCK_PERIOD),
+				(0x1F<<I2S_LRCK_PERIOD));
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x3<<I2S_FMT_MODE), (0x1<<I2S_FMT_MODE));
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x1<<I2S_FMT_TX_OFFSET),
+				(0x1<<I2S_FMT_TX_OFFSET));
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x1<<I2S_FMT_RX_OFFSET),
+				(0x1<<I2S_FMT_RX_OFFSET));
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		snd_soc_component_update_bits(component, AC_I2S_CLK,
+				(0x3FF<<I2S_LRCK_PERIOD),
+				(0x1F<<I2S_LRCK_PERIOD));
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x3<<I2S_FMT_MODE), (0x2<<I2S_FMT_MODE));
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x1<<I2S_FMT_TX_OFFSET),
+				(0x0<<I2S_FMT_TX_OFFSET));
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x1<<I2S_FMT_TX_OFFSET),
+				(0x0<<I2S_FMT_RX_OFFSET));
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		snd_soc_component_update_bits(component, AC_I2S_CLK,
+				(0x3FF<<I2S_LRCK_PERIOD),
+				(0x1F<<I2S_LRCK_PERIOD));
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x3<<I2S_FMT_MODE), (0x1<<I2S_FMT_MODE));
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x1<<I2S_FMT_TX_OFFSET),
+				(0x0<<I2S_FMT_TX_OFFSET));
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x1<<I2S_FMT_RX_OFFSET),
+				(0x0<<I2S_FMT_RX_OFFSET));
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		snd_soc_component_update_bits(component, AC_I2S_CLK,
+				(0x3FF<<I2S_LRCK_PERIOD),
+				(0x3F<<I2S_LRCK_PERIOD));
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x3<<I2S_FMT_MODE), (0x0<<I2S_FMT_MODE));
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x1<<I2S_FMT_TX_OFFSET),
+				(0x1<<I2S_FMT_TX_OFFSET));
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x1<<I2S_FMT_RX_OFFSET),
+				(0x1<<I2S_FMT_RX_OFFSET));
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		snd_soc_component_update_bits(component, AC_I2S_CLK,
+				(0x3FF<<I2S_LRCK_PERIOD),
+				(0x3F<<I2S_LRCK_PERIOD));
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x3<<I2S_FMT_MODE), (0x0<<I2S_FMT_MODE));
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x1<<I2S_FMT_TX_OFFSET),
+				(0x0<<I2S_FMT_TX_OFFSET));
+		snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x1<<I2S_FMT_RX_OFFSET),
+				(0x0<<I2S_FMT_RX_OFFSET));
+		break;
+	default:
+		dev_err(component->dev, "format setting failed\n");
+		break;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		snd_soc_component_update_bits(component, AC_I2S_FMT1,
+				(0x1<<I2S_FMT_BCLK_POLAR),
+				(0x0<<I2S_FMT_BCLK_POLAR));
+		snd_soc_component_update_bits(component, AC_I2S_FMT1,
+				(0x1<<I2S_FMT_LRCK_POLAR),
+				(0x0<<I2S_FMT_LRCK_POLAR));
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		snd_soc_component_update_bits(component, AC_I2S_FMT1,
+				(0x1<<I2S_FMT_BCLK_POLAR),
+				(0x0<<I2S_FMT_BCLK_POLAR));
+		snd_soc_component_update_bits(component, AC_I2S_FMT1,
+				(0x1<<I2S_FMT_LRCK_POLAR),
+				(0x1<<I2S_FMT_LRCK_POLAR));
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		snd_soc_component_update_bits(component, AC_I2S_FMT1,
+				(0x1<<I2S_FMT_BCLK_POLAR),
+				(0x1<<I2S_FMT_BCLK_POLAR));
+		snd_soc_component_update_bits(component, AC_I2S_FMT1,
+				(0x1<<I2S_FMT_LRCK_POLAR),
+				(0x0<<I2S_FMT_LRCK_POLAR));
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		snd_soc_component_update_bits(component, AC_I2S_FMT1,
+				(0x1<<I2S_FMT_BCLK_POLAR),
+				(0x1<<I2S_FMT_BCLK_POLAR));
+		snd_soc_component_update_bits(component, AC_I2S_FMT1,
+				(0x1<<I2S_FMT_LRCK_POLAR),
+				(0x1<<I2S_FMT_LRCK_POLAR));
+		break;
+	default:
+		dev_err(component->dev, "invert clk setting failed\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int acx00_codec_dai_set_clkdiv(struct snd_soc_dai *codec_dai,
+		int clk_id, int clk_div)
+{
+	struct acx00_priv *priv = snd_soc_dai_get_drvdata(codec_dai);
+	struct snd_soc_component *component = priv->component;
+	unsigned int bclk_div;
+	/*
+	 * when PCM mode, setting as 64fs, when I2S mode as 32fs,
+	 * then two channel, then just as 64fs
+	 */
+	unsigned int div_ratio = clk_div / 64;
+
+	switch (div_ratio) {
+	case 1:
+		bclk_div = I2S_BCLK_DIV_1;
+		break;
+	case 2:
+		bclk_div = I2S_BCLK_DIV_2;
+		break;
+	case 4:
+		bclk_div = I2S_BCLK_DIV_3;
+		break;
+	case 6:
+		bclk_div = I2S_BCLK_DIV_4;
+		break;
+	case 8:
+		bclk_div = I2S_BCLK_DIV_5;
+		break;
+	case 12:
+		bclk_div = I2S_BCLK_DIV_6;
+		break;
+	case 16:
+		bclk_div = I2S_BCLK_DIV_7;
+		break;
+	case 24:
+		bclk_div = I2S_BCLK_DIV_8;
+		break;
+	case 32:
+		bclk_div = I2S_BCLK_DIV_9;
+		break;
+	case 48:
+		bclk_div = I2S_BCLK_DIV_10;
+		break;
+	case 64:
+		bclk_div = I2S_BCLK_DIV_11;
+		break;
+	case 96:
+		bclk_div = I2S_BCLK_DIV_12;
+		break;
+	case 128:
+		bclk_div = I2S_BCLK_DIV_13;
+		break;
+	case 176:
+		bclk_div = I2S_BCLK_DIV_14;
+		break;
+	case 192:
+		bclk_div = I2S_BCLK_DIV_15;
+		break;
+	default:
+		dev_err(component->dev, "setting blck div failed\n");
+		break;
+	}
+
+	snd_soc_component_update_bits(component, AC_I2S_CLK,
+			(I2S_BCLK_DIV_MASK<<I2S_BLCK_DIV),
+			(bclk_div<<I2S_BLCK_DIV));
+	return 0;
+}
+
+static int acx00_codec_startup(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *codec_dai)
+{
+	return 0;
+}
+
+static bool acx00_loop_en;
+module_param(acx00_loop_en, bool, 0644);
+MODULE_PARM_DESC(acx00_loop_en, "ACX00-Codec audio loopback debug(Y=enable, N=disable)");
+
+static int acx00_codec_trigger(struct snd_pcm_substream *substream,
+		int cmd, struct snd_soc_dai *codec_dai)
+{
+	struct snd_soc_component *component = codec_dai->component;
+	return 0;
+}
+
+static int acx00_codec_prepare(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *codec_dai)
+{
+	struct snd_soc_component *component = codec_dai->component;
+
+	snd_soc_component_update_bits(component, AC_SYS_CLK_CTL,
+			(0x1<<SYS_CLK_I2S), (0x1<<SYS_CLK_I2S));
+	snd_soc_component_update_bits(component, AC_SYS_MOD_RST,
+			(0x1<<MOD_RST_I2S), (0x1<<MOD_RST_I2S));
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (acx00_loop_en)
+			snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x1<<I2S_FMT_LOOP),
+				(0x1<<I2S_FMT_LOOP));
+		else
+			snd_soc_component_update_bits(component, AC_I2S_FMT0,
+				(0x1<<I2S_FMT_LOOP),
+				(0x0<<I2S_FMT_LOOP));
+		acx00_codec_txctrl_enable(component, 1);
+	} else
+		acx00_codec_rxctrl_enable(component, 1);
+	return 0;
+}
+
+static int acx00_codec_digital_mute(struct snd_soc_dai *codec_dai,
+				int mute)
+{
+	struct snd_soc_component *component = codec_dai->component;
+
+	if (mute)
+		snd_soc_component_write(component, AC_I2S_DAC_VOL, 0);
+	else
+		snd_soc_component_write(component, AC_I2S_DAC_VOL, ACX00_DEF_VOL);
+	return 0;
+}
+
+static void acx00_codec_shutdown(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *dai)
+{
+	struct snd_soc_component *component = dai->component;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		acx00_codec_txctrl_enable(component, 0);
+	else
+		acx00_codec_rxctrl_enable(component, 0);
+}
+
+static const struct snd_soc_dai_ops acx00_codec_dai_ops = {
+	.hw_params	= acx00_codec_hw_params,
+	.shutdown	= acx00_codec_shutdown,
+//	.digital_mute	= acx00_codec_digital_mute,
+	.set_sysclk	= acx00_codec_dai_set_sysclk,
+	.set_fmt	= acx00_codec_dai_set_fmt,
+	.set_clkdiv	= acx00_codec_dai_set_clkdiv,
+	.startup	= acx00_codec_startup,
+	.trigger	= acx00_codec_trigger,
+	.prepare	= acx00_codec_prepare,
+};
+
+static struct snd_soc_dai_driver acx00_codec_dai[] = {
+	{
+		.name = "acx00-dai",
+		.playback = {
+			.stream_name = "Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000
+				| SNDRV_PCM_RATE_KNOT,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE
+				| SNDRV_PCM_FMTBIT_S24_LE
+				| SNDRV_PCM_FMTBIT_S32_LE,
+		},
+
+		.capture = {
+			.stream_name = "Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000
+				| SNDRV_PCM_RATE_KNOT,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE
+				| SNDRV_PCM_FMTBIT_S24_LE
+				| SNDRV_PCM_FMTBIT_S32_LE,
+		},
+
+		.ops = &acx00_codec_dai_ops,
+	},
+};
+
+static void acx00_codec_resume_work(struct work_struct *work)
+{
+	struct acx00_priv *priv = container_of(work,
+			struct acx00_priv, resume_work.work);
+
+	acx00_codec_init(priv->component);
+}
+
+static int acx00_codec_probe(struct snd_soc_component *component)
+{
+	struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
+	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+	int ret = 0;
+
+	mutex_init(&priv->mutex);
+
+	priv->component = component;
+#if 0
+	/* Add virtual switch */
+	ret = snd_soc_add_component_controls(component, acx00_codec_controls,
+					ARRAY_SIZE(acx00_codec_controls));
+	if (ret) {
+		pr_err("[audio-codec] Failed to register audio mode control, will continue without it.\n");
+	}
+	snd_soc_dapm_new_controls(dapm, acx00_codec_dapm_widgets, ARRAY_SIZE(acx00_codec_dapm_widgets));
+	snd_soc_dapm_add_routes(dapm, acx00_codec_dapm_routes, ARRAY_SIZE(acx00_codec_dapm_routes));
+#endif
+	/* using late_initcall to wait 120ms acx00-core to make chip reset */
+	acx00_codec_init(component);
+	INIT_DELAYED_WORK(&priv->spk_work, acx00_spk_enable);
+	INIT_DELAYED_WORK(&priv->resume_work, acx00_codec_resume_work);
+	return 0;
+}
+
+static void acx00_codec_remove(struct snd_soc_component *component)
+{
+	struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
+
+	cancel_delayed_work_sync(&priv->spk_work);
+	cancel_delayed_work_sync(&priv->resume_work);
+}
+
+static unsigned int acx00_codec_read(struct snd_soc_component *component,
+					unsigned int reg)
+{
+	unsigned int data;
+	struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
+
+	/* Device I/O API */
+	data = acx00_reg_read(priv->acx00, reg);
+	return data;
+}
+
+static int acx00_codec_write(struct snd_soc_component *component,
+			unsigned int reg, unsigned int value)
+{
+	struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
+
+	return acx00_reg_write(priv->acx00, reg, value);
+}
+
+static int sunxi_gpio_iodisable(u32 gpio)
+{
+	char pin_name[8];
+	u32 config, ret;
+#if 0
+	sunxi_gpio_to_name(gpio, pin_name);
+	config = 7 << 16;
+	ret = pin_config_set(SUNXI_PINCTRL, pin_name, config);
+#endif
+	return ret;
+}
+
+static int acx00_codec_suspend(struct snd_soc_component *component)
+{
+	struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
+
+	pr_debug("Enter %s\n", __func__);
+
+	clk_disable_unprepare(priv->clk);
+
+	/* PA_CTRL first setting low state, then make it iodisabled */
+	if (priv->spk_gpio_used) {
+		sunxi_gpio_iodisable(priv->spk_gpio);
+		msleep(30);
+	}
+
+	/*
+	 * when codec suspend, then the register reset, if auto reset produce
+	 * Pop & Click noise, then we should cut down the LINEOUT in this town.
+	 */
+	if (priv->enable) {
+		snd_soc_component_update_bits(component, AC_LINEOUT_CTL,
+				(1<<LINEOUT_EN), (0<<LINEOUT_EN));
+		snd_soc_component_update_bits(priv->component, AC_LINEOUT_CTL,
+				(1<<LINEL_SRC_EN), (0<<LINEL_SRC_EN));
+		snd_soc_component_update_bits(priv->component, AC_LINEOUT_CTL,
+				(1<<LINER_SRC_EN), (0<<LINER_SRC_EN));
+		priv->enable = 0;
+	}
+
+	pr_debug("Exit %s\n", __func__);
+
+	return 0;
+}
+
+static int acx00_codec_resume(struct snd_soc_component *component)
+{
+	struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
+
+	pr_debug("Enter %s\n", __func__);
+
+	if (clk_prepare_enable(priv->clk)) {
+		dev_err(component->dev, "codec resume clk failed\n");
+		return -EBUSY;
+	}
+
+	schedule_delayed_work(&priv->resume_work, msecs_to_jiffies(300));
+
+	if (priv->spk_gpio_used) {
+		gpio_direction_output(priv->spk_gpio, 1);
+		gpio_set_value(priv->spk_gpio, 0);
+	}
+
+	pr_debug("Exit %s\n", __func__);
+
+	return 0;
+}
+
+
+static int acx00_codec_set_bias_level(struct snd_soc_component *component,
+		enum snd_soc_bias_level level)
+{
+	component->dapm.bias_level = level;
+	return 0;
+}
+
+struct label {
+	const char *name;
+	int value;
+};
+
+#define LABEL(constant) { #constant, constant }
+#define LABEL_END { NULL, -1 }
+
+static struct label reg_labels[] = {
+	LABEL(AC_SYS_CLK_CTL),
+	LABEL(AC_SYS_MOD_RST),
+	LABEL(AC_SYS_SR_CTL),
+	LABEL(AC_I2S_CTL),
+	LABEL(AC_I2S_CLK),
+	LABEL(AC_I2S_FMT0),
+	LABEL(AC_I2S_FMT1),
+	LABEL(AC_I2S_MIXER_SRC),
+	LABEL(AC_I2S_MIXER_GAIN),
+	LABEL(AC_I2S_DAC_VOL),
+	LABEL(AC_I2S_ADC_VOL),
+	LABEL(AC_DAC_CTL),
+	LABEL(AC_DAC_MIXER_SRC),
+	LABEL(AC_DAC_MIXER_GAIN),
+	LABEL(AC_OUT_MIXER_CTL),
+	LABEL(AC_OUT_MIXER_SRC),
+	LABEL(AC_LINEOUT_CTL),
+	LABEL(AC_ADC_CTL),
+	LABEL(AC_MICBIAS_CTL),
+	LABEL(AC_ADC_MIC_CTL),
+	LABEL(AC_ADC_MIXER_SRC),
+	LABEL(AC_BIAS_CTL),
+	LABEL(AC_ANALOG_PROF_CTL),
+	LABEL_END,
+};
+
+static ssize_t show_audio_reg(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct acx00_priv *priv = dev_get_drvdata(dev);
+	int count = 0, i = 0;
+	unsigned int reg_val;
+
+	count += sprintf(buf, "dump audio reg:\n");
+
+	while (reg_labels[i].name != NULL) {
+		reg_val = acx00_reg_read(priv->acx00, reg_labels[i].value);
+		count += sprintf(buf + count, "%s 0x%x: 0x%x\n",
+		reg_labels[i].name, (reg_labels[i].value), reg_val);
+		i++;
+	}
+
+	return count;
+}
+
+/*
+ * param 1: 0 read;1 write
+ * param 2: 1 digital reg; 2 analog reg
+ * param 3: reg value;
+ * param 4: write value;
+ * read:
+ * echo 0,1,0x00> audio_reg
+ * echo 0,2,0x00> audio_reg
+ * write:
+ * echo 1,1,0x00,0xa > audio_reg
+ * echo 1,2,0x00,0xff > audio_reg
+*/
+static ssize_t store_audio_reg(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret;
+	int rw_flag;
+	unsigned int input_reg_val = 0;
+	int input_reg_group = 0;
+	unsigned int input_reg_offset = 0;
+	struct acx00_priv *priv = dev_get_drvdata(dev);
+
+	ret = sscanf(buf, "%d,%d,0x%x,0x%x", &rw_flag, &input_reg_group,
+			&input_reg_offset, &input_reg_val);
+	dev_info(dev, "ret:%d, reg_group:%d, reg_offset:%d, reg_val:0x%x\n",
+			ret, input_reg_group, input_reg_offset, input_reg_val);
+
+	if (input_reg_group != 1) {
+		pr_err("not exist reg group\n");
+		ret = count;
+		goto out;
+	}
+	if (!(rw_flag == 1 || rw_flag == 0)) {
+		pr_err("not rw_flag\n");
+		ret = count;
+		goto out;
+	}
+
+	if (rw_flag) {
+		acx00_reg_write(priv->acx00, input_reg_offset, input_reg_val);
+	} else {
+		input_reg_val = acx00_reg_read(priv->acx00, input_reg_offset);
+		dev_info(dev, "\n\n Reg[0x%x] : 0x%04x\n\n",
+				input_reg_offset, input_reg_val);
+	}
+	ret = count;
+
+out:
+	return ret;
+}
+
+static DEVICE_ATTR(audio_reg, 0644, show_audio_reg, store_audio_reg);
+
+static struct attribute *audio_debug_attrs[] = {
+	&dev_attr_audio_reg.attr,
+	NULL,
+};
+
+static struct attribute_group audio_debug_attr_group = {
+	.name   = "audio_reg_debug",
+	.attrs  = audio_debug_attrs,
+};
+
+static struct snd_soc_component_driver soc_codec_driver_acx00 = {
+	.probe			= acx00_codec_probe,
+	.remove			= acx00_codec_remove,
+	.suspend		= acx00_codec_suspend,
+	.resume			= acx00_codec_resume,
+	.read			= acx00_codec_read,
+	.write			= acx00_codec_write,
+//	.ignore_pmdown_time	= 1,
+	.set_bias_level		= acx00_codec_set_bias_level,
+	.controls		= acx00_codec_controls,
+	.num_controls		= ARRAY_SIZE(acx00_codec_controls),
+	.dapm_widgets		= acx00_codec_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(acx00_codec_dapm_widgets),
+	.dapm_routes		= acx00_codec_dapm_routes,
+	.num_dapm_routes	= ARRAY_SIZE(acx00_codec_dapm_routes),
+};
+
+/* through acx00 is part of mfd devices, after the mfd */
+static int acx00_codec_dev_probe(struct platform_device *pdev)
+{
+	struct acx00_priv *priv;
+	int ret;
+	struct device_node *np = of_find_compatible_node(NULL, NULL, "allwinner,ac200_codec");
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(struct acx00_priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&pdev->dev, "acx00 codec priv mem alloc failed\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, priv);
+	priv->acx00 = dev_get_drvdata(pdev->dev.parent);
+
+	if (np) {
+		ret = of_get_named_gpio(np, "gpio-spk", 0);
+		if (ret >= 0) {
+			priv->spk_gpio_used = 1;
+			priv->spk_gpio = ret;
+			if (!gpio_is_valid(priv->spk_gpio)) {
+				dev_err(&pdev->dev, "gpio-spk is valid\n");
+				ret = -EINVAL;
+				goto err_devm_kfree;
+			} else {
+				ret = devm_gpio_request(&pdev->dev,
+				priv->spk_gpio, "SPK");
+				if (ret) {
+					dev_err(&pdev->dev,
+						"failed request gpio-spk\n");
+					ret = -EBUSY;
+					goto err_devm_kfree;
+				} else {
+					gpio_direction_output(priv->spk_gpio,
+								1);
+					gpio_set_value(priv->spk_gpio, 0);
+				}
+			}
+		} else {
+			priv->spk_gpio_used = 0;
+		}
+
+		ret = of_get_named_gpio(np, "gpio-switch", 0);
+		if (ret >= 0) {
+			priv->switch_gpio = ret;
+			if (!gpio_is_valid(priv->switch_gpio)) {
+				dev_err(&pdev->dev, "gpio-switch is valid\n");
+				ret = -EINVAL;
+				goto err_devm_kfree;
+			} else {
+				ret = devm_gpio_request(&pdev->dev, priv->switch_gpio, "SWITCH");
+				if (ret) {
+					dev_err(&pdev->dev,
+						"failed request gpio-switch\n");
+					ret = -EBUSY;
+					goto err_devm_kfree;
+				} else {
+					gpio_direction_output(priv->switch_gpio, 1);
+					gpio_set_value(priv->switch_gpio, 1);
+				}
+			}
+		} 
+	}
+
+	ret = snd_soc_register_component(&pdev->dev, &soc_codec_driver_acx00,
+			acx00_codec_dai, ARRAY_SIZE(acx00_codec_dai));
+
+	if (ret < 0)
+		dev_err(&pdev->dev, "Failed register acx00: %d\n", ret);
+
+	ret  = sysfs_create_group(&pdev->dev.kobj, &audio_debug_attr_group);
+	if (ret)
+		dev_warn(&pdev->dev, "failed to create attr group\n");
+
+	return 0;
+
+err_devm_kfree:
+	devm_kfree(&pdev->dev, priv);
+	return ret;
+}
+
+/* Mark this space to clear the LINEOUT & gpio */
+static void acx00_codec_dev_shutdown(struct platform_device *pdev)
+{
+	struct acx00_priv *priv = platform_get_drvdata(pdev);
+
+	if (priv->spk_gpio_used)
+		gpio_set_value(priv->spk_gpio, 0);
+}
+
+static int acx00_codec_dev_remove(struct platform_device *pdev)
+{
+	struct acx00_priv *priv = platform_get_drvdata(pdev);
+
+#ifndef ACX00_DAPM_LINEOUT
+	/*
+	snd_soc_component_update_bits(priv->component, AC_LINEOUT_CTL,
+			(1<<LINEOUT_EN), (0<<LINEOUT_EN));
+	*/
+#endif
+	snd_soc_unregister_component(&pdev->dev);
+	clk_disable_unprepare(priv->clk);
+	devm_kfree(&pdev->dev, priv);
+	return 0;
+}
+
+static const struct of_device_id acx00_codec_match[] = {
+	{ .compatible = "x-powers,ac200-codec" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, acx00_codec_match);
+
+static struct platform_driver acx00_codec_driver = {
+	.driver = {
+		.name = "acx00-codec",
+		.of_match_table = acx00_codec_match,
+	},
+	.probe = acx00_codec_dev_probe,
+	.remove = acx00_codec_dev_remove,
+	.shutdown = acx00_codec_dev_shutdown,
+};
+
+static int __init acx00_codec_driver_init(void)
+{
+	return platform_driver_register(&acx00_codec_driver);
+}
+
+static void __exit acx00_codec_driver_exit(void)
+{
+	platform_driver_unregister(&acx00_codec_driver);
+}
+late_initcall(acx00_codec_driver_init);
+module_exit(acx00_codec_driver_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SUNXI ASoC ACX00 Codec Driver");
+MODULE_AUTHOR("wolfgang huang");
+MODULE_ALIAS("platform:acx00-codec");
+
diff --git a/sound/soc/codecs/acx00.h b/sound/soc/codecs/acx00.h
new file mode 100644
index 000000000..4d53184fc
--- /dev/null
+++ b/sound/soc/codecs/acx00.h
@@ -0,0 +1,357 @@
+/*
+ * sound\soc\codecs\acx00.h
+ * (C) Copyright 2012-2016
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Wolfgang Huang <huangjinhui@allwinnertech.com>
+ *
+ * some simple description for this code
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef __ACX00_H_
+#define __ACX00_H_
+
+/* ACX00 register offset list */
+#define AC_SYS_CLK_CTL		0x2000
+#define AC_SYS_MOD_RST		0x2002
+#define AC_SYS_SR_CTL		0x2004
+/* Left blank */
+#define AC_I2S_CTL		0x2100
+#define AC_I2S_CLK		0x2102
+#define AC_I2S_FMT0		0x2104
+/* Left blank */
+#define AC_I2S_FMT1		0x2108
+/* Left blank */
+#define AC_I2S_MIXER_SRC	0x2114
+#define AC_I2S_MIXER_GAIN	0x2116
+#define AC_I2S_DAC_VOL		0x2118
+#define AC_I2S_ADC_VOL		0x211A
+/* Left blank */
+#define AC_DAC_CTL		0x2200
+#define AC_DAC_MIXER_SRC	0x2202
+#define AC_DAC_MIXER_GAIN	0x2204
+/* Left blank */
+#define AC_OUT_MIXER_CTL	0x2220
+#define AC_OUT_MIXER_SRC	0x2222
+#define AC_LINEOUT_CTL		0x2224
+/* Left blank */
+#define AC_ADC_CTL		0x2300
+/* Left blank */
+#define AC_MICBIAS_CTL		0x2310
+/* Left blank */
+#define AC_ADC_MIC_CTL		0x2320
+#define AC_ADC_MIXER_SRC	0x2322
+/* Left blank */
+#define AC_BIAS_CTL		0x232A
+#define AC_ANALOG_PROF_CTL	0x232C
+/* Left blank */
+#define AC_ADC_DAPL_CTRL	0x2500
+#define AC_ADC_DAPR_CTRL	0x2502
+#define AC_ADC_DAPLSTA		0x2504
+#define AC_ADC_DAPRSTA		0x2506
+#define AC_ADC_DAP_LTL		0x2508
+#define AC_ADC_DAP_RTL		0x250A
+#define AC_ADC_DAP_LHAC		0x250C
+#define AC_ADC_DAP_LLAC		0x250E
+#define AC_ADC_DAP_RHAC		0x2510
+#define AC_ADC_DAP_RLAC		0x2512
+#define AC_ADC_DAP_LDT		0x2514
+#define AC_ADC_DAP_LAT		0x2516
+#define AC_ADC_DAP_RDT		0x2518
+#define AC_ADC_DAP_RAT		0x251A
+#define AC_ADC_DAP_NTH		0x251C
+#define AC_ADC_DAP_LHNAC	0x251E
+#define AC_ADC_DAP_LLNAC	0x2520
+#define AC_ADC_DAP_RHNAC	0x2522
+#define AC_ADC_DAP_RLNAC	0x2524
+#define AC_ADC_DAP_HHPFC	0x2526
+#define AC_ADC_DAP_LHPFC	0x2528
+#define AC_ADC_DAP_OPT		0x252A
+/* Left blank */
+#define AC_AGC_SEL		0x2480
+/* Left blank */
+#define AC_ADC_DAPL_CTRL	0x2500
+#define AC_ADC_DAPR_CTRL	0x2502
+#define AC_ADC_DAPLSTA		0x2504
+#define AC_ADC_DAPRSTA		0x2506
+#define AC_ADC_DAP_LTL		0x2508
+#define AC_ADC_DAP_RTL		0x250A
+#define AC_ADC_DAP_LHAC		0x250C
+#define AC_ADC_DAP_LLAC		0x250E
+#define AC_ADC_DAP_RHAC		0x2510
+#define AC_ADC_DAP_RLAC		0x2512
+#define AC_ADC_DAP_LDT		0x2514
+#define AC_ADC_DAP_LAT		0x2516
+#define AC_ADC_DAP_RDT		0x2518
+#define AC_ADC_DAP_RAT		0x251A
+#define AC_ADC_DAP_NTH		0x251C
+#define AC_ADC_DAP_LHNAC	0x251E
+#define AC_ADC_DAP_LLNAC	0x2520
+#define AC_ADC_DAP_RHNAC	0x2522
+#define AC_ADC_DAP_RLNAC	0x2524
+#define AC_ADC_DAP_HHPFC	0x2526
+#define AC_ADC_DAP_LHPFC	0x2528
+#define AC_ADC_DAP_OPT		0x252A
+/* Left blank */
+#define AC_DRC_SEL		0x2f80
+/* Left blank */
+#define AC_DRC_CHAN_CTRL	0x3000
+#define AC_DRC_HHPFC		0x3002
+#define AC_DRC_LHPFC		0x3004
+#define AC_DRC_CTRL		0x3006
+#define AC_DRC_LPFHAT		0x3008
+#define AC_DRC_LPFLAT		0x300A
+#define AC_DRC_RPFHAT		0x300C
+#define AC_DRC_RPFLAT		0x300E
+#define AC_DRC_LPFHRT		0x3010
+#define AC_DRC_LPFLRT		0x3012
+#define AC_DRC_RPFHRT		0x3014
+#define AC_DRC_RPFLRT		0x3016
+#define AC_DRC_LRMSHAT		0x3018
+#define AC_DRC_LRMSLAT		0x301A
+#define AC_DRC_RRMSHAT		0x301C
+#define AC_DRC_RRMSLAT		0x301E
+#define AC_DRC_HCT		0x3020
+#define AC_DRC_LCT		0x3022
+#define AC_DRC_HKC		0x3024
+#define AC_DRC_LKC		0x3026
+#define AC_DRC_HOPC		0x3028
+#define AC_DRC_LOPC		0x302A
+#define AC_DRC_HLT		0x302C
+#define AC_DRC_LLT		0x302E
+#define AC_DRC_HKI		0x3030
+#define AC_DRC_LKI		0x3032
+#define AC_DRC_HOPL		0x3034
+#define AC_DRC_LOPL		0x3036
+#define AC_DRC_HET		0x3038
+#define AC_DRC_LET		0x303A
+#define AC_DRC_HKE		0x303C
+#define AC_DRC_LKE		0x303E
+#define AC_DRC_HOPE		0x3040
+#define AC_DRC_LOPE		0x3042
+#define AC_DRC_HKN		0x3044
+#define AC_DRC_LKN		0x3046
+#define AC_DRC_SFHAT		0x3048
+#define AC_DRC_SFLAT		0x304A
+#define AC_DRC_SFHRT		0x304C
+#define AC_DRC_SFLRT		0x304E
+#define AC_DRC_MXGHS		0x3050
+#define AC_DRC_MXGLS		0x3052
+#define AC_DRC_MNGHS		0x3054
+#define AC_DRC_MNGLS		0x3056
+#define AC_DRC_EPSHC		0x3058
+#define AC_DRC_EPSLC		0x305A
+#define AC_DRC_OPT		0x305C
+#define AC_DRC_HPFHGAIN		0x305E
+#define AC_DRC_HPFLGAIN		0x3060
+#define AC_DRC_BISTCR		0x3100
+#define AC_DRC_BISTST		0x3102
+
+/* AC_SYS_CLK_CTL : 0x2000 */
+#define SYS_CLK_I2S		15
+#define SYS_CLK_AGC		7
+#define SYS_CLK_DRC		6
+#define SYS_CLK_ADC		3
+#define SYS_CLK_DAC		2
+
+/* AC_SYS_MOD_RST : 0x2002 */
+#define MOD_RST_I2S		15
+#define MOD_RST_AGC		7
+#define MOD_RST_DRC		6
+#define MOD_RST_ADC		3
+#define MOD_RST_DAC		2
+
+/* AC_SYS_SR_CTL : 0x2004 */
+#define SYS_SR_BIT		0
+#define SYS_SR_MASK		0xF
+#define SYS_SR_BIT_0		0	/* 8000 */
+#define SYS_SR_BIT_1		1	/* 11025 */
+#define SYS_SR_BIT_2		2	/* 12000 */
+#define SYS_SR_BIT_3		3	/* 16000 */
+#define SYS_SR_BIT_4		4	/* 22050 */
+#define SYS_SR_BIT_5		5	/* 24000 */
+#define SYS_SR_BIT_6		6	/* 32000 */
+#define SYS_SR_BIT_7		7	/* 44100 */
+#define SYS_SR_BIT_8		8	/* 48000 */
+#define SYS_SR_BIT_9		9	/* 96000 */
+#define SYS_SR_BIT_10		10	/* 192000 */
+
+/* AC_I2S_CTL : 0x2100 */
+#define I2S_SDO0_EN		3
+#define I2S_TX_EN		2
+#define I2S_RX_EN		1
+#define I2S_GEN			0
+
+/* AC_I2S_CLK : 0x2102 */
+#define I2S_BCLK_OUT		15
+#define I2S_LRCK_OUT		14
+#define I2S_BLCK_DIV		10
+#define I2S_LRCK_PERIOD		0
+/* BCLK DIV Define */
+#define I2S_BCLK_DIV_MASK	0xF
+#define I2S_BCLK_DIV_1		1
+#define I2S_BCLK_DIV_2		2
+#define I2S_BCLK_DIV_3		3
+#define I2S_BCLK_DIV_4		4
+#define I2S_BCLK_DIV_5		5
+#define I2S_BCLK_DIV_6		6
+#define I2S_BCLK_DIV_7		7
+#define I2S_BCLK_DIV_8		8
+#define I2S_BCLK_DIV_9		9
+#define I2S_BCLK_DIV_10		10
+#define I2S_BCLK_DIV_11		11
+#define I2S_BCLK_DIV_12		12
+#define I2S_BCLK_DIV_13		13
+#define I2S_BCLK_DIV_14		14
+#define I2S_BCLK_DIV_15		15
+#define I2S_LRCK_PERIOD_MASK	0x3FF
+
+/* AC_I2S_FMT0 : 0x2104 */
+#define I2S_FMT_MODE		14
+#define I2S_FMT_TX_OFFSET	10
+#define I2S_FMT_RX_OFFSET	8
+#define I2S_FMT_SAMPLE		4
+#define I2S_FMT_SLOT_WIDTH	1
+#define I2S_FMT_LOOP		0
+
+/* AC_I2S_FMT1 : 0x2108 */
+#define I2S_FMT_BCLK_POLAR	15
+#define I2S_FMT_LRCK_POLAR	14
+#define I2S_FMT_EDGE_TRANSFER	13
+#define I2S_FMT_RX_MLS		11
+#define I2S_FMT_TX_MLS		10
+#define I2S_FMT_EXTEND		9
+#define I2S_FMT_LRCK_WIDTH	4	/* PCM long/short Frame */
+#define I2S_MFT_RX_PDM		2
+#define I2S_FMT_TX_PDM		0
+
+/* AC_I2S_MIXER_SRC : 0x2114 */
+#define I2S_MIXERL_SRC_DAC	13
+#define I2S_MIXERL_SRC_ADC	12
+#define I2S_MIXERR_SRC_DAC	9
+#define I2S_MIXERR_SRC_ADC	8
+
+/* AC_I2S_MIXER_GAIN : 0x2116 */
+#define I2S_MIXERL_GAIN_DAC	13
+#define I2S_MIXERL_GAIN_ADC	12
+#define I2S_MIXERR_GAIN_DAC	9
+#define I2S_MIXERR_GAIN_ADC	8
+
+
+/* AC_I2S_DAC_VOL : 0x2118 */
+#define I2S_DACL_VOL		8
+#define I2S_DACR_VOL		0
+
+/* AC_I2S_ADC_VOL : 0x211A */
+#define I2S_ADCL_VOL		8
+#define I2S_ADCR_VOL		0
+
+/* AC_DAC_CTL : 0x2200 */
+#define DAC_CTL_DAC_EN		15
+#define DAC_CTL_HPF_EN		14
+#define DAC_CTL_FIR			13
+#define DAC_CTL_MODQU		8
+
+/* AC_DAC_MIXER_SRC : 0x2202 */
+#define DAC_MIXERL_SRC_DAC	13
+#define DAC_MIXERL_SRC_ADC	12
+#define DAC_MIXERR_SRC_DAC	9
+#define DAC_MIXERR_SRC_ADC	8
+
+/* AC_DAC_MIXER_GAIN : 0x2204 */
+#define DAC_MIXERL_GAIN_DAC	13
+#define DAC_MIXERL_GAIN_ADC	12
+#define DAC_MIXERR_GAIN_DAC	9
+#define DAC_MIXERR_GAIN_ADC	8
+
+/* AC_OUT_MIXER_CTL : 0x2220 */
+#define OUT_MIXER_DACR_EN	15
+#define OUT_MIXER_DACL_EN	14
+#define OUT_MIXER_RMIX_EN	13
+#define OUT_MIXER_LMIX_EN	12
+#define OUT_MIXER_LINE_VOL	8
+#define OUT_MIXER_MIC1_VOL	4
+#define OUT_MIXER_MIC2_VOL	0
+
+/* AC_OUT_MIXER_SRC : 0x2222 */
+#define OUT_MIXERR_SRC_MIC1	14
+#define OUT_MIXERR_SRC_MIC2	13
+#define OUT_MIXERR_SRC_PHPN	12
+#define OUT_MIXERR_SRC_PHP	11
+#define OUT_MIXERR_SRC_LINER	10
+#define OUT_MIXERR_SRC_DACR	9
+#define OUT_MIXERR_SRC_DACL	8
+#define OUT_MIXERL_SRC_MIC1	6
+#define OUT_MIXERL_SRC_MIC2	5
+#define OUT_MIXERL_SRC_PHPN	4
+#define OUT_MIXERL_SRC_PHN	3
+#define OUT_MIXERL_SRC_LINEL	2
+#define OUT_MIXERL_SRC_DACL	1
+#define OUT_MIXERL_SRC_DACR	0
+
+/* AC_LINEOUT_CTL : 0x2224 */
+#define LINEOUT_EN		15
+#define LINEL_SRC_EN		14
+#define LINER_SRC_EN		13
+#define LINEL_SRC		12
+#define LINER_SRC		11
+/* ramp just skip */
+#define LINE_SLOPE_SEL		8
+#define LINE_ANTI_TIME		5
+#define LINEOUT_VOL			0
+
+/* AC_ADC_CTL : 0x2300 */
+#define ADC_EN			15
+#define ADC_ENDM		14
+#define ADC_FIR			13
+#define ADC_DELAY_TIME		2
+#define ADC_DELAY_EN		1
+
+/* AC_MICBIAS_CTL : 0x2310 */
+#define MMBIAS_EN		15
+#define MMBIAS_CHOPPER		14
+#define MMBIAS_CHOP_CLK		12
+#define MMBIAS_SEL		8
+#define ADDA_BIAS_CUR		3
+
+/* AC_ADC_MIC_CTL : 0x2320 */
+#define ADCR_EN			15
+#define ADCL_EN			14
+#define ADC_GAIN		8
+#define MIC1_GAIN_EN		7
+#define MIC1_BOOST		4
+#define MIC2_GAIN_EN		3
+#define MIC2_BOOST		0
+
+/* AC_ADC_MIXER_SRC : 0x2322 */
+#define ADC_MIXERR_MIC1		14
+#define ADC_MIXERR_MIC2		13
+#define ADC_MIXERR_PHPN		12
+#define ADC_MIXERR_PHP		11
+#define ADC_MIXERR_LINER	10
+#define ADC_MIXERR_MIXR		9
+#define ADC_MIXERR_MIXL		8
+#define ADC_MIXERL_MIC1		6
+#define ADC_MIXERL_MIC2		5
+#define ADC_MIXERL_PHPN		4
+#define ADC_MIXERL_PHN		3
+#define ADC_MIXERL_LINEL	2
+#define ADC_MIXERL_MIXL		1
+#define ADC_MIXERL_MIXR		0
+
+/* AC_BIAS_CTL : 0x232A */
+
+/* AC_ANALOG_PROF_CTL : 0x232C */
+/* used for current performance measure */
+
+/* AC_DLDO_OSC_CTL : 0x2340 */
+/* AC_ALDO_CTL : 0x2342 */
+/* used for digital & analog LDO test... etc */
+
+#endif
+
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 9f8e868b9..f2ef01aae 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -724,7 +724,8 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
 		val = 0;
 		break;
 	case SND_SOC_DAIFMT_NB_NF:
-		val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
+		//val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
+		val = SUN8I_I2S_FMT0_LRCLK_POLARITY_NORMAL;
 		break;
 	default:
 		return -EINVAL;
@@ -796,9 +797,9 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
 			   val);
 
 	/* Set sign extension to pad out LSB with 0 */
-	regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG,
+	/* regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG,
 			   SUN8I_I2S_FMT1_REG_SEXT_MASK,
-			   SUN8I_I2S_FMT1_REG_SEXT(0));
+			   SUN8I_I2S_FMT1_REG_SEXT(0)); */
 
 	return 0;
 }
@@ -831,7 +832,8 @@ static int sun50i_h6_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
 		val = 0;
 		break;
 	case SND_SOC_DAIFMT_NB_NF:
-		val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
+		//val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
+		val = SUN8I_I2S_FMT0_LRCLK_POLARITY_NORMAL;
 		break;
 	default:
 		return -EINVAL;
@@ -903,9 +905,9 @@ static int sun50i_h6_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
 			   val);
 
 	/* Set sign extension to pad out LSB with 0 */
-	regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG,
+	/* regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG,
 			   SUN8I_I2S_FMT1_REG_SEXT_MASK,
-			   SUN8I_I2S_FMT1_REG_SEXT(0));
+			   SUN8I_I2S_FMT1_REG_SEXT(0)); */
 
 	return 0;
 }
@@ -1238,6 +1240,7 @@ static const struct regmap_config sun8i_i2s_regmap_config = {
 };
 
 static const struct regmap_config sun50i_h6_i2s_regmap_config = {
+	.name = "h6_i2s",
 	.reg_bits	= 32,
 	.reg_stride	= 4,
 	.val_bits	= 32,
