From ef05a3ce8340c7156610b173324ab793b06e0ae2 Mon Sep 17 00:00:00 2001
From: Michal Ulianko <info@itserve.cz>
Date: Mon, 29 Jul 2013 20:14:38 +0200
Subject: [PATCH 1/2] Added ASoC driver for i.MX233's builtin ADC/DAC codec.

---
 sound/soc/codecs/Kconfig             |    4 +
 sound/soc/codecs/Makefile            |    2 +
 sound/soc/codecs/mxs-builtin-codec.c | 1128 ++++++++++++++++++++++++++++++++++
 sound/soc/codecs/mxs-builtin-codec.h |  825 +++++++++++++++++++++++++
 sound/soc/mxs/Kconfig                |   10 +
 sound/soc/mxs/Makefile               |    9 +
 sound/soc/mxs/mxs-builtin-audio.c    |  120 ++++
 sound/soc/mxs/mxs-builtin-dai.c      |  588 ++++++++++++++++++
 sound/soc/mxs/mxs-builtin-pcm.c      |   69 +++
 sound/soc/mxs/mxs-builtin-pcm.h      |   25 +
 10 files changed, 2780 insertions(+)
 create mode 100644 sound/soc/codecs/mxs-builtin-codec.c
 create mode 100644 sound/soc/codecs/mxs-builtin-codec.h
 create mode 100644 sound/soc/mxs/mxs-builtin-audio.c
 create mode 100644 sound/soc/mxs/mxs-builtin-dai.c
 create mode 100644 sound/soc/mxs/mxs-builtin-pcm.c
 create mode 100644 sound/soc/mxs/mxs-builtin-pcm.h

--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -164,6 +164,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_WM9705 if SND_SOC_AC97_BUS
 	select SND_SOC_WM9712 if SND_SOC_AC97_BUS
 	select SND_SOC_WM9713 if SND_SOC_AC97_BUS
+	select SND_SOC_MXS_BUILTIN_CODEC
         help
           Normally ASoC codec drivers are only built if a machine driver which
           uses them is also built since they are only usable with a machine
@@ -789,6 +790,9 @@ config SND_SOC_WM9712
 config SND_SOC_WM9713
 	tristate
 
+config SND_SOC_MXS_BUILTIN_CODEC
+	tristate
+
 # Amp
 config SND_SOC_LM4857
 	tristate
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -166,6 +166,7 @@ snd-soc-wm9705-objs := wm9705.o
 snd-soc-wm9712-objs := wm9712.o
 snd-soc-wm9713-objs := wm9713.o
 snd-soc-wm-hubs-objs := wm_hubs.o
+snd-soc-mxs-builtin-codec-objs := mxs-builtin-codec.o
 
 # Amp
 snd-soc-max9877-objs := max9877.o
@@ -339,6 +340,7 @@ obj-$(CONFIG_SND_SOC_WM9712)	+= snd-soc-
 obj-$(CONFIG_SND_SOC_WM9713)	+= snd-soc-wm9713.o
 obj-$(CONFIG_SND_SOC_WM_ADSP)	+= snd-soc-wm-adsp.o
 obj-$(CONFIG_SND_SOC_WM_HUBS)	+= snd-soc-wm-hubs.o
+obj-$(CONFIG_SND_SOC_MXS_BUILTIN_CODEC)	+= snd-soc-mxs-builtin-codec.o
 
 # Amp
 obj-$(CONFIG_SND_SOC_MAX9877)	+= snd-soc-max9877.o
--- /dev/null
+++ b/sound/soc/codecs/mxs-builtin-codec.c
@@ -0,0 +1,1128 @@
+/*
+ * mxs-builtin-codec.c -- i.MX233 built-in codec ALSA Soc Audio driver
+ *
+ * Author: Michal Ulianko <michal.ulianko@gmail.com>
+ *
+ * Based on sound/soc/codecs/mxs-adc-codec.c for kernel 2.6.35
+ * by Vladislav Buzov <vbuzov@embeddedalley.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/clk.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "mxs-builtin-codec.h"
+
+#ifndef BF
+#define BF(value, field) (((value) << BP_##field) & BM_##field)
+#endif
+
+/* TODO Delete this and use BM_RTC_PERSISTENT0_RELEASE_GND from header file
+ * if it works. */
+#define BP_RTC_PERSISTENT0_SPARE_ANALOG	18
+#define BM_RTC_PERSISTENT0_SPARE_ANALOG	0xFFFC0000
+#define BM_RTC_PERSISTENT0_RELEASE_GND BF(0x2, RTC_PERSISTENT0_SPARE_ANALOG)
+
+/* TODO Use codec IO function soc snd write etc, instead of __writel __readl */
+
+struct mxs_adc_priv {
+	void __iomem *ain_base;
+	void __iomem *aout_base;
+	void __iomem *rtc_base;
+	struct clk *clk;
+};
+
+static unsigned int mxs_regmap[] = {
+	HW_AUDIOOUT_CTRL,
+	HW_AUDIOOUT_STAT,
+	HW_AUDIOOUT_DACSRR,
+	HW_AUDIOOUT_DACVOLUME,
+	HW_AUDIOOUT_DACDEBUG,
+	HW_AUDIOOUT_HPVOL,
+	HW_AUDIOOUT_PWRDN,
+	HW_AUDIOOUT_REFCTRL,
+	HW_AUDIOOUT_ANACTRL,
+	HW_AUDIOOUT_TEST,
+	HW_AUDIOOUT_BISTCTRL,
+	HW_AUDIOOUT_BISTSTAT0,
+	HW_AUDIOOUT_BISTSTAT1,
+	HW_AUDIOOUT_ANACLKCTRL,
+	HW_AUDIOOUT_DATA,
+	HW_AUDIOOUT_SPEAKERCTRL,
+	HW_AUDIOOUT_VERSION,
+	HW_AUDIOIN_CTRL,
+	HW_AUDIOIN_STAT,
+	HW_AUDIOIN_ADCSRR,
+	HW_AUDIOIN_ADCVOLUME,
+	HW_AUDIOIN_ADCDEBUG,
+	HW_AUDIOIN_ADCVOL,
+	HW_AUDIOIN_MICLINE,
+	HW_AUDIOIN_ANACLKCTRL,
+	HW_AUDIOIN_DATA,
+};
+
+static void __iomem *mxs_getreg(struct mxs_adc_priv *mxs_adc, int i)
+{
+	if (i <= 16)
+		return mxs_adc->aout_base + mxs_regmap[i];
+	else if (i < ADC_REGNUM)
+		return mxs_adc->ain_base + mxs_regmap[i];
+	else
+		return NULL;
+}
+
+static u8 dac_volumn_control_word[] = {
+	0x37, 0x5e, 0x7e, 0x8e,
+	0x9e, 0xae, 0xb6, 0xbe,
+	0xc6, 0xce, 0xd6, 0xde,
+	0xe6, 0xee, 0xf6, 0xfe,
+};
+
+struct dac_srr {
+	u32 rate;
+	u32 basemult;
+	u32 src_hold;
+	u32 src_int;
+	u32 src_frac;
+};
+
+static struct dac_srr srr_values[] = {
+	{192000, 0x4, 0x0, 0x0F, 0x13FF},
+	{176400, 0x4, 0x0, 0x11, 0x0037},
+	{128000, 0x4, 0x0, 0x17, 0x0E00},
+	{96000, 0x2, 0x0, 0x0F, 0x13FF},
+	{88200, 0x2, 0x0, 0x11, 0x0037},
+	{64000, 0x2, 0x0, 0x17, 0x0E00},
+	{48000, 0x1, 0x0, 0x0F, 0x13FF},
+	{44100, 0x1, 0x0, 0x11, 0x0037},
+	{32000, 0x1, 0x0, 0x17, 0x0E00},
+	{24000, 0x1, 0x1, 0x0F, 0x13FF},
+	{22050, 0x1, 0x1, 0x11, 0x0037},
+	{16000, 0x1, 0x1, 0x17, 0x0E00},
+	{12000, 0x1, 0x3, 0x0F, 0x13FF},
+	{11025, 0x1, 0x3, 0x11, 0x0037},
+	{8000, 0x1, 0x3, 0x17, 0x0E00}
+};
+
+static inline int get_srr_values(int rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(srr_values); i++)
+		if (srr_values[i].rate == rate)
+			return i;
+
+	return -1;
+}
+
+/* SoC IO functions */
+static void mxs_codec_write_cache(struct snd_soc_codec *codec, unsigned int reg, unsigned int value)
+{
+	u16 *cache = codec->reg_cache;
+	if (reg < ADC_REGNUM)
+		cache[reg] = value;
+}
+
+static int mxs_codec_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value)
+{
+	struct mxs_adc_priv *mxs_adc = snd_soc_codec_get_drvdata(codec);
+	unsigned int reg_val;
+	unsigned int mask = 0xffff;
+
+	if (reg >= ADC_REGNUM)
+		return -EIO;
+
+	mxs_codec_write_cache(codec, reg, value);
+
+	if (reg & 0x1) {
+		mask <<= 16;
+		value <<= 16;
+	}
+
+	reg_val = __raw_readl(mxs_getreg(mxs_adc, reg >> 1));
+	reg_val = (reg_val & ~mask) | value;
+	__raw_writel(reg_val, mxs_getreg(mxs_adc, reg >> 1));
+
+	return 0;
+}
+
+static unsigned int mxs_codec_read(struct snd_soc_codec *codec, unsigned int reg)
+{
+	struct mxs_adc_priv *mxs_adc = snd_soc_codec_get_drvdata(codec);
+	unsigned int reg_val;
+
+	if (reg >= ADC_REGNUM)
+		return -1;
+
+	reg_val = __raw_readl(mxs_getreg(mxs_adc, reg >> 1));
+	if (reg & 1)
+		reg_val >>= 16;
+
+	return reg_val & 0xffff;
+}
+
+// static unsigned int mxs_codec_read_cache(struct snd_soc_codec *codec, unsigned int reg)
+// {
+// 	u16 *cache = codec->reg_cache;
+// 	if (reg >= ADC_REGNUM)
+// 		return -EINVAL;
+// 	return cache[reg];
+// }
+
+static void mxs_codec_sync_reg_cache(struct snd_soc_codec *codec)
+{
+	int reg;
+	for (reg = 0; reg < ADC_REGNUM; reg += 1)
+		mxs_codec_write_cache(codec, reg,
+					   mxs_codec_read(codec, reg));
+}
+
+// static int mxs_codec_restore_reg(struct snd_soc_codec *codec, unsigned int reg)
+// {
+// 	unsigned int cached_val, hw_val;
+//
+// 	cached_val = mxs_codec_read_cache(codec, reg);
+// 	hw_val = mxs_codec_read(codec, reg);
+//
+// 	if (hw_val != cached_val)
+// 		return mxs_codec_write(codec, reg, cached_val);
+//
+// 	return 0;
+// }
+/* END SoC IO functions */
+
+/* Codec routines */
+#define VAG_BASE_VALUE  ((1400/2 - 625)/25)
+
+static void mxs_codec_dac_set_vag(struct mxs_adc_priv *mxs_adc)
+{
+	u32 refctrl_val = __raw_readl(mxs_adc->aout_base + HW_AUDIOOUT_REFCTRL);
+
+	refctrl_val &= ~(BM_AUDIOOUT_REFCTRL_VAG_VAL);
+	refctrl_val &= ~(BM_AUDIOOUT_REFCTRL_VBG_ADJ);
+	refctrl_val |= BF(VAG_BASE_VALUE, AUDIOOUT_REFCTRL_VAG_VAL) |
+		BM_AUDIOOUT_REFCTRL_ADJ_VAG |
+		BF(0xF, AUDIOOUT_REFCTRL_ADC_REFVAL) |
+		BM_AUDIOOUT_REFCTRL_ADJ_ADC |
+		BF(0x3, AUDIOOUT_REFCTRL_VBG_ADJ) | BM_AUDIOOUT_REFCTRL_RAISE_REF;
+
+	__raw_writel(refctrl_val, mxs_adc->aout_base + HW_AUDIOOUT_REFCTRL);
+}
+
+static bool mxs_codec_dac_is_capless(struct mxs_adc_priv *mxs_adc)
+{
+	if ((__raw_readl(mxs_adc->aout_base + HW_AUDIOOUT_PWRDN)
+		& BM_AUDIOOUT_PWRDN_CAPLESS) == 0)
+		return false;
+	else
+		return true;
+}
+
+static void mxs_codec_dac_arm_short_cm(struct mxs_adc_priv *mxs_adc, bool bShort)
+{
+	__raw_writel(BF(3, AUDIOOUT_ANACTRL_SHORTMODE_CM),
+		      mxs_adc->aout_base + HW_AUDIOOUT_ANACTRL_CLR);
+	__raw_writel(BM_AUDIOOUT_ANACTRL_SHORT_CM_STS,
+		      mxs_adc->aout_base + HW_AUDIOOUT_ANACTRL_CLR);
+	if (bShort)
+		__raw_writel(BF(1, AUDIOOUT_ANACTRL_SHORTMODE_CM),
+		      mxs_adc->aout_base + HW_AUDIOOUT_ANACTRL_SET);
+}
+
+static void mxs_codec_dac_arm_short_lr(struct mxs_adc_priv *mxs_adc, bool bShort)
+{
+	__raw_writel(BF(3, AUDIOOUT_ANACTRL_SHORTMODE_LR),
+		      mxs_adc->aout_base + HW_AUDIOOUT_ANACTRL_CLR);
+	__raw_writel(BM_AUDIOOUT_ANACTRL_SHORT_LR_STS,
+		      mxs_adc->aout_base + HW_AUDIOOUT_ANACTRL_CLR);
+	if (bShort)
+		__raw_writel(BF(1, AUDIOOUT_ANACTRL_SHORTMODE_LR),
+		      mxs_adc->aout_base + HW_AUDIOOUT_ANACTRL_SET);
+}
+
+static void mxs_codec_dac_set_short_trip_level(struct mxs_adc_priv *mxs_adc, u8 u8level)
+{
+	__raw_writel(__raw_readl(mxs_adc->aout_base +
+		HW_AUDIOOUT_ANACTRL)
+		& (~BM_AUDIOOUT_ANACTRL_SHORT_LVLADJL)
+		& (~BM_AUDIOOUT_ANACTRL_SHORT_LVLADJR)
+		| BF(u8level, AUDIOOUT_ANACTRL_SHORT_LVLADJL)
+		| BF(u8level, AUDIOOUT_ANACTRL_SHORT_LVLADJR),
+		mxs_adc->aout_base + HW_AUDIOOUT_ANACTRL);
+}
+
+static void mxs_codec_dac_arm_short(struct mxs_adc_priv *mxs_adc, bool bLatchCM, bool bLatchLR)
+{
+	if (bLatchCM) {
+		if (mxs_codec_dac_is_capless(mxs_adc))
+			mxs_codec_dac_arm_short_cm(mxs_adc, true);
+	} else
+		mxs_codec_dac_arm_short_cm(mxs_adc, false);
+
+	if (bLatchLR)
+		mxs_codec_dac_arm_short_lr(mxs_adc, true);
+	else
+		mxs_codec_dac_arm_short_lr(mxs_adc, false);
+}
+
+static void
+mxs_codec_dac_power_on(struct mxs_adc_priv *mxs_adc)
+{
+	/* Ungate DAC clocks */
+	__raw_writel(BM_AUDIOOUT_CTRL_CLKGATE,
+			mxs_adc->aout_base + HW_AUDIOOUT_CTRL_CLR);
+	__raw_writel(BM_AUDIOOUT_ANACLKCTRL_CLKGATE,
+			mxs_adc->aout_base + HW_AUDIOOUT_ANACLKCTRL_CLR);
+
+	/* 16 bit word length */
+	__raw_writel(BM_AUDIOOUT_CTRL_WORD_LENGTH,
+		      mxs_adc->aout_base + HW_AUDIOOUT_CTRL_SET);
+
+	/* Arm headphone LR short protect */
+	mxs_codec_dac_set_short_trip_level(mxs_adc, 0);
+	mxs_codec_dac_arm_short(mxs_adc, false, true);
+
+	/* Update DAC volume over zero crossings */
+	__raw_writel(BM_AUDIOOUT_DACVOLUME_EN_ZCD,
+		      mxs_adc->aout_base + HW_AUDIOOUT_DACVOLUME_SET);
+	/* Mute DAC */
+	__raw_writel(BM_AUDIOOUT_DACVOLUME_MUTE_LEFT |
+		      BM_AUDIOOUT_DACVOLUME_MUTE_RIGHT,
+		      mxs_adc->aout_base + HW_AUDIOOUT_DACVOLUME_SET);
+
+	/* Update HP volume over zero crossings */
+	__raw_writel(BM_AUDIOOUT_HPVOL_EN_MSTR_ZCD,
+		      mxs_adc->aout_base + HW_AUDIOOUT_HPVOL_SET);
+
+	__raw_writel(BM_AUDIOOUT_ANACTRL_HP_CLASSAB,
+		      mxs_adc->aout_base + HW_AUDIOOUT_ANACTRL_SET);
+
+	/* Mute HP output */
+	__raw_writel(BM_AUDIOOUT_HPVOL_MUTE,
+		      mxs_adc->aout_base + HW_AUDIOOUT_HPVOL_SET);
+	/* Mute speaker amp */
+	__raw_writel(BM_AUDIOOUT_SPEAKERCTRL_MUTE,
+		      mxs_adc->aout_base + HW_AUDIOOUT_SPEAKERCTRL_SET);
+	/* Enable the audioout */
+	 __raw_writel(BM_AUDIOOUT_CTRL_RUN,
+			mxs_adc->aout_base + HW_AUDIOOUT_CTRL_SET);
+}
+
+static void
+mxs_codec_dac_power_down(struct mxs_adc_priv *mxs_adc)
+{
+	/* Disable the audioout */
+	 __raw_writel(BM_AUDIOOUT_CTRL_RUN,
+		mxs_adc->aout_base + HW_AUDIOOUT_CTRL_CLR);
+	/* Disable class AB */
+	__raw_writel(BM_AUDIOOUT_ANACTRL_HP_CLASSAB,
+			mxs_adc->aout_base + HW_AUDIOOUT_ANACTRL_CLR);
+
+	/* Set hold to ground */
+	__raw_writel(BM_AUDIOOUT_ANACTRL_HP_HOLD_GND,
+		      mxs_adc->aout_base + HW_AUDIOOUT_ANACTRL_SET);
+
+	/* Mute HP output */
+	__raw_writel(BM_AUDIOOUT_HPVOL_MUTE,
+		      mxs_adc->aout_base + HW_AUDIOOUT_HPVOL_SET);
+	/* Power down HP output */
+	__raw_writel(BM_AUDIOOUT_PWRDN_HEADPHONE,
+		      mxs_adc->aout_base + HW_AUDIOOUT_PWRDN_SET);
+
+	/* Mute speaker amp */
+	__raw_writel(BM_AUDIOOUT_SPEAKERCTRL_MUTE,
+		      mxs_adc->aout_base + HW_AUDIOOUT_SPEAKERCTRL_SET);
+	/* Power down speaker amp */
+	__raw_writel(BM_AUDIOOUT_PWRDN_SPEAKER,
+		      mxs_adc->aout_base + HW_AUDIOOUT_PWRDN_SET);
+
+	/* Mute DAC */
+	__raw_writel(BM_AUDIOOUT_DACVOLUME_MUTE_LEFT |
+		      BM_AUDIOOUT_DACVOLUME_MUTE_RIGHT,
+		      mxs_adc->aout_base + HW_AUDIOOUT_DACVOLUME_SET);
+	/* Power down DAC */
+	__raw_writel(BM_AUDIOOUT_PWRDN_DAC,
+		      mxs_adc->aout_base + HW_AUDIOOUT_PWRDN_SET);
+
+	/* Gate DAC clocks */
+	__raw_writel(BM_AUDIOOUT_ANACLKCTRL_CLKGATE,
+		      mxs_adc->aout_base + HW_AUDIOOUT_ANACLKCTRL_SET);
+	__raw_writel(BM_AUDIOOUT_CTRL_CLKGATE,
+		      mxs_adc->aout_base + HW_AUDIOOUT_CTRL_SET);
+}
+
+static void
+mxs_codec_adc_power_on(struct mxs_adc_priv *mxs_adc)
+{
+	u32 reg;
+
+	/* Ungate ADC clocks */
+	__raw_writel(BM_AUDIOIN_CTRL_CLKGATE,
+			mxs_adc->ain_base + HW_AUDIOIN_CTRL_CLR);
+	__raw_writel(BM_AUDIOIN_ANACLKCTRL_CLKGATE,
+			mxs_adc->ain_base + HW_AUDIOIN_ANACLKCTRL_CLR);
+
+	/* 16 bit word length */
+	__raw_writel(BM_AUDIOIN_CTRL_WORD_LENGTH,
+		      mxs_adc->ain_base + HW_AUDIOIN_CTRL_SET);
+
+	/* Unmute ADC channels */
+	__raw_writel(BM_AUDIOIN_ADCVOL_MUTE,
+			mxs_adc->ain_base + HW_AUDIOIN_ADCVOL_CLR);
+
+	/*
+	 * The MUTE_LEFT and MUTE_RIGHT fields need to be cleared.
+	 * They aren't presented in the datasheet, so this is hardcode.
+	 */
+	__raw_writel(0x01000100, mxs_adc->ain_base + HW_AUDIOIN_ADCVOLUME_CLR);
+
+	/* Set the Input channel gain 3dB */
+	__raw_writel(BM_AUDIOIN_ADCVOL_GAIN_LEFT,
+			mxs_adc->ain_base + HW_AUDIOIN_ADCVOL_CLR);
+	__raw_writel(BM_AUDIOIN_ADCVOL_GAIN_RIGHT,
+			mxs_adc->ain_base + HW_AUDIOIN_ADCVOL_CLR);
+	__raw_writel(BF(2, AUDIOIN_ADCVOL_GAIN_LEFT),
+		      mxs_adc->ain_base + HW_AUDIOIN_ADCVOL_SET);
+	__raw_writel(BF(2, AUDIOIN_ADCVOL_GAIN_RIGHT),
+		      mxs_adc->ain_base + HW_AUDIOIN_ADCVOL_SET);
+
+	/* Select default input - Microphone */
+	__raw_writel(BM_AUDIOIN_ADCVOL_SELECT_LEFT,
+			mxs_adc->ain_base + HW_AUDIOIN_ADCVOL_CLR);
+	__raw_writel(BM_AUDIOIN_ADCVOL_SELECT_RIGHT,
+			mxs_adc->ain_base + HW_AUDIOIN_ADCVOL_CLR);
+	__raw_writel(BF
+		      (BV_AUDIOIN_ADCVOL_SELECT__MIC,
+		       AUDIOIN_ADCVOL_SELECT_LEFT),
+		      mxs_adc->ain_base + HW_AUDIOIN_ADCVOL_SET);
+	__raw_writel(BF
+		      (BV_AUDIOIN_ADCVOL_SELECT__MIC,
+		       AUDIOIN_ADCVOL_SELECT_RIGHT),
+		      mxs_adc->ain_base + HW_AUDIOIN_ADCVOL_SET);
+
+	/* Supply bias voltage to microphone */
+	__raw_writel(BF(1, AUDIOIN_MICLINE_MIC_RESISTOR),
+		      mxs_adc->ain_base + HW_AUDIOIN_MICLINE_SET);
+	__raw_writel(BM_AUDIOIN_MICLINE_MIC_SELECT,
+		      mxs_adc->ain_base + HW_AUDIOIN_MICLINE_SET);
+	__raw_writel(BF(1, AUDIOIN_MICLINE_MIC_GAIN),
+		      mxs_adc->ain_base + HW_AUDIOIN_MICLINE_SET);
+	__raw_writel(BF(7, AUDIOIN_MICLINE_MIC_BIAS),
+		      mxs_adc->ain_base + HW_AUDIOIN_MICLINE_SET);
+
+	/* Set max ADC volume */
+	reg = __raw_readl(mxs_adc->ain_base + HW_AUDIOIN_ADCVOLUME);
+	reg &= ~BM_AUDIOIN_ADCVOLUME_VOLUME_LEFT;
+	reg &= ~BM_AUDIOIN_ADCVOLUME_VOLUME_RIGHT;
+	reg |= BF(ADC_VOLUME_MAX, AUDIOIN_ADCVOLUME_VOLUME_LEFT);
+	reg |= BF(ADC_VOLUME_MAX, AUDIOIN_ADCVOLUME_VOLUME_RIGHT);
+	__raw_writel(reg, mxs_adc->ain_base + HW_AUDIOIN_ADCVOLUME);
+}
+
+static void
+mxs_codec_adc_power_down(struct mxs_adc_priv *mxs_adc)
+{
+	/* Mute ADC channels */
+	__raw_writel(BM_AUDIOIN_ADCVOL_MUTE,
+		      mxs_adc->ain_base + HW_AUDIOIN_ADCVOL_SET);
+
+	/* Power Down ADC */
+	__raw_writel(BM_AUDIOOUT_PWRDN_ADC | BM_AUDIOOUT_PWRDN_RIGHT_ADC,
+		      mxs_adc->aout_base + HW_AUDIOOUT_PWRDN_SET);
+
+	/* Gate ADC clocks */
+	__raw_writel(BM_AUDIOIN_CTRL_CLKGATE,
+		      mxs_adc->ain_base + HW_AUDIOIN_CTRL_SET);
+	__raw_writel(BM_AUDIOIN_ANACLKCTRL_CLKGATE,
+		      mxs_adc->ain_base + HW_AUDIOIN_ANACLKCTRL_SET);
+
+	/* Disable bias voltage to microphone */
+	__raw_writel(BF(0, AUDIOIN_MICLINE_MIC_RESISTOR),
+		      mxs_adc->ain_base + HW_AUDIOIN_MICLINE_SET);
+}
+
+static void mxs_codec_dac_enable(struct mxs_adc_priv *mxs_adc)
+{
+	/* Move DAC codec out of reset */
+	__raw_writel(BM_AUDIOOUT_CTRL_SFTRST,
+		mxs_adc->aout_base + HW_AUDIOOUT_CTRL_CLR);
+
+	/* Reduce analog power */
+	__raw_writel(BM_AUDIOOUT_TEST_HP_I1_ADJ,
+			mxs_adc->aout_base + HW_AUDIOOUT_TEST_CLR);
+	__raw_writel(BF(0x1, AUDIOOUT_TEST_HP_I1_ADJ),
+			mxs_adc->aout_base + HW_AUDIOOUT_TEST_SET);
+	__raw_writel(BM_AUDIOOUT_REFCTRL_LOW_PWR,
+			mxs_adc->aout_base + HW_AUDIOOUT_REFCTRL_SET);
+	__raw_writel(BM_AUDIOOUT_REFCTRL_XTAL_BGR_BIAS,
+			mxs_adc->aout_base + HW_AUDIOOUT_REFCTRL_SET);
+	__raw_writel(BM_AUDIOOUT_REFCTRL_BIAS_CTRL,
+			mxs_adc->aout_base + HW_AUDIOOUT_REFCTRL_CLR);
+	__raw_writel(BF(0x1, AUDIOOUT_REFCTRL_BIAS_CTRL),
+			mxs_adc->aout_base + HW_AUDIOOUT_REFCTRL_CLR);
+
+	/* Set Vag value */
+	mxs_codec_dac_set_vag(mxs_adc);
+
+	/* Power on DAC codec */
+	mxs_codec_dac_power_on(mxs_adc);
+}
+
+static void mxs_codec_dac_disable(struct mxs_adc_priv *mxs_adc)
+{
+	mxs_codec_dac_power_down(mxs_adc);
+}
+
+static void mxs_codec_adc_enable(struct mxs_adc_priv *mxs_adc)
+{
+	/* Move ADC codec out of reset */
+	__raw_writel(BM_AUDIOIN_CTRL_SFTRST,
+			mxs_adc->ain_base + HW_AUDIOIN_CTRL_CLR);
+
+	/* Power on ADC codec */
+	mxs_codec_adc_power_on(mxs_adc);
+}
+
+static void mxs_codec_adc_disable(struct mxs_adc_priv *mxs_adc)
+{
+	mxs_codec_adc_power_down(mxs_adc);
+}
+
+static void mxs_codec_startup(struct snd_soc_codec *codec)
+{
+	struct mxs_adc_priv *mxs_adc = snd_soc_codec_get_drvdata(codec);
+
+	/* Soft reset DAC block */
+	__raw_writel(BM_AUDIOOUT_CTRL_SFTRST,
+		      mxs_adc->aout_base + HW_AUDIOOUT_CTRL_SET);
+	while (!(__raw_readl(mxs_adc->aout_base + HW_AUDIOOUT_CTRL)
+		& BM_AUDIOOUT_CTRL_CLKGATE)){
+	}
+
+	/* Soft reset ADC block */
+	__raw_writel(BM_AUDIOIN_CTRL_SFTRST,
+		      mxs_adc->ain_base + HW_AUDIOIN_CTRL_SET);
+	while (!(__raw_readl(mxs_adc->ain_base + HW_AUDIOIN_CTRL)
+		& BM_AUDIOIN_CTRL_CLKGATE)){
+	}
+
+	mxs_codec_dac_enable(mxs_adc);
+	mxs_codec_adc_enable(mxs_adc);
+
+	/* Sync regs and cache */
+	mxs_codec_sync_reg_cache(codec);
+}
+
+static void mxs_codec_stop(struct snd_soc_codec *codec)
+{
+	struct mxs_adc_priv *mxs_adc = snd_soc_codec_get_drvdata(codec);
+
+	mxs_codec_dac_disable(mxs_adc);
+	mxs_codec_adc_disable(mxs_adc);
+}
+/* END Codec routines */
+
+/* kcontrol */
+static int dac_info_volsw(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 0xf;
+	return 0;
+}
+
+static int dac_get_volsw(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct mxs_adc_priv *mxs_adc = snd_soc_codec_get_drvdata(codec);
+	int reg, l, r;
+	int i;
+
+	reg = __raw_readl(mxs_adc->aout_base + HW_AUDIOOUT_DACVOLUME);
+
+	l = (reg & BM_AUDIOOUT_DACVOLUME_VOLUME_LEFT) >>
+	    BP_AUDIOOUT_DACVOLUME_VOLUME_LEFT;
+	r = (reg & BM_AUDIOOUT_DACVOLUME_VOLUME_RIGHT) >>
+	    BP_AUDIOOUT_DACVOLUME_VOLUME_RIGHT;
+	/*Left channel */
+	i = 0;
+	while (i < 16) {
+		if (l == dac_volumn_control_word[i]) {
+			ucontrol->value.integer.value[0] = i;
+			break;
+		}
+		i++;
+	}
+	if (i == 16)
+		ucontrol->value.integer.value[0] = i;
+	/*Right channel */
+	i = 0;
+	while (i < 16) {
+		if (r == dac_volumn_control_word[i]) {
+			ucontrol->value.integer.value[1] = i;
+			break;
+		}
+		i++;
+	}
+	if (i == 16)
+		ucontrol->value.integer.value[1] = i;
+
+	return 0;
+}
+
+static int dac_put_volsw(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct mxs_adc_priv *mxs_adc = snd_soc_codec_get_drvdata(codec);
+	int reg, l, r;
+	int i;
+
+	i = ucontrol->value.integer.value[0];
+	l = dac_volumn_control_word[i];
+	/*Get dac volume for left channel */
+	reg = BF(l, AUDIOOUT_DACVOLUME_VOLUME_LEFT);
+
+	i = ucontrol->value.integer.value[1];
+	r = dac_volumn_control_word[i];
+	/*Get dac volume for right channel */
+	reg = reg | BF(r, AUDIOOUT_DACVOLUME_VOLUME_RIGHT);
+
+	/*Clear left/right dac volume */
+	__raw_writel(BM_AUDIOOUT_DACVOLUME_VOLUME_LEFT |
+			BM_AUDIOOUT_DACVOLUME_VOLUME_RIGHT,
+			mxs_adc->aout_base + HW_AUDIOOUT_DACVOLUME_CLR);
+	__raw_writel(reg, mxs_adc->aout_base + HW_AUDIOOUT_DACVOLUME_SET);
+
+	return 0;
+}
+
+static const char *mxs_codec_adc_input_sel[] = {
+	 "Mic", "Line In 1", "Head Phone", "Line In 2" };
+
+static const char *mxs_codec_hp_output_sel[] = { "DAC Out", "Line In 1" };
+
+static const char *mxs_codec_adc_3d_sel[] = {
+	"Off", "Low", "Medium", "High" };
+
+static const struct soc_enum mxs_codec_enum[] = {
+	SOC_ENUM_SINGLE(ADC_ADCVOL_L, 12, 4, mxs_codec_adc_input_sel),
+	SOC_ENUM_SINGLE(ADC_ADCVOL_L, 4, 4, mxs_codec_adc_input_sel),
+	SOC_ENUM_SINGLE(DAC_HPVOL_H, 0, 2, mxs_codec_hp_output_sel),
+	SOC_ENUM_SINGLE(DAC_CTRL_L, 8, 4, mxs_codec_adc_3d_sel),
+};
+
+static const struct snd_kcontrol_new mxs_snd_controls[] = {
+	/* Playback Volume */
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "DAC Playback Volume",
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+		SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+		.info = dac_info_volsw,
+		.get = dac_get_volsw,
+		.put = dac_put_volsw,
+	 },
+
+	SOC_DOUBLE_R("DAC Playback Switch",
+		     DAC_VOLUME_H, DAC_VOLUME_L, 8, 0x01, 1),
+	SOC_DOUBLE("HP Playback Volume", DAC_HPVOL_L, 8, 0, 0x7F, 1),
+
+	/* Capture Volume */
+	SOC_DOUBLE_R("ADC Capture Volume",
+		     ADC_VOLUME_H, ADC_VOLUME_L, 0, 0xFF, 0),
+	SOC_DOUBLE("ADC PGA Capture Volume", ADC_ADCVOL_L, 8, 0, 0x0F, 0),
+	SOC_SINGLE("ADC PGA Capture Switch", ADC_ADCVOL_H, 8, 0x1, 1),
+	SOC_SINGLE("Mic PGA Capture Volume", ADC_MICLINE_L, 0, 0x03, 0),
+
+	/* Virtual 3D effect */
+	SOC_ENUM("3D effect", mxs_codec_enum[3]),
+};
+/* END kcontrol */
+
+/* DAPM */
+static int pga_event(struct snd_soc_dapm_widget *w,
+			struct snd_kcontrol *kcontrol, int event)
+{
+	struct mxs_adc_priv *mxs_adc = snd_soc_codec_get_drvdata(w->codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Prepare powering up HP and SPEAKER output */
+		__raw_writel(BM_AUDIOOUT_ANACTRL_HP_HOLD_GND,
+			mxs_adc->aout_base + HW_AUDIOOUT_ANACTRL_SET);
+		__raw_writel(BM_RTC_PERSISTENT0_RELEASE_GND,
+			mxs_adc->rtc_base + HW_RTC_PERSISTENT0_SET);
+		msleep(100);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		__raw_writel(BM_AUDIOOUT_ANACTRL_HP_HOLD_GND,
+			mxs_adc->aout_base + HW_AUDIOOUT_ANACTRL_CLR);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		__raw_writel(BM_RTC_PERSISTENT0_RELEASE_GND,
+			mxs_adc->rtc_base + HW_RTC_PERSISTENT0_CLR);
+		break;
+	}
+	return 0;
+}
+
+static int adc_event(struct snd_soc_dapm_widget *w,
+			struct snd_kcontrol *kcontrol, int event)
+{
+	struct mxs_adc_priv *mxs_adc = snd_soc_codec_get_drvdata(w->codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		__raw_writel(BM_RTC_PERSISTENT0_RELEASE_GND,
+			mxs_adc->rtc_base + HW_RTC_PERSISTENT0_SET);
+		msleep(100);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		__raw_writel(BM_RTC_PERSISTENT0_RELEASE_GND,
+			mxs_adc->rtc_base + HW_RTC_PERSISTENT0_CLR);
+		break;
+	}
+	return 0;
+}
+
+/* Left ADC Mux */
+static const struct snd_kcontrol_new mxs_left_adc_controls =
+SOC_DAPM_ENUM("Route", mxs_codec_enum[0]);
+
+/* Right ADC Mux */
+static const struct snd_kcontrol_new mxs_right_adc_controls =
+SOC_DAPM_ENUM("Route", mxs_codec_enum[1]);
+
+/* Head Phone Mux */
+static const struct snd_kcontrol_new mxs_hp_controls =
+SOC_DAPM_ENUM("Route", mxs_codec_enum[2]);
+
+static const struct snd_soc_dapm_widget mxs_dapm_widgets[] = {
+	SND_SOC_DAPM_ADC_E("ADC", "Capture", DAC_PWRDN_L, 8, 1, adc_event,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_DAC("DAC", "Playback", DAC_PWRDN_L, 12, 1),
+
+	SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0,
+			 &mxs_left_adc_controls),
+	SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0,
+			 &mxs_right_adc_controls),
+	SND_SOC_DAPM_MUX("HP Mux", SND_SOC_NOPM, 0, 0,
+			 &mxs_hp_controls),
+	SND_SOC_DAPM_PGA_E("HP AMP", DAC_PWRDN_L, 0, 1, NULL, 0, pga_event,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA("SPEAKER AMP", DAC_PWRDN_H, 8, 1, NULL, 0),
+	SND_SOC_DAPM_INPUT("LINE1L"),
+	SND_SOC_DAPM_INPUT("LINE1R"),
+	SND_SOC_DAPM_INPUT("LINE2L"),
+	SND_SOC_DAPM_INPUT("LINE2R"),
+	SND_SOC_DAPM_INPUT("MIC"),
+
+	SND_SOC_DAPM_OUTPUT("SPEAKER"),
+	SND_SOC_DAPM_OUTPUT("HPL"),
+	SND_SOC_DAPM_OUTPUT("HPR"),
+};
+
+/* routes for sgtl5000 */
+static const struct snd_soc_dapm_route mxs_dapm_routes[] = {
+	/* Left ADC Mux */
+	{"Left ADC Mux", "Mic", "MIC"},
+	{"Left ADC Mux", "Line In 1", "LINE1L"},
+	{"Left ADC Mux", "Line In 2", "LINE2L"},
+	{"Left ADC Mux", "Head Phone", "HPL"},
+
+	/* Right ADC Mux */
+	{"Right ADC Mux", "Mic", "MIC"},
+	{"Right ADC Mux", "Line In 1", "LINE1R"},
+	{"Right ADC Mux", "Line In 2", "LINE2R"},
+	{"Right ADC Mux", "Head Phone", "HPR"},
+
+	/* ADC */
+	{"ADC", NULL, "Left ADC Mux"},
+	{"ADC", NULL, "Right ADC Mux"},
+
+	/* HP Mux */
+	{"HP Mux", "DAC Out", "DAC"},
+	{"HP Mux", "Line In 1", "LINE1L"},
+	{"HP Mux", "Line In 1", "LINE1R"},
+
+	/* HP amp */
+	{"HP AMP", NULL, "HP Mux"},
+	/* HP output */
+	{"HPR", NULL, "HP AMP"},
+	{"HPL", NULL, "HP AMP"},
+
+	/* Speaker amp */
+	{"SPEAKER AMP", NULL, "DAC"},
+	{"SPEAKER", NULL, "SPEAKER AMP"},
+};
+/* END DAPM */
+
+static int mxs_set_bias_level(struct snd_soc_codec *codec,
+				   enum snd_soc_bias_level level)
+{
+	struct mxs_adc_priv *mxs_adc = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("dapm level %d\n", level);
+	switch (level) {
+	case SND_SOC_BIAS_ON:		/* full On */
+		if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
+			break;
+		break;
+
+	case SND_SOC_BIAS_PREPARE:	/* partial On */
+		if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE)
+			break;
+		/* Set Capless mode */
+		__raw_writel(BM_AUDIOOUT_PWRDN_CAPLESS,
+		      mxs_adc->aout_base + HW_AUDIOOUT_PWRDN_CLR);
+		break;
+
+	case SND_SOC_BIAS_STANDBY:	/* Off, with power */
+		if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
+			break;
+		/* Unset Capless mode */
+		__raw_writel(BM_AUDIOOUT_PWRDN_CAPLESS,
+			mxs_adc->aout_base + HW_AUDIOOUT_PWRDN_SET);
+		break;
+
+	case SND_SOC_BIAS_OFF:	/* Off, without power */
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+			break;
+		/* Unset Capless mode */
+		__raw_writel(BM_AUDIOOUT_PWRDN_CAPLESS,
+			mxs_adc->aout_base + HW_AUDIOOUT_PWRDN_SET);
+		break;
+	}
+
+	codec->dapm.bias_level = level;
+	return 0;
+}
+
+/* MXS-ADC Codec DAI driver */
+static int mxs_pcm_hw_params(struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *params,
+				  struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct mxs_adc_priv *mxs_adc = snd_soc_codec_get_drvdata(codec);
+	int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0;
+	int i;
+	u32 srr_value = 0;
+	u32 src_hold = 0;
+
+	i = get_srr_values(params_rate(params));
+	if (i < 0)
+		dev_warn(codec->dev, "codec doesn't support rate %d\n",
+		       params_rate(params));
+	else {
+		src_hold = srr_values[i].src_hold;
+
+		srr_value =
+		    BF(srr_values[i].basemult, AUDIOOUT_DACSRR_BASEMULT) |
+		    BF(srr_values[i].src_int, AUDIOOUT_DACSRR_SRC_INT) |
+		    BF(srr_values[i].src_frac, AUDIOOUT_DACSRR_SRC_FRAC) |
+		    BF(src_hold, AUDIOOUT_DACSRR_SRC_HOLD);
+
+		if (playback)
+			__raw_writel(srr_value,
+				     mxs_adc->aout_base + HW_AUDIOOUT_DACSRR);
+		else
+			__raw_writel(srr_value,
+				     mxs_adc->ain_base + HW_AUDIOIN_ADCSRR);
+	}
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		if (playback)
+			__raw_writel(BM_AUDIOOUT_CTRL_WORD_LENGTH,
+				mxs_adc->aout_base + HW_AUDIOOUT_CTRL_SET);
+		else
+			__raw_writel(BM_AUDIOIN_CTRL_WORD_LENGTH,
+				mxs_adc->ain_base + HW_AUDIOIN_CTRL_SET);
+
+		break;
+
+	case SNDRV_PCM_FORMAT_S32_LE:
+		if (playback)
+			__raw_writel(BM_AUDIOOUT_CTRL_WORD_LENGTH,
+				mxs_adc->aout_base + HW_AUDIOOUT_CTRL_CLR);
+		else
+			__raw_writel(BM_AUDIOIN_CTRL_WORD_LENGTH,
+				mxs_adc->ain_base + HW_AUDIOIN_CTRL_CLR);
+
+		break;
+
+	default:
+		dev_warn(codec->dev, "codec doesn't support format %d\n",
+		       params_format(params));
+
+	}
+
+	return 0;
+}
+
+/* mute the codec used by alsa core */
+static int mxs_codec_dig_mute(struct snd_soc_dai *codec_dai, int mute)
+{
+	struct mxs_adc_priv *mxs_adc = snd_soc_codec_get_drvdata(codec_dai->codec);
+	int l, r;
+	int ll, rr;
+	u32 reg, reg1, reg2;
+	u32 dac_mask = BM_AUDIOOUT_DACVOLUME_MUTE_LEFT |
+	    BM_AUDIOOUT_DACVOLUME_MUTE_RIGHT;
+
+	if (mute) {
+		reg = __raw_readl(mxs_adc->aout_base + \
+				HW_AUDIOOUT_DACVOLUME);
+
+		reg1 = reg & ~BM_AUDIOOUT_DACVOLUME_VOLUME_LEFT;
+		reg1 = reg1 & ~BM_AUDIOOUT_DACVOLUME_VOLUME_RIGHT;
+
+		l = (reg & BM_AUDIOOUT_DACVOLUME_VOLUME_LEFT) >>
+			BP_AUDIOOUT_DACVOLUME_VOLUME_LEFT;
+		r = (reg & BM_AUDIOOUT_DACVOLUME_VOLUME_RIGHT) >>
+			BP_AUDIOOUT_DACVOLUME_VOLUME_RIGHT;
+
+		/* fade out dac vol */
+		while ((l > DAC_VOLUME_MIN) || (r > DAC_VOLUME_MIN)) {
+			l -= 0x8;
+			r -= 0x8;
+			ll = l > DAC_VOLUME_MIN ? l : DAC_VOLUME_MIN;
+			rr = r > DAC_VOLUME_MIN ? r : DAC_VOLUME_MIN;
+			reg2 = reg1 | BF_AUDIOOUT_DACVOLUME_VOLUME_LEFT(ll)
+				| BF_AUDIOOUT_DACVOLUME_VOLUME_RIGHT(rr);
+			__raw_writel(reg2,
+				mxs_adc->aout_base + HW_AUDIOOUT_DACVOLUME);
+			msleep(1);
+		}
+
+		__raw_writel(dac_mask,
+			mxs_adc->aout_base + HW_AUDIOOUT_DACVOLUME_SET);
+		reg = reg | dac_mask;
+		__raw_writel(reg,
+			mxs_adc->aout_base + HW_AUDIOOUT_DACVOLUME);
+	} else
+		__raw_writel(dac_mask,
+			mxs_adc->aout_base + HW_AUDIOOUT_DACVOLUME_CLR);
+
+	return 0;
+}
+
+#define MXS_ADC_RATES	SNDRV_PCM_RATE_8000_192000
+#define MXS_ADC_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static const struct snd_soc_dai_ops mxs_codec_dai_ops = {
+	.hw_params = mxs_pcm_hw_params,
+	.digital_mute = mxs_codec_dig_mute,
+};
+
+static struct snd_soc_dai_driver mxs_codec_dai_driver = {
+	.name = "mxs-builtin-codec-dai",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = MXS_ADC_RATES,
+		.formats = MXS_ADC_FORMATS,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = MXS_ADC_RATES,
+		.formats = MXS_ADC_FORMATS,
+	},
+	.ops = &mxs_codec_dai_ops,
+};
+/* END MXS-ADC Codec DAI driver */
+
+/* MXS-ADC Codec driver */
+static int mxs_codec_driver_probe(struct snd_soc_codec *codec)
+{
+	int ret = 0;
+	/* We don't use snd_soc_codec_set_cache_io because we are using
+	 * our own IO functions: write, read. */
+
+	mxs_codec_startup(codec);
+
+	/* leading to standby state */
+	ret = mxs_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	if (ret)
+		goto err;
+
+	return 0;
+
+err:
+	mxs_codec_stop(codec);
+
+	return ret;
+}
+
+static int mxs_codec_driver_remove(struct snd_soc_codec *codec)
+{
+	mxs_codec_stop(codec);
+
+	return 0;
+}
+
+// static int mxs_codec_driver_suspend(struct snd_soc_codec *codec)
+// {
+// 	/* TODO Enable power management. */
+// 	return 0;
+// }
+
+// static int mxs_codec_driver_resume(struct snd_soc_codec *codec)
+// {
+// 	/* TODO Enable power management. */
+// 	return 0;
+// }
+
+static struct snd_soc_codec_driver mxs_codec_driver = {
+	.probe = mxs_codec_driver_probe,
+	.remove = mxs_codec_driver_remove,
+// 	.suspend = mxs_codec_driver_suspend,
+// 	.resume = mxs_codec_driver_resume,
+	.set_bias_level = mxs_set_bias_level,
+	.reg_cache_size = ADC_REGNUM,
+	.reg_word_size = sizeof(u16),
+	.reg_cache_step = 1,
+// 	.reg_cache_default = mxsadc_regs,
+// 	.volatile_register = sgtl5000_volatile_register,
+	.controls = mxs_snd_controls,
+	.num_controls = ARRAY_SIZE(mxs_snd_controls),
+	.dapm_widgets = mxs_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(mxs_dapm_widgets),
+	.dapm_routes = mxs_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(mxs_dapm_routes),
+	.write = mxs_codec_write,
+	.read = mxs_codec_read,
+};
+/* END MXS-ADC Codec driver */
+
+/* Underlying platform device that registers codec */
+static int mxs_adc_probe(struct platform_device *pdev)
+{
+	struct mxs_adc_priv *mxs_adc;
+	struct resource *r;
+	int ret;
+
+	mxs_adc = devm_kzalloc(&pdev->dev, sizeof(struct mxs_adc_priv), GFP_KERNEL);
+	if (!mxs_adc)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, mxs_adc);
+
+	/* audio-in IO memory */
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "audioin");
+	if (IS_ERR(r)) {
+		dev_err(&pdev->dev, "failed to get resource\n");
+		return PTR_ERR(r);
+	}
+
+	mxs_adc->ain_base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
+	if (IS_ERR(mxs_adc->ain_base)) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		return PTR_ERR(mxs_adc->ain_base);
+	}
+
+	/* audio-out IO memory */
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "audioout");
+	if (IS_ERR(r)) {
+		dev_err(&pdev->dev, "failed to get resource\n");
+		return PTR_ERR(r);
+	}
+
+	mxs_adc->aout_base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
+	if (IS_ERR(mxs_adc->aout_base)) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		return PTR_ERR(mxs_adc->aout_base);
+	}
+
+	/* rtc IO memory */
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc");
+	if (IS_ERR(r)) {
+		dev_err(&pdev->dev, "failed to get resource\n");
+		return PTR_ERR(r);
+	}
+
+	mxs_adc->rtc_base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
+	if (IS_ERR(mxs_adc->rtc_base)) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		return PTR_ERR(mxs_adc->rtc_base);
+	}
+
+	/* Get audio clock */
+	mxs_adc->clk = devm_clk_get(&pdev->dev, "filt");
+	if (IS_ERR(mxs_adc->clk)) {
+		ret = PTR_ERR(mxs_adc->clk);
+		dev_err(&pdev->dev, "%s: Clock initialization failed\n", __func__);
+		return ret;
+	}
+
+	/* Turn on audio clock */
+	ret = clk_prepare_enable(mxs_adc->clk);
+	if (unlikely(ret != 0)) {
+		dev_err(&pdev->dev, "%s: Clock prepare or enable failed\n", __func__);
+		return ret;
+	}
+
+	ret = snd_soc_register_codec(&pdev->dev,
+			&mxs_codec_driver,&mxs_codec_dai_driver, 1);
+	if (unlikely(ret != 0)) {
+		dev_err(&pdev->dev, "Codec registration failed\n");
+		goto disable_clk;
+	}
+
+	return 0;
+
+disable_clk:
+	clk_disable_unprepare(mxs_adc->clk);
+	return ret;
+}
+
+static int mxs_adc_remove(struct platform_device *pdev)
+{
+	struct mxs_adc_priv *mxs_adc = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(mxs_adc->clk);
+	snd_soc_unregister_codec(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id mxs_adc_dt_ids[] = {
+	{ .compatible = "fsl,mxs-builtin-codec", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxs_adc_dt_ids);
+
+static struct platform_driver mxs_adc_driver = {
+	.driver = {
+		   .name = "mxs-builtin-codec",
+		   .owner = THIS_MODULE,
+		   .of_match_table = mxs_adc_dt_ids,
+		   },
+	.probe = mxs_adc_probe,
+	.remove = mxs_adc_remove,
+};
+
+module_platform_driver(mxs_adc_driver);
+/* END Underlying platform device that registers codec */
+
+MODULE_DESCRIPTION("Freescale MXS ADC/DAC SoC Codec Driver");
+MODULE_AUTHOR("Michal Ulianko <michal.ulianko@gmail.com>");
+MODULE_LICENSE("GPL");
--- /dev/null
+++ b/sound/soc/codecs/mxs-builtin-codec.h
@@ -0,0 +1,825 @@
+#ifndef __MXS_ADC_CODEC_H
+
+#include <linux/io.h>
+
+/* MXS ADC/DAC registers */
+#define DAC_CTRL_L		0
+#define DAC_CTRL_H		1
+#define DAC_STAT_L		2
+#define DAC_STAT_H		3
+#define DAC_SRR_L		4
+#define DAC_VOLUME_L		6
+#define DAC_VOLUME_H		7
+#define DAC_DEBUG_L		8
+#define DAC_DEBUG_H		9
+#define DAC_HPVOL_L		10
+#define DAC_HPVOL_H		11
+#define DAC_PWRDN_L		12
+#define DAC_PWRDN_H		13
+#define DAC_REFCTRL_L		14
+#define DAC_REFCTRL_H		15
+#define DAC_ANACTRL_L		16
+#define DAC_ANACTRL_H		17
+#define DAC_TEST_L		18
+#define DAC_TEST_H		19
+#define DAC_BISTCTRL_L		20
+#define DAC_BISTCTRL_H		21
+#define DAC_BISTSTAT0_L		22
+#define DAC_BISTSTAT0_H		23
+#define DAC_BISTSTAT1_L		24
+#define DAC_BISTSTAT1_H		25
+#define DAC_ANACLKCTRL_L	26
+#define DAC_ANACLKCTRL_H	27
+#define DAC_DATA_L		28
+#define DAC_DATA_H		29
+#define DAC_SPEAKERCTRL_L	30
+#define DAC_SPEAKERCTRL_H	31
+#define DAC_VERSION_L		32
+#define DAC_VERSION_H		33
+#define ADC_CTRL_L		34
+#define ADC_CTRL_H		35
+#define ADC_STAT_L		36
+#define ADC_STAT_H		37
+#define ADC_SRR_L		38
+#define ADC_SRR_H		39
+#define ADC_VOLUME_L		40
+#define ADC_VOLUME_H		41
+#define ADC_DEBUG_L		42
+#define ADC_DEBUG_H		43
+#define ADC_ADCVOL_L		44
+#define ADC_ADCVOL_H		45
+#define ADC_MICLINE_L		46
+#define ADC_MICLINE_H		47
+#define ADC_ANACLKCTRL_L	48
+#define ADC_ANACLKCTRL_H	49
+#define ADC_DATA_L		50
+#define ADC_DATA_H		51
+
+#define ADC_REGNUM	52
+
+#define DAC_VOLUME_MIN	0x37
+#define DAC_VOLUME_MAX	0xFE
+#define ADC_VOLUME_MIN	0x37
+#define ADC_VOLUME_MAX	0xFE
+#define HP_VOLUME_MAX	0x0
+#define HP_VOLUME_MIN	0x7F
+#define LO_VOLUME_MAX	0x0
+#define LO_VOLUME_MIN	0x1F
+
+/* RTC */
+#define HW_RTC_PERSISTENT0	(0x00000060)
+#define HW_RTC_PERSISTENT0_SET	(0x00000064)
+#define HW_RTC_PERSISTENT0_CLR	(0x00000068)
+#define HW_RTC_PERSISTENT0_TOG	(0x0000006c)
+
+// TODO
+//#define BM_RTC_PERSISTENT0_RELEASE_GND	0x00080000
+
+/* AUDIOOUT */
+#define HW_AUDIOOUT_CTRL	(0x00000000)
+#define HW_AUDIOOUT_CTRL_SET	(0x00000004)
+#define HW_AUDIOOUT_CTRL_CLR	(0x00000008)
+#define HW_AUDIOOUT_CTRL_TOG	(0x0000000c)
+
+#define BM_AUDIOOUT_CTRL_SFTRST	0x80000000
+#define BM_AUDIOOUT_CTRL_CLKGATE	0x40000000
+#define BP_AUDIOOUT_CTRL_RSRVD4	21
+#define BM_AUDIOOUT_CTRL_RSRVD4	0x3FE00000
+#define BF_AUDIOOUT_CTRL_RSRVD4(v)  \
+		(((v) << 21) & BM_AUDIOOUT_CTRL_RSRVD4)
+#define BP_AUDIOOUT_CTRL_DMAWAIT_COUNT	16
+#define BM_AUDIOOUT_CTRL_DMAWAIT_COUNT	0x001F0000
+#define BF_AUDIOOUT_CTRL_DMAWAIT_COUNT(v)  \
+		(((v) << 16) & BM_AUDIOOUT_CTRL_DMAWAIT_COUNT)
+#define BM_AUDIOOUT_CTRL_RSRVD3	0x00008000
+#define BM_AUDIOOUT_CTRL_LR_SWAP	0x00004000
+#define BM_AUDIOOUT_CTRL_EDGE_SYNC	0x00002000
+#define BM_AUDIOOUT_CTRL_INVERT_1BIT	0x00001000
+#define BP_AUDIOOUT_CTRL_RSRVD2	10
+#define BM_AUDIOOUT_CTRL_RSRVD2	0x00000C00
+#define BF_AUDIOOUT_CTRL_RSRVD2(v)  \
+		(((v) << 10) & BM_AUDIOOUT_CTRL_RSRVD2)
+#define BP_AUDIOOUT_CTRL_SS3D_EFFECT	8
+#define BM_AUDIOOUT_CTRL_SS3D_EFFECT	0x00000300
+#define BF_AUDIOOUT_CTRL_SS3D_EFFECT(v)  \
+		(((v) << 8) & BM_AUDIOOUT_CTRL_SS3D_EFFECT)
+#define BM_AUDIOOUT_CTRL_RSRVD1	0x00000080
+#define BM_AUDIOOUT_CTRL_WORD_LENGTH	0x00000040
+#define BM_AUDIOOUT_CTRL_DAC_ZERO_ENABLE	0x00000020
+#define BM_AUDIOOUT_CTRL_LOOPBACK	0x00000010
+#define BM_AUDIOOUT_CTRL_FIFO_UNDERFLOW_IRQ	0x00000008
+#define BM_AUDIOOUT_CTRL_FIFO_OVERFLOW_IRQ	0x00000004
+#define BM_AUDIOOUT_CTRL_FIFO_ERROR_IRQ_EN	0x00000002
+#define BM_AUDIOOUT_CTRL_RUN	0x00000001
+
+#define HW_AUDIOOUT_STAT	(0x00000010)
+#define HW_AUDIOOUT_STAT_SET	(0x00000014)
+#define HW_AUDIOOUT_STAT_CLR	(0x00000018)
+#define HW_AUDIOOUT_STAT_TOG	(0x0000001c)
+
+#define BM_AUDIOOUT_STAT_DAC_PRESENT	0x80000000
+#define BP_AUDIOOUT_STAT_RSRVD1	0
+#define BM_AUDIOOUT_STAT_RSRVD1	0x7FFFFFFF
+#define BF_AUDIOOUT_STAT_RSRVD1(v)  \
+		(((v) << 0) & BM_AUDIOOUT_STAT_RSRVD1)
+
+#define HW_AUDIOOUT_DACSRR	(0x00000020)
+#define HW_AUDIOOUT_DACSRR_SET	(0x00000024)
+#define HW_AUDIOOUT_DACSRR_CLR	(0x00000028)
+#define HW_AUDIOOUT_DACSRR_TOG	(0x0000002c)
+
+#define BM_AUDIOOUT_DACSRR_OSR	0x80000000
+#define BV_AUDIOOUT_DACSRR_OSR__OSR6  0x0
+#define BV_AUDIOOUT_DACSRR_OSR__OSR12 0x1
+#define BP_AUDIOOUT_DACSRR_BASEMULT	28
+#define BM_AUDIOOUT_DACSRR_BASEMULT	0x70000000
+#define BF_AUDIOOUT_DACSRR_BASEMULT(v)  \
+		(((v) << 28) & BM_AUDIOOUT_DACSRR_BASEMULT)
+#define BV_AUDIOOUT_DACSRR_BASEMULT__SINGLE_RATE 0x1
+#define BV_AUDIOOUT_DACSRR_BASEMULT__DOUBLE_RATE 0x2
+#define BV_AUDIOOUT_DACSRR_BASEMULT__QUAD_RATE   0x4
+#define BM_AUDIOOUT_DACSRR_RSRVD2	0x08000000
+#define BP_AUDIOOUT_DACSRR_SRC_HOLD	24
+#define BM_AUDIOOUT_DACSRR_SRC_HOLD	0x07000000
+#define BF_AUDIOOUT_DACSRR_SRC_HOLD(v)  \
+		(((v) << 24) & BM_AUDIOOUT_DACSRR_SRC_HOLD)
+#define BP_AUDIOOUT_DACSRR_RSRVD1	21
+#define BM_AUDIOOUT_DACSRR_RSRVD1	0x00E00000
+#define BF_AUDIOOUT_DACSRR_RSRVD1(v)  \
+		(((v) << 21) & BM_AUDIOOUT_DACSRR_RSRVD1)
+#define BP_AUDIOOUT_DACSRR_SRC_INT	16
+#define BM_AUDIOOUT_DACSRR_SRC_INT	0x001F0000
+#define BF_AUDIOOUT_DACSRR_SRC_INT(v)  \
+		(((v) << 16) & BM_AUDIOOUT_DACSRR_SRC_INT)
+#define BP_AUDIOOUT_DACSRR_RSRVD0	13
+#define BM_AUDIOOUT_DACSRR_RSRVD0	0x0000E000
+#define BF_AUDIOOUT_DACSRR_RSRVD0(v)  \
+		(((v) << 13) & BM_AUDIOOUT_DACSRR_RSRVD0)
+#define BP_AUDIOOUT_DACSRR_SRC_FRAC	0
+#define BM_AUDIOOUT_DACSRR_SRC_FRAC	0x00001FFF
+#define BF_AUDIOOUT_DACSRR_SRC_FRAC(v)  \
+		(((v) << 0) & BM_AUDIOOUT_DACSRR_SRC_FRAC)
+
+#define HW_AUDIOOUT_DACVOLUME	(0x00000030)
+#define HW_AUDIOOUT_DACVOLUME_SET	(0x00000034)
+#define HW_AUDIOOUT_DACVOLUME_CLR	(0x00000038)
+#define HW_AUDIOOUT_DACVOLUME_TOG	(0x0000003c)
+
+#define BP_AUDIOOUT_DACVOLUME_RSRVD4	29
+#define BM_AUDIOOUT_DACVOLUME_RSRVD4	0xE0000000
+#define BF_AUDIOOUT_DACVOLUME_RSRVD4(v) \
+		(((v) << 29) & BM_AUDIOOUT_DACVOLUME_RSRVD4)
+#define BM_AUDIOOUT_DACVOLUME_VOLUME_UPDATE_LEFT	0x10000000
+#define BP_AUDIOOUT_DACVOLUME_RSRVD3	26
+#define BM_AUDIOOUT_DACVOLUME_RSRVD3	0x0C000000
+#define BF_AUDIOOUT_DACVOLUME_RSRVD3(v)  \
+		(((v) << 26) & BM_AUDIOOUT_DACVOLUME_RSRVD3)
+#define BM_AUDIOOUT_DACVOLUME_EN_ZCD	0x02000000
+#define BM_AUDIOOUT_DACVOLUME_MUTE_LEFT	0x01000000
+#define BP_AUDIOOUT_DACVOLUME_VOLUME_LEFT	16
+#define BM_AUDIOOUT_DACVOLUME_VOLUME_LEFT	0x00FF0000
+#define BF_AUDIOOUT_DACVOLUME_VOLUME_LEFT(v)  \
+		(((v) << 16) & BM_AUDIOOUT_DACVOLUME_VOLUME_LEFT)
+#define BP_AUDIOOUT_DACVOLUME_RSRVD2	13
+#define BM_AUDIOOUT_DACVOLUME_RSRVD2	0x0000E000
+#define BF_AUDIOOUT_DACVOLUME_RSRVD2(v)  \
+		(((v) << 13) & BM_AUDIOOUT_DACVOLUME_RSRVD2)
+#define BM_AUDIOOUT_DACVOLUME_VOLUME_UPDATE_RIGHT	0x00001000
+#define BP_AUDIOOUT_DACVOLUME_RSRVD1	9
+#define BM_AUDIOOUT_DACVOLUME_RSRVD1	0x00000E00
+#define BF_AUDIOOUT_DACVOLUME_RSRVD1(v)  \
+		(((v) << 9) & BM_AUDIOOUT_DACVOLUME_RSRVD1)
+#define BM_AUDIOOUT_DACVOLUME_MUTE_RIGHT	0x00000100
+#define BP_AUDIOOUT_DACVOLUME_VOLUME_RIGHT	0
+#define BM_AUDIOOUT_DACVOLUME_VOLUME_RIGHT	0x000000FF
+#define BF_AUDIOOUT_DACVOLUME_VOLUME_RIGHT(v)  \
+		(((v) << 0) & BM_AUDIOOUT_DACVOLUME_VOLUME_RIGHT)
+
+#define HW_AUDIOOUT_DACDEBUG	(0x00000040)
+#define HW_AUDIOOUT_DACDEBUG_SET	(0x00000044)
+#define HW_AUDIOOUT_DACDEBUG_CLR	(0x00000048)
+#define HW_AUDIOOUT_DACDEBUG_TOG	(0x0000004c)
+
+#define BM_AUDIOOUT_DACDEBUG_ENABLE_DACDMA	0x80000000
+#define BP_AUDIOOUT_DACDEBUG_RSRVD2	12
+#define BM_AUDIOOUT_DACDEBUG_RSRVD2	0x7FFFF000
+#define BF_AUDIOOUT_DACDEBUG_RSRVD2(v)  \
+		(((v) << 12) & BM_AUDIOOUT_DACDEBUG_RSRVD2)
+#define BP_AUDIOOUT_DACDEBUG_RAM_SS	8
+#define BM_AUDIOOUT_DACDEBUG_RAM_SS	0x00000F00
+#define BF_AUDIOOUT_DACDEBUG_RAM_SS(v)  \
+		(((v) << 8) & BM_AUDIOOUT_DACDEBUG_RAM_SS)
+#define BP_AUDIOOUT_DACDEBUG_RSRVD1	6
+#define BM_AUDIOOUT_DACDEBUG_RSRVD1	0x000000C0
+#define BF_AUDIOOUT_DACDEBUG_RSRVD1(v)  \
+		(((v) << 6) & BM_AUDIOOUT_DACDEBUG_RSRVD1)
+#define BM_AUDIOOUT_DACDEBUG_SET_INTERRUPT1_CLK_CROSS	0x00000020
+#define BM_AUDIOOUT_DACDEBUG_SET_INTERRUPT0_CLK_CROSS	0x00000010
+#define BM_AUDIOOUT_DACDEBUG_SET_INTERRUPT1_HAND_SHAKE	0x00000008
+#define BM_AUDIOOUT_DACDEBUG_SET_INTERRUPT0_HAND_SHAKE	0x00000004
+#define BM_AUDIOOUT_DACDEBUG_DMA_PREQ	0x00000002
+#define BM_AUDIOOUT_DACDEBUG_FIFO_STATUS	0x00000001
+
+#define HW_AUDIOOUT_HPVOL	(0x00000050)
+#define HW_AUDIOOUT_HPVOL_SET	(0x00000054)
+#define HW_AUDIOOUT_HPVOL_CLR	(0x00000058)
+#define HW_AUDIOOUT_HPVOL_TOG	(0x0000005c)
+
+#define BP_AUDIOOUT_HPVOL_RSRVD5	29
+#define BM_AUDIOOUT_HPVOL_RSRVD5	0xE0000000
+#define BF_AUDIOOUT_HPVOL_RSRVD5(v) \
+		(((v) << 29) & BM_AUDIOOUT_HPVOL_RSRVD5)
+#define BM_AUDIOOUT_HPVOL_VOLUME_UPDATE_PENDING	0x10000000
+#define BP_AUDIOOUT_HPVOL_RSRVD4	26
+#define BM_AUDIOOUT_HPVOL_RSRVD4	0x0C000000
+#define BF_AUDIOOUT_HPVOL_RSRVD4(v)  \
+		(((v) << 26) & BM_AUDIOOUT_HPVOL_RSRVD4)
+#define BM_AUDIOOUT_HPVOL_EN_MSTR_ZCD	0x02000000
+#define BM_AUDIOOUT_HPVOL_MUTE	0x01000000
+#define BP_AUDIOOUT_HPVOL_RSRVD3	17
+#define BM_AUDIOOUT_HPVOL_RSRVD3	0x00FE0000
+#define BF_AUDIOOUT_HPVOL_RSRVD3(v)  \
+		(((v) << 17) & BM_AUDIOOUT_HPVOL_RSRVD3)
+#define BM_AUDIOOUT_HPVOL_SELECT	0x00010000
+#define BM_AUDIOOUT_HPVOL_RSRVD2	0x00008000
+#define BP_AUDIOOUT_HPVOL_VOL_LEFT	8
+#define BM_AUDIOOUT_HPVOL_VOL_LEFT	0x00007F00
+#define BF_AUDIOOUT_HPVOL_VOL_LEFT(v)  \
+		(((v) << 8) & BM_AUDIOOUT_HPVOL_VOL_LEFT)
+#define BM_AUDIOOUT_HPVOL_RSRVD1	0x00000080
+#define BP_AUDIOOUT_HPVOL_VOL_RIGHT	0
+#define BM_AUDIOOUT_HPVOL_VOL_RIGHT	0x0000007F
+#define BF_AUDIOOUT_HPVOL_VOL_RIGHT(v)  \
+		(((v) << 0) & BM_AUDIOOUT_HPVOL_VOL_RIGHT)
+
+#define HW_AUDIOOUT_RESERVED	(0x00000060)
+#define HW_AUDIOOUT_RESERVED_SET	(0x00000064)
+#define HW_AUDIOOUT_RESERVED_CLR	(0x00000068)
+#define HW_AUDIOOUT_RESERVED_TOG	(0x0000006c)
+
+#define BP_AUDIOOUT_RESERVED_RSRVD1	0
+#define BM_AUDIOOUT_RESERVED_RSRVD1	0xFFFFFFFF
+#define BF_AUDIOOUT_RESERVED_RSRVD1(v)	(v)
+
+#define HW_AUDIOOUT_PWRDN	(0x00000070)
+#define HW_AUDIOOUT_PWRDN_SET	(0x00000074)
+#define HW_AUDIOOUT_PWRDN_CLR	(0x00000078)
+#define HW_AUDIOOUT_PWRDN_TOG	(0x0000007c)
+
+#define BP_AUDIOOUT_PWRDN_RSRVD7	25
+#define BM_AUDIOOUT_PWRDN_RSRVD7	0xFE000000
+#define BF_AUDIOOUT_PWRDN_RSRVD7(v) \
+		(((v) << 25) & BM_AUDIOOUT_PWRDN_RSRVD7)
+#define BM_AUDIOOUT_PWRDN_SPEAKER	0x01000000
+#define BP_AUDIOOUT_PWRDN_RSRVD6	21
+#define BM_AUDIOOUT_PWRDN_RSRVD6	0x00E00000
+#define BF_AUDIOOUT_PWRDN_RSRVD6(v)  \
+		(((v) << 21) & BM_AUDIOOUT_PWRDN_RSRVD6)
+#define BM_AUDIOOUT_PWRDN_SELFBIAS	0x00100000
+#define BP_AUDIOOUT_PWRDN_RSRVD5	17
+#define BM_AUDIOOUT_PWRDN_RSRVD5	0x000E0000
+#define BF_AUDIOOUT_PWRDN_RSRVD5(v)  \
+		(((v) << 17) & BM_AUDIOOUT_PWRDN_RSRVD5)
+#define BM_AUDIOOUT_PWRDN_RIGHT_ADC	0x00010000
+#define BP_AUDIOOUT_PWRDN_RSRVD4	13
+#define BM_AUDIOOUT_PWRDN_RSRVD4	0x0000E000
+#define BF_AUDIOOUT_PWRDN_RSRVD4(v)  \
+		(((v) << 13) & BM_AUDIOOUT_PWRDN_RSRVD4)
+#define BM_AUDIOOUT_PWRDN_DAC	0x00001000
+#define BP_AUDIOOUT_PWRDN_RSRVD3	9
+#define BM_AUDIOOUT_PWRDN_RSRVD3	0x00000E00
+#define BF_AUDIOOUT_PWRDN_RSRVD3(v)  \
+		(((v) << 9) & BM_AUDIOOUT_PWRDN_RSRVD3)
+#define BM_AUDIOOUT_PWRDN_ADC	0x00000100
+#define BP_AUDIOOUT_PWRDN_RSRVD2	5
+#define BM_AUDIOOUT_PWRDN_RSRVD2	0x000000E0
+#define BF_AUDIOOUT_PWRDN_RSRVD2(v)  \
+		(((v) << 5) & BM_AUDIOOUT_PWRDN_RSRVD2)
+#define BM_AUDIOOUT_PWRDN_CAPLESS	0x00000010
+#define BP_AUDIOOUT_PWRDN_RSRVD1	1
+#define BM_AUDIOOUT_PWRDN_RSRVD1	0x0000000E
+#define BF_AUDIOOUT_PWRDN_RSRVD1(v)  \
+		(((v) << 1) & BM_AUDIOOUT_PWRDN_RSRVD1)
+#define BM_AUDIOOUT_PWRDN_HEADPHONE	0x00000001
+
+#define HW_AUDIOOUT_REFCTRL	(0x00000080)
+#define HW_AUDIOOUT_REFCTRL_SET	(0x00000084)
+#define HW_AUDIOOUT_REFCTRL_CLR	(0x00000088)
+#define HW_AUDIOOUT_REFCTRL_TOG	(0x0000008c)
+
+#define BP_AUDIOOUT_REFCTRL_RSRVD4	27
+#define BM_AUDIOOUT_REFCTRL_RSRVD4	0xF8000000
+#define BF_AUDIOOUT_REFCTRL_RSRVD4(v) \
+		(((v) << 27) & BM_AUDIOOUT_REFCTRL_RSRVD4)
+#define BM_AUDIOOUT_REFCTRL_FASTSETTLING	0x04000000
+#define BM_AUDIOOUT_REFCTRL_RAISE_REF	0x02000000
+#define BM_AUDIOOUT_REFCTRL_XTAL_BGR_BIAS	0x01000000
+#define BM_AUDIOOUT_REFCTRL_RSRVD3	0x00800000
+#define BP_AUDIOOUT_REFCTRL_VBG_ADJ	20
+#define BM_AUDIOOUT_REFCTRL_VBG_ADJ	0x00700000
+#define BF_AUDIOOUT_REFCTRL_VBG_ADJ(v)  \
+		(((v) << 20) & BM_AUDIOOUT_REFCTRL_VBG_ADJ)
+#define BM_AUDIOOUT_REFCTRL_LOW_PWR	0x00080000
+#define BM_AUDIOOUT_REFCTRL_LW_REF	0x00040000
+#define BP_AUDIOOUT_REFCTRL_BIAS_CTRL	16
+#define BM_AUDIOOUT_REFCTRL_BIAS_CTRL	0x00030000
+#define BF_AUDIOOUT_REFCTRL_BIAS_CTRL(v)  \
+		(((v) << 16) & BM_AUDIOOUT_REFCTRL_BIAS_CTRL)
+#define BM_AUDIOOUT_REFCTRL_RSRVD2	0x00008000
+#define BM_AUDIOOUT_REFCTRL_VDDXTAL_TO_VDDD	0x00004000
+#define BM_AUDIOOUT_REFCTRL_ADJ_ADC	0x00002000
+#define BM_AUDIOOUT_REFCTRL_ADJ_VAG	0x00001000
+#define BP_AUDIOOUT_REFCTRL_ADC_REFVAL	8
+#define BM_AUDIOOUT_REFCTRL_ADC_REFVAL	0x00000F00
+#define BF_AUDIOOUT_REFCTRL_ADC_REFVAL(v)  \
+		(((v) << 8) & BM_AUDIOOUT_REFCTRL_ADC_REFVAL)
+#define BP_AUDIOOUT_REFCTRL_VAG_VAL	4
+#define BM_AUDIOOUT_REFCTRL_VAG_VAL	0x000000F0
+#define BF_AUDIOOUT_REFCTRL_VAG_VAL(v)  \
+		(((v) << 4) & BM_AUDIOOUT_REFCTRL_VAG_VAL)
+#define BM_AUDIOOUT_REFCTRL_RSRVD1	0x00000008
+#define BP_AUDIOOUT_REFCTRL_DAC_ADJ	0
+#define BM_AUDIOOUT_REFCTRL_DAC_ADJ	0x00000007
+#define BF_AUDIOOUT_REFCTRL_DAC_ADJ(v)  \
+		(((v) << 0) & BM_AUDIOOUT_REFCTRL_DAC_ADJ)
+
+#define HW_AUDIOOUT_ANACTRL	(0x00000090)
+#define HW_AUDIOOUT_ANACTRL_SET	(0x00000094)
+#define HW_AUDIOOUT_ANACTRL_CLR	(0x00000098)
+#define HW_AUDIOOUT_ANACTRL_TOG	(0x0000009c)
+
+#define BP_AUDIOOUT_ANACTRL_RSRVD8	29
+#define BM_AUDIOOUT_ANACTRL_RSRVD8	0xE0000000
+#define BF_AUDIOOUT_ANACTRL_RSRVD8(v) \
+		(((v) << 29) & BM_AUDIOOUT_ANACTRL_RSRVD8)
+#define BM_AUDIOOUT_ANACTRL_SHORT_CM_STS	0x10000000
+#define BP_AUDIOOUT_ANACTRL_RSRVD7	25
+#define BM_AUDIOOUT_ANACTRL_RSRVD7	0x0E000000
+#define BF_AUDIOOUT_ANACTRL_RSRVD7(v)  \
+		(((v) << 25) & BM_AUDIOOUT_ANACTRL_RSRVD7)
+#define BM_AUDIOOUT_ANACTRL_SHORT_LR_STS	0x01000000
+#define BP_AUDIOOUT_ANACTRL_RSRVD6	22
+#define BM_AUDIOOUT_ANACTRL_RSRVD6	0x00C00000
+#define BF_AUDIOOUT_ANACTRL_RSRVD6(v)  \
+		(((v) << 22) & BM_AUDIOOUT_ANACTRL_RSRVD6)
+#define BP_AUDIOOUT_ANACTRL_SHORTMODE_CM	20
+#define BM_AUDIOOUT_ANACTRL_SHORTMODE_CM	0x00300000
+#define BF_AUDIOOUT_ANACTRL_SHORTMODE_CM(v)  \
+		(((v) << 20) & BM_AUDIOOUT_ANACTRL_SHORTMODE_CM)
+#define BM_AUDIOOUT_ANACTRL_RSRVD5	0x00080000
+#define BP_AUDIOOUT_ANACTRL_SHORTMODE_LR	17
+#define BM_AUDIOOUT_ANACTRL_SHORTMODE_LR	0x00060000
+#define BF_AUDIOOUT_ANACTRL_SHORTMODE_LR(v)  \
+		(((v) << 17) & BM_AUDIOOUT_ANACTRL_SHORTMODE_LR)
+#define BP_AUDIOOUT_ANACTRL_RSRVD4	15
+#define BM_AUDIOOUT_ANACTRL_RSRVD4	0x00018000
+#define BF_AUDIOOUT_ANACTRL_RSRVD4(v)  \
+		(((v) << 15) & BM_AUDIOOUT_ANACTRL_RSRVD4)
+#define BP_AUDIOOUT_ANACTRL_SHORT_LVLADJL	12
+#define BM_AUDIOOUT_ANACTRL_SHORT_LVLADJL	0x00007000
+#define BF_AUDIOOUT_ANACTRL_SHORT_LVLADJL(v)  \
+		(((v) << 12) & BM_AUDIOOUT_ANACTRL_SHORT_LVLADJL)
+#define BM_AUDIOOUT_ANACTRL_RSRVD3	0x00000800
+#define BP_AUDIOOUT_ANACTRL_SHORT_LVLADJR	8
+#define BM_AUDIOOUT_ANACTRL_SHORT_LVLADJR	0x00000700
+#define BF_AUDIOOUT_ANACTRL_SHORT_LVLADJR(v)  \
+		(((v) << 8) & BM_AUDIOOUT_ANACTRL_SHORT_LVLADJR)
+#define BP_AUDIOOUT_ANACTRL_RSRVD2	6
+#define BM_AUDIOOUT_ANACTRL_RSRVD2	0x000000C0
+#define BF_AUDIOOUT_ANACTRL_RSRVD2(v)  \
+		(((v) << 6) & BM_AUDIOOUT_ANACTRL_RSRVD2)
+#define BM_AUDIOOUT_ANACTRL_HP_HOLD_GND	0x00000020
+#define BM_AUDIOOUT_ANACTRL_HP_CLASSAB	0x00000010
+#define BP_AUDIOOUT_ANACTRL_RSRVD1	0
+#define BM_AUDIOOUT_ANACTRL_RSRVD1	0x0000000F
+#define BF_AUDIOOUT_ANACTRL_RSRVD1(v)  \
+		(((v) << 0) & BM_AUDIOOUT_ANACTRL_RSRVD1)
+
+#define HW_AUDIOOUT_TEST	(0x000000a0)
+#define HW_AUDIOOUT_TEST_SET	(0x000000a4)
+#define HW_AUDIOOUT_TEST_CLR	(0x000000a8)
+#define HW_AUDIOOUT_TEST_TOG	(0x000000ac)
+
+#define BM_AUDIOOUT_TEST_RSRVD4	0x80000000
+#define BP_AUDIOOUT_TEST_HP_ANTIPOP	28
+#define BM_AUDIOOUT_TEST_HP_ANTIPOP	0x70000000
+#define BF_AUDIOOUT_TEST_HP_ANTIPOP(v)  \
+		(((v) << 28) & BM_AUDIOOUT_TEST_HP_ANTIPOP)
+#define BM_AUDIOOUT_TEST_RSRVD3	0x08000000
+#define BM_AUDIOOUT_TEST_TM_ADCIN_TOHP	0x04000000
+#define BM_AUDIOOUT_TEST_TM_LOOP	0x02000000
+#define BM_AUDIOOUT_TEST_TM_HPCOMMON	0x01000000
+#define BP_AUDIOOUT_TEST_HP_I1_ADJ	22
+#define BM_AUDIOOUT_TEST_HP_I1_ADJ	0x00C00000
+#define BF_AUDIOOUT_TEST_HP_I1_ADJ(v)  \
+		(((v) << 22) & BM_AUDIOOUT_TEST_HP_I1_ADJ)
+#define BP_AUDIOOUT_TEST_HP_IALL_ADJ	20
+#define BM_AUDIOOUT_TEST_HP_IALL_ADJ	0x00300000
+#define BF_AUDIOOUT_TEST_HP_IALL_ADJ(v)  \
+		(((v) << 20) & BM_AUDIOOUT_TEST_HP_IALL_ADJ)
+#define BP_AUDIOOUT_TEST_RSRVD2	14
+#define BM_AUDIOOUT_TEST_RSRVD2	0x000FC000
+#define BF_AUDIOOUT_TEST_RSRVD2(v)  \
+		(((v) << 14) & BM_AUDIOOUT_TEST_RSRVD2)
+#define BM_AUDIOOUT_TEST_VAG_CLASSA	0x00002000
+#define BM_AUDIOOUT_TEST_VAG_DOUBLE_I	0x00001000
+#define BP_AUDIOOUT_TEST_RSRVD1	4
+#define BM_AUDIOOUT_TEST_RSRVD1	0x00000FF0
+#define BF_AUDIOOUT_TEST_RSRVD1(v)  \
+		(((v) << 4) & BM_AUDIOOUT_TEST_RSRVD1)
+#define BM_AUDIOOUT_TEST_ADCTODAC_LOOP	0x00000008
+#define BM_AUDIOOUT_TEST_DAC_CLASSA	0x00000004
+#define BM_AUDIOOUT_TEST_DAC_DOUBLE_I	0x00000002
+#define BM_AUDIOOUT_TEST_DAC_DIS_RTZ	0x00000001
+
+#define HW_AUDIOOUT_BISTCTRL	(0x000000b0)
+#define HW_AUDIOOUT_BISTCTRL_SET	(0x000000b4)
+#define HW_AUDIOOUT_BISTCTRL_CLR	(0x000000b8)
+#define HW_AUDIOOUT_BISTCTRL_TOG	(0x000000bc)
+
+#define BP_AUDIOOUT_BISTCTRL_RSVD0	4
+#define BM_AUDIOOUT_BISTCTRL_RSVD0	0xFFFFFFF0
+#define BF_AUDIOOUT_BISTCTRL_RSVD0(v) \
+		(((v) << 4) & BM_AUDIOOUT_BISTCTRL_RSVD0)
+#define BM_AUDIOOUT_BISTCTRL_FAIL	0x00000008
+#define BM_AUDIOOUT_BISTCTRL_PASS	0x00000004
+#define BM_AUDIOOUT_BISTCTRL_DONE	0x00000002
+#define BM_AUDIOOUT_BISTCTRL_START	0x00000001
+
+#define HW_AUDIOOUT_BISTSTAT0	(0x000000c0)
+#define HW_AUDIOOUT_BISTSTAT0_SET	(0x000000c4)
+#define HW_AUDIOOUT_BISTSTAT0_CLR	(0x000000c8)
+#define HW_AUDIOOUT_BISTSTAT0_TOG	(0x000000cc)
+
+#define BP_AUDIOOUT_BISTSTAT0_RSVD0	24
+#define BM_AUDIOOUT_BISTSTAT0_RSVD0	0xFF000000
+#define BF_AUDIOOUT_BISTSTAT0_RSVD0(v) \
+		(((v) << 24) & BM_AUDIOOUT_BISTSTAT0_RSVD0)
+#define BP_AUDIOOUT_BISTSTAT0_DATA	0
+#define BM_AUDIOOUT_BISTSTAT0_DATA	0x00FFFFFF
+#define BF_AUDIOOUT_BISTSTAT0_DATA(v)  \
+		(((v) << 0) & BM_AUDIOOUT_BISTSTAT0_DATA)
+
+#define HW_AUDIOOUT_BISTSTAT1	(0x000000d0)
+#define HW_AUDIOOUT_BISTSTAT1_SET	(0x000000d4)
+#define HW_AUDIOOUT_BISTSTAT1_CLR	(0x000000d8)
+#define HW_AUDIOOUT_BISTSTAT1_TOG	(0x000000dc)
+
+#define BP_AUDIOOUT_BISTSTAT1_RSVD1	29
+#define BM_AUDIOOUT_BISTSTAT1_RSVD1	0xE0000000
+#define BF_AUDIOOUT_BISTSTAT1_RSVD1(v) \
+		(((v) << 29) & BM_AUDIOOUT_BISTSTAT1_RSVD1)
+#define BP_AUDIOOUT_BISTSTAT1_STATE	24
+#define BM_AUDIOOUT_BISTSTAT1_STATE	0x1F000000
+#define BF_AUDIOOUT_BISTSTAT1_STATE(v)  \
+		(((v) << 24) & BM_AUDIOOUT_BISTSTAT1_STATE)
+#define BP_AUDIOOUT_BISTSTAT1_RSVD0	8
+#define BM_AUDIOOUT_BISTSTAT1_RSVD0	0x00FFFF00
+#define BF_AUDIOOUT_BISTSTAT1_RSVD0(v)  \
+		(((v) << 8) & BM_AUDIOOUT_BISTSTAT1_RSVD0)
+#define BP_AUDIOOUT_BISTSTAT1_ADDR	0
+#define BM_AUDIOOUT_BISTSTAT1_ADDR	0x000000FF
+#define BF_AUDIOOUT_BISTSTAT1_ADDR(v)  \
+		(((v) << 0) & BM_AUDIOOUT_BISTSTAT1_ADDR)
+
+#define HW_AUDIOOUT_ANACLKCTRL	(0x000000e0)
+#define HW_AUDIOOUT_ANACLKCTRL_SET	(0x000000e4)
+#define HW_AUDIOOUT_ANACLKCTRL_CLR	(0x000000e8)
+#define HW_AUDIOOUT_ANACLKCTRL_TOG	(0x000000ec)
+
+#define BM_AUDIOOUT_ANACLKCTRL_CLKGATE	0x80000000
+#define BP_AUDIOOUT_ANACLKCTRL_RSRVD3	5
+#define BM_AUDIOOUT_ANACLKCTRL_RSRVD3	0x7FFFFFE0
+#define BF_AUDIOOUT_ANACLKCTRL_RSRVD3(v)  \
+		(((v) << 5) & BM_AUDIOOUT_ANACLKCTRL_RSRVD3)
+#define BM_AUDIOOUT_ANACLKCTRL_INVERT_DACCLK	0x00000010
+#define BM_AUDIOOUT_ANACLKCTRL_RSRVD2	0x00000008
+#define BP_AUDIOOUT_ANACLKCTRL_DACDIV	0
+#define BM_AUDIOOUT_ANACLKCTRL_DACDIV	0x00000007
+#define BF_AUDIOOUT_ANACLKCTRL_DACDIV(v)  \
+		(((v) << 0) & BM_AUDIOOUT_ANACLKCTRL_DACDIV)
+
+#define HW_AUDIOOUT_DATA	(0x000000f0)
+#define HW_AUDIOOUT_DATA_SET	(0x000000f4)
+#define HW_AUDIOOUT_DATA_CLR	(0x000000f8)
+#define HW_AUDIOOUT_DATA_TOG	(0x000000fc)
+
+#define BP_AUDIOOUT_DATA_HIGH	16
+#define BM_AUDIOOUT_DATA_HIGH	0xFFFF0000
+#define BF_AUDIOOUT_DATA_HIGH(v) \
+		(((v) << 16) & BM_AUDIOOUT_DATA_HIGH)
+#define BP_AUDIOOUT_DATA_LOW	0
+#define BM_AUDIOOUT_DATA_LOW	0x0000FFFF
+#define BF_AUDIOOUT_DATA_LOW(v)  \
+		(((v) << 0) & BM_AUDIOOUT_DATA_LOW)
+
+#define HW_AUDIOOUT_SPEAKERCTRL	(0x00000100)
+#define HW_AUDIOOUT_SPEAKERCTRL_SET	(0x00000104)
+#define HW_AUDIOOUT_SPEAKERCTRL_CLR	(0x00000108)
+#define HW_AUDIOOUT_SPEAKERCTRL_TOG	(0x0000010c)
+
+#define BP_AUDIOOUT_SPEAKERCTRL_RSRVD2	25
+#define BM_AUDIOOUT_SPEAKERCTRL_RSRVD2	0xFE000000
+#define BF_AUDIOOUT_SPEAKERCTRL_RSRVD2(v) \
+		(((v) << 25) & BM_AUDIOOUT_SPEAKERCTRL_RSRVD2)
+#define BM_AUDIOOUT_SPEAKERCTRL_MUTE	0x01000000
+#define BP_AUDIOOUT_SPEAKERCTRL_I1_ADJ	22
+#define BM_AUDIOOUT_SPEAKERCTRL_I1_ADJ	0x00C00000
+#define BF_AUDIOOUT_SPEAKERCTRL_I1_ADJ(v)  \
+		(((v) << 22) & BM_AUDIOOUT_SPEAKERCTRL_I1_ADJ)
+#define BP_AUDIOOUT_SPEAKERCTRL_IALL_ADJ	20
+#define BM_AUDIOOUT_SPEAKERCTRL_IALL_ADJ	0x00300000
+#define BF_AUDIOOUT_SPEAKERCTRL_IALL_ADJ(v)  \
+		(((v) << 20) & BM_AUDIOOUT_SPEAKERCTRL_IALL_ADJ)
+#define BP_AUDIOOUT_SPEAKERCTRL_RSRVD1	16
+#define BM_AUDIOOUT_SPEAKERCTRL_RSRVD1	0x000F0000
+#define BF_AUDIOOUT_SPEAKERCTRL_RSRVD1(v)  \
+		(((v) << 16) & BM_AUDIOOUT_SPEAKERCTRL_RSRVD1)
+#define BP_AUDIOOUT_SPEAKERCTRL_POSDRIVER	14
+#define BM_AUDIOOUT_SPEAKERCTRL_POSDRIVER	0x0000C000
+#define BF_AUDIOOUT_SPEAKERCTRL_POSDRIVER(v)  \
+		(((v) << 14) & BM_AUDIOOUT_SPEAKERCTRL_POSDRIVER)
+#define BP_AUDIOOUT_SPEAKERCTRL_NEGDRIVER	12
+#define BM_AUDIOOUT_SPEAKERCTRL_NEGDRIVER	0x00003000
+#define BF_AUDIOOUT_SPEAKERCTRL_NEGDRIVER(v)  \
+		(((v) << 12) & BM_AUDIOOUT_SPEAKERCTRL_NEGDRIVER)
+#define BP_AUDIOOUT_SPEAKERCTRL_RSRVD0	0
+#define BM_AUDIOOUT_SPEAKERCTRL_RSRVD0	0x00000FFF
+#define BF_AUDIOOUT_SPEAKERCTRL_RSRVD0(v)  \
+		(((v) << 0) & BM_AUDIOOUT_SPEAKERCTRL_RSRVD0)
+
+#define HW_AUDIOOUT_VERSION	(0x00000200)
+
+#define BP_AUDIOOUT_VERSION_MAJOR	24
+#define BM_AUDIOOUT_VERSION_MAJOR	0xFF000000
+#define BF_AUDIOOUT_VERSION_MAJOR(v) \
+		(((v) << 24) & BM_AUDIOOUT_VERSION_MAJOR)
+#define BP_AUDIOOUT_VERSION_MINOR	16
+#define BM_AUDIOOUT_VERSION_MINOR	0x00FF0000
+#define BF_AUDIOOUT_VERSION_MINOR(v)  \
+		(((v) << 16) & BM_AUDIOOUT_VERSION_MINOR)
+#define BP_AUDIOOUT_VERSION_STEP	0
+#define BM_AUDIOOUT_VERSION_STEP	0x0000FFFF
+#define BF_AUDIOOUT_VERSION_STEP(v)  \
+		(((v) << 0) & BM_AUDIOOUT_VERSION_STEP)
+
+/* AUDIOIN */
+#define HW_AUDIOIN_CTRL	(0x00000000)
+#define HW_AUDIOIN_CTRL_SET	(0x00000004)
+#define HW_AUDIOIN_CTRL_CLR	(0x00000008)
+#define HW_AUDIOIN_CTRL_TOG	(0x0000000c)
+
+#define BM_AUDIOIN_CTRL_SFTRST	0x80000000
+#define BM_AUDIOIN_CTRL_CLKGATE	0x40000000
+#define BP_AUDIOIN_CTRL_RSRVD3	21
+#define BM_AUDIOIN_CTRL_RSRVD3	0x3FE00000
+#define BF_AUDIOIN_CTRL_RSRVD3(v)  \
+		(((v) << 21) & BM_AUDIOIN_CTRL_RSRVD3)
+#define BP_AUDIOIN_CTRL_DMAWAIT_COUNT	16
+#define BM_AUDIOIN_CTRL_DMAWAIT_COUNT	0x001F0000
+#define BF_AUDIOIN_CTRL_DMAWAIT_COUNT(v)  \
+		(((v) << 16) & BM_AUDIOIN_CTRL_DMAWAIT_COUNT)
+#define BP_AUDIOIN_CTRL_RSRVD1	11
+#define BM_AUDIOIN_CTRL_RSRVD1	0x0000F800
+#define BF_AUDIOIN_CTRL_RSRVD1(v)  \
+		(((v) << 11) & BM_AUDIOIN_CTRL_RSRVD1)
+#define BM_AUDIOIN_CTRL_LR_SWAP	0x00000400
+#define BM_AUDIOIN_CTRL_EDGE_SYNC	0x00000200
+#define BM_AUDIOIN_CTRL_INVERT_1BIT	0x00000100
+#define BM_AUDIOIN_CTRL_OFFSET_ENABLE	0x00000080
+#define BM_AUDIOIN_CTRL_HPF_ENABLE	0x00000040
+#define BM_AUDIOIN_CTRL_WORD_LENGTH	0x00000020
+#define BM_AUDIOIN_CTRL_LOOPBACK	0x00000010
+#define BM_AUDIOIN_CTRL_FIFO_UNDERFLOW_IRQ	0x00000008
+#define BM_AUDIOIN_CTRL_FIFO_OVERFLOW_IRQ	0x00000004
+#define BM_AUDIOIN_CTRL_FIFO_ERROR_IRQ_EN	0x00000002
+#define BM_AUDIOIN_CTRL_RUN	0x00000001
+
+#define HW_AUDIOIN_STAT	(0x00000010)
+#define HW_AUDIOIN_STAT_SET	(0x00000014)
+#define HW_AUDIOIN_STAT_CLR	(0x00000018)
+#define HW_AUDIOIN_STAT_TOG	(0x0000001c)
+
+#define BM_AUDIOIN_STAT_ADC_PRESENT	0x80000000
+#define BP_AUDIOIN_STAT_RSRVD3	0
+#define BM_AUDIOIN_STAT_RSRVD3	0x7FFFFFFF
+#define BF_AUDIOIN_STAT_RSRVD3(v)  \
+		(((v) << 0) & BM_AUDIOIN_STAT_RSRVD3)
+
+#define HW_AUDIOIN_ADCSRR	(0x00000020)
+#define HW_AUDIOIN_ADCSRR_SET	(0x00000024)
+#define HW_AUDIOIN_ADCSRR_CLR	(0x00000028)
+#define HW_AUDIOIN_ADCSRR_TOG	(0x0000002c)
+
+#define BM_AUDIOIN_ADCSRR_OSR	0x80000000
+#define BV_AUDIOIN_ADCSRR_OSR__OSR6  0x0
+#define BV_AUDIOIN_ADCSRR_OSR__OSR12 0x1
+#define BP_AUDIOIN_ADCSRR_BASEMULT	28
+#define BM_AUDIOIN_ADCSRR_BASEMULT	0x70000000
+#define BF_AUDIOIN_ADCSRR_BASEMULT(v)  \
+		(((v) << 28) & BM_AUDIOIN_ADCSRR_BASEMULT)
+#define BV_AUDIOIN_ADCSRR_BASEMULT__SINGLE_RATE 0x1
+#define BV_AUDIOIN_ADCSRR_BASEMULT__DOUBLE_RATE 0x2
+#define BV_AUDIOIN_ADCSRR_BASEMULT__QUAD_RATE   0x4
+#define BM_AUDIOIN_ADCSRR_RSRVD2	0x08000000
+#define BP_AUDIOIN_ADCSRR_SRC_HOLD	24
+#define BM_AUDIOIN_ADCSRR_SRC_HOLD	0x07000000
+#define BF_AUDIOIN_ADCSRR_SRC_HOLD(v)  \
+		(((v) << 24) & BM_AUDIOIN_ADCSRR_SRC_HOLD)
+#define BP_AUDIOIN_ADCSRR_RSRVD1	21
+#define BM_AUDIOIN_ADCSRR_RSRVD1	0x00E00000
+#define BF_AUDIOIN_ADCSRR_RSRVD1(v)  \
+		(((v) << 21) & BM_AUDIOIN_ADCSRR_RSRVD1)
+#define BP_AUDIOIN_ADCSRR_SRC_INT	16
+#define BM_AUDIOIN_ADCSRR_SRC_INT	0x001F0000
+#define BF_AUDIOIN_ADCSRR_SRC_INT(v)  \
+		(((v) << 16) & BM_AUDIOIN_ADCSRR_SRC_INT)
+#define BP_AUDIOIN_ADCSRR_RSRVD0	13
+#define BM_AUDIOIN_ADCSRR_RSRVD0	0x0000E000
+#define BF_AUDIOIN_ADCSRR_RSRVD0(v)  \
+		(((v) << 13) & BM_AUDIOIN_ADCSRR_RSRVD0)
+#define BP_AUDIOIN_ADCSRR_SRC_FRAC	0
+#define BM_AUDIOIN_ADCSRR_SRC_FRAC	0x00001FFF
+#define BF_AUDIOIN_ADCSRR_SRC_FRAC(v)  \
+		(((v) << 0) & BM_AUDIOIN_ADCSRR_SRC_FRAC)
+
+#define HW_AUDIOIN_ADCVOLUME	(0x00000030)
+#define HW_AUDIOIN_ADCVOLUME_SET	(0x00000034)
+#define HW_AUDIOIN_ADCVOLUME_CLR	(0x00000038)
+#define HW_AUDIOIN_ADCVOLUME_TOG	(0x0000003c)
+
+#define BP_AUDIOIN_ADCVOLUME_RSRVD5	29
+#define BM_AUDIOIN_ADCVOLUME_RSRVD5	0xE0000000
+#define BF_AUDIOIN_ADCVOLUME_RSRVD5(v) \
+		(((v) << 29) & BM_AUDIOIN_ADCVOLUME_RSRVD5)
+#define BM_AUDIOIN_ADCVOLUME_VOLUME_UPDATE_LEFT	0x10000000
+#define BP_AUDIOIN_ADCVOLUME_RSRVD4	26
+#define BM_AUDIOIN_ADCVOLUME_RSRVD4	0x0C000000
+#define BF_AUDIOIN_ADCVOLUME_RSRVD4(v)  \
+		(((v) << 26) & BM_AUDIOIN_ADCVOLUME_RSRVD4)
+#define BM_AUDIOIN_ADCVOLUME_EN_ZCD	0x02000000
+#define BM_AUDIOIN_ADCVOLUME_RSRVD3	0x01000000
+#define BP_AUDIOIN_ADCVOLUME_VOLUME_LEFT	16
+#define BM_AUDIOIN_ADCVOLUME_VOLUME_LEFT	0x00FF0000
+#define BF_AUDIOIN_ADCVOLUME_VOLUME_LEFT(v)  \
+		(((v) << 16) & BM_AUDIOIN_ADCVOLUME_VOLUME_LEFT)
+#define BP_AUDIOIN_ADCVOLUME_RSRVD2	13
+#define BM_AUDIOIN_ADCVOLUME_RSRVD2	0x0000E000
+#define BF_AUDIOIN_ADCVOLUME_RSRVD2(v)  \
+		(((v) << 13) & BM_AUDIOIN_ADCVOLUME_RSRVD2)
+#define BM_AUDIOIN_ADCVOLUME_VOLUME_UPDATE_RIGHT	0x00001000
+#define BP_AUDIOIN_ADCVOLUME_RSRVD1	8
+#define BM_AUDIOIN_ADCVOLUME_RSRVD1	0x00000F00
+#define BF_AUDIOIN_ADCVOLUME_RSRVD1(v)  \
+		(((v) << 8) & BM_AUDIOIN_ADCVOLUME_RSRVD1)
+#define BP_AUDIOIN_ADCVOLUME_VOLUME_RIGHT	0
+#define BM_AUDIOIN_ADCVOLUME_VOLUME_RIGHT	0x000000FF
+#define BF_AUDIOIN_ADCVOLUME_VOLUME_RIGHT(v)  \
+		(((v) << 0) & BM_AUDIOIN_ADCVOLUME_VOLUME_RIGHT)
+
+#define HW_AUDIOIN_ADCDEBUG	(0x00000040)
+#define HW_AUDIOIN_ADCDEBUG_SET	(0x00000044)
+#define HW_AUDIOIN_ADCDEBUG_CLR	(0x00000048)
+#define HW_AUDIOIN_ADCDEBUG_TOG	(0x0000004c)
+
+#define BM_AUDIOIN_ADCDEBUG_ENABLE_ADCDMA	0x80000000
+#define BP_AUDIOIN_ADCDEBUG_RSRVD1	4
+#define BM_AUDIOIN_ADCDEBUG_RSRVD1	0x7FFFFFF0
+#define BF_AUDIOIN_ADCDEBUG_RSRVD1(v)  \
+		(((v) << 4) & BM_AUDIOIN_ADCDEBUG_RSRVD1)
+#define BM_AUDIOIN_ADCDEBUG_ADC_DMA_REQ_HAND_SHAKE_CLK_CROSS	0x00000008
+#define BM_AUDIOIN_ADCDEBUG_SET_INTERRUPT3_HAND_SHAKE	0x00000004
+#define BM_AUDIOIN_ADCDEBUG_DMA_PREQ	0x00000002
+#define BM_AUDIOIN_ADCDEBUG_FIFO_STATUS	0x00000001
+
+#define HW_AUDIOIN_ADCVOL	(0x00000050)
+#define HW_AUDIOIN_ADCVOL_SET	(0x00000054)
+#define HW_AUDIOIN_ADCVOL_CLR	(0x00000058)
+#define HW_AUDIOIN_ADCVOL_TOG	(0x0000005c)
+
+#define BP_AUDIOIN_ADCVOL_RSRVD4	29
+#define BM_AUDIOIN_ADCVOL_RSRVD4	0xE0000000
+#define BF_AUDIOIN_ADCVOL_RSRVD4(v) \
+		(((v) << 29) & BM_AUDIOIN_ADCVOL_RSRVD4)
+#define BM_AUDIOIN_ADCVOL_VOLUME_UPDATE_PENDING	0x10000000
+#define BP_AUDIOIN_ADCVOL_RSRVD3	26
+#define BM_AUDIOIN_ADCVOL_RSRVD3	0x0C000000
+#define BF_AUDIOIN_ADCVOL_RSRVD3(v)  \
+		(((v) << 26) & BM_AUDIOIN_ADCVOL_RSRVD3)
+#define BM_AUDIOIN_ADCVOL_EN_ADC_ZCD	0x02000000
+#define BM_AUDIOIN_ADCVOL_MUTE	0x01000000
+#define BP_AUDIOIN_ADCVOL_RSRVD2	14
+#define BM_AUDIOIN_ADCVOL_RSRVD2	0x00FFC000
+#define BF_AUDIOIN_ADCVOL_RSRVD2(v)  \
+		(((v) << 14) & BM_AUDIOIN_ADCVOL_RSRVD2)
+#define BP_AUDIOIN_ADCVOL_SELECT_LEFT	12
+#define BM_AUDIOIN_ADCVOL_SELECT_LEFT	0x00003000
+#define BF_AUDIOIN_ADCVOL_SELECT_LEFT(v)  \
+		(((v) << 12) & BM_AUDIOIN_ADCVOL_SELECT_LEFT)
+#define BP_AUDIOIN_ADCVOL_GAIN_LEFT	8
+#define BM_AUDIOIN_ADCVOL_GAIN_LEFT	0x00000F00
+#define BF_AUDIOIN_ADCVOL_GAIN_LEFT(v)  \
+		(((v) << 8) & BM_AUDIOIN_ADCVOL_GAIN_LEFT)
+#define BP_AUDIOIN_ADCVOL_RSRVD1	6
+#define BM_AUDIOIN_ADCVOL_RSRVD1	0x000000C0
+#define BF_AUDIOIN_ADCVOL_RSRVD1(v)  \
+		(((v) << 6) & BM_AUDIOIN_ADCVOL_RSRVD1)
+#define BP_AUDIOIN_ADCVOL_SELECT_RIGHT	4
+#define BM_AUDIOIN_ADCVOL_SELECT_RIGHT	0x00000030
+#define BF_AUDIOIN_ADCVOL_SELECT_RIGHT(v)  \
+		(((v) << 4) & BM_AUDIOIN_ADCVOL_SELECT_RIGHT)
+#define BP_AUDIOIN_ADCVOL_GAIN_RIGHT	0
+#define BM_AUDIOIN_ADCVOL_GAIN_RIGHT	0x0000000F
+#define BF_AUDIOIN_ADCVOL_GAIN_RIGHT(v)  \
+		(((v) << 0) & BM_AUDIOIN_ADCVOL_GAIN_RIGHT)
+
+#define HW_AUDIOIN_MICLINE	(0x00000060)
+#define HW_AUDIOIN_MICLINE_SET	(0x00000064)
+#define HW_AUDIOIN_MICLINE_CLR	(0x00000068)
+#define HW_AUDIOIN_MICLINE_TOG	(0x0000006c)
+
+#define BP_AUDIOIN_MICLINE_RSRVD6	30
+#define BM_AUDIOIN_MICLINE_RSRVD6	0xC0000000
+#define BF_AUDIOIN_MICLINE_RSRVD6(v) \
+		(((v) << 30) & BM_AUDIOIN_MICLINE_RSRVD6)
+#define BM_AUDIOIN_MICLINE_DIVIDE_LINE1	0x20000000
+#define BM_AUDIOIN_MICLINE_DIVIDE_LINE2	0x10000000
+#define BP_AUDIOIN_MICLINE_RSRVD5	25
+#define BM_AUDIOIN_MICLINE_RSRVD5	0x0E000000
+#define BF_AUDIOIN_MICLINE_RSRVD5(v)  \
+		(((v) << 25) & BM_AUDIOIN_MICLINE_RSRVD5)
+#define BM_AUDIOIN_MICLINE_MIC_SELECT	0x01000000
+#define BP_AUDIOIN_MICLINE_RSRVD4	22
+#define BM_AUDIOIN_MICLINE_RSRVD4	0x00C00000
+#define BF_AUDIOIN_MICLINE_RSRVD4(v)  \
+		(((v) << 22) & BM_AUDIOIN_MICLINE_RSRVD4)
+#define BP_AUDIOIN_MICLINE_MIC_RESISTOR	20
+#define BM_AUDIOIN_MICLINE_MIC_RESISTOR	0x00300000
+#define BF_AUDIOIN_MICLINE_MIC_RESISTOR(v)  \
+		(((v) << 20) & BM_AUDIOIN_MICLINE_MIC_RESISTOR)
+#define BM_AUDIOIN_MICLINE_RSRVD3	0x00080000
+#define BP_AUDIOIN_MICLINE_MIC_BIAS	16
+#define BM_AUDIOIN_MICLINE_MIC_BIAS	0x00070000
+#define BF_AUDIOIN_MICLINE_MIC_BIAS(v)  \
+		(((v) << 16) & BM_AUDIOIN_MICLINE_MIC_BIAS)
+#define BP_AUDIOIN_MICLINE_RSRVD2	6
+#define BM_AUDIOIN_MICLINE_RSRVD2	0x0000FFC0
+#define BF_AUDIOIN_MICLINE_RSRVD2(v)  \
+		(((v) << 6) & BM_AUDIOIN_MICLINE_RSRVD2)
+#define BP_AUDIOIN_MICLINE_MIC_CHOPCLK	4
+#define BM_AUDIOIN_MICLINE_MIC_CHOPCLK	0x00000030
+#define BF_AUDIOIN_MICLINE_MIC_CHOPCLK(v)  \
+		(((v) << 4) & BM_AUDIOIN_MICLINE_MIC_CHOPCLK)
+#define BP_AUDIOIN_MICLINE_RSRVD1	2
+#define BM_AUDIOIN_MICLINE_RSRVD1	0x0000000C
+#define BF_AUDIOIN_MICLINE_RSRVD1(v)  \
+		(((v) << 2) & BM_AUDIOIN_MICLINE_RSRVD1)
+#define BP_AUDIOIN_MICLINE_MIC_GAIN	0
+#define BM_AUDIOIN_MICLINE_MIC_GAIN	0x00000003
+#define BF_AUDIOIN_MICLINE_MIC_GAIN(v)  \
+		(((v) << 0) & BM_AUDIOIN_MICLINE_MIC_GAIN)
+
+#define HW_AUDIOIN_ANACLKCTRL	(0x00000070)
+#define HW_AUDIOIN_ANACLKCTRL_SET	(0x00000074)
+#define HW_AUDIOIN_ANACLKCTRL_CLR	(0x00000078)
+#define HW_AUDIOIN_ANACLKCTRL_TOG	(0x0000007c)
+
+#define BM_AUDIOIN_ANACLKCTRL_CLKGATE	0x80000000
+#define BP_AUDIOIN_ANACLKCTRL_RSRVD4	11
+#define BM_AUDIOIN_ANACLKCTRL_RSRVD4	0x7FFFF800
+#define BF_AUDIOIN_ANACLKCTRL_RSRVD4(v)  \
+		(((v) << 11) & BM_AUDIOIN_ANACLKCTRL_RSRVD4)
+#define BM_AUDIOIN_ANACLKCTRL_DITHER_OFF	0x00000400
+#define BM_AUDIOIN_ANACLKCTRL_SLOW_DITHER	0x00000200
+#define BM_AUDIOIN_ANACLKCTRL_INVERT_ADCCLK	0x00000100
+#define BP_AUDIOIN_ANACLKCTRL_RSRVD3	6
+#define BM_AUDIOIN_ANACLKCTRL_RSRVD3	0x000000C0
+#define BF_AUDIOIN_ANACLKCTRL_RSRVD3(v)  \
+		(((v) << 6) & BM_AUDIOIN_ANACLKCTRL_RSRVD3)
+#define BP_AUDIOIN_ANACLKCTRL_ADCCLK_SHIFT	4
+#define BM_AUDIOIN_ANACLKCTRL_ADCCLK_SHIFT	0x00000030
+#define BF_AUDIOIN_ANACLKCTRL_ADCCLK_SHIFT(v)  \
+		(((v) << 4) & BM_AUDIOIN_ANACLKCTRL_ADCCLK_SHIFT)
+#define BM_AUDIOIN_ANACLKCTRL_RSRVD2	0x00000008
+#define BP_AUDIOIN_ANACLKCTRL_ADCDIV	0
+#define BM_AUDIOIN_ANACLKCTRL_ADCDIV	0x00000007
+#define BF_AUDIOIN_ANACLKCTRL_ADCDIV(v)  \
+		(((v) << 0) & BM_AUDIOIN_ANACLKCTRL_ADCDIV)
+
+#define HW_AUDIOIN_DATA	(0x00000080)
+#define HW_AUDIOIN_DATA_SET	(0x00000084)
+#define HW_AUDIOIN_DATA_CLR	(0x00000088)
+#define HW_AUDIOIN_DATA_TOG	(0x0000008c)
+
+#define BP_AUDIOIN_DATA_HIGH	16
+#define BM_AUDIOIN_DATA_HIGH	0xFFFF0000
+#define BF_AUDIOIN_DATA_HIGH(v) \
+		(((v) << 16) & BM_AUDIOIN_DATA_HIGH)
+#define BP_AUDIOIN_DATA_LOW	0
+#define BM_AUDIOIN_DATA_LOW	0x0000FFFF
+#define BF_AUDIOIN_DATA_LOW(v)  \
+		(((v) << 0) & BM_AUDIOIN_DATA_LOW)
+
+#define BV_AUDIOIN_ADCVOL_SELECT__MIC	0x00
+
+#endif /* __MXS_ADC_CODEC_H */
--- a/sound/soc/mxs/Kconfig
+++ b/sound/soc/mxs/Kconfig
@@ -19,3 +19,13 @@ config SND_SOC_MXS_SGTL5000
 	  a sgtl5000 codec.
 
 endif	# SND_MXS_SOC
+
+
+config SND_MXS_SOC_BUILTIN
+	tristate "SoC Audio for Freescale i.MX23 built-in codec"
+	depends on ARCH_MXS
+	select SND_SOC_GENERIC_DMAENGINE_PCM
+	select SND_SOC_MXS_BUILTIN_CODEC
+	help
+	  Say Y or M if you want to add support for codecs attached to
+	  the MXS SAIF interface.
--- a/sound/soc/mxs/Makefile
+++ b/sound/soc/mxs/Makefile
@@ -8,3 +8,12 @@ obj-$(CONFIG_SND_MXS_SOC) += snd-soc-mxs
 snd-soc-mxs-sgtl5000-objs := mxs-sgtl5000.o
 
 obj-$(CONFIG_SND_SOC_MXS_SGTL5000) += snd-soc-mxs-sgtl5000.o
+
+# i.MX23 built-in audio Machine and Platform support
+snd-soc-mxs-builtin-pcm-objs := mxs-builtin-pcm.o
+snd-soc-mxs-builtin-dai-objs := mxs-builtin-dai.o
+snd-soc-mxs-builtin-audio-objs := mxs-builtin-audio.o
+
+obj-$(CONFIG_SND_MXS_SOC_BUILTIN) += snd-soc-mxs-builtin-pcm.o
+obj-$(CONFIG_SND_MXS_SOC_BUILTIN) += snd-soc-mxs-builtin-dai.o
+obj-$(CONFIG_SND_MXS_SOC_BUILTIN) += snd-soc-mxs-builtin-audio.o
--- /dev/null
+++ b/sound/soc/mxs/mxs-builtin-audio.c
@@ -0,0 +1,120 @@
+/*
+ * mxs-builtin-audio.c -- i.MX233 built-in codec ALSA Soc Audio driver
+ *
+ * Author: Michal Ulianko <michal.ulianko@gmail.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/device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/soc-dapm.h>
+#include <asm/mach-types.h>
+
+static struct snd_soc_dai_link mxs_adc_dai_link[] = {
+	{
+		.name		= "MXS ADC/DAC",
+		.stream_name	= "MXS ADC/DAC",
+		.codec_dai_name	= "mxs-builtin-codec-dai",
+//		.codec_name	= "mxs-builtin-codec",
+//		.cpu_dai_name	= "mxs-builtin-cpu-dai",
+//		.platform_name	= "mxs-builtin-cpu-dai",
+//		.ops		= &mxs_sgtl5000_hifi_ops,
+	},
+};
+
+static struct snd_soc_card mxs_adc_audio = {
+	.name		= "mxs-builtin-audio",
+	.owner		= THIS_MODULE,
+	.dai_link	= mxs_adc_dai_link,
+	.num_links	= ARRAY_SIZE(mxs_adc_dai_link),
+};
+
+static int mxsadc_audio_probe_dt(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *cpu_dai_np, *codec_np;
+	int ret = 0;
+
+	if (!np)
+		return 1; /* no device tree */
+
+	cpu_dai_np = of_parse_phandle(np, "cpu-dai", 0);
+	codec_np = of_parse_phandle(np, "audio-codec", 0);
+	if (!cpu_dai_np || !codec_np) {
+		dev_err(&pdev->dev, "phandle missing or invalid\n");
+		return -EINVAL;
+	}
+
+	mxs_adc_dai_link[0].codec_name = NULL;
+	mxs_adc_dai_link[0].codec_of_node = codec_np;
+	mxs_adc_dai_link[0].cpu_dai_name = NULL;
+	mxs_adc_dai_link[0].cpu_of_node = cpu_dai_np;
+	mxs_adc_dai_link[0].platform_name = NULL;
+	mxs_adc_dai_link[0].platform_of_node = cpu_dai_np;
+
+//	of_node_put(codec_np);
+//	of_node_put(cpu_dai_np);
+
+	return ret;
+}
+
+static int mxsadc_audio_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &mxs_adc_audio;
+	int ret;
+
+	ret = mxsadc_audio_probe_dt(pdev);
+	if (ret < 0)
+		return ret;
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+
+	ret = snd_soc_register_card(card);
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mxsadc_audio_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+
+	return 0;
+}
+
+static const struct of_device_id mxs_adc_audio_dt_ids[] = {
+	{ .compatible = "fsl,mxs-builtin-audio", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxs_adc_audio_dt_ids);
+
+static struct platform_driver mxs_adc_audio_driver = {
+	.driver = {
+		.name = "mxs-builtin-audio",
+		.owner = THIS_MODULE,
+		.of_match_table = mxs_adc_audio_dt_ids,
+	},
+	.probe = mxsadc_audio_probe,
+	.remove = mxsadc_audio_remove,
+};
+
+module_platform_driver(mxs_adc_audio_driver);
+
+MODULE_DESCRIPTION("Freescale MXS ADC/DAC SoC Machine Driver");
+MODULE_AUTHOR("Michal Ulianko <michal.ulianko@gmail.com>");
+MODULE_LICENSE("GPL");
--- /dev/null
+++ b/sound/soc/mxs/mxs-builtin-dai.c
@@ -0,0 +1,588 @@
+/*
+ * mxs-builtin-dai.c -- i.MX233 built-in codec ALSA Soc Audio driver
+ *
+ * Author: Michal Ulianko <michal.ulianko@gmail.com>
+ *
+ * Based on sound/soc/mxs/mxs-adc.c for kernel 2.6.35
+ * by Vladislav Buzov <vbuzov@embeddedalley.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/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "../codecs/mxs-builtin-codec.h"
+#include "mxs-builtin-pcm.h"
+
+#define ADC_VOLUME_MIN  0x37
+
+/* TODO Use codec IO function soc snd write etc, instead of __writel __readl */
+
+// TODO use container_of
+struct mxs_irq_data {
+	struct snd_pcm_substream *substream;
+	struct mxs_adc_priv *mxs_adc;
+};
+
+struct mxs_adc_priv {
+	struct mxs_irq_data irq_data;
+	int dma_adc_err_irq;
+	int dma_dac_err_irq;
+	int hp_short_irq;
+	void __iomem *audioin_base;
+	void __iomem *audioout_base;
+	void __iomem *rtc_base;
+};
+
+typedef struct {
+	struct work_struct work;
+	struct timer_list timer;
+
+	/* target workqueue and CPU ->timer uses to queue ->work */
+	struct workqueue_struct *wq;
+	int cpu;
+
+	struct mxs_adc_priv *mxs_adc;
+} my_delayed_work_t;
+
+// static struct delayed_work work;
+// static struct delayed_work adc_ramp_work;
+// static struct delayed_work dac_ramp_work;
+// static struct delayed_work test;
+static my_delayed_work_t work;
+static my_delayed_work_t adc_ramp_work;
+static my_delayed_work_t dac_ramp_work;
+static my_delayed_work_t test;
+static bool adc_ramp_done = 1;
+static bool dac_ramp_done = 1;
+
+static inline void mxs_adc_schedule_work(struct delayed_work *work)
+{
+	schedule_delayed_work(work, HZ / 10);
+}
+
+static void mxs_adc_work(struct work_struct *work)
+{
+	struct mxs_adc_priv *mxs_adc = ((my_delayed_work_t *)work)->mxs_adc;
+	/* disable irq */
+	disable_irq(mxs_adc->hp_short_irq);
+
+	while (true) {
+		__raw_writel(BM_AUDIOOUT_PWRDN_HEADPHONE,
+		      mxs_adc->audioout_base + HW_AUDIOOUT_PWRDN_CLR);
+		msleep(10);
+		if ((__raw_readl(mxs_adc->audioout_base + HW_AUDIOOUT_ANACTRL)
+			& BM_AUDIOOUT_ANACTRL_SHORT_LR_STS) != 0) {
+			/* rearm the short protection */
+			__raw_writel(BM_AUDIOOUT_ANACTRL_SHORTMODE_LR,
+				mxs_adc->audioout_base + HW_AUDIOOUT_ANACTRL_CLR);
+			__raw_writel(BM_AUDIOOUT_ANACTRL_SHORT_LR_STS,
+				mxs_adc->audioout_base + HW_AUDIOOUT_ANACTRL_CLR);
+			__raw_writel(BF_AUDIOOUT_ANACTRL_SHORTMODE_LR(0x1),
+				mxs_adc->audioout_base + HW_AUDIOOUT_ANACTRL_SET);
+
+			__raw_writel(BM_AUDIOOUT_PWRDN_HEADPHONE,
+				mxs_adc->audioout_base + HW_AUDIOOUT_PWRDN_SET);
+			printk(KERN_WARNING "WARNING : Headphone LR short!\r\n");
+		} else {
+			printk(KERN_WARNING "INFO : Headphone LR no longer short!\r\n");
+			break;
+		}
+		msleep(1000);
+	}
+
+	/* power up the HEADPHONE and un-mute the HPVOL */
+	__raw_writel(BM_AUDIOOUT_HPVOL_MUTE,
+	      mxs_adc->audioout_base + HW_AUDIOOUT_HPVOL_CLR);
+	__raw_writel(BM_AUDIOOUT_PWRDN_HEADPHONE,
+		      mxs_adc->audioout_base + HW_AUDIOOUT_PWRDN_CLR);
+
+	/* enable irq for next short detect*/
+	enable_irq(mxs_adc->hp_short_irq);
+}
+
+static void mxs_adc_schedule_ramp_work(struct delayed_work *work)
+{
+	schedule_delayed_work(work, msecs_to_jiffies(2));
+	adc_ramp_done = 0;
+}
+
+static void mxs_adc_ramp_work(struct work_struct *work)
+{
+	struct mxs_adc_priv *mxs_adc = ((my_delayed_work_t *)work)->mxs_adc;
+	u32 reg = 0;
+	u32 reg1 = 0;
+	u32 reg2 = 0;
+	u32 l, r;
+	u32 ll, rr;
+	int i;
+
+	reg = __raw_readl(mxs_adc->audioin_base + \
+		HW_AUDIOIN_ADCVOLUME);
+
+	reg1 = reg & ~BM_AUDIOIN_ADCVOLUME_VOLUME_LEFT;
+	reg1 = reg1 & ~BM_AUDIOIN_ADCVOLUME_VOLUME_RIGHT;
+	/* minimize adc volume */
+	reg2 = reg1 |
+	    BF_AUDIOIN_ADCVOLUME_VOLUME_LEFT(ADC_VOLUME_MIN) |
+	    BF_AUDIOIN_ADCVOLUME_VOLUME_RIGHT(ADC_VOLUME_MIN);
+	__raw_writel(reg2,
+		mxs_adc->audioin_base + HW_AUDIOIN_ADCVOLUME);
+	msleep(1);
+
+	l = (reg & BM_AUDIOIN_ADCVOLUME_VOLUME_LEFT) >>
+		BP_AUDIOIN_ADCVOLUME_VOLUME_LEFT;
+	r = (reg & BM_AUDIOIN_ADCVOLUME_VOLUME_RIGHT) >>
+		BP_AUDIOIN_ADCVOLUME_VOLUME_RIGHT;
+
+	/* fade in adc vol */
+	for (i = ADC_VOLUME_MIN; (i < l) || (i < r);) {
+		i += 0x8;
+		ll = i < l ? i : l;
+		rr = i < r ? i : r;
+		reg2 = reg1 |
+		    BF_AUDIOIN_ADCVOLUME_VOLUME_LEFT(ll) |
+		    BF_AUDIOIN_ADCVOLUME_VOLUME_RIGHT(rr);
+		__raw_writel(reg2,
+		    mxs_adc->audioin_base + HW_AUDIOIN_ADCVOLUME);
+		msleep(1);
+	}
+	adc_ramp_done = 1;
+}
+
+static void mxs_dac_schedule_ramp_work(struct delayed_work *work)
+{
+	schedule_delayed_work(work, msecs_to_jiffies(2));
+	dac_ramp_done = 0;
+}
+
+static void mxs_dac_ramp_work(struct work_struct *work)
+{
+	struct mxs_adc_priv *mxs_adc = ((my_delayed_work_t *)work)->mxs_adc;
+	u32 reg = 0;
+	u32 reg1 = 0;
+	u32 l, r;
+	u32 ll, rr;
+	int i;
+
+	/* unmute hp and speaker */
+	__raw_writel(BM_AUDIOOUT_HPVOL_MUTE,
+		mxs_adc->audioout_base + HW_AUDIOOUT_HPVOL_CLR);
+	__raw_writel(BM_AUDIOOUT_SPEAKERCTRL_MUTE,
+		mxs_adc->audioout_base + HW_AUDIOOUT_SPEAKERCTRL_CLR);
+
+	reg = __raw_readl(mxs_adc->audioout_base + \
+			HW_AUDIOOUT_HPVOL);
+
+	reg1 = reg & ~BM_AUDIOOUT_HPVOL_VOL_LEFT;
+	reg1 = reg1 & ~BM_AUDIOOUT_HPVOL_VOL_RIGHT;
+
+	l = (reg & BM_AUDIOOUT_HPVOL_VOL_LEFT) >>
+		BP_AUDIOOUT_HPVOL_VOL_LEFT;
+	r = (reg & BM_AUDIOOUT_HPVOL_VOL_RIGHT) >>
+		BP_AUDIOOUT_HPVOL_VOL_RIGHT;
+	/* fade in hp vol */
+	for (i = 0x7f; i > 0 ;) {
+		i -= 0x8;
+		ll = i > (int)l ? i : l;
+		rr = i > (int)r ? i : r;
+		reg = reg1 | BF_AUDIOOUT_HPVOL_VOL_LEFT(ll)
+			| BF_AUDIOOUT_HPVOL_VOL_RIGHT(rr);
+		__raw_writel(reg,
+			mxs_adc->audioout_base + HW_AUDIOOUT_HPVOL);
+		msleep(1);
+	}
+	dac_ramp_done = 1;
+}
+
+/* IRQs */
+static irqreturn_t mxs_short_irq(int irq, void *dev_id)
+{
+	struct mxs_adc_priv *mxs_adc = dev_id;
+	//struct snd_pcm_substream *substream = mxs_adc->irq_data.substream;
+
+	__raw_writel(BM_AUDIOOUT_ANACTRL_SHORTMODE_LR,
+		mxs_adc->audioout_base + HW_AUDIOOUT_ANACTRL_CLR);
+	__raw_writel(BM_AUDIOOUT_ANACTRL_SHORT_LR_STS,
+		mxs_adc->audioout_base + HW_AUDIOOUT_ANACTRL_CLR);
+	__raw_writel(BF_AUDIOOUT_ANACTRL_SHORTMODE_LR(0x1),
+		mxs_adc->audioout_base + HW_AUDIOOUT_ANACTRL_SET);
+
+	__raw_writel(BM_AUDIOOUT_HPVOL_MUTE,
+	      mxs_adc->audioout_base + HW_AUDIOOUT_HPVOL_SET);
+	__raw_writel(BM_AUDIOOUT_PWRDN_HEADPHONE,
+		      mxs_adc->audioout_base + HW_AUDIOOUT_PWRDN_SET);
+	__raw_writel(BM_AUDIOOUT_ANACTRL_HP_CLASSAB,
+		mxs_adc->audioout_base + HW_AUDIOOUT_ANACTRL_SET);
+
+	mxs_adc_schedule_work((struct delayed_work *) &work);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t mxs_err_irq(int irq, void *dev_id)
+{
+	struct mxs_adc_priv *mxs_adc = dev_id;
+	struct snd_pcm_substream *substream = mxs_adc->irq_data.substream;
+	int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0;
+	u32 ctrl_reg;
+	u32 overflow_mask;
+	u32 underflow_mask;
+
+	if (playback) {
+		ctrl_reg = __raw_readl(mxs_adc->audioout_base + HW_AUDIOOUT_CTRL);
+		underflow_mask = BM_AUDIOOUT_CTRL_FIFO_UNDERFLOW_IRQ;
+		overflow_mask = BM_AUDIOOUT_CTRL_FIFO_OVERFLOW_IRQ;
+	} else {
+		ctrl_reg = __raw_readl(mxs_adc->audioin_base + HW_AUDIOIN_CTRL);
+		underflow_mask = BM_AUDIOIN_CTRL_FIFO_UNDERFLOW_IRQ;
+		overflow_mask = BM_AUDIOIN_CTRL_FIFO_OVERFLOW_IRQ;
+	}
+
+	if (ctrl_reg & underflow_mask) {
+		printk(KERN_DEBUG "%s underflow detected\n",
+		       playback ? "DAC" : "ADC");
+
+		if (playback)
+			__raw_writel(
+				BM_AUDIOOUT_CTRL_FIFO_UNDERFLOW_IRQ,
+				mxs_adc->audioout_base + HW_AUDIOOUT_CTRL_CLR);
+		else
+			__raw_writel(
+				BM_AUDIOIN_CTRL_FIFO_UNDERFLOW_IRQ,
+				mxs_adc->audioin_base + HW_AUDIOIN_CTRL_CLR);
+
+	} else if (ctrl_reg & overflow_mask) {
+		printk(KERN_DEBUG "%s overflow detected\n",
+		       playback ? "DAC" : "ADC");
+
+		if (playback)
+			__raw_writel(
+				BM_AUDIOOUT_CTRL_FIFO_OVERFLOW_IRQ,
+				mxs_adc->audioout_base + HW_AUDIOOUT_CTRL_CLR);
+		else
+			__raw_writel(BM_AUDIOIN_CTRL_FIFO_OVERFLOW_IRQ,
+				mxs_adc->audioin_base + HW_AUDIOIN_CTRL_CLR);
+	} else
+		printk(KERN_WARNING "Unknown DAC error interrupt\n");
+
+	return IRQ_HANDLED;
+}
+/* END IRQs */
+
+static int mxs_trigger(struct snd_pcm_substream *substream,
+				int cmd,
+				struct snd_soc_dai *cpu_dai)
+{
+	struct mxs_adc_priv *mxs_adc = snd_soc_dai_get_drvdata(cpu_dai);
+	int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0;
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+
+		if (playback) {
+			/* enable the fifo error interrupt */
+			__raw_writel(BM_AUDIOOUT_CTRL_FIFO_ERROR_IRQ_EN,
+			mxs_adc->audioout_base + HW_AUDIOOUT_CTRL_SET);
+			/* write a data to data reg to trigger the transfer */
+			__raw_writel(0x0,
+				mxs_adc->audioout_base + HW_AUDIOOUT_DATA);
+			mxs_dac_schedule_ramp_work((struct delayed_work *) &dac_ramp_work);
+		} else {
+// 		    mxs_dma_get_info(prtd->dma_ch, &dma_info);
+// 		    cur_bar1 = dma_info.buf_addr;
+// 		    xfer_count1 = dma_info.xfer_count;
+
+		    __raw_writel(BM_AUDIOIN_CTRL_RUN,
+			mxs_adc->audioin_base + HW_AUDIOIN_CTRL_SET);
+		    udelay(100);
+
+// 		    mxs_dma_get_info(prtd->dma_ch, &dma_info);
+// 		    cur_bar2 = dma_info.buf_addr;
+// 		    xfer_count2 = dma_info.xfer_count;
+//
+// 		    /* check if DMA getting stuck */
+// 		    if ((xfer_count1 == xfer_count2) && (cur_bar1 == cur_bar2))
+// 			/* read a data from data reg to trigger the receive */
+// 			reg = __raw_readl(mxs_adc->audioin_base + HW_AUDIOIN_DATA);
+
+		    mxs_adc_schedule_ramp_work((struct delayed_work *) &adc_ramp_work);
+		}
+		break;
+
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+
+		if (playback) {
+// 			printk(KERN_INFO "SNDRV_PCM_TRIGGER_START\n");
+// 			printk(KERN_INFO "ctrl:%x\n", __raw_readl(mxs_adc->audioout_base + HW_AUDIOOUT_CTRL));
+// 			printk(KERN_INFO "stat:%x\n", __raw_readl(mxs_adc->audioout_base + HW_AUDIOOUT_STAT));
+// 			printk(KERN_INFO "srr:%x\n", __raw_readl(mxs_adc->audioout_base + HW_AUDIOOUT_DACSRR));
+// 			printk(KERN_INFO "vol:%x\n", __raw_readl(mxs_adc->audioout_base + HW_AUDIOOUT_DACVOLUME));
+// 			printk(KERN_INFO "debug:%x\n", __raw_readl(mxs_adc->audioout_base + HW_AUDIOOUT_DACDEBUG));
+// 			printk(KERN_INFO "hpvol:%x\n", __raw_readl(mxs_adc->audioout_base + HW_AUDIOOUT_HPVOL));
+// 			printk(KERN_INFO "pwrdn:%x\n", __raw_readl(mxs_adc->audioout_base + HW_AUDIOOUT_PWRDN));
+// 			printk(KERN_INFO "refc:%x\n", __raw_readl(mxs_adc->audioout_base + HW_AUDIOOUT_REFCTRL));
+// 			printk(KERN_INFO "anac:%x\n", __raw_readl(mxs_adc->audioout_base + HW_AUDIOOUT_ANACTRL));
+// 			printk(KERN_INFO "test:%x\n", __raw_readl(mxs_adc->audioout_base + HW_AUDIOOUT_TEST));
+// 			printk(KERN_INFO "bist:%x\n", __raw_readl(mxs_adc->audioout_base + HW_AUDIOOUT_BISTCTRL));
+// 			printk(KERN_INFO "anaclk:%x\n", __raw_readl(mxs_adc->audioout_base + HW_AUDIOOUT_ANACLKCTRL));
+
+			if (dac_ramp_done == 0) {
+				cancel_delayed_work((struct delayed_work *) &dac_ramp_work);
+				dac_ramp_done = 1;
+			}
+			__raw_writel(BM_AUDIOOUT_HPVOL_MUTE,
+			  mxs_adc->audioout_base + HW_AUDIOOUT_HPVOL_SET);
+			__raw_writel(BM_AUDIOOUT_SPEAKERCTRL_MUTE,
+			  mxs_adc->audioout_base + HW_AUDIOOUT_SPEAKERCTRL_SET);
+			/* disable the fifo error interrupt */
+			__raw_writel(BM_AUDIOOUT_CTRL_FIFO_ERROR_IRQ_EN,
+				mxs_adc->audioout_base + HW_AUDIOOUT_CTRL_CLR);
+			mdelay(50);
+		} else {
+			if (adc_ramp_done == 0) {
+				cancel_delayed_work((struct delayed_work *) &adc_ramp_work);
+				adc_ramp_done = 1;
+			}
+			__raw_writel(BM_AUDIOIN_CTRL_RUN,
+				mxs_adc->audioin_base + HW_AUDIOIN_CTRL_CLR);
+		}
+		break;
+
+	default:
+		printk(KERN_ERR "TRIGGER ERROR\n");
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int mxs_startup(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *cpu_dai)
+{
+	struct mxs_adc_priv *mxs_adc = snd_soc_dai_get_drvdata(cpu_dai);
+	int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0;
+	mxs_adc->irq_data.mxs_adc = mxs_adc;
+	mxs_adc->irq_data.substream = substream;
+
+	work.mxs_adc = mxs_adc;
+	adc_ramp_work.mxs_adc = mxs_adc;
+	dac_ramp_work.mxs_adc = mxs_adc;
+	test.mxs_adc = mxs_adc;
+	INIT_DELAYED_WORK(&work, mxs_adc_work);
+	INIT_DELAYED_WORK(&adc_ramp_work, mxs_adc_ramp_work);
+	INIT_DELAYED_WORK(&dac_ramp_work, mxs_dac_ramp_work);
+
+	/* Enable error interrupt */
+	if (playback) {
+		__raw_writel(BM_AUDIOOUT_CTRL_FIFO_OVERFLOW_IRQ,
+			mxs_adc->audioout_base + HW_AUDIOOUT_CTRL_CLR);
+		__raw_writel(BM_AUDIOOUT_CTRL_FIFO_UNDERFLOW_IRQ,
+			mxs_adc->audioout_base + HW_AUDIOOUT_CTRL_CLR);
+	} else {
+		__raw_writel(BM_AUDIOIN_CTRL_FIFO_OVERFLOW_IRQ,
+			mxs_adc->audioin_base + HW_AUDIOIN_CTRL_CLR);
+		__raw_writel(BM_AUDIOIN_CTRL_FIFO_UNDERFLOW_IRQ,
+			mxs_adc->audioin_base + HW_AUDIOIN_CTRL_CLR);
+		__raw_writel(BM_AUDIOIN_CTRL_FIFO_ERROR_IRQ_EN,
+			mxs_adc->audioin_base + HW_AUDIOIN_CTRL_SET);
+	}
+
+	return 0;
+}
+
+static void mxs_shutdown(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *cpu_dai)
+{
+	struct mxs_adc_priv *mxs_adc = snd_soc_dai_get_drvdata(cpu_dai);
+	int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0;
+
+	/* Disable error interrupt */
+	if (playback) {
+		__raw_writel(BM_AUDIOOUT_CTRL_FIFO_ERROR_IRQ_EN,
+			mxs_adc->audioout_base + HW_AUDIOOUT_CTRL_CLR);
+	} else {
+		__raw_writel(BM_AUDIOIN_CTRL_FIFO_ERROR_IRQ_EN,
+			mxs_adc->audioin_base + HW_AUDIOIN_CTRL_CLR);
+	}
+}
+
+#define MXS_ADC_RATES	SNDRV_PCM_RATE_8000_192000
+#define MXS_ADC_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static const struct snd_soc_dai_ops mxs_adc_dai_ops = {
+	.startup = mxs_startup,
+	.trigger = mxs_trigger,
+	.shutdown = mxs_shutdown,
+};
+
+static int mxs_dai_probe(struct snd_soc_dai *dai)
+{
+	// TODO This does not make any sense.
+	struct mxs_adc_priv *mxs_adc = dev_get_drvdata(dai->dev);
+
+	snd_soc_dai_set_drvdata(dai, mxs_adc);
+
+	return 0;
+}
+
+static struct snd_soc_dai_driver mxs_adc_dai = {
+	.name = "mxs-builtin-cpu-dai",
+	.probe = mxs_dai_probe,
+	.playback = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = MXS_ADC_RATES,
+		.formats = MXS_ADC_FORMATS,
+	},
+	.capture = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = MXS_ADC_RATES,
+		.formats = MXS_ADC_FORMATS,
+	},
+	.ops = &mxs_adc_dai_ops,
+};
+
+static const struct snd_soc_component_driver mxs_adc_component = {
+	.name		= "mxs-xxx",	//TODO change this name
+};
+
+static int mxs_adc_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct mxs_adc_priv *mxs_adc;
+	int ret = 0;
+
+	if (!np)
+		return -EINVAL;
+
+	mxs_adc = devm_kzalloc(&pdev->dev, sizeof(*mxs_adc), GFP_KERNEL);
+	if (!mxs_adc)
+		return -ENOMEM;
+
+	mxs_adc->audioout_base = devm_ioremap(&pdev->dev, 0x80048000, 0x2000);
+	if (IS_ERR(mxs_adc->audioout_base))
+		return PTR_ERR(mxs_adc->audioout_base);
+
+	mxs_adc->audioin_base = devm_ioremap(&pdev->dev, 0x8004c000, 0x2000);
+	if (IS_ERR(mxs_adc->audioin_base))
+		return PTR_ERR(mxs_adc->audioin_base);
+
+	mxs_adc->rtc_base = devm_ioremap(&pdev->dev, 0x8005c000, 0x2000);
+	if (IS_ERR(mxs_adc->rtc_base))
+		return PTR_ERR(mxs_adc->rtc_base);
+
+	/* Get IRQ numbers */
+	mxs_adc->dma_adc_err_irq = platform_get_irq(pdev, 0);
+	if (mxs_adc->dma_adc_err_irq < 0) {
+		ret = mxs_adc->dma_adc_err_irq;
+		dev_err(&pdev->dev, "failed to get ADC DMA ERR irq resource: %d\n", ret);
+		return ret;
+	}
+
+	mxs_adc->dma_dac_err_irq = platform_get_irq(pdev, 1);
+	if (mxs_adc->dma_dac_err_irq < 0) {
+		ret = mxs_adc->dma_dac_err_irq;
+		dev_err(&pdev->dev, "failed to get DAC DMA ERR irq resource: %d\n", ret);
+		return ret;
+	}
+
+	mxs_adc->hp_short_irq = platform_get_irq(pdev, 2);
+	if (mxs_adc->hp_short_irq < 0) {
+		ret = mxs_adc->hp_short_irq;
+		dev_err(&pdev->dev, "failed to get HP_SHORT irq resource: %d\n", ret);
+		return ret;
+	}
+
+	/* Request IRQs */
+	ret = devm_request_irq(&pdev->dev, mxs_adc->dma_adc_err_irq, mxs_err_irq, 0, "MXS DAC and ADC Error",
+			  mxs_adc);
+	if (ret) {
+		printk(KERN_ERR "%s: Unable to request ADC/DAC error irq %d\n",
+		       __func__, mxs_adc->dma_adc_err_irq);
+		return ret;
+	}
+
+	ret = devm_request_irq(&pdev->dev, mxs_adc->dma_dac_err_irq, mxs_err_irq, 0, "MXS DAC and ADC Error",
+			  mxs_adc);
+	if (ret) {
+		printk(KERN_ERR "%s: Unable to request ADC/DAC error irq %d\n",
+		       __func__, mxs_adc->dma_dac_err_irq);
+		return ret;
+	}
+
+	ret = devm_request_irq(&pdev->dev, mxs_adc->hp_short_irq, mxs_short_irq,
+		IRQF_DISABLED | IRQF_SHARED, "MXS DAC and ADC HP SHORT", mxs_adc);
+	if (ret) {
+		printk(KERN_ERR "%s: Unable to request ADC/DAC HP SHORT irq %d\n",
+		       __func__, mxs_adc->hp_short_irq);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, mxs_adc);
+
+	ret = snd_soc_register_component(&pdev->dev, &mxs_adc_component, &mxs_adc_dai, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "register DAI failed\n");
+		return ret;
+	}
+
+	ret = mxs_adc_pcm_platform_register(&pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
+		goto failed_pdev_alloc;
+	}
+
+	return 0;
+
+failed_pdev_alloc:
+	snd_soc_unregister_component(&pdev->dev);
+
+	return ret;
+}
+
+static int mxs_adc_remove(struct platform_device *pdev)
+{
+	mxs_adc_pcm_platform_unregister(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id mxs_adc_dai_dt_ids[] = {
+	{ .compatible = "fsl,mxs-builtin-cpu-dai", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxs_adc_dai_dt_ids);
+
+static struct platform_driver mxs_adc_dai_driver = {
+	.probe = mxs_adc_probe,
+	.remove = mxs_adc_remove,
+
+	.driver = {
+		.name = "mxs-builtin-cpu-dai",
+		.owner = THIS_MODULE,
+		.of_match_table = mxs_adc_dai_dt_ids,
+	},
+};
+
+module_platform_driver(mxs_adc_dai_driver);
+
+MODULE_DESCRIPTION("Freescale MXS ADC/DAC SoC Codec DAI Driver");
+MODULE_AUTHOR("Michal Ulianko <michal.ulianko@gmail.com>");
+MODULE_LICENSE("GPL");
--- /dev/null
+++ b/sound/soc/mxs/mxs-builtin-pcm.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Based on sound/soc/imx/imx-pcm-dma-mx2.c
+ *
+ * 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.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
+
+#include "mxs-builtin-pcm.h"
+
+static const struct snd_pcm_hardware snd_mxs_hardware = {
+	.info			= SNDRV_PCM_INFO_MMAP |
+				  SNDRV_PCM_INFO_MMAP_VALID |
+				  SNDRV_PCM_INFO_PAUSE |
+				  SNDRV_PCM_INFO_RESUME |
+				  SNDRV_PCM_INFO_INTERLEAVED,
+	.formats		= SNDRV_PCM_FMTBIT_S16_LE |
+				  SNDRV_PCM_FMTBIT_S20_3LE |
+				  SNDRV_PCM_FMTBIT_S24_LE,
+	.channels_min		= 2,
+	.channels_max		= 2,
+	.period_bytes_min	= 32,
+	.period_bytes_max	= 8192,
+	.periods_min		= 1,
+	.periods_max		= 52,
+	.buffer_bytes_max	= 64 * 1024,
+	.fifo_size		= 32,
+};
+
+static const struct snd_dmaengine_pcm_config mxs_dmaengine_pcm_config = {
+	.pcm_hardware = &snd_mxs_hardware,
+	.prealloc_buffer_size = 64 * 1024,
+};
+
+int mxs_adc_pcm_platform_register(struct device *dev)
+{
+	return snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config,
+		SND_DMAENGINE_PCM_FLAG_NO_RESIDUE);
+}
+EXPORT_SYMBOL_GPL(mxs_adc_pcm_platform_register);
+
+void mxs_adc_pcm_platform_unregister(struct device *dev)
+{
+	snd_dmaengine_pcm_unregister(dev);
+}
+EXPORT_SYMBOL_GPL(mxs_adc_pcm_platform_unregister);
+
+MODULE_LICENSE("GPL");
--- /dev/null
+++ b/sound/soc/mxs/mxs-builtin-pcm.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _MXS_PCM_H
+#define _MXS_PCM_H
+
+int mxs_adc_pcm_platform_register(struct device *dev);
+void mxs_adc_pcm_platform_unregister(struct device *dev);
+
+#endif
