zte's code,first commit

Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/Kconfig b/ap/os/linux/linux-3.4.x/sound/soc/omap/Kconfig
new file mode 100644
index 0000000..deafbfa
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/Kconfig
@@ -0,0 +1,152 @@
+config SND_OMAP_SOC
+	tristate "SoC Audio for the Texas Instruments OMAP chips"
+	depends on ARCH_OMAP
+
+config SND_OMAP_SOC_DMIC
+	tristate
+
+config SND_OMAP_SOC_MCBSP
+	tristate
+
+config SND_OMAP_SOC_MCPDM
+	tristate
+
+config SND_OMAP_SOC_HDMI
+	tristate
+
+config SND_OMAP_SOC_N810
+	tristate "SoC Audio support for Nokia N810"
+	depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C
+	depends on OMAP_MUX
+	select SND_OMAP_SOC_MCBSP
+	select SND_SOC_TLV320AIC3X
+	help
+	  Say Y if you want to add support for SoC audio on Nokia N810.
+
+config SND_OMAP_SOC_RX51
+	tristate "SoC Audio support for Nokia RX-51"
+	depends on SND_OMAP_SOC && MACH_NOKIA_RX51
+	select SND_OMAP_SOC_MCBSP
+	select SND_SOC_TLV320AIC3X
+	select SND_SOC_TPA6130A2
+	help
+	  Say Y if you want to add support for SoC audio on Nokia RX-51
+	  hardware. This is also known as Nokia N900 product.
+
+config SND_OMAP_SOC_AMS_DELTA
+	tristate "SoC Audio support for Amstrad E3 (Delta) videophone"
+	depends on SND_OMAP_SOC && MACH_AMS_DELTA
+	select SND_OMAP_SOC_MCBSP
+	select SND_SOC_CX20442
+	help
+	  Say Y  if you want to add support  for SoC audio device  connected to
+	  a handset and a speakerphone found on Amstrad E3 (Delta) videophone.
+
+	  Note that in order to get those devices fully supported,  you have to
+	  build  the kernel  with  standard  serial port  driver  included  and
+	  configured for at least 4 ports.  Then, from userspace, you must load
+	  a line discipline #19 on the modem (ttyS3) serial line.  The simplest
+	  way to achieve this is to install util-linux-ng  and use the included
+	  ldattach  utility.  This  can be  started  automatically  from  udev,
+	  a simple rule like this one should do the trick (it does for me):
+	  	ACTION=="add", KERNEL=="controlC0", \
+				RUN+="/usr/sbin/ldattach 19 /dev/ttyS3"
+
+config SND_OMAP_SOC_OSK5912
+	tristate "SoC Audio support for omap osk5912"
+	depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C
+	select SND_OMAP_SOC_MCBSP
+	select SND_SOC_TLV320AIC23
+	help
+	  Say Y if you want to add support for SoC audio on osk5912.
+
+config SND_OMAP_SOC_OVERO
+	tristate "SoC Audio support for Gumstix Overo and CompuLab CM-T35"
+	depends on TWL4030_CORE && SND_OMAP_SOC && (MACH_OVERO || MACH_CM_T35)
+	select SND_OMAP_SOC_MCBSP
+	select SND_SOC_TWL4030
+	help
+	  Say Y if you want to add support for SoC audio on the
+	  Gumstix Overo or CompuLab CM-T35
+
+config SND_OMAP_SOC_OMAP3EVM
+	tristate "SoC Audio support for OMAP3EVM board"
+	depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3EVM
+	select SND_OMAP_SOC_MCBSP
+	select SND_SOC_TWL4030
+	help
+	  Say Y if you want to add support for SoC audio on the omap3evm board.
+
+config SND_OMAP_SOC_AM3517EVM
+	tristate "SoC Audio support for OMAP3517 / AM3517 EVM"
+	depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C
+	select SND_OMAP_SOC_MCBSP
+	select SND_SOC_TLV320AIC23
+	help
+	  Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517
+	  EVM.
+
+config SND_OMAP_SOC_SDP3430
+	tristate "SoC Audio support for Texas Instruments SDP3430"
+	depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP
+	select SND_OMAP_SOC_MCBSP
+	select SND_SOC_TWL4030
+	help
+	  Say Y if you want to add support for SoC audio on Texas Instruments
+	  SDP3430.
+
+config SND_OMAP_SOC_OMAP_ABE_TWL6040
+	tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec"
+	depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4
+	select SND_OMAP_SOC_DMIC
+	select SND_OMAP_SOC_MCPDM
+	select SND_SOC_TWL6040
+	select SND_SOC_DMIC
+	help
+	  Say Y if you want to add support for SoC audio on OMAP boards using
+	  ABE and twl6040 codec. This driver currently supports:
+	  - SDP4430/Blaze boards
+	  - PandaBoard (4430)
+	  - PandaBoardES (4460)
+
+config SND_OMAP_SOC_OMAP4_HDMI
+	tristate "SoC Audio support for Texas Instruments OMAP4 HDMI"
+	depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS && ARCH_OMAP4
+	select SND_OMAP_SOC_HDMI
+	help
+	  Say Y if you want to add support for SoC HDMI audio on Texas Instruments
+	  OMAP4 chips
+
+config SND_OMAP_SOC_OMAP3_PANDORA
+	tristate "SoC Audio support for OMAP3 Pandora"
+	depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA
+	select SND_OMAP_SOC_MCBSP
+	select SND_SOC_TWL4030
+	help
+	  Say Y if you want to add support for SoC audio on the OMAP3 Pandora.
+
+config SND_OMAP_SOC_OMAP3_BEAGLE
+	tristate "SoC Audio support for OMAP3 Beagle and Devkit8000"
+	depends on TWL4030_CORE && SND_OMAP_SOC
+	depends on (MACH_OMAP3_BEAGLE || MACH_DEVKIT8000)
+	select SND_OMAP_SOC_MCBSP
+	select SND_SOC_TWL4030
+	help
+	  Say Y if you want to add support for SoC audio on the Beagleboard or
+	  the clone Devkit8000.
+
+config SND_OMAP_SOC_ZOOM2
+	tristate "SoC Audio support for Zoom2"
+	depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2
+	select SND_OMAP_SOC_MCBSP
+	select SND_SOC_TWL4030
+	help
+	  Say Y if you want to add support for Soc audio on Zoom2 board.
+
+config SND_OMAP_SOC_IGEP0020
+	tristate "SoC Audio support for IGEP v2"
+	depends on TWL4030_CORE && SND_OMAP_SOC && MACH_IGEP0020
+	select SND_OMAP_SOC_MCBSP
+	select SND_SOC_TWL4030
+	help
+	  Say Y if you want to add support for Soc audio on IGEP v2 board.
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/Makefile b/ap/os/linux/linux-3.4.x/sound/soc/omap/Makefile
new file mode 100644
index 0000000..1d656bc
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/Makefile
@@ -0,0 +1,44 @@
+# OMAP Platform Support
+snd-soc-omap-objs := omap-pcm.o
+snd-soc-omap-dmic-objs := omap-dmic.o
+snd-soc-omap-mcbsp-objs := omap-mcbsp.o mcbsp.o
+snd-soc-omap-mcpdm-objs := omap-mcpdm.o
+snd-soc-omap-hdmi-objs := omap-hdmi.o
+
+obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o
+obj-$(CONFIG_SND_OMAP_SOC_DMIC) += snd-soc-omap-dmic.o
+obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
+obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o
+obj-$(CONFIG_SND_OMAP_SOC_HDMI) += snd-soc-omap-hdmi.o
+
+# OMAP Machine Support
+snd-soc-n810-objs := n810.o
+snd-soc-rx51-objs := rx51.o
+snd-soc-ams-delta-objs := ams-delta.o
+snd-soc-osk5912-objs := osk5912.o
+snd-soc-overo-objs := overo.o
+snd-soc-omap3evm-objs := omap3evm.o
+snd-soc-am3517evm-objs := am3517evm.o
+snd-soc-sdp3430-objs := sdp3430.o
+snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o
+snd-soc-omap3pandora-objs := omap3pandora.o
+snd-soc-omap3beagle-objs := omap3beagle.o
+snd-soc-zoom2-objs := zoom2.o
+snd-soc-igep0020-objs := igep0020.o
+snd-soc-omap4-hdmi-objs := omap4-hdmi-card.o
+
+obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
+obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o
+obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o
+obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
+obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
+obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o
+obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o
+obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o
+obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
+obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o
+obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
+obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
+obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
+obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o
+obj-$(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) += snd-soc-omap4-hdmi.o
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/am3517evm.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/am3517evm.c
new file mode 100644
index 0000000..009533a
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/am3517evm.c
@@ -0,0 +1,161 @@
+/*
+ * am3517evm.c  -- ALSA SoC support for OMAP3517 / AM3517 EVM
+ *
+ * Author: Anuj Aggarwal <anuj.aggarwal@ti.com>
+ *
+ * Based on sound/soc/omap/beagle.c by Steve Sakoman
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <plat/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+
+#include "../codecs/tlv320aic23.h"
+
+#define CODEC_CLOCK 	12000000
+
+static int am3517evm_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret;
+
+	/* Set the codec system clock for DAC and ADC */
+	ret = snd_soc_dai_set_sysclk(codec_dai, 0,
+			CODEC_CLOCK, SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set codec system clock\n");
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_CLKR_SRC_CLKX, 0,
+				SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_CLKR_SRC_CLKX\n");
+		return ret;
+	}
+
+	snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0,
+				SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops am3517evm_ops = {
+	.hw_params = am3517evm_hw_params,
+};
+
+/* am3517evm machine dapm widgets */
+static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Line Out", NULL),
+	SND_SOC_DAPM_LINE("Line In", NULL),
+	SND_SOC_DAPM_MIC("Mic In", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	/* Line Out connected to LLOUT, RLOUT */
+	{"Line Out", NULL, "LOUT"},
+	{"Line Out", NULL, "ROUT"},
+
+	{"LLINEIN", NULL, "Line In"},
+	{"RLINEIN", NULL, "Line In"},
+
+	{"MICIN", NULL, "Mic In"},
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link am3517evm_dai = {
+	.name = "TLV320AIC23",
+	.stream_name = "AIC23",
+	.cpu_dai_name = "omap-mcbsp.1",
+	.codec_dai_name = "tlv320aic23-hifi",
+	.platform_name = "omap-pcm-audio",
+	.codec_name = "tlv320aic23-codec.2-001a",
+	.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBM_CFM,
+	.ops = &am3517evm_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_am3517evm = {
+	.name = "am3517evm",
+	.owner = THIS_MODULE,
+	.dai_link = &am3517evm_dai,
+	.num_links = 1,
+
+	.dapm_widgets = tlv320aic23_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
+static struct platform_device *am3517evm_snd_device;
+
+static int __init am3517evm_soc_init(void)
+{
+	int ret;
+
+	if (!machine_is_omap3517evm())
+		return -ENODEV;
+	pr_info("OMAP3517 / AM3517 EVM SoC init\n");
+
+	am3517evm_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!am3517evm_snd_device) {
+		printk(KERN_ERR "Platform device allocation failed\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(am3517evm_snd_device, &snd_soc_am3517evm);
+
+	ret = platform_device_add(am3517evm_snd_device);
+	if (ret)
+		goto err1;
+
+	return 0;
+
+err1:
+	printk(KERN_ERR "Unable to add platform device\n");
+	platform_device_put(am3517evm_snd_device);
+
+	return ret;
+}
+
+static void __exit am3517evm_soc_exit(void)
+{
+	platform_device_unregister(am3517evm_snd_device);
+}
+
+module_init(am3517evm_soc_init);
+module_exit(am3517evm_soc_exit);
+
+MODULE_AUTHOR("Anuj Aggarwal <anuj.aggarwal@ti.com>");
+MODULE_DESCRIPTION("ALSA SoC OMAP3517 / AM3517 EVM");
+MODULE_LICENSE("GPL v2");
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/ams-delta.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/ams-delta.c
new file mode 100644
index 0000000..7d4fa8e
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/ams-delta.c
@@ -0,0 +1,630 @@
+/*
+ * ams-delta.c  --  SoC audio for Amstrad E3 (Delta) videophone
+ *
+ * Copyright (C) 2009 Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
+ *
+ * Initially based on sound/soc/omap/osk5912.x
+ * Copyright (C) 2008 Mistral Solutions
+ *
+ * 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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/gpio.h>
+#include <linux/spinlock.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+
+#include <sound/soc.h>
+#include <sound/jack.h>
+
+#include <asm/mach-types.h>
+
+#include <plat/board-ams-delta.h>
+#include <plat/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/cx20442.h"
+
+
+/* Board specific DAPM widgets */
+static const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = {
+	/* Handset */
+	SND_SOC_DAPM_MIC("Mouthpiece", NULL),
+	SND_SOC_DAPM_HP("Earpiece", NULL),
+	/* Handsfree/Speakerphone */
+	SND_SOC_DAPM_MIC("Microphone", NULL),
+	SND_SOC_DAPM_SPK("Speaker", NULL),
+};
+
+/* How they are connected to codec pins */
+static const struct snd_soc_dapm_route ams_delta_audio_map[] = {
+	{"TELIN", NULL, "Mouthpiece"},
+	{"Earpiece", NULL, "TELOUT"},
+
+	{"MIC", NULL, "Microphone"},
+	{"Speaker", NULL, "SPKOUT"},
+};
+
+/*
+ * Controls, functional after the modem line discipline is activated.
+ */
+
+/* Virtual switch: audio input/output constellations */
+static const char *ams_delta_audio_mode[] =
+	{"Mixed", "Handset", "Handsfree", "Speakerphone"};
+
+/* Selection <-> pin translation */
+#define AMS_DELTA_MOUTHPIECE	0
+#define AMS_DELTA_EARPIECE	1
+#define AMS_DELTA_MICROPHONE	2
+#define AMS_DELTA_SPEAKER	3
+#define AMS_DELTA_AGC		4
+
+#define AMS_DELTA_MIXED		((1 << AMS_DELTA_EARPIECE) | \
+						(1 << AMS_DELTA_MICROPHONE))
+#define AMS_DELTA_HANDSET	((1 << AMS_DELTA_MOUTHPIECE) | \
+						(1 << AMS_DELTA_EARPIECE))
+#define AMS_DELTA_HANDSFREE	((1 << AMS_DELTA_MICROPHONE) | \
+						(1 << AMS_DELTA_SPEAKER))
+#define AMS_DELTA_SPEAKERPHONE	(AMS_DELTA_HANDSFREE | (1 << AMS_DELTA_AGC))
+
+static const unsigned short ams_delta_audio_mode_pins[] = {
+	AMS_DELTA_MIXED,
+	AMS_DELTA_HANDSET,
+	AMS_DELTA_HANDSFREE,
+	AMS_DELTA_SPEAKERPHONE,
+};
+
+static unsigned short ams_delta_audio_agc;
+
+static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct soc_enum *control = (struct soc_enum *)kcontrol->private_value;
+	unsigned short pins;
+	int pin, changed = 0;
+
+	/* Refuse any mode changes if we are not able to control the codec. */
+	if (!codec->hw_write)
+		return -EUNATCH;
+
+	if (ucontrol->value.enumerated.item[0] >= control->max)
+		return -EINVAL;
+
+	mutex_lock(&codec->mutex);
+
+	/* Translate selection to bitmap */
+	pins = ams_delta_audio_mode_pins[ucontrol->value.enumerated.item[0]];
+
+	/* Setup pins after corresponding bits if changed */
+	pin = !!(pins & (1 << AMS_DELTA_MOUTHPIECE));
+	if (pin != snd_soc_dapm_get_pin_status(dapm, "Mouthpiece")) {
+		changed = 1;
+		if (pin)
+			snd_soc_dapm_enable_pin(dapm, "Mouthpiece");
+		else
+			snd_soc_dapm_disable_pin(dapm, "Mouthpiece");
+	}
+	pin = !!(pins & (1 << AMS_DELTA_EARPIECE));
+	if (pin != snd_soc_dapm_get_pin_status(dapm, "Earpiece")) {
+		changed = 1;
+		if (pin)
+			snd_soc_dapm_enable_pin(dapm, "Earpiece");
+		else
+			snd_soc_dapm_disable_pin(dapm, "Earpiece");
+	}
+	pin = !!(pins & (1 << AMS_DELTA_MICROPHONE));
+	if (pin != snd_soc_dapm_get_pin_status(dapm, "Microphone")) {
+		changed = 1;
+		if (pin)
+			snd_soc_dapm_enable_pin(dapm, "Microphone");
+		else
+			snd_soc_dapm_disable_pin(dapm, "Microphone");
+	}
+	pin = !!(pins & (1 << AMS_DELTA_SPEAKER));
+	if (pin != snd_soc_dapm_get_pin_status(dapm, "Speaker")) {
+		changed = 1;
+		if (pin)
+			snd_soc_dapm_enable_pin(dapm, "Speaker");
+		else
+			snd_soc_dapm_disable_pin(dapm, "Speaker");
+	}
+	pin = !!(pins & (1 << AMS_DELTA_AGC));
+	if (pin != ams_delta_audio_agc) {
+		ams_delta_audio_agc = pin;
+		changed = 1;
+		if (pin)
+			snd_soc_dapm_enable_pin(dapm, "AGCIN");
+		else
+			snd_soc_dapm_disable_pin(dapm, "AGCIN");
+	}
+	if (changed)
+		snd_soc_dapm_sync(dapm);
+
+	mutex_unlock(&codec->mutex);
+
+	return changed;
+}
+
+static int ams_delta_get_audio_mode(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	unsigned short pins, mode;
+
+	pins = ((snd_soc_dapm_get_pin_status(dapm, "Mouthpiece") <<
+							AMS_DELTA_MOUTHPIECE) |
+			(snd_soc_dapm_get_pin_status(dapm, "Earpiece") <<
+							AMS_DELTA_EARPIECE));
+	if (pins)
+		pins |= (snd_soc_dapm_get_pin_status(dapm, "Microphone") <<
+							AMS_DELTA_MICROPHONE);
+	else
+		pins = ((snd_soc_dapm_get_pin_status(dapm, "Microphone") <<
+							AMS_DELTA_MICROPHONE) |
+			(snd_soc_dapm_get_pin_status(dapm, "Speaker") <<
+							AMS_DELTA_SPEAKER) |
+			(ams_delta_audio_agc << AMS_DELTA_AGC));
+
+	for (mode = 0; mode < ARRAY_SIZE(ams_delta_audio_mode); mode++)
+		if (pins == ams_delta_audio_mode_pins[mode])
+			break;
+
+	if (mode >= ARRAY_SIZE(ams_delta_audio_mode))
+		return -EINVAL;
+
+	ucontrol->value.enumerated.item[0] = mode;
+
+	return 0;
+}
+
+static const struct soc_enum ams_delta_audio_enum[] = {
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ams_delta_audio_mode),
+						ams_delta_audio_mode),
+};
+
+static const struct snd_kcontrol_new ams_delta_audio_controls[] = {
+	SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum[0],
+			ams_delta_get_audio_mode, ams_delta_set_audio_mode),
+};
+
+/* Hook switch */
+static struct snd_soc_jack ams_delta_hook_switch;
+static struct snd_soc_jack_gpio ams_delta_hook_switch_gpios[] = {
+	{
+		.gpio = 4,
+		.name = "hook_switch",
+		.report = SND_JACK_HEADSET,
+		.invert = 1,
+		.debounce_time = 150,
+	}
+};
+
+/* After we are able to control the codec over the modem,
+ * the hook switch can be used for dynamic DAPM reconfiguration. */
+static struct snd_soc_jack_pin ams_delta_hook_switch_pins[] = {
+	/* Handset */
+	{
+		.pin = "Mouthpiece",
+		.mask = SND_JACK_MICROPHONE,
+	},
+	{
+		.pin = "Earpiece",
+		.mask = SND_JACK_HEADPHONE,
+	},
+	/* Handsfree */
+	{
+		.pin = "Microphone",
+		.mask = SND_JACK_MICROPHONE,
+		.invert = 1,
+	},
+	{
+		.pin = "Speaker",
+		.mask = SND_JACK_HEADPHONE,
+		.invert = 1,
+	},
+};
+
+
+/*
+ * Modem line discipline, required for making above controls functional.
+ * Activated from userspace with ldattach, possibly invoked from udev rule.
+ */
+
+/* To actually apply any modem controlled configuration changes to the codec,
+ * we must connect codec DAI pins to the modem for a moment.  Be careful not
+ * to interfere with our digital mute function that shares the same hardware. */
+static struct timer_list cx81801_timer;
+static bool cx81801_cmd_pending;
+static bool ams_delta_muted;
+static DEFINE_SPINLOCK(ams_delta_lock);
+
+static void cx81801_timeout(unsigned long data)
+{
+	int muted;
+
+	spin_lock(&ams_delta_lock);
+	cx81801_cmd_pending = 0;
+	muted = ams_delta_muted;
+	spin_unlock(&ams_delta_lock);
+
+	/* Reconnect the codec DAI back from the modem to the CPU DAI
+	 * only if digital mute still off */
+	if (!muted)
+		ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0);
+}
+
+/*
+ * Used for passing a codec structure pointer
+ * from the board initialization code to the tty line discipline.
+ */
+static struct snd_soc_codec *cx20442_codec;
+
+/* Line discipline .open() */
+static int cx81801_open(struct tty_struct *tty)
+{
+	int ret;
+
+	if (!cx20442_codec)
+		return -ENODEV;
+
+	/*
+	 * Pass the codec structure pointer for use by other ldisc callbacks,
+	 * both the card and the codec specific parts.
+	 */
+	tty->disc_data = cx20442_codec;
+
+	ret = v253_ops.open(tty);
+
+	if (ret < 0)
+		tty->disc_data = NULL;
+
+	return ret;
+}
+
+/* Line discipline .close() */
+static void cx81801_close(struct tty_struct *tty)
+{
+	struct snd_soc_codec *codec = tty->disc_data;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+	del_timer_sync(&cx81801_timer);
+
+	/* Prevent the hook switch from further changing the DAPM pins */
+	INIT_LIST_HEAD(&ams_delta_hook_switch.pins);
+
+	if (!codec)
+		return;
+
+	v253_ops.close(tty);
+
+	/* Revert back to default audio input/output constellation */
+	snd_soc_dapm_disable_pin(dapm, "Mouthpiece");
+	snd_soc_dapm_enable_pin(dapm, "Earpiece");
+	snd_soc_dapm_enable_pin(dapm, "Microphone");
+	snd_soc_dapm_disable_pin(dapm, "Speaker");
+	snd_soc_dapm_disable_pin(dapm, "AGCIN");
+	snd_soc_dapm_sync(dapm);
+}
+
+/* Line discipline .hangup() */
+static int cx81801_hangup(struct tty_struct *tty)
+{
+	cx81801_close(tty);
+	return 0;
+}
+
+/* Line discipline .receive_buf() */
+static void cx81801_receive(struct tty_struct *tty,
+				const unsigned char *cp, char *fp, int count)
+{
+	struct snd_soc_codec *codec = tty->disc_data;
+	const unsigned char *c;
+	int apply, ret;
+
+	if (!codec)
+		return;
+
+	if (!codec->hw_write) {
+		/* First modem response, complete setup procedure */
+
+		/* Initialize timer used for config pulse generation */
+		setup_timer(&cx81801_timer, cx81801_timeout, 0);
+
+		v253_ops.receive_buf(tty, cp, fp, count);
+
+		/* Link hook switch to DAPM pins */
+		ret = snd_soc_jack_add_pins(&ams_delta_hook_switch,
+					ARRAY_SIZE(ams_delta_hook_switch_pins),
+					ams_delta_hook_switch_pins);
+		if (ret)
+			dev_warn(codec->dev,
+				"Failed to link hook switch to DAPM pins, "
+				"will continue with hook switch unlinked.\n");
+
+		return;
+	}
+
+	v253_ops.receive_buf(tty, cp, fp, count);
+
+	for (c = &cp[count - 1]; c >= cp; c--) {
+		if (*c != '\r')
+			continue;
+		/* Complete modem response received, apply config to codec */
+
+		spin_lock_bh(&ams_delta_lock);
+		mod_timer(&cx81801_timer, jiffies + msecs_to_jiffies(150));
+		apply = !ams_delta_muted && !cx81801_cmd_pending;
+		cx81801_cmd_pending = 1;
+		spin_unlock_bh(&ams_delta_lock);
+
+		/* Apply config pulse by connecting the codec to the modem
+		 * if not already done */
+		if (apply)
+			ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC,
+						AMS_DELTA_LATCH2_MODEM_CODEC);
+		break;
+	}
+}
+
+/* Line discipline .write_wakeup() */
+static void cx81801_wakeup(struct tty_struct *tty)
+{
+	v253_ops.write_wakeup(tty);
+}
+
+static struct tty_ldisc_ops cx81801_ops = {
+	.magic = TTY_LDISC_MAGIC,
+	.name = "cx81801",
+	.owner = THIS_MODULE,
+	.open = cx81801_open,
+	.close = cx81801_close,
+	.hangup = cx81801_hangup,
+	.receive_buf = cx81801_receive,
+	.write_wakeup = cx81801_wakeup,
+};
+
+
+/*
+ * Even if not very useful, the sound card can still work without any of the
+ * above functonality activated.  You can still control its audio input/output
+ * constellation and speakerphone gain from userspace by issuing AT commands
+ * over the modem port.
+ */
+
+static int ams_delta_hw_params(struct snd_pcm_substream *substream,
+			 struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+	/* Set cpu DAI configuration */
+	return snd_soc_dai_set_fmt(rtd->cpu_dai,
+				   SND_SOC_DAIFMT_DSP_A |
+				   SND_SOC_DAIFMT_NB_NF |
+				   SND_SOC_DAIFMT_CBM_CFM);
+}
+
+static struct snd_soc_ops ams_delta_ops = {
+	.hw_params = ams_delta_hw_params,
+};
+
+
+/* Digital mute implemented using modem/CPU multiplexer.
+ * Shares hardware with codec config pulse generation */
+static bool ams_delta_muted = 1;
+
+static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+	int apply;
+
+	if (ams_delta_muted == mute)
+		return 0;
+
+	spin_lock_bh(&ams_delta_lock);
+	ams_delta_muted = mute;
+	apply = !cx81801_cmd_pending;
+	spin_unlock_bh(&ams_delta_lock);
+
+	if (apply)
+		ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC,
+				mute ? AMS_DELTA_LATCH2_MODEM_CODEC : 0);
+	return 0;
+}
+
+/* Our codec DAI probably doesn't have its own .ops structure */
+static const struct snd_soc_dai_ops ams_delta_dai_ops = {
+	.digital_mute = ams_delta_digital_mute,
+};
+
+/* Will be used if the codec ever has its own digital_mute function */
+static int ams_delta_startup(struct snd_pcm_substream *substream)
+{
+	return ams_delta_digital_mute(NULL, 0);
+}
+
+static void ams_delta_shutdown(struct snd_pcm_substream *substream)
+{
+	ams_delta_digital_mute(NULL, 1);
+}
+
+
+/*
+ * Card initialization
+ */
+
+static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_card *card = rtd->card;
+	int ret;
+	/* Codec is ready, now add/activate board specific controls */
+
+	/* Store a pointer to the codec structure for tty ldisc use */
+	cx20442_codec = codec;
+
+	/* Set up digital mute if not provided by the codec */
+	if (!codec_dai->driver->ops) {
+		codec_dai->driver->ops = &ams_delta_dai_ops;
+	} else {
+		ams_delta_ops.startup = ams_delta_startup;
+		ams_delta_ops.shutdown = ams_delta_shutdown;
+	}
+
+	/* Add hook switch - can be used to control the codec from userspace
+	 * even if line discipline fails */
+	ret = snd_soc_jack_new(rtd->codec, "hook_switch",
+				SND_JACK_HEADSET, &ams_delta_hook_switch);
+	if (ret)
+		dev_warn(card->dev,
+				"Failed to allocate resources for hook switch, "
+				"will continue without one.\n");
+	else {
+		ret = snd_soc_jack_add_gpios(&ams_delta_hook_switch,
+					ARRAY_SIZE(ams_delta_hook_switch_gpios),
+					ams_delta_hook_switch_gpios);
+		if (ret)
+			dev_warn(card->dev,
+				"Failed to set up hook switch GPIO line, "
+				"will continue with hook switch inactive.\n");
+	}
+
+	/* Register optional line discipline for over the modem control */
+	ret = tty_register_ldisc(N_V253, &cx81801_ops);
+	if (ret) {
+		dev_warn(card->dev,
+				"Failed to register line discipline, "
+				"will continue without any controls.\n");
+		return 0;
+	}
+
+	/* Add board specific DAPM widgets and routes */
+	ret = snd_soc_dapm_new_controls(dapm, ams_delta_dapm_widgets,
+					ARRAY_SIZE(ams_delta_dapm_widgets));
+	if (ret) {
+		dev_warn(card->dev,
+				"Failed to register DAPM controls, "
+				"will continue without any.\n");
+		return 0;
+	}
+
+	ret = snd_soc_dapm_add_routes(dapm, ams_delta_audio_map,
+					ARRAY_SIZE(ams_delta_audio_map));
+	if (ret) {
+		dev_warn(card->dev,
+				"Failed to set up DAPM routes, "
+				"will continue with codec default map.\n");
+		return 0;
+	}
+
+	/* Set up initial pin constellation */
+	snd_soc_dapm_disable_pin(dapm, "Mouthpiece");
+	snd_soc_dapm_enable_pin(dapm, "Earpiece");
+	snd_soc_dapm_enable_pin(dapm, "Microphone");
+	snd_soc_dapm_disable_pin(dapm, "Speaker");
+	snd_soc_dapm_disable_pin(dapm, "AGCIN");
+	snd_soc_dapm_disable_pin(dapm, "AGCOUT");
+
+	/* Add virtual switch */
+	ret = snd_soc_add_codec_controls(codec, ams_delta_audio_controls,
+					ARRAY_SIZE(ams_delta_audio_controls));
+	if (ret)
+		dev_warn(card->dev,
+				"Failed to register audio mode control, "
+				"will continue without it.\n");
+
+	return 0;
+}
+
+/* DAI glue - connects codec <--> CPU */
+static struct snd_soc_dai_link ams_delta_dai_link = {
+	.name = "CX20442",
+	.stream_name = "CX20442",
+	.cpu_dai_name = "omap-mcbsp.1",
+	.codec_dai_name = "cx20442-voice",
+	.init = ams_delta_cx20442_init,
+	.platform_name = "omap-pcm-audio",
+	.codec_name = "cx20442-codec",
+	.ops = &ams_delta_ops,
+};
+
+/* Audio card driver */
+static struct snd_soc_card ams_delta_audio_card = {
+	.name = "AMS_DELTA",
+	.owner = THIS_MODULE,
+	.dai_link = &ams_delta_dai_link,
+	.num_links = 1,
+};
+
+/* Module init/exit */
+static struct platform_device *ams_delta_audio_platform_device;
+static struct platform_device *cx20442_platform_device;
+
+static int __init ams_delta_module_init(void)
+{
+	int ret;
+
+	if (!(machine_is_ams_delta()))
+		return -ENODEV;
+
+	ams_delta_audio_platform_device =
+			platform_device_alloc("soc-audio", -1);
+	if (!ams_delta_audio_platform_device)
+		return -ENOMEM;
+
+	platform_set_drvdata(ams_delta_audio_platform_device,
+				&ams_delta_audio_card);
+
+	ret = platform_device_add(ams_delta_audio_platform_device);
+	if (ret)
+		goto err;
+
+	/*
+	 * Codec platform device could be registered from elsewhere (board?),
+	 * but I do it here as it makes sense only if used with the card.
+	 */
+	cx20442_platform_device =
+		platform_device_register_simple("cx20442-codec", -1, NULL, 0);
+	return 0;
+err:
+	platform_device_put(ams_delta_audio_platform_device);
+	return ret;
+}
+late_initcall(ams_delta_module_init);
+
+static void __exit ams_delta_module_exit(void)
+{
+	if (tty_unregister_ldisc(N_V253) != 0)
+		dev_warn(&ams_delta_audio_platform_device->dev,
+			"failed to unregister V253 line discipline\n");
+
+	snd_soc_jack_free_gpios(&ams_delta_hook_switch,
+			ARRAY_SIZE(ams_delta_hook_switch_gpios),
+			ams_delta_hook_switch_gpios);
+
+	platform_device_unregister(cx20442_platform_device);
+	platform_device_unregister(ams_delta_audio_platform_device);
+}
+module_exit(ams_delta_module_exit);
+
+MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>");
+MODULE_DESCRIPTION("ALSA SoC driver for Amstrad E3 (Delta) videophone");
+MODULE_LICENSE("GPL");
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/igep0020.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/igep0020.c
new file mode 100644
index 0000000..e835781
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/igep0020.c
@@ -0,0 +1,120 @@
+/*
+ * igep0020.c  --  SoC audio for IGEP v2
+ *
+ * Based on sound/soc/omap/overo.c by Steve Sakoman
+ *
+ * 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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <plat/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+
+static int igep2_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret;
+
+	/* Set the codec system clock for DAC and ADC */
+	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+					    SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set codec system clock\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops igep2_ops = {
+	.hw_params = igep2_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link igep2_dai = {
+	.name = "TWL4030",
+	.stream_name = "TWL4030",
+	.cpu_dai_name = "omap-mcbsp.2",
+	.codec_dai_name = "twl4030-hifi",
+	.platform_name = "omap-pcm-audio",
+	.codec_name = "twl4030-codec",
+	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBM_CFM,
+	.ops = &igep2_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_card_igep2 = {
+	.name = "igep2",
+	.owner = THIS_MODULE,
+	.dai_link = &igep2_dai,
+	.num_links = 1,
+};
+
+static struct platform_device *igep2_snd_device;
+
+static int __init igep2_soc_init(void)
+{
+	int ret;
+
+	if (!machine_is_igep0020())
+		return -ENODEV;
+	printk(KERN_INFO "IGEP v2 SoC init\n");
+
+	igep2_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!igep2_snd_device) {
+		printk(KERN_ERR "Platform device allocation failed\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(igep2_snd_device, &snd_soc_card_igep2);
+
+	ret = platform_device_add(igep2_snd_device);
+	if (ret)
+		goto err1;
+
+	return 0;
+
+err1:
+	printk(KERN_ERR "Unable to add platform device\n");
+	platform_device_put(igep2_snd_device);
+
+	return ret;
+}
+module_init(igep2_soc_init);
+
+static void __exit igep2_soc_exit(void)
+{
+	platform_device_unregister(igep2_snd_device);
+}
+module_exit(igep2_soc_exit);
+
+MODULE_AUTHOR("Enric Balletbo i Serra <eballetbo@iseebcn.com>");
+MODULE_DESCRIPTION("ALSA SoC IGEP v2");
+MODULE_LICENSE("GPL");
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/mcbsp.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/mcbsp.c
new file mode 100644
index 0000000..fb67772
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/mcbsp.c
@@ -0,0 +1,1040 @@
+/*
+ * sound/soc/omap/mcbsp.c
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Samuel Ortiz <samuel.ortiz@nokia.com>
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
+ *          Peter Ujfalusi <peter.ujfalusi@ti.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.
+ *
+ * Multichannel mode not supported.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <plat/mcbsp.h>
+
+#include "mcbsp.h"
+
+static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
+{
+	void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
+
+	if (mcbsp->pdata->reg_size == 2) {
+		((u16 *)mcbsp->reg_cache)[reg] = (u16)val;
+		__raw_writew((u16)val, addr);
+	} else {
+		((u32 *)mcbsp->reg_cache)[reg] = val;
+		__raw_writel(val, addr);
+	}
+}
+
+static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
+{
+	void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
+
+	if (mcbsp->pdata->reg_size == 2) {
+		return !from_cache ? __raw_readw(addr) :
+				     ((u16 *)mcbsp->reg_cache)[reg];
+	} else {
+		return !from_cache ? __raw_readl(addr) :
+				     ((u32 *)mcbsp->reg_cache)[reg];
+	}
+}
+
+static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
+{
+	__raw_writel(val, mcbsp->st_data->io_base_st + reg);
+}
+
+static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
+{
+	return __raw_readl(mcbsp->st_data->io_base_st + reg);
+}
+
+#define MCBSP_READ(mcbsp, reg) \
+		omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 0)
+#define MCBSP_WRITE(mcbsp, reg, val) \
+		omap_mcbsp_write(mcbsp, OMAP_MCBSP_REG_##reg, val)
+#define MCBSP_READ_CACHE(mcbsp, reg) \
+		omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 1)
+
+#define MCBSP_ST_READ(mcbsp, reg) \
+			omap_mcbsp_st_read(mcbsp, OMAP_ST_REG_##reg)
+#define MCBSP_ST_WRITE(mcbsp, reg, val) \
+			omap_mcbsp_st_write(mcbsp, OMAP_ST_REG_##reg, val)
+
+static void omap_mcbsp_dump_reg(struct omap_mcbsp *mcbsp)
+{
+	dev_dbg(mcbsp->dev, "**** McBSP%d regs ****\n", mcbsp->id);
+	dev_dbg(mcbsp->dev, "DRR2:  0x%04x\n",
+			MCBSP_READ(mcbsp, DRR2));
+	dev_dbg(mcbsp->dev, "DRR1:  0x%04x\n",
+			MCBSP_READ(mcbsp, DRR1));
+	dev_dbg(mcbsp->dev, "DXR2:  0x%04x\n",
+			MCBSP_READ(mcbsp, DXR2));
+	dev_dbg(mcbsp->dev, "DXR1:  0x%04x\n",
+			MCBSP_READ(mcbsp, DXR1));
+	dev_dbg(mcbsp->dev, "SPCR2: 0x%04x\n",
+			MCBSP_READ(mcbsp, SPCR2));
+	dev_dbg(mcbsp->dev, "SPCR1: 0x%04x\n",
+			MCBSP_READ(mcbsp, SPCR1));
+	dev_dbg(mcbsp->dev, "RCR2:  0x%04x\n",
+			MCBSP_READ(mcbsp, RCR2));
+	dev_dbg(mcbsp->dev, "RCR1:  0x%04x\n",
+			MCBSP_READ(mcbsp, RCR1));
+	dev_dbg(mcbsp->dev, "XCR2:  0x%04x\n",
+			MCBSP_READ(mcbsp, XCR2));
+	dev_dbg(mcbsp->dev, "XCR1:  0x%04x\n",
+			MCBSP_READ(mcbsp, XCR1));
+	dev_dbg(mcbsp->dev, "SRGR2: 0x%04x\n",
+			MCBSP_READ(mcbsp, SRGR2));
+	dev_dbg(mcbsp->dev, "SRGR1: 0x%04x\n",
+			MCBSP_READ(mcbsp, SRGR1));
+	dev_dbg(mcbsp->dev, "PCR0:  0x%04x\n",
+			MCBSP_READ(mcbsp, PCR0));
+	dev_dbg(mcbsp->dev, "***********************\n");
+}
+
+static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
+{
+	struct omap_mcbsp *mcbsp_tx = dev_id;
+	u16 irqst_spcr2;
+
+	irqst_spcr2 = MCBSP_READ(mcbsp_tx, SPCR2);
+	dev_dbg(mcbsp_tx->dev, "TX IRQ callback : 0x%x\n", irqst_spcr2);
+
+	if (irqst_spcr2 & XSYNC_ERR) {
+		dev_err(mcbsp_tx->dev, "TX Frame Sync Error! : 0x%x\n",
+			irqst_spcr2);
+		/* Writing zero to XSYNC_ERR clears the IRQ */
+		MCBSP_WRITE(mcbsp_tx, SPCR2, MCBSP_READ_CACHE(mcbsp_tx, SPCR2));
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)
+{
+	struct omap_mcbsp *mcbsp_rx = dev_id;
+	u16 irqst_spcr1;
+
+	irqst_spcr1 = MCBSP_READ(mcbsp_rx, SPCR1);
+	dev_dbg(mcbsp_rx->dev, "RX IRQ callback : 0x%x\n", irqst_spcr1);
+
+	if (irqst_spcr1 & RSYNC_ERR) {
+		dev_err(mcbsp_rx->dev, "RX Frame Sync Error! : 0x%x\n",
+			irqst_spcr1);
+		/* Writing zero to RSYNC_ERR clears the IRQ */
+		MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1));
+	}
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * omap_mcbsp_config simply write a config to the
+ * appropriate McBSP.
+ * You either call this function or set the McBSP registers
+ * by yourself before calling omap_mcbsp_start().
+ */
+void omap_mcbsp_config(struct omap_mcbsp *mcbsp,
+		       const struct omap_mcbsp_reg_cfg *config)
+{
+	dev_dbg(mcbsp->dev, "Configuring McBSP%d  phys_base: 0x%08lx\n",
+			mcbsp->id, mcbsp->phys_base);
+
+	/* We write the given config */
+	MCBSP_WRITE(mcbsp, SPCR2, config->spcr2);
+	MCBSP_WRITE(mcbsp, SPCR1, config->spcr1);
+	MCBSP_WRITE(mcbsp, RCR2, config->rcr2);
+	MCBSP_WRITE(mcbsp, RCR1, config->rcr1);
+	MCBSP_WRITE(mcbsp, XCR2, config->xcr2);
+	MCBSP_WRITE(mcbsp, XCR1, config->xcr1);
+	MCBSP_WRITE(mcbsp, SRGR2, config->srgr2);
+	MCBSP_WRITE(mcbsp, SRGR1, config->srgr1);
+	MCBSP_WRITE(mcbsp, MCR2, config->mcr2);
+	MCBSP_WRITE(mcbsp, MCR1, config->mcr1);
+	MCBSP_WRITE(mcbsp, PCR0, config->pcr0);
+	if (mcbsp->pdata->has_ccr) {
+		MCBSP_WRITE(mcbsp, XCCR, config->xccr);
+		MCBSP_WRITE(mcbsp, RCCR, config->rccr);
+	}
+	/* Enable wakeup behavior */
+	if (mcbsp->pdata->has_wakeup)
+		MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
+}
+
+/**
+ * omap_mcbsp_dma_reg_params - returns the address of mcbsp data register
+ * @id - mcbsp id
+ * @stream - indicates the direction of data flow (rx or tx)
+ *
+ * Returns the address of mcbsp data transmit register or data receive register
+ * to be used by DMA for transferring/receiving data based on the value of
+ * @stream for the requested mcbsp given by @id
+ */
+static int omap_mcbsp_dma_reg_params(struct omap_mcbsp *mcbsp,
+				     unsigned int stream)
+{
+	int data_reg;
+
+	if (mcbsp->pdata->reg_size == 2) {
+		if (stream)
+			data_reg = OMAP_MCBSP_REG_DRR1;
+		else
+			data_reg = OMAP_MCBSP_REG_DXR1;
+	} else {
+		if (stream)
+			data_reg = OMAP_MCBSP_REG_DRR;
+		else
+			data_reg = OMAP_MCBSP_REG_DXR;
+	}
+
+	return mcbsp->phys_dma_base + data_reg * mcbsp->pdata->reg_step;
+}
+
+static void omap_st_on(struct omap_mcbsp *mcbsp)
+{
+	unsigned int w;
+
+	if (mcbsp->pdata->enable_st_clock)
+		mcbsp->pdata->enable_st_clock(mcbsp->id, 1);
+
+	/* Enable McBSP Sidetone */
+	w = MCBSP_READ(mcbsp, SSELCR);
+	MCBSP_WRITE(mcbsp, SSELCR, w | SIDETONEEN);
+
+	/* Enable Sidetone from Sidetone Core */
+	w = MCBSP_ST_READ(mcbsp, SSELCR);
+	MCBSP_ST_WRITE(mcbsp, SSELCR, w | ST_SIDETONEEN);
+}
+
+static void omap_st_off(struct omap_mcbsp *mcbsp)
+{
+	unsigned int w;
+
+	w = MCBSP_ST_READ(mcbsp, SSELCR);
+	MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN));
+
+	w = MCBSP_READ(mcbsp, SSELCR);
+	MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));
+
+	if (mcbsp->pdata->enable_st_clock)
+		mcbsp->pdata->enable_st_clock(mcbsp->id, 0);
+}
+
+static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir)
+{
+	u16 val, i;
+
+	val = MCBSP_ST_READ(mcbsp, SSELCR);
+
+	if (val & ST_COEFFWREN)
+		MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN));
+
+	MCBSP_ST_WRITE(mcbsp, SSELCR, val | ST_COEFFWREN);
+
+	for (i = 0; i < 128; i++)
+		MCBSP_ST_WRITE(mcbsp, SFIRCR, fir[i]);
+
+	i = 0;
+
+	val = MCBSP_ST_READ(mcbsp, SSELCR);
+	while (!(val & ST_COEFFWRDONE) && (++i < 1000))
+		val = MCBSP_ST_READ(mcbsp, SSELCR);
+
+	MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN));
+
+	if (i == 1000)
+		dev_err(mcbsp->dev, "McBSP FIR load error!\n");
+}
+
+static void omap_st_chgain(struct omap_mcbsp *mcbsp)
+{
+	u16 w;
+	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+
+	w = MCBSP_ST_READ(mcbsp, SSELCR);
+
+	MCBSP_ST_WRITE(mcbsp, SGAINCR, ST_CH0GAIN(st_data->ch0gain) | \
+		      ST_CH1GAIN(st_data->ch1gain));
+}
+
+int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain)
+{
+	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+	int ret = 0;
+
+	if (!st_data)
+		return -ENOENT;
+
+	spin_lock_irq(&mcbsp->lock);
+	if (channel == 0)
+		st_data->ch0gain = chgain;
+	else if (channel == 1)
+		st_data->ch1gain = chgain;
+	else
+		ret = -EINVAL;
+
+	if (st_data->enabled)
+		omap_st_chgain(mcbsp);
+	spin_unlock_irq(&mcbsp->lock);
+
+	return ret;
+}
+
+int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain)
+{
+	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+	int ret = 0;
+
+	if (!st_data)
+		return -ENOENT;
+
+	spin_lock_irq(&mcbsp->lock);
+	if (channel == 0)
+		*chgain = st_data->ch0gain;
+	else if (channel == 1)
+		*chgain = st_data->ch1gain;
+	else
+		ret = -EINVAL;
+	spin_unlock_irq(&mcbsp->lock);
+
+	return ret;
+}
+
+static int omap_st_start(struct omap_mcbsp *mcbsp)
+{
+	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+
+	if (st_data->enabled && !st_data->running) {
+		omap_st_fir_write(mcbsp, st_data->taps);
+		omap_st_chgain(mcbsp);
+
+		if (!mcbsp->free) {
+			omap_st_on(mcbsp);
+			st_data->running = 1;
+		}
+	}
+
+	return 0;
+}
+
+int omap_st_enable(struct omap_mcbsp *mcbsp)
+{
+	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+
+	if (!st_data)
+		return -ENODEV;
+
+	spin_lock_irq(&mcbsp->lock);
+	st_data->enabled = 1;
+	omap_st_start(mcbsp);
+	spin_unlock_irq(&mcbsp->lock);
+
+	return 0;
+}
+
+static int omap_st_stop(struct omap_mcbsp *mcbsp)
+{
+	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+
+	if (st_data->running) {
+		if (!mcbsp->free) {
+			omap_st_off(mcbsp);
+			st_data->running = 0;
+		}
+	}
+
+	return 0;
+}
+
+int omap_st_disable(struct omap_mcbsp *mcbsp)
+{
+	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+	int ret = 0;
+
+	if (!st_data)
+		return -ENODEV;
+
+	spin_lock_irq(&mcbsp->lock);
+	omap_st_stop(mcbsp);
+	st_data->enabled = 0;
+	spin_unlock_irq(&mcbsp->lock);
+
+	return ret;
+}
+
+int omap_st_is_enabled(struct omap_mcbsp *mcbsp)
+{
+	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+
+	if (!st_data)
+		return -ENODEV;
+
+	return st_data->enabled;
+}
+
+/*
+ * omap_mcbsp_set_rx_threshold configures the transmit threshold in words.
+ * The threshold parameter is 1 based, and it is converted (threshold - 1)
+ * for the THRSH2 register.
+ */
+void omap_mcbsp_set_tx_threshold(struct omap_mcbsp *mcbsp, u16 threshold)
+{
+	if (mcbsp->pdata->buffer_size == 0)
+		return;
+
+	if (threshold && threshold <= mcbsp->max_tx_thres)
+		MCBSP_WRITE(mcbsp, THRSH2, threshold - 1);
+}
+
+/*
+ * omap_mcbsp_set_rx_threshold configures the receive threshold in words.
+ * The threshold parameter is 1 based, and it is converted (threshold - 1)
+ * for the THRSH1 register.
+ */
+void omap_mcbsp_set_rx_threshold(struct omap_mcbsp *mcbsp, u16 threshold)
+{
+	if (mcbsp->pdata->buffer_size == 0)
+		return;
+
+	if (threshold && threshold <= mcbsp->max_rx_thres)
+		MCBSP_WRITE(mcbsp, THRSH1, threshold - 1);
+}
+
+/*
+ * omap_mcbsp_get_tx_delay returns the number of used slots in the McBSP FIFO
+ */
+u16 omap_mcbsp_get_tx_delay(struct omap_mcbsp *mcbsp)
+{
+	u16 buffstat;
+
+	if (mcbsp->pdata->buffer_size == 0)
+		return 0;
+
+	/* Returns the number of free locations in the buffer */
+	buffstat = MCBSP_READ(mcbsp, XBUFFSTAT);
+
+	/* Number of slots are different in McBSP ports */
+	return mcbsp->pdata->buffer_size - buffstat;
+}
+
+/*
+ * omap_mcbsp_get_rx_delay returns the number of free slots in the McBSP FIFO
+ * to reach the threshold value (when the DMA will be triggered to read it)
+ */
+u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp)
+{
+	u16 buffstat, threshold;
+
+	if (mcbsp->pdata->buffer_size == 0)
+		return 0;
+
+	/* Returns the number of used locations in the buffer */
+	buffstat = MCBSP_READ(mcbsp, RBUFFSTAT);
+	/* RX threshold */
+	threshold = MCBSP_READ(mcbsp, THRSH1);
+
+	/* Return the number of location till we reach the threshold limit */
+	if (threshold <= buffstat)
+		return 0;
+	else
+		return threshold - buffstat;
+}
+
+int omap_mcbsp_request(struct omap_mcbsp *mcbsp)
+{
+	void *reg_cache;
+	int err;
+
+	reg_cache = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL);
+	if (!reg_cache) {
+		return -ENOMEM;
+	}
+
+	spin_lock(&mcbsp->lock);
+	if (!mcbsp->free) {
+		dev_err(mcbsp->dev, "McBSP%d is currently in use\n",
+			mcbsp->id);
+		err = -EBUSY;
+		goto err_kfree;
+	}
+
+	mcbsp->free = false;
+	mcbsp->reg_cache = reg_cache;
+	spin_unlock(&mcbsp->lock);
+
+	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request)
+		mcbsp->pdata->ops->request(mcbsp->id - 1);
+
+	/*
+	 * Make sure that transmitter, receiver and sample-rate generator are
+	 * not running before activating IRQs.
+	 */
+	MCBSP_WRITE(mcbsp, SPCR1, 0);
+	MCBSP_WRITE(mcbsp, SPCR2, 0);
+
+	err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler,
+				0, "McBSP", (void *)mcbsp);
+	if (err != 0) {
+		dev_err(mcbsp->dev, "Unable to request TX IRQ %d "
+				"for McBSP%d\n", mcbsp->tx_irq,
+				mcbsp->id);
+		goto err_clk_disable;
+	}
+
+	if (mcbsp->rx_irq) {
+		err = request_irq(mcbsp->rx_irq,
+				omap_mcbsp_rx_irq_handler,
+				0, "McBSP", (void *)mcbsp);
+		if (err != 0) {
+			dev_err(mcbsp->dev, "Unable to request RX IRQ %d "
+					"for McBSP%d\n", mcbsp->rx_irq,
+					mcbsp->id);
+			goto err_free_irq;
+		}
+	}
+
+	return 0;
+err_free_irq:
+	free_irq(mcbsp->tx_irq, (void *)mcbsp);
+err_clk_disable:
+	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
+		mcbsp->pdata->ops->free(mcbsp->id - 1);
+
+	/* Disable wakeup behavior */
+	if (mcbsp->pdata->has_wakeup)
+		MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
+
+	spin_lock(&mcbsp->lock);
+	mcbsp->free = true;
+	mcbsp->reg_cache = NULL;
+err_kfree:
+	spin_unlock(&mcbsp->lock);
+	kfree(reg_cache);
+
+	return err;
+}
+
+void omap_mcbsp_free(struct omap_mcbsp *mcbsp)
+{
+	void *reg_cache;
+
+	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
+		mcbsp->pdata->ops->free(mcbsp->id - 1);
+
+	/* Disable wakeup behavior */
+	if (mcbsp->pdata->has_wakeup)
+		MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
+
+	if (mcbsp->rx_irq)
+		free_irq(mcbsp->rx_irq, (void *)mcbsp);
+	free_irq(mcbsp->tx_irq, (void *)mcbsp);
+
+	reg_cache = mcbsp->reg_cache;
+
+	/*
+	 * Select CLKS source from internal source unconditionally before
+	 * marking the McBSP port as free.
+	 * If the external clock source via MCBSP_CLKS pin has been selected the
+	 * system will refuse to enter idle if the CLKS pin source is not reset
+	 * back to internal source.
+	 */
+	if (!cpu_class_is_omap1())
+		omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PRCM_SRC);
+
+	spin_lock(&mcbsp->lock);
+	if (mcbsp->free)
+		dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id);
+	else
+		mcbsp->free = true;
+	mcbsp->reg_cache = NULL;
+	spin_unlock(&mcbsp->lock);
+
+	if (reg_cache)
+		kfree(reg_cache);
+}
+
+/*
+ * Here we start the McBSP, by enabling transmitter, receiver or both.
+ * If no transmitter or receiver is active prior calling, then sample-rate
+ * generator and frame sync are started.
+ */
+void omap_mcbsp_start(struct omap_mcbsp *mcbsp, int tx, int rx)
+{
+	int enable_srg = 0;
+	u16 w;
+
+	if (mcbsp->st_data)
+		omap_st_start(mcbsp);
+
+	/* Only enable SRG, if McBSP is master */
+	w = MCBSP_READ_CACHE(mcbsp, PCR0);
+	if (w & (FSXM | FSRM | CLKXM | CLKRM))
+		enable_srg = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
+				MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
+
+	if (enable_srg) {
+		/* Start the sample generator */
+		w = MCBSP_READ_CACHE(mcbsp, SPCR2);
+		MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 6));
+	}
+
+	/* Enable transmitter and receiver */
+	tx &= 1;
+	w = MCBSP_READ_CACHE(mcbsp, SPCR2);
+	MCBSP_WRITE(mcbsp, SPCR2, w | tx);
+
+	rx &= 1;
+	w = MCBSP_READ_CACHE(mcbsp, SPCR1);
+	MCBSP_WRITE(mcbsp, SPCR1, w | rx);
+
+	/*
+	 * Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec
+	 * REVISIT: 100us may give enough time for two CLKSRG, however
+	 * due to some unknown PM related, clock gating etc. reason it
+	 * is now at 500us.
+	 */
+	udelay(500);
+
+	if (enable_srg) {
+		/* Start frame sync */
+		w = MCBSP_READ_CACHE(mcbsp, SPCR2);
+		MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7));
+	}
+
+	if (mcbsp->pdata->has_ccr) {
+		/* Release the transmitter and receiver */
+		w = MCBSP_READ_CACHE(mcbsp, XCCR);
+		w &= ~(tx ? XDISABLE : 0);
+		MCBSP_WRITE(mcbsp, XCCR, w);
+		w = MCBSP_READ_CACHE(mcbsp, RCCR);
+		w &= ~(rx ? RDISABLE : 0);
+		MCBSP_WRITE(mcbsp, RCCR, w);
+	}
+
+	/* Dump McBSP Regs */
+	omap_mcbsp_dump_reg(mcbsp);
+}
+
+void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx)
+{
+	int idle;
+	u16 w;
+
+	/* Reset transmitter */
+	tx &= 1;
+	if (mcbsp->pdata->has_ccr) {
+		w = MCBSP_READ_CACHE(mcbsp, XCCR);
+		w |= (tx ? XDISABLE : 0);
+		MCBSP_WRITE(mcbsp, XCCR, w);
+	}
+	w = MCBSP_READ_CACHE(mcbsp, SPCR2);
+	MCBSP_WRITE(mcbsp, SPCR2, w & ~tx);
+
+	/* Reset receiver */
+	rx &= 1;
+	if (mcbsp->pdata->has_ccr) {
+		w = MCBSP_READ_CACHE(mcbsp, RCCR);
+		w |= (rx ? RDISABLE : 0);
+		MCBSP_WRITE(mcbsp, RCCR, w);
+	}
+	w = MCBSP_READ_CACHE(mcbsp, SPCR1);
+	MCBSP_WRITE(mcbsp, SPCR1, w & ~rx);
+
+	idle = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
+			MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
+
+	if (idle) {
+		/* Reset the sample rate generator */
+		w = MCBSP_READ_CACHE(mcbsp, SPCR2);
+		MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6));
+	}
+
+	if (mcbsp->st_data)
+		omap_st_stop(mcbsp);
+}
+
+int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id)
+{
+	const char *src;
+
+	if (fck_src_id == MCBSP_CLKS_PAD_SRC)
+		src = "clks_ext";
+	else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
+		src = "clks_fclk";
+	else
+		return -EINVAL;
+
+	if (mcbsp->pdata->set_clk_src)
+		return mcbsp->pdata->set_clk_src(mcbsp->dev, mcbsp->fclk, src);
+	else
+		return -EINVAL;
+}
+
+int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux)
+{
+	const char *signal, *src;
+
+	if (!mcbsp->pdata->mux_signal)
+		return -EINVAL;
+
+	switch (mux) {
+	case CLKR_SRC_CLKR:
+		signal = "clkr";
+		src = "clkr";
+		break;
+	case CLKR_SRC_CLKX:
+		signal = "clkr";
+		src = "clkx";
+		break;
+	case FSR_SRC_FSR:
+		signal = "fsr";
+		src = "fsr";
+		break;
+	case FSR_SRC_FSX:
+		signal = "fsr";
+		src = "fsx";
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return mcbsp->pdata->mux_signal(mcbsp->dev, signal, src);
+}
+
+#define max_thres(m)			(mcbsp->pdata->buffer_size)
+#define valid_threshold(m, val)		((val) <= max_thres(m))
+#define THRESHOLD_PROP_BUILDER(prop)					\
+static ssize_t prop##_show(struct device *dev,				\
+			struct device_attribute *attr, char *buf)	\
+{									\
+	struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);		\
+									\
+	return sprintf(buf, "%u\n", mcbsp->prop);			\
+}									\
+									\
+static ssize_t prop##_store(struct device *dev,				\
+				struct device_attribute *attr,		\
+				const char *buf, size_t size)		\
+{									\
+	struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);		\
+	unsigned long val;						\
+	int status;							\
+									\
+	status = strict_strtoul(buf, 0, &val);				\
+	if (status)							\
+		return status;						\
+									\
+	if (!valid_threshold(mcbsp, val))				\
+		return -EDOM;						\
+									\
+	mcbsp->prop = val;						\
+	return size;							\
+}									\
+									\
+static DEVICE_ATTR(prop, 0644, prop##_show, prop##_store);
+
+THRESHOLD_PROP_BUILDER(max_tx_thres);
+THRESHOLD_PROP_BUILDER(max_rx_thres);
+
+static const char *dma_op_modes[] = {
+	"element", "threshold", "frame",
+};
+
+static ssize_t dma_op_mode_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+	int dma_op_mode, i = 0;
+	ssize_t len = 0;
+	const char * const *s;
+
+	dma_op_mode = mcbsp->dma_op_mode;
+
+	for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++) {
+		if (dma_op_mode == i)
+			len += sprintf(buf + len, "[%s] ", *s);
+		else
+			len += sprintf(buf + len, "%s ", *s);
+	}
+	len += sprintf(buf + len, "\n");
+
+	return len;
+}
+
+static ssize_t dma_op_mode_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+	const char * const *s;
+	int i = 0;
+
+	for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++)
+		if (sysfs_streq(buf, *s))
+			break;
+
+	if (i == ARRAY_SIZE(dma_op_modes))
+		return -EINVAL;
+
+	spin_lock_irq(&mcbsp->lock);
+	if (!mcbsp->free) {
+		size = -EBUSY;
+		goto unlock;
+	}
+	mcbsp->dma_op_mode = i;
+
+unlock:
+	spin_unlock_irq(&mcbsp->lock);
+
+	return size;
+}
+
+static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store);
+
+static const struct attribute *additional_attrs[] = {
+	&dev_attr_max_tx_thres.attr,
+	&dev_attr_max_rx_thres.attr,
+	&dev_attr_dma_op_mode.attr,
+	NULL,
+};
+
+static const struct attribute_group additional_attr_group = {
+	.attrs = (struct attribute **)additional_attrs,
+};
+
+static ssize_t st_taps_show(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+	ssize_t status = 0;
+	int i;
+
+	spin_lock_irq(&mcbsp->lock);
+	for (i = 0; i < st_data->nr_taps; i++)
+		status += sprintf(&buf[status], (i ? ", %d" : "%d"),
+				  st_data->taps[i]);
+	if (i)
+		status += sprintf(&buf[status], "\n");
+	spin_unlock_irq(&mcbsp->lock);
+
+	return status;
+}
+
+static ssize_t st_taps_store(struct device *dev,
+			     struct device_attribute *attr,
+			     const char *buf, size_t size)
+{
+	struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+	int val, tmp, status, i = 0;
+
+	spin_lock_irq(&mcbsp->lock);
+	memset(st_data->taps, 0, sizeof(st_data->taps));
+	st_data->nr_taps = 0;
+
+	do {
+		status = sscanf(buf, "%d%n", &val, &tmp);
+		if (status < 0 || status == 0) {
+			size = -EINVAL;
+			goto out;
+		}
+		if (val < -32768 || val > 32767) {
+			size = -EINVAL;
+			goto out;
+		}
+		st_data->taps[i++] = val;
+		buf += tmp;
+		if (*buf != ',')
+			break;
+		buf++;
+	} while (1);
+
+	st_data->nr_taps = i;
+
+out:
+	spin_unlock_irq(&mcbsp->lock);
+
+	return size;
+}
+
+static DEVICE_ATTR(st_taps, 0644, st_taps_show, st_taps_store);
+
+static const struct attribute *sidetone_attrs[] = {
+	&dev_attr_st_taps.attr,
+	NULL,
+};
+
+static const struct attribute_group sidetone_attr_group = {
+	.attrs = (struct attribute **)sidetone_attrs,
+};
+
+static int __devinit omap_st_add(struct omap_mcbsp *mcbsp,
+				 struct resource *res)
+{
+	struct omap_mcbsp_st_data *st_data;
+	int err;
+
+	st_data = devm_kzalloc(mcbsp->dev, sizeof(*mcbsp->st_data), GFP_KERNEL);
+	if (!st_data)
+		return -ENOMEM;
+
+	st_data->io_base_st = devm_ioremap(mcbsp->dev, res->start,
+					   resource_size(res));
+	if (!st_data->io_base_st)
+		return -ENOMEM;
+
+	err = sysfs_create_group(&mcbsp->dev->kobj, &sidetone_attr_group);
+	if (err)
+		return err;
+
+	mcbsp->st_data = st_data;
+	return 0;
+}
+
+/*
+ * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
+ * 730 has only 2 McBSP, and both of them are MPU peripherals.
+ */
+int __devinit omap_mcbsp_init(struct platform_device *pdev)
+{
+	struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
+	struct resource *res;
+	int ret = 0;
+
+	spin_lock_init(&mcbsp->lock);
+	mcbsp->free = true;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
+	if (!res) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!res) {
+			dev_err(mcbsp->dev, "invalid memory resource\n");
+			return -ENOMEM;
+		}
+	}
+	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
+				     dev_name(&pdev->dev))) {
+		dev_err(mcbsp->dev, "memory region already claimed\n");
+		return -ENODEV;
+	}
+
+	mcbsp->phys_base = res->start;
+	mcbsp->reg_cache_size = resource_size(res);
+	mcbsp->io_base = devm_ioremap(&pdev->dev, res->start,
+				      resource_size(res));
+	if (!mcbsp->io_base)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
+	if (!res)
+		mcbsp->phys_dma_base = mcbsp->phys_base;
+	else
+		mcbsp->phys_dma_base = res->start;
+
+	mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx");
+	mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
+
+	/* From OMAP4 there will be a single irq line */
+	if (mcbsp->tx_irq == -ENXIO) {
+		mcbsp->tx_irq = platform_get_irq(pdev, 0);
+		mcbsp->rx_irq = 0;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
+	if (!res) {
+		dev_err(&pdev->dev, "invalid rx DMA channel\n");
+		return -ENODEV;
+	}
+	/* RX DMA request number, and port address configuration */
+	mcbsp->dma_data[1].name = "Audio Capture";
+	mcbsp->dma_data[1].dma_req = res->start;
+	mcbsp->dma_data[1].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 1);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
+	if (!res) {
+		dev_err(&pdev->dev, "invalid tx DMA channel\n");
+		return -ENODEV;
+	}
+	/* TX DMA request number, and port address configuration */
+	mcbsp->dma_data[0].name = "Audio Playback";
+	mcbsp->dma_data[0].dma_req = res->start;
+	mcbsp->dma_data[0].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 0);
+
+	mcbsp->fclk = clk_get(&pdev->dev, "fck");
+	if (IS_ERR(mcbsp->fclk)) {
+		ret = PTR_ERR(mcbsp->fclk);
+		dev_err(mcbsp->dev, "unable to get fck: %d\n", ret);
+		return ret;
+	}
+
+	mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
+	if (mcbsp->pdata->buffer_size) {
+		/*
+		 * Initially configure the maximum thresholds to a safe value.
+		 * The McBSP FIFO usage with these values should not go under
+		 * 16 locations.
+		 * If the whole FIFO without safety buffer is used, than there
+		 * is a possibility that the DMA will be not able to push the
+		 * new data on time, causing channel shifts in runtime.
+		 */
+		mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10;
+		mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10;
+
+		ret = sysfs_create_group(&mcbsp->dev->kobj,
+					 &additional_attr_group);
+		if (ret) {
+			dev_err(mcbsp->dev,
+				"Unable to create additional controls\n");
+			goto err_thres;
+		}
+	} else {
+		mcbsp->max_tx_thres = -EINVAL;
+		mcbsp->max_rx_thres = -EINVAL;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone");
+	if (res) {
+		ret = omap_st_add(mcbsp, res);
+		if (ret) {
+			dev_err(mcbsp->dev,
+				"Unable to create sidetone controls\n");
+			goto err_st;
+		}
+	}
+
+	return 0;
+
+err_st:
+	if (mcbsp->pdata->buffer_size)
+		sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
+err_thres:
+	clk_put(mcbsp->fclk);
+	return ret;
+}
+
+void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp)
+{
+	if (mcbsp->pdata->buffer_size)
+		sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
+
+	if (mcbsp->st_data)
+		sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
+}
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/mcbsp.h b/ap/os/linux/linux-3.4.x/sound/soc/omap/mcbsp.h
new file mode 100644
index 0000000..a944fcc
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/mcbsp.h
@@ -0,0 +1,346 @@
+/*
+ * sound/soc/omap/mcbsp.h
+ *
+ * OMAP Multi-Channel Buffered Serial Port
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
+ *          Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef __ASOC_MCBSP_H
+#define __ASOC_MCBSP_H
+
+#include "omap-pcm.h"
+
+/* McBSP register numbers. Register address offset = num * reg_step */
+enum {
+	/* Common registers */
+	OMAP_MCBSP_REG_SPCR2 = 4,
+	OMAP_MCBSP_REG_SPCR1,
+	OMAP_MCBSP_REG_RCR2,
+	OMAP_MCBSP_REG_RCR1,
+	OMAP_MCBSP_REG_XCR2,
+	OMAP_MCBSP_REG_XCR1,
+	OMAP_MCBSP_REG_SRGR2,
+	OMAP_MCBSP_REG_SRGR1,
+	OMAP_MCBSP_REG_MCR2,
+	OMAP_MCBSP_REG_MCR1,
+	OMAP_MCBSP_REG_RCERA,
+	OMAP_MCBSP_REG_RCERB,
+	OMAP_MCBSP_REG_XCERA,
+	OMAP_MCBSP_REG_XCERB,
+	OMAP_MCBSP_REG_PCR0,
+	OMAP_MCBSP_REG_RCERC,
+	OMAP_MCBSP_REG_RCERD,
+	OMAP_MCBSP_REG_XCERC,
+	OMAP_MCBSP_REG_XCERD,
+	OMAP_MCBSP_REG_RCERE,
+	OMAP_MCBSP_REG_RCERF,
+	OMAP_MCBSP_REG_XCERE,
+	OMAP_MCBSP_REG_XCERF,
+	OMAP_MCBSP_REG_RCERG,
+	OMAP_MCBSP_REG_RCERH,
+	OMAP_MCBSP_REG_XCERG,
+	OMAP_MCBSP_REG_XCERH,
+
+	/* OMAP1-OMAP2420 registers */
+	OMAP_MCBSP_REG_DRR2 = 0,
+	OMAP_MCBSP_REG_DRR1,
+	OMAP_MCBSP_REG_DXR2,
+	OMAP_MCBSP_REG_DXR1,
+
+	/* OMAP2430 and onwards */
+	OMAP_MCBSP_REG_DRR = 0,
+	OMAP_MCBSP_REG_DXR = 2,
+	OMAP_MCBSP_REG_SYSCON =	35,
+	OMAP_MCBSP_REG_THRSH2,
+	OMAP_MCBSP_REG_THRSH1,
+	OMAP_MCBSP_REG_IRQST = 40,
+	OMAP_MCBSP_REG_IRQEN,
+	OMAP_MCBSP_REG_WAKEUPEN,
+	OMAP_MCBSP_REG_XCCR,
+	OMAP_MCBSP_REG_RCCR,
+	OMAP_MCBSP_REG_XBUFFSTAT,
+	OMAP_MCBSP_REG_RBUFFSTAT,
+	OMAP_MCBSP_REG_SSELCR,
+};
+
+/* OMAP3 sidetone control registers */
+#define OMAP_ST_REG_REV		0x00
+#define OMAP_ST_REG_SYSCONFIG	0x10
+#define OMAP_ST_REG_IRQSTATUS	0x18
+#define OMAP_ST_REG_IRQENABLE	0x1C
+#define OMAP_ST_REG_SGAINCR	0x24
+#define OMAP_ST_REG_SFIRCR	0x28
+#define OMAP_ST_REG_SSELCR	0x2C
+
+/************************** McBSP SPCR1 bit definitions ***********************/
+#define RRST			BIT(0)
+#define RRDY			BIT(1)
+#define RFULL			BIT(2)
+#define RSYNC_ERR		BIT(3)
+#define RINTM(value)		(((value) & 0x3) << 4)	/* bits 4:5 */
+#define ABIS			BIT(6)
+#define DXENA			BIT(7)
+#define CLKSTP(value)		(((value) & 0x3) << 11)	/* bits 11:12 */
+#define RJUST(value)		(((value) & 0x3) << 13)	/* bits 13:14 */
+#define ALB			BIT(15)
+#define DLB			BIT(15)
+
+/************************** McBSP SPCR2 bit definitions ***********************/
+#define XRST			BIT(0)
+#define XRDY			BIT(1)
+#define XEMPTY			BIT(2)
+#define XSYNC_ERR		BIT(3)
+#define XINTM(value)		(((value) & 0x3) << 4)	/* bits 4:5 */
+#define GRST			BIT(6)
+#define FRST			BIT(7)
+#define SOFT			BIT(8)
+#define FREE			BIT(9)
+
+/************************** McBSP PCR bit definitions *************************/
+#define CLKRP			BIT(0)
+#define CLKXP			BIT(1)
+#define FSRP			BIT(2)
+#define FSXP			BIT(3)
+#define DR_STAT			BIT(4)
+#define DX_STAT			BIT(5)
+#define CLKS_STAT		BIT(6)
+#define SCLKME			BIT(7)
+#define CLKRM			BIT(8)
+#define CLKXM			BIT(9)
+#define FSRM			BIT(10)
+#define FSXM			BIT(11)
+#define RIOEN			BIT(12)
+#define XIOEN			BIT(13)
+#define IDLE_EN			BIT(14)
+
+/************************** McBSP RCR1 bit definitions ************************/
+#define RWDLEN1(value)		(((value) & 0x7) << 5)	/* Bits 5:7 */
+#define RFRLEN1(value)		(((value) & 0x7f) << 8)	/* Bits 8:14 */
+
+/************************** McBSP XCR1 bit definitions ************************/
+#define XWDLEN1(value)		(((value) & 0x7) << 5)	/* Bits 5:7 */
+#define XFRLEN1(value)		(((value) & 0x7f) << 8)	/* Bits 8:14 */
+
+/*************************** McBSP RCR2 bit definitions ***********************/
+#define RDATDLY(value)		((value) & 0x3)		/* Bits 0:1 */
+#define RFIG			BIT(2)
+#define RCOMPAND(value)		(((value) & 0x3) << 3)	/* Bits 3:4 */
+#define RWDLEN2(value)		(((value) & 0x7) << 5)	/* Bits 5:7 */
+#define RFRLEN2(value)		(((value) & 0x7f) << 8)	/* Bits 8:14 */
+#define RPHASE			BIT(15)
+
+/*************************** McBSP XCR2 bit definitions ***********************/
+#define XDATDLY(value)		((value) & 0x3)		/* Bits 0:1 */
+#define XFIG			BIT(2)
+#define XCOMPAND(value)		(((value) & 0x3) << 3)	/* Bits 3:4 */
+#define XWDLEN2(value)		(((value) & 0x7) << 5)	/* Bits 5:7 */
+#define XFRLEN2(value)		(((value) & 0x7f) << 8)	/* Bits 8:14 */
+#define XPHASE			BIT(15)
+
+/************************* McBSP SRGR1 bit definitions ************************/
+#define CLKGDV(value)		((value) & 0x7f)		/* Bits 0:7 */
+#define FWID(value)		(((value) & 0xff) << 8)	/* Bits 8:15 */
+
+/************************* McBSP SRGR2 bit definitions ************************/
+#define FPER(value)		((value) & 0x0fff)	/* Bits 0:11 */
+#define FSGM			BIT(12)
+#define CLKSM			BIT(13)
+#define CLKSP			BIT(14)
+#define GSYNC			BIT(15)
+
+/************************* McBSP MCR1 bit definitions *************************/
+#define RMCM			BIT(0)
+#define RCBLK(value)		(((value) & 0x7) << 2)	/* Bits 2:4 */
+#define RPABLK(value)		(((value) & 0x3) << 5)	/* Bits 5:6 */
+#define RPBBLK(value)		(((value) & 0x3) << 7)	/* Bits 7:8 */
+
+/************************* McBSP MCR2 bit definitions *************************/
+#define XMCM(value)		((value) & 0x3)		/* Bits 0:1 */
+#define XCBLK(value)		(((value) & 0x7) << 2)	/* Bits 2:4 */
+#define XPABLK(value)		(((value) & 0x3) << 5)	/* Bits 5:6 */
+#define XPBBLK(value)		(((value) & 0x3) << 7)	/* Bits 7:8 */
+
+/*********************** McBSP XCCR bit definitions *************************/
+#define XDISABLE		BIT(0)
+#define XDMAEN			BIT(3)
+#define DILB			BIT(5)
+#define XFULL_CYCLE		BIT(11)
+#define DXENDLY(value)		(((value) & 0x3) << 12)	/* Bits 12:13 */
+#define PPCONNECT		BIT(14)
+#define EXTCLKGATE		BIT(15)
+
+/********************** McBSP RCCR bit definitions *************************/
+#define RDISABLE		BIT(0)
+#define RDMAEN			BIT(3)
+#define RFULL_CYCLE		BIT(11)
+
+/********************** McBSP SYSCONFIG bit definitions ********************/
+#define SOFTRST			BIT(1)
+#define ENAWAKEUP		BIT(2)
+#define SIDLEMODE(value)	(((value) & 0x3) << 3)
+#define CLOCKACTIVITY(value)	(((value) & 0x3) << 8)
+
+/********************** McBSP SSELCR bit definitions ***********************/
+#define SIDETONEEN		BIT(10)
+
+/********************** McBSP Sidetone SYSCONFIG bit definitions ***********/
+#define ST_AUTOIDLE		BIT(0)
+
+/********************** McBSP Sidetone SGAINCR bit definitions *************/
+#define ST_CH0GAIN(value)	((value) & 0xffff)	/* Bits 0:15 */
+#define ST_CH1GAIN(value)	(((value) & 0xffff) << 16) /* Bits 16:31 */
+
+/********************** McBSP Sidetone SFIRCR bit definitions **************/
+#define ST_FIRCOEFF(value)	((value) & 0xffff)	/* Bits 0:15 */
+
+/********************** McBSP Sidetone SSELCR bit definitions **************/
+#define ST_SIDETONEEN		BIT(0)
+#define ST_COEFFWREN		BIT(1)
+#define ST_COEFFWRDONE		BIT(2)
+
+/********************** McBSP DMA operating modes **************************/
+#define MCBSP_DMA_MODE_ELEMENT		0
+#define MCBSP_DMA_MODE_THRESHOLD	1
+#define MCBSP_DMA_MODE_FRAME		2
+
+/********************** McBSP WAKEUPEN bit definitions *********************/
+#define RSYNCERREN		BIT(0)
+#define RFSREN			BIT(1)
+#define REOFEN			BIT(2)
+#define RRDYEN			BIT(3)
+#define XSYNCERREN		BIT(7)
+#define XFSXEN			BIT(8)
+#define XEOFEN			BIT(9)
+#define XRDYEN			BIT(10)
+#define XEMPTYEOFEN		BIT(14)
+
+/* Clock signal muxing options */
+#define CLKR_SRC_CLKR		0 /* CLKR signal is from the CLKR pin */
+#define CLKR_SRC_CLKX		1 /* CLKR signal is from the CLKX pin */
+#define FSR_SRC_FSR		2 /* FSR signal is from the FSR pin */
+#define FSR_SRC_FSX		3 /* FSR signal is from the FSX pin */
+
+/* McBSP functional clock sources */
+#define MCBSP_CLKS_PRCM_SRC	0
+#define MCBSP_CLKS_PAD_SRC	1
+
+/* we don't do multichannel for now */
+struct omap_mcbsp_reg_cfg {
+	u16 spcr2;
+	u16 spcr1;
+	u16 rcr2;
+	u16 rcr1;
+	u16 xcr2;
+	u16 xcr1;
+	u16 srgr2;
+	u16 srgr1;
+	u16 mcr2;
+	u16 mcr1;
+	u16 pcr0;
+	u16 rcerc;
+	u16 rcerd;
+	u16 xcerc;
+	u16 xcerd;
+	u16 rcere;
+	u16 rcerf;
+	u16 xcere;
+	u16 xcerf;
+	u16 rcerg;
+	u16 rcerh;
+	u16 xcerg;
+	u16 xcerh;
+	u16 xccr;
+	u16 rccr;
+};
+
+struct omap_mcbsp_st_data {
+	void __iomem *io_base_st;
+	bool running;
+	bool enabled;
+	s16 taps[128];	/* Sidetone filter coefficients */
+	int nr_taps;	/* Number of filter coefficients in use */
+	s16 ch0gain;
+	s16 ch1gain;
+};
+
+struct omap_mcbsp {
+	struct device *dev;
+	struct clk *fclk;
+	spinlock_t lock;
+	unsigned long phys_base;
+	unsigned long phys_dma_base;
+	void __iomem *io_base;
+	u8 id;
+	/*
+	 * Flags indicating is the bus already activated and configured by
+	 * another substream
+	 */
+	int active;
+	int configured;
+	u8 free;
+
+	int rx_irq;
+	int tx_irq;
+
+	/* Protect the field .free, while checking if the mcbsp is in use */
+	struct omap_mcbsp_platform_data *pdata;
+	struct omap_mcbsp_st_data *st_data;
+	struct omap_mcbsp_reg_cfg cfg_regs;
+	struct omap_pcm_dma_data dma_data[2];
+	int dma_op_mode;
+	u16 max_tx_thres;
+	u16 max_rx_thres;
+	void *reg_cache;
+	int reg_cache_size;
+
+	unsigned int fmt;
+	unsigned int in_freq;
+	int clk_div;
+	int wlen;
+};
+
+void omap_mcbsp_config(struct omap_mcbsp *mcbsp,
+		       const struct omap_mcbsp_reg_cfg *config);
+void omap_mcbsp_set_tx_threshold(struct omap_mcbsp *mcbsp, u16 threshold);
+void omap_mcbsp_set_rx_threshold(struct omap_mcbsp *mcbsp, u16 threshold);
+u16 omap_mcbsp_get_tx_delay(struct omap_mcbsp *mcbsp);
+u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp);
+int omap_mcbsp_get_dma_op_mode(struct omap_mcbsp *mcbsp);
+int omap_mcbsp_request(struct omap_mcbsp *mcbsp);
+void omap_mcbsp_free(struct omap_mcbsp *mcbsp);
+void omap_mcbsp_start(struct omap_mcbsp *mcbsp, int tx, int rx);
+void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx);
+
+/* McBSP functional clock source changing function */
+int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id);
+
+/* McBSP signal muxing API */
+int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux);
+
+/* Sidetone specific API */
+int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain);
+int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain);
+int omap_st_enable(struct omap_mcbsp *mcbsp);
+int omap_st_disable(struct omap_mcbsp *mcbsp);
+int omap_st_is_enabled(struct omap_mcbsp *mcbsp);
+
+int __devinit omap_mcbsp_init(struct platform_device *pdev);
+void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp);
+
+#endif /* __ASOC_MCBSP_H */
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/n810.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/n810.c
new file mode 100644
index 0000000..abac4b6
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/n810.c
@@ -0,0 +1,384 @@
+/*
+ * n810.c  --  SoC audio for Nokia N810
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <plat/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+
+#define N810_HEADSET_AMP_GPIO	10
+#define N810_SPEAKER_AMP_GPIO	101
+
+enum {
+	N810_JACK_DISABLED,
+	N810_JACK_HP,
+	N810_JACK_HS,
+	N810_JACK_MIC,
+};
+
+static struct clk *sys_clkout2;
+static struct clk *sys_clkout2_src;
+static struct clk *func96m_clk;
+
+static int n810_spk_func;
+static int n810_jack_func;
+static int n810_dmic_func;
+
+static void n810_ext_control(struct snd_soc_dapm_context *dapm)
+{
+	int hp = 0, line1l = 0;
+
+	switch (n810_jack_func) {
+	case N810_JACK_HS:
+		line1l = 1;
+	case N810_JACK_HP:
+		hp = 1;
+		break;
+	case N810_JACK_MIC:
+		line1l = 1;
+		break;
+	}
+
+	if (n810_spk_func)
+		snd_soc_dapm_enable_pin(dapm, "Ext Spk");
+	else
+		snd_soc_dapm_disable_pin(dapm, "Ext Spk");
+
+	if (hp)
+		snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
+	else
+		snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
+	if (line1l)
+		snd_soc_dapm_enable_pin(dapm, "LINE1L");
+	else
+		snd_soc_dapm_disable_pin(dapm, "LINE1L");
+
+	if (n810_dmic_func)
+		snd_soc_dapm_enable_pin(dapm, "DMic");
+	else
+		snd_soc_dapm_disable_pin(dapm, "DMic");
+
+	snd_soc_dapm_sync(dapm);
+}
+
+static int n810_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+
+	snd_pcm_hw_constraint_minmax(runtime,
+				     SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
+
+	n810_ext_control(&codec->dapm);
+	return clk_enable(sys_clkout2);
+}
+
+static void n810_shutdown(struct snd_pcm_substream *substream)
+{
+	clk_disable(sys_clkout2);
+}
+
+static int n810_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int err;
+
+	/* Set the codec system clock for DAC and ADC */
+	err = snd_soc_dai_set_sysclk(codec_dai, 0, 12000000,
+					    SND_SOC_CLOCK_IN);
+
+	return err;
+}
+
+static struct snd_soc_ops n810_ops = {
+	.startup = n810_startup,
+	.hw_params = n810_hw_params,
+	.shutdown = n810_shutdown,
+};
+
+static int n810_get_spk(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = n810_spk_func;
+
+	return 0;
+}
+
+static int n810_set_spk(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
+
+	if (n810_spk_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	n810_spk_func = ucontrol->value.integer.value[0];
+	n810_ext_control(&card->dapm);
+
+	return 1;
+}
+
+static int n810_get_jack(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = n810_jack_func;
+
+	return 0;
+}
+
+static int n810_set_jack(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
+
+	if (n810_jack_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	n810_jack_func = ucontrol->value.integer.value[0];
+	n810_ext_control(&card->dapm);
+
+	return 1;
+}
+
+static int n810_get_input(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = n810_dmic_func;
+
+	return 0;
+}
+
+static int n810_set_input(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
+
+	if (n810_dmic_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	n810_dmic_func = ucontrol->value.integer.value[0];
+	n810_ext_control(&card->dapm);
+
+	return 1;
+}
+
+static int n810_spk_event(struct snd_soc_dapm_widget *w,
+			  struct snd_kcontrol *k, int event)
+{
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		gpio_set_value(N810_SPEAKER_AMP_GPIO, 1);
+	else
+		gpio_set_value(N810_SPEAKER_AMP_GPIO, 0);
+
+	return 0;
+}
+
+static int n810_jack_event(struct snd_soc_dapm_widget *w,
+			   struct snd_kcontrol *k, int event)
+{
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		gpio_set_value(N810_HEADSET_AMP_GPIO, 1);
+	else
+		gpio_set_value(N810_HEADSET_AMP_GPIO, 0);
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget aic33_dapm_widgets[] = {
+	SND_SOC_DAPM_SPK("Ext Spk", n810_spk_event),
+	SND_SOC_DAPM_HP("Headphone Jack", n810_jack_event),
+	SND_SOC_DAPM_MIC("DMic", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	{"Headphone Jack", NULL, "HPLOUT"},
+	{"Headphone Jack", NULL, "HPROUT"},
+
+	{"Ext Spk", NULL, "LLOUT"},
+	{"Ext Spk", NULL, "RLOUT"},
+
+	{"DMic Rate 64", NULL, "Mic Bias 2V"},
+	{"Mic Bias 2V", NULL, "DMic"},
+};
+
+static const char *spk_function[] = {"Off", "On"};
+static const char *jack_function[] = {"Off", "Headphone", "Headset", "Mic"};
+static const char *input_function[] = {"ADC", "Digital Mic"};
+static const struct soc_enum n810_enum[] = {
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function),
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function),
+};
+
+static const struct snd_kcontrol_new aic33_n810_controls[] = {
+	SOC_ENUM_EXT("Speaker Function", n810_enum[0],
+		     n810_get_spk, n810_set_spk),
+	SOC_ENUM_EXT("Jack Function", n810_enum[1],
+		     n810_get_jack, n810_set_jack),
+	SOC_ENUM_EXT("Input Select",  n810_enum[2],
+		     n810_get_input, n810_set_input),
+};
+
+static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+	/* Not connected */
+	snd_soc_dapm_nc_pin(dapm, "MONO_LOUT");
+	snd_soc_dapm_nc_pin(dapm, "HPLCOM");
+	snd_soc_dapm_nc_pin(dapm, "HPRCOM");
+	snd_soc_dapm_nc_pin(dapm, "MIC3L");
+	snd_soc_dapm_nc_pin(dapm, "MIC3R");
+	snd_soc_dapm_nc_pin(dapm, "LINE1R");
+	snd_soc_dapm_nc_pin(dapm, "LINE2L");
+	snd_soc_dapm_nc_pin(dapm, "LINE2R");
+
+	return 0;
+}
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link n810_dai = {
+	.name = "TLV320AIC33",
+	.stream_name = "AIC33",
+	.cpu_dai_name = "omap-mcbsp.2",
+	.platform_name = "omap-pcm-audio",
+	.codec_name = "tlv320aic3x-codec.2-0018",
+	.codec_dai_name = "tlv320aic3x-hifi",
+	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBM_CFM,
+	.init = n810_aic33_init,
+	.ops = &n810_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_n810 = {
+	.name = "N810",
+	.owner = THIS_MODULE,
+	.dai_link = &n810_dai,
+	.num_links = 1,
+
+	.controls = aic33_n810_controls,
+	.num_controls = ARRAY_SIZE(aic33_n810_controls),
+	.dapm_widgets = aic33_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(aic33_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
+static struct platform_device *n810_snd_device;
+
+static int __init n810_soc_init(void)
+{
+	int err;
+	struct device *dev;
+
+	if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax()))
+		return -ENODEV;
+
+	n810_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!n810_snd_device)
+		return -ENOMEM;
+
+	platform_set_drvdata(n810_snd_device, &snd_soc_n810);
+	err = platform_device_add(n810_snd_device);
+	if (err)
+		goto err1;
+
+	dev = &n810_snd_device->dev;
+
+	sys_clkout2_src = clk_get(dev, "sys_clkout2_src");
+	if (IS_ERR(sys_clkout2_src)) {
+		dev_err(dev, "Could not get sys_clkout2_src clock\n");
+		err = PTR_ERR(sys_clkout2_src);
+		goto err2;
+	}
+	sys_clkout2 = clk_get(dev, "sys_clkout2");
+	if (IS_ERR(sys_clkout2)) {
+		dev_err(dev, "Could not get sys_clkout2\n");
+		err = PTR_ERR(sys_clkout2);
+		goto err3;
+	}
+	/*
+	 * Configure 12 MHz output on SYS_CLKOUT2. Therefore we must use
+	 * 96 MHz as its parent in order to get 12 MHz
+	 */
+	func96m_clk = clk_get(dev, "func_96m_ck");
+	if (IS_ERR(func96m_clk)) {
+		dev_err(dev, "Could not get func 96M clock\n");
+		err = PTR_ERR(func96m_clk);
+		goto err4;
+	}
+	clk_set_parent(sys_clkout2_src, func96m_clk);
+	clk_set_rate(sys_clkout2, 12000000);
+
+	BUG_ON((gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0) ||
+	       (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0));
+
+	gpio_direction_output(N810_HEADSET_AMP_GPIO, 0);
+	gpio_direction_output(N810_SPEAKER_AMP_GPIO, 0);
+
+	return 0;
+err4:
+	clk_put(sys_clkout2);
+err3:
+	clk_put(sys_clkout2_src);
+err2:
+	platform_device_del(n810_snd_device);
+err1:
+	platform_device_put(n810_snd_device);
+
+	return err;
+}
+
+static void __exit n810_soc_exit(void)
+{
+	gpio_free(N810_SPEAKER_AMP_GPIO);
+	gpio_free(N810_HEADSET_AMP_GPIO);
+	clk_put(sys_clkout2_src);
+	clk_put(sys_clkout2);
+	clk_put(func96m_clk);
+
+	platform_device_unregister(n810_snd_device);
+}
+
+module_init(n810_soc_init);
+module_exit(n810_soc_exit);
+
+MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
+MODULE_DESCRIPTION("ALSA SoC Nokia N810");
+MODULE_LICENSE("GPL");
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-abe-twl6040.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-abe-twl6040.c
new file mode 100644
index 0000000..9c2f090
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-abe-twl6040.c
@@ -0,0 +1,349 @@
+/*
+ * omap-abe-twl6040.c  --  SoC audio for TI OMAP based boards with ABE and
+ *			   twl6040 codec
+ *
+ * Author: Misael Lopez Cruz <misael.lopez@ti.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/twl6040.h>
+#include <linux/platform_data/omap-abe-twl6040.h>
+#include <linux/module.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+
+#include <asm/mach-types.h>
+#include <plat/hardware.h>
+#include <plat/mux.h>
+
+#include "omap-dmic.h"
+#include "omap-mcpdm.h"
+#include "omap-pcm.h"
+#include "../codecs/twl6040.h"
+
+static int omap_abe_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_card *card = codec->card;
+	struct omap_abe_twl6040_data *pdata = dev_get_platdata(card->dev);
+	int clk_id, freq;
+	int ret;
+
+	clk_id = twl6040_get_clk_id(rtd->codec);
+	if (clk_id == TWL6040_SYSCLK_SEL_HPPLL)
+		freq = pdata->mclk_freq;
+	else if (clk_id == TWL6040_SYSCLK_SEL_LPPLL)
+		freq = 32768;
+	else
+		return -EINVAL;
+
+	/* set the codec mclk */
+	ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
+				SND_SOC_CLOCK_IN);
+	if (ret) {
+		printk(KERN_ERR "can't set codec system clock\n");
+		return ret;
+	}
+	return ret;
+}
+
+static struct snd_soc_ops omap_abe_ops = {
+	.hw_params = omap_abe_hw_params,
+};
+
+static int omap_abe_dmic_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret = 0;
+
+	ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_SYSCLK_PAD_CLKS,
+				     19200000, SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set DMIC cpu system clock\n");
+		return ret;
+	}
+	ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_ABE_DMIC_CLK, 2400000,
+				     SND_SOC_CLOCK_OUT);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set DMIC output clock\n");
+		return ret;
+	}
+	return 0;
+}
+
+static struct snd_soc_ops omap_abe_dmic_ops = {
+	.hw_params = omap_abe_dmic_hw_params,
+};
+
+/* Headset jack */
+static struct snd_soc_jack hs_jack;
+
+/*Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin hs_jack_pins[] = {
+	{
+		.pin = "Headset Mic",
+		.mask = SND_JACK_MICROPHONE,
+	},
+	{
+		.pin = "Headset Stereophone",
+		.mask = SND_JACK_HEADPHONE,
+	},
+};
+
+/* SDP4430 machine DAPM */
+static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
+	/* Outputs */
+	SND_SOC_DAPM_HP("Headset Stereophone", NULL),
+	SND_SOC_DAPM_SPK("Earphone Spk", NULL),
+	SND_SOC_DAPM_SPK("Ext Spk", NULL),
+	SND_SOC_DAPM_LINE("Line Out", NULL),
+	SND_SOC_DAPM_SPK("Vibrator", NULL),
+
+	/* Inputs */
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("Main Handset Mic", NULL),
+	SND_SOC_DAPM_MIC("Sub Handset Mic", NULL),
+	SND_SOC_DAPM_LINE("Line In", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	/* Routings for outputs */
+	{"Headset Stereophone", NULL, "HSOL"},
+	{"Headset Stereophone", NULL, "HSOR"},
+
+	{"Earphone Spk", NULL, "EP"},
+
+	{"Ext Spk", NULL, "HFL"},
+	{"Ext Spk", NULL, "HFR"},
+
+	{"Line Out", NULL, "AUXL"},
+	{"Line Out", NULL, "AUXR"},
+
+	{"Vibrator", NULL, "VIBRAL"},
+	{"Vibrator", NULL, "VIBRAR"},
+
+	/* Routings for inputs */
+	{"HSMIC", NULL, "Headset Mic"},
+	{"Headset Mic", NULL, "Headset Mic Bias"},
+
+	{"MAINMIC", NULL, "Main Handset Mic"},
+	{"Main Handset Mic", NULL, "Main Mic Bias"},
+
+	{"SUBMIC", NULL, "Sub Handset Mic"},
+	{"Sub Handset Mic", NULL, "Main Mic Bias"},
+
+	{"AFML", NULL, "Line In"},
+	{"AFMR", NULL, "Line In"},
+};
+
+static inline void twl6040_disconnect_pin(struct snd_soc_dapm_context *dapm,
+					  int connected, char *pin)
+{
+	if (!connected)
+		snd_soc_dapm_disable_pin(dapm, pin);
+}
+
+static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_card *card = codec->card;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct omap_abe_twl6040_data *pdata = dev_get_platdata(card->dev);
+	int hs_trim;
+	int ret = 0;
+
+	/* Disable not connected paths if not used */
+	twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone");
+	twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk");
+	twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk");
+	twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out");
+	twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vibrator");
+	twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic");
+	twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic");
+	twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic");
+	twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In");
+
+	/*
+	 * Configure McPDM offset cancellation based on the HSOTRIM value from
+	 * twl6040.
+	 */
+	hs_trim = twl6040_get_trim_value(codec, TWL6040_TRIM_HSOTRIM);
+	omap_mcpdm_configure_dn_offsets(rtd, TWL6040_HSF_TRIM_LEFT(hs_trim),
+					TWL6040_HSF_TRIM_RIGHT(hs_trim));
+
+	/* Headset jack detection only if it is supported */
+	if (pdata->jack_detection) {
+		ret = snd_soc_jack_new(codec, "Headset Jack",
+					SND_JACK_HEADSET, &hs_jack);
+		if (ret)
+			return ret;
+
+		ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
+					hs_jack_pins);
+		twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
+	}
+
+	return ret;
+}
+
+static const struct snd_soc_dapm_widget dmic_dapm_widgets[] = {
+	SND_SOC_DAPM_MIC("Digital Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route dmic_audio_map[] = {
+	{"DMic", NULL, "Digital Mic"},
+	{"Digital Mic", NULL, "Digital Mic1 Bias"},
+};
+
+static int omap_abe_dmic_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int ret;
+
+	ret = snd_soc_dapm_new_controls(dapm, dmic_dapm_widgets,
+				ARRAY_SIZE(dmic_dapm_widgets));
+	if (ret)
+		return ret;
+
+	return snd_soc_dapm_add_routes(dapm, dmic_audio_map,
+				ARRAY_SIZE(dmic_audio_map));
+}
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link twl6040_dmic_dai[] = {
+	{
+		.name = "TWL6040",
+		.stream_name = "TWL6040",
+		.cpu_dai_name = "omap-mcpdm",
+		.codec_dai_name = "twl6040-legacy",
+		.platform_name = "omap-pcm-audio",
+		.codec_name = "twl6040-codec",
+		.init = omap_abe_twl6040_init,
+		.ops = &omap_abe_ops,
+	},
+	{
+		.name = "DMIC",
+		.stream_name = "DMIC Capture",
+		.cpu_dai_name = "omap-dmic",
+		.codec_dai_name = "dmic-hifi",
+		.platform_name = "omap-pcm-audio",
+		.codec_name = "dmic-codec",
+		.init = omap_abe_dmic_init,
+		.ops = &omap_abe_dmic_ops,
+	},
+};
+
+static struct snd_soc_dai_link twl6040_only_dai[] = {
+	{
+		.name = "TWL6040",
+		.stream_name = "TWL6040",
+		.cpu_dai_name = "omap-mcpdm",
+		.codec_dai_name = "twl6040-legacy",
+		.platform_name = "omap-pcm-audio",
+		.codec_name = "twl6040-codec",
+		.init = omap_abe_twl6040_init,
+		.ops = &omap_abe_ops,
+	},
+};
+
+/* Audio machine driver */
+static struct snd_soc_card omap_abe_card = {
+	.owner = THIS_MODULE,
+
+	.dapm_widgets = twl6040_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
+static __devinit int omap_abe_probe(struct platform_device *pdev)
+{
+	struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev);
+	struct snd_soc_card *card = &omap_abe_card;
+	int ret;
+
+	card->dev = &pdev->dev;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "Missing pdata\n");
+		return -ENODEV;
+	}
+
+	if (pdata->card_name) {
+		card->name = pdata->card_name;
+	} else {
+		dev_err(&pdev->dev, "Card name is not provided\n");
+		return -ENODEV;
+	}
+
+	if (!pdata->mclk_freq) {
+		dev_err(&pdev->dev, "MCLK frequency missing\n");
+		return -ENODEV;
+	}
+
+	if (pdata->has_dmic) {
+		card->dai_link = twl6040_dmic_dai;
+		card->num_links = ARRAY_SIZE(twl6040_dmic_dai);
+	} else {
+		card->dai_link = twl6040_only_dai;
+		card->num_links = ARRAY_SIZE(twl6040_only_dai);
+	}
+
+	ret = snd_soc_register_card(card);
+	if (ret)
+		dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+			ret);
+
+	return ret;
+}
+
+static int __devexit omap_abe_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+
+	return 0;
+}
+
+static struct platform_driver omap_abe_driver = {
+	.driver = {
+		.name = "omap-abe-twl6040",
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+	},
+	.probe = omap_abe_probe,
+	.remove = __devexit_p(omap_abe_remove),
+};
+
+module_platform_driver(omap_abe_driver);
+
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
+MODULE_DESCRIPTION("ALSA SoC for OMAP boards with ABE and twl6040 codec");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:omap-abe-twl6040");
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-dmic.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-dmic.c
new file mode 100644
index 0000000..4dcb5a7
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-dmic.c
@@ -0,0 +1,545 @@
+/*
+ * omap-dmic.c  --  OMAP ASoC DMIC DAI driver
+ *
+ * Copyright (C) 2010 - 2011 Texas Instruments
+ *
+ * Author: David Lambert <dlambert@ti.com>
+ *	   Misael Lopez Cruz <misael.lopez@ti.com>
+ *	   Liam Girdwood <lrg@ti.com>
+ *	   Peter Ujfalusi <peter.ujfalusi@ti.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <plat/dma.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include "omap-pcm.h"
+#include "omap-dmic.h"
+
+struct omap_dmic {
+	struct device *dev;
+	void __iomem *io_base;
+	struct clk *fclk;
+	int fclk_freq;
+	int out_freq;
+	int clk_div;
+	int sysclk;
+	int threshold;
+	u32 ch_enabled;
+	bool active;
+	struct mutex mutex;
+};
+
+/*
+ * Stream DMA parameters
+ */
+static struct omap_pcm_dma_data omap_dmic_dai_dma_params = {
+	.name		= "DMIC capture",
+	.data_type	= OMAP_DMA_DATA_TYPE_S32,
+	.sync_mode	= OMAP_DMA_SYNC_PACKET,
+};
+
+static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val)
+{
+	__raw_writel(val, dmic->io_base + reg);
+}
+
+static inline int omap_dmic_read(struct omap_dmic *dmic, u16 reg)
+{
+	return __raw_readl(dmic->io_base + reg);
+}
+
+static inline void omap_dmic_start(struct omap_dmic *dmic)
+{
+	u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
+
+	/* Configure DMA controller */
+	omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_SET_REG,
+			OMAP_DMIC_DMA_ENABLE);
+
+	omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl | dmic->ch_enabled);
+}
+
+static inline void omap_dmic_stop(struct omap_dmic *dmic)
+{
+	u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
+	omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG,
+			ctrl & ~OMAP_DMIC_UP_ENABLE_MASK);
+
+	/* Disable DMA request generation */
+	omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_CLR_REG,
+			OMAP_DMIC_DMA_ENABLE);
+
+}
+
+static inline int dmic_is_enabled(struct omap_dmic *dmic)
+{
+	return omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG) &
+						OMAP_DMIC_UP_ENABLE_MASK;
+}
+
+static int omap_dmic_dai_startup(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+	int ret = 0;
+
+	mutex_lock(&dmic->mutex);
+
+	if (!dai->active)
+		dmic->active = 1;
+	else
+		ret = -EBUSY;
+
+	mutex_unlock(&dmic->mutex);
+
+	return ret;
+}
+
+static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream,
+				    struct snd_soc_dai *dai)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+	mutex_lock(&dmic->mutex);
+
+	if (!dai->active)
+		dmic->active = 0;
+
+	mutex_unlock(&dmic->mutex);
+}
+
+static int omap_dmic_select_divider(struct omap_dmic *dmic, int sample_rate)
+{
+	int divider = -EINVAL;
+
+	/*
+	 * 192KHz rate is only supported with 19.2MHz/3.84MHz clock
+	 * configuration.
+	 */
+	if (sample_rate == 192000) {
+		if (dmic->fclk_freq == 19200000 && dmic->out_freq == 3840000)
+			divider = 0x6; /* Divider: 5 (192KHz sampling rate) */
+		else
+			dev_err(dmic->dev,
+				"invalid clock configuration for 192KHz\n");
+
+		return divider;
+	}
+
+	switch (dmic->out_freq) {
+	case 1536000:
+		if (dmic->fclk_freq != 24576000)
+			goto div_err;
+		divider = 0x4; /* Divider: 16 */
+		break;
+	case 2400000:
+		switch (dmic->fclk_freq) {
+		case 12000000:
+			divider = 0x5; /* Divider: 5 */
+			break;
+		case 19200000:
+			divider = 0x0; /* Divider: 8 */
+			break;
+		case 24000000:
+			divider = 0x2; /* Divider: 10 */
+			break;
+		default:
+			goto div_err;
+		}
+		break;
+	case 3072000:
+		if (dmic->fclk_freq != 24576000)
+			goto div_err;
+		divider = 0x3; /* Divider: 8 */
+		break;
+	case 3840000:
+		if (dmic->fclk_freq != 19200000)
+			goto div_err;
+		divider = 0x1; /* Divider: 5 (96KHz sampling rate) */
+		break;
+	default:
+		dev_err(dmic->dev, "invalid out frequency: %dHz\n",
+			dmic->out_freq);
+		break;
+	}
+
+	return divider;
+
+div_err:
+	dev_err(dmic->dev, "invalid out frequency %dHz for %dHz input\n",
+		dmic->out_freq, dmic->fclk_freq);
+	return -EINVAL;
+}
+
+static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
+				    struct snd_pcm_hw_params *params,
+				    struct snd_soc_dai *dai)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+	int channels;
+
+	dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params));
+	if (dmic->clk_div < 0) {
+		dev_err(dmic->dev, "no valid divider for %dHz from %dHz\n",
+			dmic->out_freq, dmic->fclk_freq);
+		return -EINVAL;
+	}
+
+	dmic->ch_enabled = 0;
+	channels = params_channels(params);
+	switch (channels) {
+	case 6:
+		dmic->ch_enabled |= OMAP_DMIC_UP3_ENABLE;
+	case 4:
+		dmic->ch_enabled |= OMAP_DMIC_UP2_ENABLE;
+	case 2:
+		dmic->ch_enabled |= OMAP_DMIC_UP1_ENABLE;
+		break;
+	default:
+		dev_err(dmic->dev, "invalid number of legacy channels\n");
+		return -EINVAL;
+	}
+
+	/* packet size is threshold * channels */
+	omap_dmic_dai_dma_params.packet_size = dmic->threshold * channels;
+	snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params);
+
+	return 0;
+}
+
+static int omap_dmic_dai_prepare(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+	u32 ctrl;
+
+	/* Configure uplink threshold */
+	omap_dmic_write(dmic, OMAP_DMIC_FIFO_CTRL_REG, dmic->threshold);
+
+	ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
+
+	/* Set dmic out format */
+	ctrl &= ~(OMAP_DMIC_FORMAT | OMAP_DMIC_POLAR_MASK);
+	ctrl |= (OMAP_DMICOUTFORMAT_LJUST | OMAP_DMIC_POLAR1 |
+		 OMAP_DMIC_POLAR2 | OMAP_DMIC_POLAR3);
+
+	/* Configure dmic clock divider */
+	ctrl &= ~OMAP_DMIC_CLK_DIV_MASK;
+	ctrl |= OMAP_DMIC_CLK_DIV(dmic->clk_div);
+
+	omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl);
+
+	omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG,
+			ctrl | OMAP_DMICOUTFORMAT_LJUST | OMAP_DMIC_POLAR1 |
+			OMAP_DMIC_POLAR2 | OMAP_DMIC_POLAR3);
+
+	return 0;
+}
+
+static int omap_dmic_dai_trigger(struct snd_pcm_substream *substream,
+				  int cmd, struct snd_soc_dai *dai)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		omap_dmic_start(dmic);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		omap_dmic_stop(dmic);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id,
+				 unsigned int freq)
+{
+	struct clk *parent_clk;
+	char *parent_clk_name;
+	int ret = 0;
+
+	switch (freq) {
+	case 12000000:
+	case 19200000:
+	case 24000000:
+	case 24576000:
+		break;
+	default:
+		dev_err(dmic->dev, "invalid input frequency: %dHz\n", freq);
+		dmic->fclk_freq = 0;
+		return -EINVAL;
+	}
+
+	if (dmic->sysclk == clk_id) {
+		dmic->fclk_freq = freq;
+		return 0;
+	}
+
+	/* re-parent not allowed if a stream is ongoing */
+	if (dmic->active && dmic_is_enabled(dmic)) {
+		dev_err(dmic->dev, "can't re-parent when DMIC active\n");
+		return -EBUSY;
+	}
+
+	switch (clk_id) {
+	case OMAP_DMIC_SYSCLK_PAD_CLKS:
+		parent_clk_name = "pad_clks_ck";
+		break;
+	case OMAP_DMIC_SYSCLK_SLIMBLUS_CLKS:
+		parent_clk_name = "slimbus_clk";
+		break;
+	case OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS:
+		parent_clk_name = "dmic_sync_mux_ck";
+		break;
+	default:
+		dev_err(dmic->dev, "fclk clk_id (%d) not supported\n", clk_id);
+		return -EINVAL;
+	}
+
+	parent_clk = clk_get(dmic->dev, parent_clk_name);
+	if (IS_ERR(parent_clk)) {
+		dev_err(dmic->dev, "can't get %s\n", parent_clk_name);
+		return -ENODEV;
+	}
+
+	mutex_lock(&dmic->mutex);
+	if (dmic->active) {
+		/* disable clock while reparenting */
+		pm_runtime_put_sync(dmic->dev);
+		ret = clk_set_parent(dmic->fclk, parent_clk);
+		pm_runtime_get_sync(dmic->dev);
+	} else {
+		ret = clk_set_parent(dmic->fclk, parent_clk);
+	}
+	mutex_unlock(&dmic->mutex);
+
+	if (ret < 0) {
+		dev_err(dmic->dev, "re-parent failed\n");
+		goto err_busy;
+	}
+
+	dmic->sysclk = clk_id;
+	dmic->fclk_freq = freq;
+
+err_busy:
+	clk_put(parent_clk);
+
+	return ret;
+}
+
+static int omap_dmic_select_outclk(struct omap_dmic *dmic, int clk_id,
+				    unsigned int freq)
+{
+	int ret = 0;
+
+	if (clk_id != OMAP_DMIC_ABE_DMIC_CLK) {
+		dev_err(dmic->dev, "output clk_id (%d) not supported\n",
+			clk_id);
+		return -EINVAL;
+	}
+
+	switch (freq) {
+	case 1536000:
+	case 2400000:
+	case 3072000:
+	case 3840000:
+		dmic->out_freq = freq;
+		break;
+	default:
+		dev_err(dmic->dev, "invalid out frequency: %dHz\n", freq);
+		dmic->out_freq = 0;
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int omap_dmic_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
+				    unsigned int freq, int dir)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+	if (dir == SND_SOC_CLOCK_IN)
+		return omap_dmic_select_fclk(dmic, clk_id, freq);
+	else if (dir == SND_SOC_CLOCK_OUT)
+		return omap_dmic_select_outclk(dmic, clk_id, freq);
+
+	dev_err(dmic->dev, "invalid clock direction (%d)\n", dir);
+	return -EINVAL;
+}
+
+static const struct snd_soc_dai_ops omap_dmic_dai_ops = {
+	.startup	= omap_dmic_dai_startup,
+	.shutdown	= omap_dmic_dai_shutdown,
+	.hw_params	= omap_dmic_dai_hw_params,
+	.prepare	= omap_dmic_dai_prepare,
+	.trigger	= omap_dmic_dai_trigger,
+	.set_sysclk	= omap_dmic_set_dai_sysclk,
+};
+
+static int omap_dmic_probe(struct snd_soc_dai *dai)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+	pm_runtime_enable(dmic->dev);
+
+	/* Disable lines while request is ongoing */
+	pm_runtime_get_sync(dmic->dev);
+	omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, 0x00);
+	pm_runtime_put_sync(dmic->dev);
+
+	/* Configure DMIC threshold value */
+	dmic->threshold = OMAP_DMIC_THRES_MAX - 3;
+	return 0;
+}
+
+static int omap_dmic_remove(struct snd_soc_dai *dai)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+	pm_runtime_disable(dmic->dev);
+
+	return 0;
+}
+
+static struct snd_soc_dai_driver omap_dmic_dai = {
+	.name = "omap-dmic",
+	.probe = omap_dmic_probe,
+	.remove = omap_dmic_remove,
+	.capture = {
+		.channels_min = 2,
+		.channels_max = 6,
+		.rates = SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
+		.formats = SNDRV_PCM_FMTBIT_S32_LE,
+		.sig_bits = 24,
+	},
+	.ops = &omap_dmic_dai_ops,
+};
+
+static __devinit int asoc_dmic_probe(struct platform_device *pdev)
+{
+	struct omap_dmic *dmic;
+	struct resource *res;
+	int ret;
+
+	dmic = devm_kzalloc(&pdev->dev, sizeof(struct omap_dmic), GFP_KERNEL);
+	if (!dmic)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, dmic);
+	dmic->dev = &pdev->dev;
+	dmic->sysclk = OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS;
+
+	mutex_init(&dmic->mutex);
+
+	dmic->fclk = clk_get(dmic->dev, "dmic_fck");
+	if (IS_ERR(dmic->fclk)) {
+		dev_err(dmic->dev, "cant get dmic_fck\n");
+		return -ENODEV;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
+	if (!res) {
+		dev_err(dmic->dev, "invalid dma memory resource\n");
+		ret = -ENODEV;
+		goto err_put_clk;
+	}
+	omap_dmic_dai_dma_params.port_addr = res->start + OMAP_DMIC_DATA_REG;
+
+	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!res) {
+		dev_err(dmic->dev, "invalid dma resource\n");
+		ret = -ENODEV;
+		goto err_put_clk;
+	}
+	omap_dmic_dai_dma_params.dma_req = res->start;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
+	if (!res) {
+		dev_err(dmic->dev, "invalid memory resource\n");
+		ret = -ENODEV;
+		goto err_put_clk;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+				     resource_size(res), pdev->name)) {
+		dev_err(dmic->dev, "memory region already claimed\n");
+		ret = -ENODEV;
+		goto err_put_clk;
+	}
+
+	dmic->io_base = devm_ioremap(&pdev->dev, res->start,
+				     resource_size(res));
+	if (!dmic->io_base) {
+		ret = -ENOMEM;
+		goto err_put_clk;
+	}
+
+	ret = snd_soc_register_dai(&pdev->dev, &omap_dmic_dai);
+	if (ret)
+		goto err_put_clk;
+
+	return 0;
+
+err_put_clk:
+	clk_put(dmic->fclk);
+	return ret;
+}
+
+static int __devexit asoc_dmic_remove(struct platform_device *pdev)
+{
+	struct omap_dmic *dmic = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_dai(&pdev->dev);
+	clk_put(dmic->fclk);
+
+	return 0;
+}
+
+static struct platform_driver asoc_dmic_driver = {
+	.driver = {
+		.name = "omap-dmic",
+		.owner = THIS_MODULE,
+	},
+	.probe = asoc_dmic_probe,
+	.remove = __devexit_p(asoc_dmic_remove),
+};
+
+module_platform_driver(asoc_dmic_driver);
+
+MODULE_ALIAS("platform:omap-dmic");
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_DESCRIPTION("OMAP DMIC ASoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-dmic.h b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-dmic.h
new file mode 100644
index 0000000..231e728
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-dmic.h
@@ -0,0 +1,69 @@
+/*
+ * omap-dmic.h  --  OMAP Digital Microphone Controller
+ *
+ * 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.
+ */
+
+#ifndef _OMAP_DMIC_H
+#define _OMAP_DMIC_H
+
+#define OMAP_DMIC_REVISION_REG		0x00
+#define OMAP_DMIC_SYSCONFIG_REG		0x10
+#define OMAP_DMIC_IRQSTATUS_RAW_REG	0x24
+#define OMAP_DMIC_IRQSTATUS_REG		0x28
+#define OMAP_DMIC_IRQENABLE_SET_REG	0x2C
+#define OMAP_DMIC_IRQENABLE_CLR_REG	0x30
+#define OMAP_DMIC_IRQWAKE_EN_REG	0x34
+#define OMAP_DMIC_DMAENABLE_SET_REG	0x38
+#define OMAP_DMIC_DMAENABLE_CLR_REG	0x3C
+#define OMAP_DMIC_DMAWAKEEN_REG		0x40
+#define OMAP_DMIC_CTRL_REG		0x44
+#define OMAP_DMIC_DATA_REG		0x48
+#define OMAP_DMIC_FIFO_CTRL_REG		0x4C
+#define OMAP_DMIC_FIFO_DMIC1R_DATA_REG	0x50
+#define OMAP_DMIC_FIFO_DMIC1L_DATA_REG	0x54
+#define OMAP_DMIC_FIFO_DMIC2R_DATA_REG	0x58
+#define OMAP_DMIC_FIFO_DMIC2L_DATA_REG	0x5C
+#define OMAP_DMIC_FIFO_DMIC3R_DATA_REG	0x60
+#define OMAP_DMIC_FIFO_DMIC3L_DATA_REG	0x64
+
+/* IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR bit fields */
+#define OMAP_DMIC_IRQ			(1 << 0)
+#define OMAP_DMIC_IRQ_FULL		(1 << 1)
+#define OMAP_DMIC_IRQ_ALMST_EMPTY	(1 << 2)
+#define OMAP_DMIC_IRQ_EMPTY		(1 << 3)
+#define OMAP_DMIC_IRQ_MASK		0x07
+
+/* DMIC_DMAENABLE bit fields */
+#define OMAP_DMIC_DMA_ENABLE		0x1
+
+/* DMIC_CTRL bit fields */
+#define OMAP_DMIC_UP1_ENABLE		(1 << 0)
+#define OMAP_DMIC_UP2_ENABLE		(1 << 1)
+#define OMAP_DMIC_UP3_ENABLE		(1 << 2)
+#define OMAP_DMIC_UP_ENABLE_MASK	0x7
+#define OMAP_DMIC_FORMAT		(1 << 3)
+#define OMAP_DMIC_POLAR1		(1 << 4)
+#define OMAP_DMIC_POLAR2		(1 << 5)
+#define OMAP_DMIC_POLAR3		(1 << 6)
+#define OMAP_DMIC_POLAR_MASK		(0x7 << 4)
+#define OMAP_DMIC_CLK_DIV(x)		(((x) & 0x7) << 7)
+#define OMAP_DMIC_CLK_DIV_MASK		(0x7 << 7)
+#define	OMAP_DMIC_RESET			(1 << 10)
+
+#define OMAP_DMICOUTFORMAT_LJUST	(0 << 3)
+#define OMAP_DMICOUTFORMAT_RJUST	(1 << 3)
+
+/* DMIC_FIFO_CTRL bit fields */
+#define OMAP_DMIC_THRES_MAX		0xF
+
+enum omap_dmic_clk {
+	OMAP_DMIC_SYSCLK_PAD_CLKS,		/* PAD_CLKS */
+	OMAP_DMIC_SYSCLK_SLIMBLUS_CLKS,		/* SLIMBUS_CLK */
+	OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS,		/* DMIC_SYNC_MUX_CLK */
+	OMAP_DMIC_ABE_DMIC_CLK,			/* abe_dmic_clk */
+};
+
+#endif
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-hdmi.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-hdmi.c
new file mode 100644
index 0000000..38e0def
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-hdmi.c
@@ -0,0 +1,148 @@
+/*
+ * omap-hdmi.c
+ *
+ * OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors.
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Authors: Jorge Candelaria <jorge.candelaria@ti.com>
+ *          Ricardo Neri <ricardo.neri@ti.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <plat/dma.h>
+#include "omap-pcm.h"
+#include "omap-hdmi.h"
+
+#define DRV_NAME "hdmi-audio-dai"
+
+static struct omap_pcm_dma_data omap_hdmi_dai_dma_params = {
+	.name = "HDMI playback",
+	.sync_mode = OMAP_DMA_SYNC_PACKET,
+};
+
+static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
+{
+	int err;
+	/*
+	 * Make sure that the period bytes are multiple of the DMA packet size.
+	 * Largest packet size we use is 32 32-bit words = 128 bytes
+	 */
+	err = snd_pcm_hw_constraint_step(substream->runtime, 0,
+				 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
+				    struct snd_pcm_hw_params *params,
+				    struct snd_soc_dai *dai)
+{
+	int err = 0;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		omap_hdmi_dai_dma_params.packet_size = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		omap_hdmi_dai_dma_params.packet_size = 32;
+		break;
+	default:
+		err = -EINVAL;
+	}
+
+	omap_hdmi_dai_dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
+
+	snd_soc_dai_set_dma_data(dai, substream,
+				 &omap_hdmi_dai_dma_params);
+
+	return err;
+}
+
+static const struct snd_soc_dai_ops omap_hdmi_dai_ops = {
+	.startup	= omap_hdmi_dai_startup,
+	.hw_params	= omap_hdmi_dai_hw_params,
+};
+
+static struct snd_soc_dai_driver omap_hdmi_dai = {
+	.playback = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = OMAP_HDMI_RATES,
+		.formats = OMAP_HDMI_FORMATS,
+	},
+	.ops = &omap_hdmi_dai_ops,
+};
+
+static __devinit int omap_hdmi_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct resource *hdmi_rsrc;
+
+	hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!hdmi_rsrc) {
+		dev_err(&pdev->dev, "Cannot obtain IORESOURCE_MEM HDMI\n");
+		return -EINVAL;
+	}
+
+	omap_hdmi_dai_dma_params.port_addr =  hdmi_rsrc->start
+		+ OMAP_HDMI_AUDIO_DMA_PORT;
+
+	hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!hdmi_rsrc) {
+		dev_err(&pdev->dev, "Cannot obtain IORESOURCE_DMA HDMI\n");
+		return -EINVAL;
+	}
+
+	omap_hdmi_dai_dma_params.dma_req =  hdmi_rsrc->start;
+
+	ret = snd_soc_register_dai(&pdev->dev, &omap_hdmi_dai);
+	return ret;
+}
+
+static int __devexit omap_hdmi_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_dai(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver hdmi_dai_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = omap_hdmi_probe,
+	.remove = __devexit_p(omap_hdmi_remove),
+};
+
+module_platform_driver(hdmi_dai_driver);
+
+MODULE_AUTHOR("Jorge Candelaria <jorge.candelaria@ti.com>");
+MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
+MODULE_DESCRIPTION("OMAP HDMI SoC Interface");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-hdmi.h b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-hdmi.h
new file mode 100644
index 0000000..34c298d
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-hdmi.h
@@ -0,0 +1,36 @@
+/*
+ * omap-hdmi.h
+ *
+ * Definitions for OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors.
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Authors: Jorge Candelaria <jorge.candelaria@ti.com>
+ *          Ricardo Neri <ricardo.neri@ti.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_HDMI_H__
+#define __OMAP_HDMI_H__
+
+#define OMAP_HDMI_AUDIO_DMA_PORT 0x8c
+
+#define OMAP_HDMI_RATES	(SNDRV_PCM_RATE_32000 | \
+				SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+
+#define OMAP_HDMI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+				SNDRV_PCM_FMTBIT_S24_LE)
+
+#endif
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-mcbsp.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-mcbsp.c
new file mode 100644
index 0000000..6912ac7
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-mcbsp.c
@@ -0,0 +1,817 @@
+/*
+ * omap-mcbsp.c  --  OMAP ALSA SoC DAI driver using McBSP port
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
+ *          Peter Ujfalusi <peter.ujfalusi@ti.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/pm_runtime.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <plat/dma.h>
+#include <plat/mcbsp.h>
+#include "mcbsp.h"
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+
+#define OMAP_MCBSP_RATES	(SNDRV_PCM_RATE_8000_96000)
+
+#define OMAP_MCBSP_SOC_SINGLE_S16_EXT(xname, xmin, xmax, \
+	xhandler_get, xhandler_put) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = omap_mcbsp_st_info_volsw, \
+	.get = xhandler_get, .put = xhandler_put, \
+	.private_value = (unsigned long) &(struct soc_mixer_control) \
+	{.min = xmin, .max = xmax} }
+
+enum {
+	OMAP_MCBSP_WORD_8 = 0,
+	OMAP_MCBSP_WORD_12,
+	OMAP_MCBSP_WORD_16,
+	OMAP_MCBSP_WORD_20,
+	OMAP_MCBSP_WORD_24,
+	OMAP_MCBSP_WORD_32,
+};
+
+/*
+ * Stream DMA parameters. DMA request line and port address are set runtime
+ * since they are different between OMAP1 and later OMAPs
+ */
+static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+	struct omap_pcm_dma_data *dma_data;
+	int words;
+
+	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+
+	/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
+	if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
+		/*
+		 * Configure McBSP threshold based on either:
+		 * packet_size, when the sDMA is in packet mode, or
+		 * based on the period size.
+		 */
+		if (dma_data->packet_size)
+			words = dma_data->packet_size;
+		else
+			words = snd_pcm_lib_period_bytes(substream) /
+							(mcbsp->wlen / 8);
+	else
+		words = 1;
+
+	/* Configure McBSP internal buffer usage */
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		omap_mcbsp_set_tx_threshold(mcbsp, words);
+	else
+		omap_mcbsp_set_rx_threshold(mcbsp, words);
+}
+
+static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
+				    struct snd_pcm_hw_rule *rule)
+{
+	struct snd_interval *buffer_size = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_BUFFER_SIZE);
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+	struct omap_mcbsp *mcbsp = rule->private;
+	struct snd_interval frames;
+	int size;
+
+	snd_interval_any(&frames);
+	size = mcbsp->pdata->buffer_size;
+
+	frames.min = size / channels->min;
+	frames.integer = 1;
+	return snd_interval_refine(buffer_size, &frames);
+}
+
+static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *cpu_dai)
+{
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+	int err = 0;
+
+	if (!cpu_dai->active)
+		err = omap_mcbsp_request(mcbsp);
+
+	/*
+	 * OMAP3 McBSP FIFO is word structured.
+	 * McBSP2 has 1024 + 256 = 1280 word long buffer,
+	 * McBSP1,3,4,5 has 128 word long buffer
+	 * This means that the size of the FIFO depends on the sample format.
+	 * For example on McBSP3:
+	 * 16bit samples: size is 128 * 2 = 256 bytes
+	 * 32bit samples: size is 128 * 4 = 512 bytes
+	 * It is simpler to place constraint for buffer and period based on
+	 * channels.
+	 * McBSP3 as example again (16 or 32 bit samples):
+	 * 1 channel (mono): size is 128 frames (128 words)
+	 * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words)
+	 * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words)
+	 */
+	if (mcbsp->pdata->buffer_size) {
+		/*
+		* Rule for the buffer size. We should not allow
+		* smaller buffer than the FIFO size to avoid underruns
+		*/
+		snd_pcm_hw_rule_add(substream->runtime, 0,
+				    SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+				    omap_mcbsp_hwrule_min_buffersize,
+				    mcbsp,
+				    SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+
+		/* Make sure, that the period size is always even */
+		snd_pcm_hw_constraint_step(substream->runtime, 0,
+					   SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
+	}
+
+	return err;
+}
+
+static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
+				    struct snd_soc_dai *cpu_dai)
+{
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+
+	if (!cpu_dai->active) {
+		omap_mcbsp_free(mcbsp);
+		mcbsp->configured = 0;
+	}
+}
+
+static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+				  struct snd_soc_dai *cpu_dai)
+{
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+	int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		mcbsp->active++;
+		omap_mcbsp_start(mcbsp, play, !play);
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		omap_mcbsp_stop(mcbsp, play, !play);
+		mcbsp->active--;
+		break;
+	default:
+		err = -EINVAL;
+	}
+
+	return err;
+}
+
+static snd_pcm_sframes_t omap_mcbsp_dai_delay(
+			struct snd_pcm_substream *substream,
+			struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+	u16 fifo_use;
+	snd_pcm_sframes_t delay;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		fifo_use = omap_mcbsp_get_tx_delay(mcbsp);
+	else
+		fifo_use = omap_mcbsp_get_rx_delay(mcbsp);
+
+	/*
+	 * Divide the used locations with the channel count to get the
+	 * FIFO usage in samples (don't care about partial samples in the
+	 * buffer).
+	 */
+	delay = fifo_use / substream->runtime->channels;
+
+	return delay;
+}
+
+static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
+				    struct snd_pcm_hw_params *params,
+				    struct snd_soc_dai *cpu_dai)
+{
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+	struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
+	struct omap_pcm_dma_data *dma_data;
+	int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
+	int pkt_size = 0;
+	unsigned int format, div, framesize, master;
+
+	dma_data = &mcbsp->dma_data[substream->stream];
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		dma_data->data_type = OMAP_DMA_DATA_TYPE_S16;
+		wlen = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		dma_data->data_type = OMAP_DMA_DATA_TYPE_S32;
+		wlen = 32;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (mcbsp->pdata->buffer_size) {
+		dma_data->set_threshold = omap_mcbsp_set_threshold;
+		/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
+		if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) {
+			int period_words, max_thrsh;
+
+			period_words = params_period_bytes(params) / (wlen / 8);
+			if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+				max_thrsh = mcbsp->max_tx_thres;
+			else
+				max_thrsh = mcbsp->max_rx_thres;
+			/*
+			 * If the period contains less or equal number of words,
+			 * we are using the original threshold mode setup:
+			 * McBSP threshold = sDMA frame size = period_size
+			 * Otherwise we switch to sDMA packet mode:
+			 * McBSP threshold = sDMA packet size
+			 * sDMA frame size = period size
+			 */
+			if (period_words > max_thrsh) {
+				int divider = 0;
+
+				/*
+				 * Look for the biggest threshold value, which
+				 * divides the period size evenly.
+				 */
+				divider = period_words / max_thrsh;
+				if (period_words % max_thrsh)
+					divider++;
+				while (period_words % divider &&
+					divider < period_words)
+					divider++;
+				if (divider == period_words)
+					return -EINVAL;
+
+				pkt_size = period_words / divider;
+				sync_mode = OMAP_DMA_SYNC_PACKET;
+			} else {
+				sync_mode = OMAP_DMA_SYNC_FRAME;
+			}
+		}
+	}
+
+	dma_data->sync_mode = sync_mode;
+	dma_data->packet_size = pkt_size;
+
+	snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
+
+	if (mcbsp->configured) {
+		/* McBSP already configured by another stream */
+		return 0;
+	}
+
+	regs->rcr2	&= ~(RPHASE | RFRLEN2(0x7f) | RWDLEN2(7));
+	regs->xcr2	&= ~(RPHASE | XFRLEN2(0x7f) | XWDLEN2(7));
+	regs->rcr1	&= ~(RFRLEN1(0x7f) | RWDLEN1(7));
+	regs->xcr1	&= ~(XFRLEN1(0x7f) | XWDLEN1(7));
+	format = mcbsp->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+	wpf = channels = params_channels(params);
+	if (channels == 2 && (format == SND_SOC_DAIFMT_I2S ||
+			      format == SND_SOC_DAIFMT_LEFT_J)) {
+		/* Use dual-phase frames */
+		regs->rcr2	|= RPHASE;
+		regs->xcr2	|= XPHASE;
+		/* Set 1 word per (McBSP) frame for phase1 and phase2 */
+		wpf--;
+		regs->rcr2	|= RFRLEN2(wpf - 1);
+		regs->xcr2	|= XFRLEN2(wpf - 1);
+	}
+
+	regs->rcr1	|= RFRLEN1(wpf - 1);
+	regs->xcr1	|= XFRLEN1(wpf - 1);
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		/* Set word lengths */
+		regs->rcr2	|= RWDLEN2(OMAP_MCBSP_WORD_16);
+		regs->rcr1	|= RWDLEN1(OMAP_MCBSP_WORD_16);
+		regs->xcr2	|= XWDLEN2(OMAP_MCBSP_WORD_16);
+		regs->xcr1	|= XWDLEN1(OMAP_MCBSP_WORD_16);
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		/* Set word lengths */
+		regs->rcr2	|= RWDLEN2(OMAP_MCBSP_WORD_32);
+		regs->rcr1	|= RWDLEN1(OMAP_MCBSP_WORD_32);
+		regs->xcr2	|= XWDLEN2(OMAP_MCBSP_WORD_32);
+		regs->xcr1	|= XWDLEN1(OMAP_MCBSP_WORD_32);
+		break;
+	default:
+		/* Unsupported PCM format */
+		return -EINVAL;
+	}
+
+	/* In McBSP master modes, FRAME (i.e. sample rate) is generated
+	 * by _counting_ BCLKs. Calculate frame size in BCLKs */
+	master = mcbsp->fmt & SND_SOC_DAIFMT_MASTER_MASK;
+	if (master ==	SND_SOC_DAIFMT_CBS_CFS) {
+		div = mcbsp->clk_div ? mcbsp->clk_div : 1;
+		framesize = (mcbsp->in_freq / div) / params_rate(params);
+
+		if (framesize < wlen * channels) {
+			printk(KERN_ERR "%s: not enough bandwidth for desired rate and "
+					"channels\n", __func__);
+			return -EINVAL;
+		}
+	} else
+		framesize = wlen * channels;
+
+	/* Set FS period and length in terms of bit clock periods */
+	regs->srgr2	&= ~FPER(0xfff);
+	regs->srgr1	&= ~FWID(0xff);
+	switch (format) {
+	case SND_SOC_DAIFMT_I2S:
+	case SND_SOC_DAIFMT_LEFT_J:
+		regs->srgr2	|= FPER(framesize - 1);
+		regs->srgr1	|= FWID((framesize >> 1) - 1);
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+	case SND_SOC_DAIFMT_DSP_B:
+		regs->srgr2	|= FPER(framesize - 1);
+		regs->srgr1	|= FWID(0);
+		break;
+	}
+
+	omap_mcbsp_config(mcbsp, &mcbsp->cfg_regs);
+	mcbsp->wlen = wlen;
+	mcbsp->configured = 1;
+
+	return 0;
+}
+
+/*
+ * This must be called before _set_clkdiv and _set_sysclk since McBSP register
+ * cache is initialized here
+ */
+static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+				      unsigned int fmt)
+{
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+	struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
+	bool inv_fs = false;
+
+	if (mcbsp->configured)
+		return 0;
+
+	mcbsp->fmt = fmt;
+	memset(regs, 0, sizeof(*regs));
+	/* Generic McBSP register settings */
+	regs->spcr2	|= XINTM(3) | FREE;
+	regs->spcr1	|= RINTM(3);
+	/* RFIG and XFIG are not defined in 34xx */
+	if (!cpu_is_omap34xx() && !cpu_is_omap44xx()) {
+		regs->rcr2	|= RFIG;
+		regs->xcr2	|= XFIG;
+	}
+	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+		regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE;
+		regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		/* 1-bit data delay */
+		regs->rcr2	|= RDATDLY(1);
+		regs->xcr2	|= XDATDLY(1);
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		/* 0-bit data delay */
+		regs->rcr2	|= RDATDLY(0);
+		regs->xcr2	|= XDATDLY(0);
+		regs->spcr1	|= RJUST(2);
+		/* Invert FS polarity configuration */
+		inv_fs = true;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		/* 1-bit data delay */
+		regs->rcr2      |= RDATDLY(1);
+		regs->xcr2      |= XDATDLY(1);
+		/* Invert FS polarity configuration */
+		inv_fs = true;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		/* 0-bit data delay */
+		regs->rcr2      |= RDATDLY(0);
+		regs->xcr2      |= XDATDLY(0);
+		/* Invert FS polarity configuration */
+		inv_fs = true;
+		break;
+	default:
+		/* Unsupported data format */
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		/* McBSP master. Set FS and bit clocks as outputs */
+		regs->pcr0	|= FSXM | FSRM |
+				   CLKXM | CLKRM;
+		/* Sample rate generator drives the FS */
+		regs->srgr2	|= FSGM;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		/* McBSP slave */
+		break;
+	default:
+		/* Unsupported master/slave configuration */
+		return -EINVAL;
+	}
+
+	/* Set bit clock (CLKX/CLKR) and FS polarities */
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		/*
+		 * Normal BCLK + FS.
+		 * FS active low. TX data driven on falling edge of bit clock
+		 * and RX data sampled on rising edge of bit clock.
+		 */
+		regs->pcr0	|= FSXP | FSRP |
+				   CLKXP | CLKRP;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		regs->pcr0	|= CLKXP | CLKRP;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		regs->pcr0	|= FSXP | FSRP;
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (inv_fs == true)
+		regs->pcr0 ^= FSXP | FSRP;
+
+	return 0;
+}
+
+static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
+				     int div_id, int div)
+{
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+	struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
+
+	if (div_id != OMAP_MCBSP_CLKGDV)
+		return -ENODEV;
+
+	mcbsp->clk_div = div;
+	regs->srgr1	&= ~CLKGDV(0xff);
+	regs->srgr1	|= CLKGDV(div - 1);
+
+	return 0;
+}
+
+static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
+					 int clk_id, unsigned int freq,
+					 int dir)
+{
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+	struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
+	int err = 0;
+
+	if (mcbsp->active) {
+		if (freq == mcbsp->in_freq)
+			return 0;
+		else
+			return -EBUSY;
+	}
+
+	if (clk_id == OMAP_MCBSP_SYSCLK_CLK ||
+	    clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK ||
+	    clk_id == OMAP_MCBSP_SYSCLK_CLKS_EXT ||
+	    clk_id == OMAP_MCBSP_SYSCLK_CLKX_EXT ||
+	    clk_id == OMAP_MCBSP_SYSCLK_CLKR_EXT) {
+		mcbsp->in_freq = freq;
+		regs->srgr2	&= ~CLKSM;
+		regs->pcr0	&= ~SCLKME;
+	} else if (cpu_class_is_omap1()) {
+		/*
+		 * McBSP CLKR/FSR signal muxing functions are only available on
+		 * OMAP2 or newer versions
+		 */
+		return -EINVAL;
+	}
+
+	switch (clk_id) {
+	case OMAP_MCBSP_SYSCLK_CLK:
+		regs->srgr2	|= CLKSM;
+		break;
+	case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
+		if (cpu_class_is_omap1()) {
+			err = -EINVAL;
+			break;
+		}
+		err = omap2_mcbsp_set_clks_src(mcbsp,
+					       MCBSP_CLKS_PRCM_SRC);
+		break;
+	case OMAP_MCBSP_SYSCLK_CLKS_EXT:
+		if (cpu_class_is_omap1()) {
+			err = 0;
+			break;
+		}
+		err = omap2_mcbsp_set_clks_src(mcbsp,
+					       MCBSP_CLKS_PAD_SRC);
+		break;
+
+	case OMAP_MCBSP_SYSCLK_CLKX_EXT:
+		regs->srgr2	|= CLKSM;
+	case OMAP_MCBSP_SYSCLK_CLKR_EXT:
+		regs->pcr0	|= SCLKME;
+		break;
+
+
+	case OMAP_MCBSP_CLKR_SRC_CLKR:
+		err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKR);
+		break;
+	case OMAP_MCBSP_CLKR_SRC_CLKX:
+		err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKX);
+		break;
+	case OMAP_MCBSP_FSR_SRC_FSR:
+		err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSR);
+		break;
+	case OMAP_MCBSP_FSR_SRC_FSX:
+		err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSX);
+		break;
+	default:
+		err = -ENODEV;
+	}
+
+	return err;
+}
+
+static const struct snd_soc_dai_ops mcbsp_dai_ops = {
+	.startup	= omap_mcbsp_dai_startup,
+	.shutdown	= omap_mcbsp_dai_shutdown,
+	.trigger	= omap_mcbsp_dai_trigger,
+	.delay		= omap_mcbsp_dai_delay,
+	.hw_params	= omap_mcbsp_dai_hw_params,
+	.set_fmt	= omap_mcbsp_dai_set_dai_fmt,
+	.set_clkdiv	= omap_mcbsp_dai_set_clkdiv,
+	.set_sysclk	= omap_mcbsp_dai_set_dai_sysclk,
+};
+
+static int omap_mcbsp_probe(struct snd_soc_dai *dai)
+{
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai);
+
+	pm_runtime_enable(mcbsp->dev);
+
+	return 0;
+}
+
+static int omap_mcbsp_remove(struct snd_soc_dai *dai)
+{
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai);
+
+	pm_runtime_disable(mcbsp->dev);
+
+	return 0;
+}
+
+static struct snd_soc_dai_driver omap_mcbsp_dai = {
+	.probe = omap_mcbsp_probe,
+	.remove = omap_mcbsp_remove,
+	.playback = {
+		.channels_min = 1,
+		.channels_max = 16,
+		.rates = OMAP_MCBSP_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
+	},
+	.capture = {
+		.channels_min = 1,
+		.channels_max = 16,
+		.rates = OMAP_MCBSP_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
+	},
+	.ops = &mcbsp_dai_ops,
+};
+
+static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_info *uinfo)
+{
+	struct soc_mixer_control *mc =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	int max = mc->max;
+	int min = mc->min;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = min;
+	uinfo->value.integer.max = max;
+	return 0;
+}
+
+#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(channel)			\
+static int								\
+omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc,	\
+					struct snd_ctl_elem_value *uc)	\
+{									\
+	struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc);		\
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);	\
+	struct soc_mixer_control *mc =					\
+		(struct soc_mixer_control *)kc->private_value;		\
+	int max = mc->max;						\
+	int min = mc->min;						\
+	int val = uc->value.integer.value[0];				\
+									\
+	if (val < min || val > max)					\
+		return -EINVAL;						\
+									\
+	/* OMAP McBSP implementation uses index values 0..4 */		\
+	return omap_st_set_chgain(mcbsp, channel, val);			\
+}
+
+#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(channel)			\
+static int								\
+omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc,	\
+					struct snd_ctl_elem_value *uc)	\
+{									\
+	struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc);		\
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);	\
+	s16 chgain;							\
+									\
+	if (omap_st_get_chgain(mcbsp, channel, &chgain))		\
+		return -EAGAIN;						\
+									\
+	uc->value.integer.value[0] = chgain;				\
+	return 0;							\
+}
+
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(0)
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(1)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(0)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(1)
+
+static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+	u8 value = ucontrol->value.integer.value[0];
+
+	if (value == omap_st_is_enabled(mcbsp))
+		return 0;
+
+	if (value)
+		omap_st_enable(mcbsp);
+	else
+		omap_st_disable(mcbsp);
+
+	return 1;
+}
+
+static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+
+	ucontrol->value.integer.value[0] = omap_st_is_enabled(mcbsp);
+	return 0;
+}
+
+static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = {
+	SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0,
+			omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
+	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume",
+				      -32768, 32767,
+				      omap_mcbsp_get_st_ch0_volume,
+				      omap_mcbsp_set_st_ch0_volume),
+	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume",
+				      -32768, 32767,
+				      omap_mcbsp_get_st_ch1_volume,
+				      omap_mcbsp_set_st_ch1_volume),
+};
+
+static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = {
+	SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0,
+			omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
+	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume",
+				      -32768, 32767,
+				      omap_mcbsp_get_st_ch0_volume,
+				      omap_mcbsp_set_st_ch0_volume),
+	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume",
+				      -32768, 32767,
+				      omap_mcbsp_get_st_ch1_volume,
+				      omap_mcbsp_set_st_ch1_volume),
+};
+
+int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+
+	if (!mcbsp->st_data)
+		return -ENODEV;
+
+	switch (cpu_dai->id) {
+	case 2: /* McBSP 2 */
+		return snd_soc_add_dai_controls(cpu_dai,
+					omap_mcbsp2_st_controls,
+					ARRAY_SIZE(omap_mcbsp2_st_controls));
+	case 3: /* McBSP 3 */
+		return snd_soc_add_dai_controls(cpu_dai,
+					omap_mcbsp3_st_controls,
+					ARRAY_SIZE(omap_mcbsp3_st_controls));
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
+
+static __devinit int asoc_mcbsp_probe(struct platform_device *pdev)
+{
+	struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct omap_mcbsp *mcbsp;
+	int ret;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "missing platform data.\n");
+		return -EINVAL;
+	}
+	mcbsp = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcbsp), GFP_KERNEL);
+	if (!mcbsp)
+		return -ENOMEM;
+
+	mcbsp->id = pdev->id;
+	mcbsp->pdata = pdata;
+	mcbsp->dev = &pdev->dev;
+	platform_set_drvdata(pdev, mcbsp);
+
+	ret = omap_mcbsp_init(pdev);
+	if (!ret)
+		return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai);
+
+	return ret;
+}
+
+static int __devexit asoc_mcbsp_remove(struct platform_device *pdev)
+{
+	struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_dai(&pdev->dev);
+
+	if (mcbsp->pdata->ops && mcbsp->pdata->ops->free)
+		mcbsp->pdata->ops->free(mcbsp->id);
+
+	omap_mcbsp_sysfs_remove(mcbsp);
+
+	clk_put(mcbsp->fclk);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver asoc_mcbsp_driver = {
+	.driver = {
+			.name = "omap-mcbsp",
+			.owner = THIS_MODULE,
+	},
+
+	.probe = asoc_mcbsp_probe,
+	.remove = __devexit_p(asoc_mcbsp_remove),
+};
+
+module_platform_driver(asoc_mcbsp_driver);
+
+MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
+MODULE_DESCRIPTION("OMAP I2S SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-mcbsp.h b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-mcbsp.h
new file mode 100644
index 0000000..f877b16
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-mcbsp.h
@@ -0,0 +1,64 @@
+/*
+ * omap-mcbsp.h
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
+ *          Peter Ujfalusi <peter.ujfalusi@ti.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_I2S_H__
+#define __OMAP_I2S_H__
+
+/* Source clocks for McBSP sample rate generator */
+enum omap_mcbsp_clksrg_clk {
+	OMAP_MCBSP_SYSCLK_CLKS_FCLK,	/* Internal FCLK */
+	OMAP_MCBSP_SYSCLK_CLKS_EXT,	/* External CLKS pin */
+	OMAP_MCBSP_SYSCLK_CLK,		/* Internal ICLK */
+	OMAP_MCBSP_SYSCLK_CLKX_EXT,	/* External CLKX pin */
+	OMAP_MCBSP_SYSCLK_CLKR_EXT,	/* External CLKR pin */
+	OMAP_MCBSP_CLKR_SRC_CLKR,	/* CLKR from CLKR pin */
+	OMAP_MCBSP_CLKR_SRC_CLKX,	/* CLKR from CLKX pin */
+	OMAP_MCBSP_FSR_SRC_FSR,		/* FSR from FSR pin */
+	OMAP_MCBSP_FSR_SRC_FSX,		/* FSR from FSX pin */
+};
+
+/* McBSP dividers */
+enum omap_mcbsp_div {
+	OMAP_MCBSP_CLKGDV,		/* Sample rate generator divider */
+};
+
+#if defined(CONFIG_SOC_OMAP2420)
+#define NUM_LINKS	2
+#endif
+#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
+#undef  NUM_LINKS
+#define NUM_LINKS	3
+#endif
+#if defined(CONFIG_ARCH_OMAP4)
+#undef  NUM_LINKS
+#define NUM_LINKS	4
+#endif
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_OMAP2430)
+#undef  NUM_LINKS
+#define NUM_LINKS	5
+#endif
+
+int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd);
+
+#endif
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-mcpdm.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-mcpdm.c
new file mode 100644
index 0000000..3970556
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-mcpdm.c
@@ -0,0 +1,524 @@
+/*
+ * omap-mcpdm.c  --  OMAP ALSA SoC DAI driver using McPDM port
+ *
+ * Copyright (C) 2009 - 2011 Texas Instruments
+ *
+ * Author: Misael Lopez Cruz <misael.lopez@ti.com>
+ * Contact: Jorge Eduardo Candelaria <x0107209@ti.com>
+ *          Margarita Olaya <magi.olaya@ti.com>
+ *          Peter Ujfalusi <peter.ujfalusi@ti.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <plat/dma.h>
+#include <plat/omap_hwmod.h>
+#include "omap-mcpdm.h"
+#include "omap-pcm.h"
+
+struct omap_mcpdm {
+	struct device *dev;
+	unsigned long phys_base;
+	void __iomem *io_base;
+	int irq;
+
+	struct mutex mutex;
+
+	/* channel data */
+	u32 dn_channels;
+	u32 up_channels;
+
+	/* McPDM FIFO thresholds */
+	u32 dn_threshold;
+	u32 up_threshold;
+
+	/* McPDM dn offsets for rx1, and 2 channels */
+	u32 dn_rx_offset;
+};
+
+/*
+ * Stream DMA parameters
+ */
+static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = {
+	{
+		.name = "Audio playback",
+		.dma_req = OMAP44XX_DMA_MCPDM_DL,
+		.data_type = OMAP_DMA_DATA_TYPE_S32,
+		.sync_mode = OMAP_DMA_SYNC_PACKET,
+		.port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_DN_DATA,
+	},
+	{
+		.name = "Audio capture",
+		.dma_req = OMAP44XX_DMA_MCPDM_UP,
+		.data_type = OMAP_DMA_DATA_TYPE_S32,
+		.sync_mode = OMAP_DMA_SYNC_PACKET,
+		.port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_UP_DATA,
+	},
+};
+
+static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val)
+{
+	__raw_writel(val, mcpdm->io_base + reg);
+}
+
+static inline int omap_mcpdm_read(struct omap_mcpdm *mcpdm, u16 reg)
+{
+	return __raw_readl(mcpdm->io_base + reg);
+}
+
+#ifdef DEBUG
+static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm)
+{
+	dev_dbg(mcpdm->dev, "***********************\n");
+	dev_dbg(mcpdm->dev, "IRQSTATUS_RAW:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS_RAW));
+	dev_dbg(mcpdm->dev, "IRQSTATUS:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS));
+	dev_dbg(mcpdm->dev, "IRQENABLE_SET:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_IRQENABLE_SET));
+	dev_dbg(mcpdm->dev, "IRQENABLE_CLR:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_IRQENABLE_CLR));
+	dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_IRQWAKE_EN));
+	dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_DMAENABLE_SET));
+	dev_dbg(mcpdm->dev, "DMAENABLE_CLR:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_DMAENABLE_CLR));
+	dev_dbg(mcpdm->dev, "DMAWAKEEN:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_DMAWAKEEN));
+	dev_dbg(mcpdm->dev, "CTRL:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL));
+	dev_dbg(mcpdm->dev, "DN_DATA:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_DN_DATA));
+	dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_UP_DATA));
+	dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_FIFO_CTRL_DN));
+	dev_dbg(mcpdm->dev, "FIFO_CTRL_UP:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_FIFO_CTRL_UP));
+	dev_dbg(mcpdm->dev, "***********************\n");
+}
+#else
+static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {}
+#endif
+
+/*
+ * Enables the transfer through the PDM interface to/from the Phoenix
+ * codec by enabling the corresponding UP or DN channels.
+ */
+static void omap_mcpdm_start(struct omap_mcpdm *mcpdm)
+{
+	u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+	ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+	ctrl |= mcpdm->dn_channels | mcpdm->up_channels;
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+	ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+}
+
+/*
+ * Disables the transfer through the PDM interface to/from the Phoenix
+ * codec by disabling the corresponding UP or DN channels.
+ */
+static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm)
+{
+	u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+	ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+	ctrl &= ~(mcpdm->dn_channels | mcpdm->up_channels);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+	ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+}
+
+/*
+ * Is the physical McPDM interface active.
+ */
+static inline int omap_mcpdm_active(struct omap_mcpdm *mcpdm)
+{
+	return omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL) &
+					(MCPDM_PDM_DN_MASK | MCPDM_PDM_UP_MASK);
+}
+
+/*
+ * Configures McPDM uplink, and downlink for audio.
+ * This function should be called before omap_mcpdm_start.
+ */
+static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm)
+{
+	omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_SET,
+			MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL |
+			MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL);
+
+	/* Enable DN RX1/2 offset cancellation feature, if configured */
+	if (mcpdm->dn_rx_offset) {
+		u32 dn_offset = mcpdm->dn_rx_offset;
+
+		omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset);
+		dn_offset |= (MCPDM_DN_OFST_RX1_EN | MCPDM_DN_OFST_RX2_EN);
+		omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset);
+	}
+
+	omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, mcpdm->dn_threshold);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, mcpdm->up_threshold);
+
+	omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET,
+			MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE);
+}
+
+/*
+ * Cleans McPDM uplink, and downlink configuration.
+ * This function should be called when the stream is closed.
+ */
+static void omap_mcpdm_close_streams(struct omap_mcpdm *mcpdm)
+{
+	/* Disable irq request generation for downlink */
+	omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_CLR,
+			MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL);
+
+	/* Disable DMA request generation for downlink */
+	omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_CLR, MCPDM_DMA_DN_ENABLE);
+
+	/* Disable irq request generation for uplink */
+	omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_CLR,
+			MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL);
+
+	/* Disable DMA request generation for uplink */
+	omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_CLR, MCPDM_DMA_UP_ENABLE);
+
+	/* Disable RX1/2 offset cancellation */
+	if (mcpdm->dn_rx_offset)
+		omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, 0);
+}
+
+static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id)
+{
+	struct omap_mcpdm *mcpdm = dev_id;
+	int irq_status;
+
+	irq_status = omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS);
+
+	/* Acknowledge irq event */
+	omap_mcpdm_write(mcpdm, MCPDM_REG_IRQSTATUS, irq_status);
+
+	if (irq_status & MCPDM_DN_IRQ_FULL)
+		dev_dbg(mcpdm->dev, "DN (playback) FIFO Full\n");
+
+	if (irq_status & MCPDM_DN_IRQ_EMPTY)
+		dev_dbg(mcpdm->dev, "DN (playback) FIFO Empty\n");
+
+	if (irq_status & MCPDM_DN_IRQ)
+		dev_dbg(mcpdm->dev, "DN (playback) write request\n");
+
+	if (irq_status & MCPDM_UP_IRQ_FULL)
+		dev_dbg(mcpdm->dev, "UP (capture) FIFO Full\n");
+
+	if (irq_status & MCPDM_UP_IRQ_EMPTY)
+		dev_dbg(mcpdm->dev, "UP (capture) FIFO Empty\n");
+
+	if (irq_status & MCPDM_UP_IRQ)
+		dev_dbg(mcpdm->dev, "UP (capture) write request\n");
+
+	return IRQ_HANDLED;
+}
+
+static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
+{
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+	mutex_lock(&mcpdm->mutex);
+
+	if (!dai->active) {
+		/* Enable watch dog for ES above ES 1.0 to avoid saturation */
+		if (omap_rev() != OMAP4430_REV_ES1_0) {
+			u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+			omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL,
+					 ctrl | MCPDM_WD_EN);
+		}
+		omap_mcpdm_open_streams(mcpdm);
+	}
+
+	mutex_unlock(&mcpdm->mutex);
+
+	return 0;
+}
+
+static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
+{
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+	mutex_lock(&mcpdm->mutex);
+
+	if (!dai->active) {
+		if (omap_mcpdm_active(mcpdm)) {
+			omap_mcpdm_stop(mcpdm);
+			omap_mcpdm_close_streams(mcpdm);
+		}
+	}
+
+	mutex_unlock(&mcpdm->mutex);
+}
+
+static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
+				    struct snd_pcm_hw_params *params,
+				    struct snd_soc_dai *dai)
+{
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+	int stream = substream->stream;
+	struct omap_pcm_dma_data *dma_data;
+	int channels;
+	int link_mask = 0;
+
+	channels = params_channels(params);
+	switch (channels) {
+	case 5:
+		if (stream == SNDRV_PCM_STREAM_CAPTURE)
+			/* up to 3 channels for capture */
+			return -EINVAL;
+		link_mask |= 1 << 4;
+	case 4:
+		if (stream == SNDRV_PCM_STREAM_CAPTURE)
+			/* up to 3 channels for capture */
+			return -EINVAL;
+		link_mask |= 1 << 3;
+	case 3:
+		link_mask |= 1 << 2;
+	case 2:
+		link_mask |= 1 << 1;
+	case 1:
+		link_mask |= 1 << 0;
+		break;
+	default:
+		/* unsupported number of channels */
+		return -EINVAL;
+	}
+
+	dma_data = &omap_mcpdm_dai_dma_params[stream];
+
+	/* Configure McPDM channels, and DMA packet size */
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		mcpdm->dn_channels = link_mask << 3;
+		dma_data->packet_size =
+			(MCPDM_DN_THRES_MAX - mcpdm->dn_threshold) * channels;
+	} else {
+		mcpdm->up_channels = link_mask << 0;
+		dma_data->packet_size = mcpdm->up_threshold * channels;
+	}
+
+	snd_soc_dai_set_dma_data(dai, substream, dma_data);
+
+	return 0;
+}
+
+static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
+{
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+	if (!omap_mcpdm_active(mcpdm)) {
+		omap_mcpdm_start(mcpdm);
+		omap_mcpdm_reg_dump(mcpdm);
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops omap_mcpdm_dai_ops = {
+	.startup	= omap_mcpdm_dai_startup,
+	.shutdown	= omap_mcpdm_dai_shutdown,
+	.hw_params	= omap_mcpdm_dai_hw_params,
+	.prepare	= omap_mcpdm_prepare,
+};
+
+static int omap_mcpdm_probe(struct snd_soc_dai *dai)
+{
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+	int ret;
+
+	pm_runtime_enable(mcpdm->dev);
+
+	/* Disable lines while request is ongoing */
+	pm_runtime_get_sync(mcpdm->dev);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00);
+
+	ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
+				0, "McPDM", (void *)mcpdm);
+
+	pm_runtime_put_sync(mcpdm->dev);
+
+	if (ret) {
+		dev_err(mcpdm->dev, "Request for IRQ failed\n");
+		pm_runtime_disable(mcpdm->dev);
+	}
+
+	/* Configure McPDM threshold values */
+	mcpdm->dn_threshold = 2;
+	mcpdm->up_threshold = MCPDM_UP_THRES_MAX - 3;
+	return ret;
+}
+
+static int omap_mcpdm_remove(struct snd_soc_dai *dai)
+{
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+	free_irq(mcpdm->irq, (void *)mcpdm);
+	pm_runtime_disable(mcpdm->dev);
+
+	return 0;
+}
+
+#define OMAP_MCPDM_RATES	(SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+#define OMAP_MCPDM_FORMATS	SNDRV_PCM_FMTBIT_S32_LE
+
+static struct snd_soc_dai_driver omap_mcpdm_dai = {
+	.probe = omap_mcpdm_probe,
+	.remove = omap_mcpdm_remove,
+	.probe_order = SND_SOC_COMP_ORDER_LATE,
+	.remove_order = SND_SOC_COMP_ORDER_EARLY,
+	.playback = {
+		.channels_min = 1,
+		.channels_max = 5,
+		.rates = OMAP_MCPDM_RATES,
+		.formats = OMAP_MCPDM_FORMATS,
+		.sig_bits = 24,
+	},
+	.capture = {
+		.channels_min = 1,
+		.channels_max = 3,
+		.rates = OMAP_MCPDM_RATES,
+		.formats = OMAP_MCPDM_FORMATS,
+		.sig_bits = 24,
+	},
+	.ops = &omap_mcpdm_dai_ops,
+};
+
+void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd,
+				    u8 rx1, u8 rx2)
+{
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(rtd->cpu_dai);
+
+	mcpdm->dn_rx_offset = MCPDM_DNOFST_RX1(rx1) | MCPDM_DNOFST_RX2(rx2);
+}
+EXPORT_SYMBOL_GPL(omap_mcpdm_configure_dn_offsets);
+
+static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
+{
+	struct omap_mcpdm *mcpdm;
+	struct resource *res;
+	int ret = 0;
+
+	mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL);
+	if (!mcpdm)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, mcpdm);
+
+	mutex_init(&mcpdm->mutex);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no resource\n");
+		goto err_res;
+	}
+
+	if (!request_mem_region(res->start, resource_size(res), "McPDM")) {
+		ret = -EBUSY;
+		goto err_res;
+	}
+
+	mcpdm->io_base = ioremap(res->start, resource_size(res));
+	if (!mcpdm->io_base) {
+		ret = -ENOMEM;
+		goto err_iomap;
+	}
+
+	mcpdm->irq = platform_get_irq(pdev, 0);
+	if (mcpdm->irq < 0) {
+		ret = mcpdm->irq;
+		goto err_irq;
+	}
+
+	mcpdm->dev = &pdev->dev;
+
+	ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai);
+	if (!ret)
+		return 0;
+
+err_irq:
+	iounmap(mcpdm->io_base);
+err_iomap:
+	release_mem_region(res->start, resource_size(res));
+err_res:
+	kfree(mcpdm);
+	return ret;
+}
+
+static int __devexit asoc_mcpdm_remove(struct platform_device *pdev)
+{
+	struct omap_mcpdm *mcpdm = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	snd_soc_unregister_dai(&pdev->dev);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	iounmap(mcpdm->io_base);
+	release_mem_region(res->start, resource_size(res));
+
+	kfree(mcpdm);
+	return 0;
+}
+
+static struct platform_driver asoc_mcpdm_driver = {
+	.driver = {
+		.name	= "omap-mcpdm",
+		.owner	= THIS_MODULE,
+	},
+
+	.probe	= asoc_mcpdm_probe,
+	.remove	= __devexit_p(asoc_mcpdm_remove),
+};
+
+module_platform_driver(asoc_mcpdm_driver);
+
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
+MODULE_DESCRIPTION("OMAP PDM SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-mcpdm.h b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-mcpdm.h
new file mode 100644
index 0000000..de8cf26
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-mcpdm.h
@@ -0,0 +1,107 @@
+/*
+ * omap-mcpdm.h
+ *
+ * Copyright (C) 2009 - 2011 Texas Instruments
+ *
+ * Contact: Misael Lopez Cruz <misael.lopez@ti.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_MCPDM_H__
+#define __OMAP_MCPDM_H__
+
+#define MCPDM_REG_REVISION		0x00
+#define MCPDM_REG_SYSCONFIG		0x10
+#define MCPDM_REG_IRQSTATUS_RAW		0x24
+#define MCPDM_REG_IRQSTATUS		0x28
+#define MCPDM_REG_IRQENABLE_SET		0x2C
+#define MCPDM_REG_IRQENABLE_CLR		0x30
+#define MCPDM_REG_IRQWAKE_EN		0x34
+#define MCPDM_REG_DMAENABLE_SET		0x38
+#define MCPDM_REG_DMAENABLE_CLR		0x3C
+#define MCPDM_REG_DMAWAKEEN		0x40
+#define MCPDM_REG_CTRL			0x44
+#define MCPDM_REG_DN_DATA		0x48
+#define MCPDM_REG_UP_DATA		0x4C
+#define MCPDM_REG_FIFO_CTRL_DN		0x50
+#define MCPDM_REG_FIFO_CTRL_UP		0x54
+#define MCPDM_REG_DN_OFFSET		0x58
+
+/*
+ * MCPDM_IRQ bit fields
+ * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR
+ */
+
+#define MCPDM_DN_IRQ			(1 << 0)
+#define MCPDM_DN_IRQ_EMPTY		(1 << 1)
+#define MCPDM_DN_IRQ_ALMST_EMPTY	(1 << 2)
+#define MCPDM_DN_IRQ_FULL		(1 << 3)
+
+#define MCPDM_UP_IRQ			(1 << 8)
+#define MCPDM_UP_IRQ_EMPTY		(1 << 9)
+#define MCPDM_UP_IRQ_ALMST_FULL		(1 << 10)
+#define MCPDM_UP_IRQ_FULL		(1 << 11)
+
+#define MCPDM_DOWNLINK_IRQ_MASK		0x00F
+#define MCPDM_UPLINK_IRQ_MASK		0xF00
+
+/*
+ * MCPDM_DMAENABLE bit fields
+ */
+
+#define MCPDM_DMA_DN_ENABLE		(1 << 0)
+#define MCPDM_DMA_UP_ENABLE		(1 << 1)
+
+/*
+ * MCPDM_CTRL bit fields
+ */
+
+#define MCPDM_PDM_UPLINK_EN(x)		(1 << (x - 1)) /* ch1 is at bit 0 */
+#define MCPDM_PDM_DOWNLINK_EN(x)	(1 << (x + 2)) /* ch1 is at bit 3 */
+#define MCPDM_PDMOUTFORMAT		(1 << 8)
+#define MCPDM_CMD_INT			(1 << 9)
+#define MCPDM_STATUS_INT		(1 << 10)
+#define MCPDM_SW_UP_RST			(1 << 11)
+#define MCPDM_SW_DN_RST			(1 << 12)
+#define MCPDM_WD_EN			(1 << 14)
+#define MCPDM_PDM_UP_MASK		0x7
+#define MCPDM_PDM_DN_MASK		(0x1f << 3)
+
+
+#define MCPDM_PDMOUTFORMAT_LJUST	(0 << 8)
+#define MCPDM_PDMOUTFORMAT_RJUST	(1 << 8)
+
+/*
+ * MCPDM_FIFO_CTRL bit fields
+ */
+
+#define MCPDM_UP_THRES_MAX		0xF
+#define MCPDM_DN_THRES_MAX		0xF
+
+/*
+ * MCPDM_DN_OFFSET bit fields
+ */
+
+#define MCPDM_DN_OFST_RX1_EN		(1 << 0)
+#define MCPDM_DNOFST_RX1(x)		((x & 0x1f) << 1)
+#define MCPDM_DN_OFST_RX2_EN		(1 << 8)
+#define MCPDM_DNOFST_RX2(x)		((x & 0x1f) << 9)
+
+void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd,
+				    u8 rx1, u8 rx2);
+
+#endif	/* End of __OMAP_MCPDM_H__ */
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-pcm.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-pcm.c
new file mode 100644
index 0000000..96bce55
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-pcm.c
@@ -0,0 +1,443 @@
+/*
+ * omap-pcm.c  --  ALSA PCM interface for the OMAP SoC
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
+ *          Peter Ujfalusi <peter.ujfalusi@ti.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <plat/dma.h>
+#include "omap-pcm.h"
+
+static const struct snd_pcm_hardware omap_pcm_hardware = {
+	.info			= SNDRV_PCM_INFO_MMAP |
+				  SNDRV_PCM_INFO_MMAP_VALID |
+				  SNDRV_PCM_INFO_INTERLEAVED |
+				  SNDRV_PCM_INFO_PAUSE |
+				  SNDRV_PCM_INFO_RESUME |
+				  SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
+	.formats		= SNDRV_PCM_FMTBIT_S16_LE |
+				  SNDRV_PCM_FMTBIT_S32_LE,
+	.period_bytes_min	= 32,
+	.period_bytes_max	= 64 * 1024,
+	.periods_min		= 2,
+	.periods_max		= 255,
+	.buffer_bytes_max	= 128 * 1024,
+};
+
+struct omap_runtime_data {
+	spinlock_t			lock;
+	struct omap_pcm_dma_data	*dma_data;
+	int				dma_ch;
+	int				period_index;
+};
+
+static void omap_pcm_dma_irq(int ch, u16 stat, void *data)
+{
+	struct snd_pcm_substream *substream = data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct omap_runtime_data *prtd = runtime->private_data;
+	unsigned long flags;
+
+	if ((cpu_is_omap1510())) {
+		/*
+		 * OMAP1510 doesn't fully support DMA progress counter
+		 * and there is no software emulation implemented yet,
+		 * so have to maintain our own progress counters
+		 * that can be used by omap_pcm_pointer() instead.
+		 */
+		spin_lock_irqsave(&prtd->lock, flags);
+		if ((stat == OMAP_DMA_LAST_IRQ) &&
+				(prtd->period_index == runtime->periods - 1)) {
+			/* we are in sync, do nothing */
+			spin_unlock_irqrestore(&prtd->lock, flags);
+			return;
+		}
+		if (prtd->period_index >= 0) {
+			if (stat & OMAP_DMA_BLOCK_IRQ) {
+				/* end of buffer reached, loop back */
+				prtd->period_index = 0;
+			} else if (stat & OMAP_DMA_LAST_IRQ) {
+				/* update the counter for the last period */
+				prtd->period_index = runtime->periods - 1;
+			} else if (++prtd->period_index >= runtime->periods) {
+				/* end of buffer missed? loop back */
+				prtd->period_index = 0;
+			}
+		}
+		spin_unlock_irqrestore(&prtd->lock, flags);
+	}
+
+	snd_pcm_period_elapsed(substream);
+}
+
+/* this may get called several times by oss emulation */
+static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
+			      struct snd_pcm_hw_params *params)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct omap_runtime_data *prtd = runtime->private_data;
+	struct omap_pcm_dma_data *dma_data;
+
+	int err = 0;
+
+	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+
+	/* return if this is a bufferless transfer e.g.
+	 * codec <--> BT codec or GSM modem -- lg FIXME */
+	if (!dma_data)
+		return 0;
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+	runtime->dma_bytes = params_buffer_bytes(params);
+
+	if (prtd->dma_data)
+		return 0;
+	prtd->dma_data = dma_data;
+	err = omap_request_dma(dma_data->dma_req, dma_data->name,
+			       omap_pcm_dma_irq, substream, &prtd->dma_ch);
+	if (!err) {
+		/*
+		 * Link channel with itself so DMA doesn't need any
+		 * reprogramming while looping the buffer
+		 */
+		omap_dma_link_lch(prtd->dma_ch, prtd->dma_ch);
+	}
+
+	return err;
+}
+
+static int omap_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct omap_runtime_data *prtd = runtime->private_data;
+
+	if (prtd->dma_data == NULL)
+		return 0;
+
+	omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch);
+	omap_free_dma(prtd->dma_ch);
+	prtd->dma_data = NULL;
+
+	snd_pcm_set_runtime_buffer(substream, NULL);
+
+	return 0;
+}
+
+static int omap_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct omap_runtime_data *prtd = runtime->private_data;
+	struct omap_pcm_dma_data *dma_data = prtd->dma_data;
+	struct omap_dma_channel_params dma_params;
+	int bytes;
+
+	/* return if this is a bufferless transfer e.g.
+	 * codec <--> BT codec or GSM modem -- lg FIXME */
+	if (!prtd->dma_data)
+		return 0;
+
+	memset(&dma_params, 0, sizeof(dma_params));
+	dma_params.data_type			= dma_data->data_type;
+	dma_params.trigger			= dma_data->dma_req;
+	dma_params.sync_mode			= dma_data->sync_mode;
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		dma_params.src_amode		= OMAP_DMA_AMODE_POST_INC;
+		dma_params.dst_amode		= OMAP_DMA_AMODE_CONSTANT;
+		dma_params.src_or_dst_synch	= OMAP_DMA_DST_SYNC;
+		dma_params.src_start		= runtime->dma_addr;
+		dma_params.dst_start		= dma_data->port_addr;
+		dma_params.dst_port		= OMAP_DMA_PORT_MPUI;
+		dma_params.dst_fi		= dma_data->packet_size;
+	} else {
+		dma_params.src_amode		= OMAP_DMA_AMODE_CONSTANT;
+		dma_params.dst_amode		= OMAP_DMA_AMODE_POST_INC;
+		dma_params.src_or_dst_synch	= OMAP_DMA_SRC_SYNC;
+		dma_params.src_start		= dma_data->port_addr;
+		dma_params.dst_start		= runtime->dma_addr;
+		dma_params.src_port		= OMAP_DMA_PORT_MPUI;
+		dma_params.src_fi		= dma_data->packet_size;
+	}
+	/*
+	 * Set DMA transfer frame size equal to ALSA period size and frame
+	 * count as no. of ALSA periods. Then with DMA frame interrupt enabled,
+	 * we can transfer the whole ALSA buffer with single DMA transfer but
+	 * still can get an interrupt at each period bounary
+	 */
+	bytes = snd_pcm_lib_period_bytes(substream);
+	dma_params.elem_count	= bytes >> dma_data->data_type;
+	dma_params.frame_count	= runtime->periods;
+	omap_set_dma_params(prtd->dma_ch, &dma_params);
+
+	if ((cpu_is_omap1510()))
+		omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ |
+			      OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ);
+	else if (!substream->runtime->no_period_wakeup)
+		omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
+	else {
+		/*
+		 * No period wakeup:
+		 * we need to disable BLOCK_IRQ, which is enabled by the omap
+		 * dma core at request dma time.
+		 */
+		omap_disable_dma_irq(prtd->dma_ch, OMAP_DMA_BLOCK_IRQ);
+	}
+
+	if (!(cpu_class_is_omap1())) {
+		omap_set_dma_src_burst_mode(prtd->dma_ch,
+						OMAP_DMA_DATA_BURST_16);
+		omap_set_dma_dest_burst_mode(prtd->dma_ch,
+						OMAP_DMA_DATA_BURST_16);
+	}
+
+	return 0;
+}
+
+static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct omap_runtime_data *prtd = runtime->private_data;
+	struct omap_pcm_dma_data *dma_data = prtd->dma_data;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&prtd->lock, flags);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		prtd->period_index = 0;
+		/* Configure McBSP internal buffer usage */
+		if (dma_data->set_threshold)
+			dma_data->set_threshold(substream);
+
+		omap_start_dma(prtd->dma_ch);
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		prtd->period_index = -1;
+		omap_stop_dma(prtd->dma_ch);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	spin_unlock_irqrestore(&prtd->lock, flags);
+
+	return ret;
+}
+
+static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct omap_runtime_data *prtd = runtime->private_data;
+	dma_addr_t ptr;
+	snd_pcm_uframes_t offset;
+
+	if (cpu_is_omap1510()) {
+		offset = prtd->period_index * runtime->period_size;
+	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		ptr = omap_get_dma_dst_pos(prtd->dma_ch);
+		offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
+	} else {
+		ptr = omap_get_dma_src_pos(prtd->dma_ch);
+		offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
+	}
+
+	if (offset >= runtime->buffer_size)
+		offset = 0;
+
+	return offset;
+}
+
+static int omap_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct omap_runtime_data *prtd;
+	int ret;
+
+	snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware);
+
+	/* Ensure that buffer size is a multiple of period size */
+	ret = snd_pcm_hw_constraint_integer(runtime,
+					    SNDRV_PCM_HW_PARAM_PERIODS);
+	if (ret < 0)
+		goto out;
+
+	prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
+	if (prtd == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	spin_lock_init(&prtd->lock);
+	runtime->private_data = prtd;
+
+out:
+	return ret;
+}
+
+static int omap_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	kfree(runtime->private_data);
+	return 0;
+}
+
+static int omap_pcm_mmap(struct snd_pcm_substream *substream,
+	struct vm_area_struct *vma)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+				     runtime->dma_area,
+				     runtime->dma_addr,
+				     runtime->dma_bytes);
+}
+
+static struct snd_pcm_ops omap_pcm_ops = {
+	.open		= omap_pcm_open,
+	.close		= omap_pcm_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= omap_pcm_hw_params,
+	.hw_free	= omap_pcm_hw_free,
+	.prepare	= omap_pcm_prepare,
+	.trigger	= omap_pcm_trigger,
+	.pointer	= omap_pcm_pointer,
+	.mmap		= omap_pcm_mmap,
+};
+
+static u64 omap_pcm_dmamask = DMA_BIT_MASK(32);
+
+static int omap_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
+	int stream)
+{
+	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+	size_t size = omap_pcm_hardware.buffer_bytes_max;
+
+	buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	buf->dev.dev = pcm->card->dev;
+	buf->private_data = NULL;
+	buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+					   &buf->addr, GFP_KERNEL);
+	if (!buf->area)
+		return -ENOMEM;
+
+	buf->bytes = size;
+	return 0;
+}
+
+static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_dma_buffer *buf;
+	int stream;
+
+	for (stream = 0; stream < 2; stream++) {
+		substream = pcm->streams[stream].substream;
+		if (!substream)
+			continue;
+
+		buf = &substream->dma_buffer;
+		if (!buf->area)
+			continue;
+
+		dma_free_writecombine(pcm->card->dev, buf->bytes,
+				      buf->area, buf->addr);
+		buf->area = NULL;
+	}
+}
+
+static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_pcm *pcm = rtd->pcm;
+	int ret = 0;
+
+	if (!card->dev->dma_mask)
+		card->dev->dma_mask = &omap_pcm_dmamask;
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+		ret = omap_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_PLAYBACK);
+		if (ret)
+			goto out;
+	}
+
+	if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+		ret = omap_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_CAPTURE);
+		if (ret)
+			goto out;
+	}
+
+out:
+	/* free preallocated buffers in case of error */
+	if (ret)
+		omap_pcm_free_dma_buffers(pcm);
+
+	return ret;
+}
+
+static struct snd_soc_platform_driver omap_soc_platform = {
+	.ops		= &omap_pcm_ops,
+	.pcm_new	= omap_pcm_new,
+	.pcm_free	= omap_pcm_free_dma_buffers,
+};
+
+static __devinit int omap_pcm_probe(struct platform_device *pdev)
+{
+	return snd_soc_register_platform(&pdev->dev,
+			&omap_soc_platform);
+}
+
+static int __devexit omap_pcm_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_platform(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver omap_pcm_driver = {
+	.driver = {
+			.name = "omap-pcm-audio",
+			.owner = THIS_MODULE,
+	},
+
+	.probe = omap_pcm_probe,
+	.remove = __devexit_p(omap_pcm_remove),
+};
+
+module_platform_driver(omap_pcm_driver);
+
+MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
+MODULE_DESCRIPTION("OMAP PCM DMA module");
+MODULE_LICENSE("GPL");
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-pcm.h b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-pcm.h
new file mode 100644
index 0000000..b92248c
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap-pcm.h
@@ -0,0 +1,40 @@
+/*
+ * omap-pcm.h
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
+ *          Peter Ujfalusi <peter.ujfalusi@ti.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_PCM_H__
+#define __OMAP_PCM_H__
+
+struct snd_pcm_substream;
+
+struct omap_pcm_dma_data {
+	char		*name;		/* stream identifier */
+	int		dma_req;	/* DMA request line */
+	unsigned long	port_addr;	/* transmit/receive register */
+	void (*set_threshold)(struct snd_pcm_substream *substream);
+	int		data_type;	/* data type 8,16,32 */
+	int		sync_mode;	/* DMA sync mode */
+	int		packet_size;	/* packet size only in PACKET mode */
+};
+
+#endif
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/omap3beagle.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap3beagle.c
new file mode 100644
index 0000000..2830dfd
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap3beagle.c
@@ -0,0 +1,150 @@
+/*
+ * omap3beagle.c  --  SoC audio for OMAP3 Beagle
+ *
+ * Author: Steve Sakoman <steve@sakoman.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <plat/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+
+static int omap3beagle_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	unsigned int fmt;
+	int ret;
+
+	switch (params_channels(params)) {
+	case 2: /* Stereo I2S mode */
+		fmt =	SND_SOC_DAIFMT_I2S |
+			SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBM_CFM;
+		break;
+	case 4: /* Four channel TDM mode */
+		fmt =	SND_SOC_DAIFMT_DSP_A |
+			SND_SOC_DAIFMT_IB_NF |
+			SND_SOC_DAIFMT_CBM_CFM;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Set codec DAI configuration */
+	ret = snd_soc_dai_set_fmt(codec_dai, fmt);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set codec DAI configuration\n");
+		return ret;
+	}
+
+	/* Set cpu DAI configuration */
+	ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set cpu DAI configuration\n");
+		return ret;
+	}
+
+	/* Set the codec system clock for DAC and ADC */
+	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+				     SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set codec system clock\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops omap3beagle_ops = {
+	.hw_params = omap3beagle_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link omap3beagle_dai = {
+	.name = "TWL4030",
+	.stream_name = "TWL4030",
+	.cpu_dai_name = "omap-mcbsp.2",
+	.platform_name = "omap-pcm-audio",
+	.codec_dai_name = "twl4030-hifi",
+	.codec_name = "twl4030-codec",
+	.ops = &omap3beagle_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_omap3beagle = {
+	.name = "omap3beagle",
+	.owner = THIS_MODULE,
+	.dai_link = &omap3beagle_dai,
+	.num_links = 1,
+};
+
+static struct platform_device *omap3beagle_snd_device;
+
+static int __init omap3beagle_soc_init(void)
+{
+	int ret;
+
+	if (!(machine_is_omap3_beagle() || machine_is_devkit8000()))
+		return -ENODEV;
+	pr_info("OMAP3 Beagle/Devkit8000 SoC init\n");
+
+	omap3beagle_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!omap3beagle_snd_device) {
+		printk(KERN_ERR "Platform device allocation failed\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(omap3beagle_snd_device, &snd_soc_omap3beagle);
+
+	ret = platform_device_add(omap3beagle_snd_device);
+	if (ret)
+		goto err1;
+
+	return 0;
+
+err1:
+	printk(KERN_ERR "Unable to add platform device\n");
+	platform_device_put(omap3beagle_snd_device);
+
+	return ret;
+}
+
+static void __exit omap3beagle_soc_exit(void)
+{
+	platform_device_unregister(omap3beagle_snd_device);
+}
+
+module_init(omap3beagle_soc_init);
+module_exit(omap3beagle_soc_exit);
+
+MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
+MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle");
+MODULE_LICENSE("GPL");
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/omap3evm.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap3evm.c
new file mode 100644
index 0000000..3d468c9
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap3evm.c
@@ -0,0 +1,118 @@
+/*
+ * omap3evm.c  -- ALSA SoC support for OMAP3 EVM
+ *
+ * Author: Anuj Aggarwal <anuj.aggarwal@ti.com>
+ *
+ * Based on sound/soc/omap/beagle.c by Steve Sakoman
+ *
+ * Copyright (C) 2008 Texas Instruments, Incorporated
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <plat/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+
+static int omap3evm_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret;
+
+	/* Set the codec system clock for DAC and ADC */
+	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+				     SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		printk(KERN_ERR "Can't set codec system clock\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops omap3evm_ops = {
+	.hw_params = omap3evm_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link omap3evm_dai = {
+	.name 		= "TWL4030",
+	.stream_name 	= "TWL4030",
+	.cpu_dai_name = "omap-mcbsp.2",
+	.codec_dai_name = "twl4030-hifi",
+	.platform_name = "omap-pcm-audio",
+	.codec_name = "twl4030-codec",
+	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBM_CFM,
+	.ops 		= &omap3evm_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_omap3evm = {
+	.name = "omap3evm",
+	.owner = THIS_MODULE,
+	.dai_link = &omap3evm_dai,
+	.num_links = 1,
+};
+
+static struct platform_device *omap3evm_snd_device;
+
+static int __init omap3evm_soc_init(void)
+{
+	int ret;
+
+	if (!machine_is_omap3evm())
+		return -ENODEV;
+	pr_info("OMAP3 EVM SoC init\n");
+
+	omap3evm_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!omap3evm_snd_device) {
+		printk(KERN_ERR "Platform device allocation failed\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(omap3evm_snd_device, &snd_soc_omap3evm);
+	ret = platform_device_add(omap3evm_snd_device);
+	if (ret)
+		goto err1;
+
+	return 0;
+
+err1:
+	printk(KERN_ERR "Unable to add platform device\n");
+	platform_device_put(omap3evm_snd_device);
+
+	return ret;
+}
+
+static void __exit omap3evm_soc_exit(void)
+{
+	platform_device_unregister(omap3evm_snd_device);
+}
+
+module_init(omap3evm_soc_init);
+module_exit(omap3evm_soc_exit);
+
+MODULE_AUTHOR("Anuj Aggarwal <anuj.aggarwal@ti.com>");
+MODULE_DESCRIPTION("ALSA SoC OMAP3 EVM");
+MODULE_LICENSE("GPL v2");
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/omap3pandora.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap3pandora.c
new file mode 100644
index 0000000..4c3a097
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap3pandora.c
@@ -0,0 +1,325 @@
+/*
+ * omap3pandora.c  --  SoC audio for Pandora Handheld Console
+ *
+ * Author: Gražvydas Ignotas <notasas@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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
+#include <linux/module.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include <asm/mach-types.h>
+#include <plat/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+
+#define OMAP3_PANDORA_DAC_POWER_GPIO	118
+#define OMAP3_PANDORA_AMP_POWER_GPIO	14
+
+#define PREFIX "ASoC omap3pandora: "
+
+static struct regulator *omap3pandora_dac_reg;
+
+static int omap3pandora_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret;
+
+	/* Set the codec system clock for DAC and ADC */
+	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+					    SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		pr_err(PREFIX "can't set codec system clock\n");
+		return ret;
+	}
+
+	/* Set McBSP clock to external */
+	ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_EXT,
+				     256 * params_rate(params),
+				     SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		pr_err(PREFIX "can't set cpu system clock\n");
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, 8);
+	if (ret < 0) {
+		pr_err(PREFIX "can't set SRG clock divider\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *k, int event)
+{
+	/*
+	 * The PCM1773 DAC datasheet requires 1ms delay between switching
+	 * VCC power on/off and /PD pin high/low
+	 */
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		regulator_enable(omap3pandora_dac_reg);
+		mdelay(1);
+		gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1);
+	} else {
+		gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 0);
+		mdelay(1);
+		regulator_disable(omap3pandora_dac_reg);
+	}
+
+	return 0;
+}
+
+static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *k, int event)
+{
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 1);
+	else
+		gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 0);
+
+	return 0;
+}
+
+/*
+ * Audio paths on Pandora board:
+ *
+ *  |O| ---> PCM DAC +-> AMP -> Headphone Jack
+ *  |M|         A    +--------> Line Out
+ *  |A| <~~clk~~+
+ *  |P| <--- TWL4030 <--------- Line In and MICs
+ */
+static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = {
+	SND_SOC_DAPM_DAC_E("PCM DAC", "HiFi Playback", SND_SOC_NOPM,
+			   0, 0, omap3pandora_dac_event,
+			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+	SND_SOC_DAPM_PGA_E("Headphone Amplifier", SND_SOC_NOPM,
+			   0, 0, NULL, 0, omap3pandora_hp_event,
+			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_LINE("Line Out", NULL),
+};
+
+static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = {
+	SND_SOC_DAPM_MIC("Mic (internal)", NULL),
+	SND_SOC_DAPM_MIC("Mic (external)", NULL),
+	SND_SOC_DAPM_LINE("Line In", NULL),
+};
+
+static const struct snd_soc_dapm_route omap3pandora_out_map[] = {
+	{"PCM DAC", NULL, "APLL Enable"},
+	{"Headphone Amplifier", NULL, "PCM DAC"},
+	{"Line Out", NULL, "PCM DAC"},
+	{"Headphone Jack", NULL, "Headphone Amplifier"},
+};
+
+static const struct snd_soc_dapm_route omap3pandora_in_map[] = {
+	{"AUXL", NULL, "Line In"},
+	{"AUXR", NULL, "Line In"},
+
+	{"MAINMIC", NULL, "Mic Bias 1"},
+	{"Mic Bias 1", NULL, "Mic (internal)"},
+
+	{"SUBMIC", NULL, "Mic Bias 2"},
+	{"Mic Bias 2", NULL, "Mic (external)"},
+};
+
+static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int ret;
+
+	/* All TWL4030 output pins are floating */
+	snd_soc_dapm_nc_pin(dapm, "EARPIECE");
+	snd_soc_dapm_nc_pin(dapm, "PREDRIVEL");
+	snd_soc_dapm_nc_pin(dapm, "PREDRIVER");
+	snd_soc_dapm_nc_pin(dapm, "HSOL");
+	snd_soc_dapm_nc_pin(dapm, "HSOR");
+	snd_soc_dapm_nc_pin(dapm, "CARKITL");
+	snd_soc_dapm_nc_pin(dapm, "CARKITR");
+	snd_soc_dapm_nc_pin(dapm, "HFL");
+	snd_soc_dapm_nc_pin(dapm, "HFR");
+	snd_soc_dapm_nc_pin(dapm, "VIBRA");
+
+	ret = snd_soc_dapm_new_controls(dapm, omap3pandora_out_dapm_widgets,
+				ARRAY_SIZE(omap3pandora_out_dapm_widgets));
+	if (ret < 0)
+		return ret;
+
+	return snd_soc_dapm_add_routes(dapm, omap3pandora_out_map,
+		ARRAY_SIZE(omap3pandora_out_map));
+}
+
+static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int ret;
+
+	/* Not comnnected */
+	snd_soc_dapm_nc_pin(dapm, "HSMIC");
+	snd_soc_dapm_nc_pin(dapm, "CARKITMIC");
+	snd_soc_dapm_nc_pin(dapm, "DIGIMIC0");
+	snd_soc_dapm_nc_pin(dapm, "DIGIMIC1");
+
+	ret = snd_soc_dapm_new_controls(dapm, omap3pandora_in_dapm_widgets,
+				ARRAY_SIZE(omap3pandora_in_dapm_widgets));
+	if (ret < 0)
+		return ret;
+
+	return snd_soc_dapm_add_routes(dapm, omap3pandora_in_map,
+		ARRAY_SIZE(omap3pandora_in_map));
+}
+
+static struct snd_soc_ops omap3pandora_ops = {
+	.hw_params = omap3pandora_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link omap3pandora_dai[] = {
+	{
+		.name = "PCM1773",
+		.stream_name = "HiFi Out",
+		.cpu_dai_name = "omap-mcbsp.2",
+		.codec_dai_name = "twl4030-hifi",
+		.platform_name = "omap-pcm-audio",
+		.codec_name = "twl4030-codec",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			   SND_SOC_DAIFMT_CBS_CFS,
+		.ops = &omap3pandora_ops,
+		.init = omap3pandora_out_init,
+	}, {
+		.name = "TWL4030",
+		.stream_name = "Line/Mic In",
+		.cpu_dai_name = "omap-mcbsp.4",
+		.codec_dai_name = "twl4030-hifi",
+		.platform_name = "omap-pcm-audio",
+		.codec_name = "twl4030-codec",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			   SND_SOC_DAIFMT_CBS_CFS,
+		.ops = &omap3pandora_ops,
+		.init = omap3pandora_in_init,
+	}
+};
+
+/* SoC card */
+static struct snd_soc_card snd_soc_card_omap3pandora = {
+	.name = "omap3pandora",
+	.owner = THIS_MODULE,
+	.dai_link = omap3pandora_dai,
+	.num_links = ARRAY_SIZE(omap3pandora_dai),
+};
+
+static struct platform_device *omap3pandora_snd_device;
+
+static int __init omap3pandora_soc_init(void)
+{
+	int ret;
+
+	if (!machine_is_omap3_pandora())
+		return -ENODEV;
+
+	pr_info("OMAP3 Pandora SoC init\n");
+
+	ret = gpio_request(OMAP3_PANDORA_DAC_POWER_GPIO, "dac_power");
+	if (ret) {
+		pr_err(PREFIX "Failed to get DAC power GPIO\n");
+		return ret;
+	}
+
+	ret = gpio_direction_output(OMAP3_PANDORA_DAC_POWER_GPIO, 0);
+	if (ret) {
+		pr_err(PREFIX "Failed to set DAC power GPIO direction\n");
+		goto fail0;
+	}
+
+	ret = gpio_request(OMAP3_PANDORA_AMP_POWER_GPIO, "amp_power");
+	if (ret) {
+		pr_err(PREFIX "Failed to get amp power GPIO\n");
+		goto fail0;
+	}
+
+	ret = gpio_direction_output(OMAP3_PANDORA_AMP_POWER_GPIO, 0);
+	if (ret) {
+		pr_err(PREFIX "Failed to set amp power GPIO direction\n");
+		goto fail1;
+	}
+
+	omap3pandora_snd_device = platform_device_alloc("soc-audio", -1);
+	if (omap3pandora_snd_device == NULL) {
+		pr_err(PREFIX "Platform device allocation failed\n");
+		ret = -ENOMEM;
+		goto fail1;
+	}
+
+	platform_set_drvdata(omap3pandora_snd_device, &snd_soc_card_omap3pandora);
+
+	ret = platform_device_add(omap3pandora_snd_device);
+	if (ret) {
+		pr_err(PREFIX "Unable to add platform device\n");
+		goto fail2;
+	}
+
+	omap3pandora_dac_reg = regulator_get(&omap3pandora_snd_device->dev, "vcc");
+	if (IS_ERR(omap3pandora_dac_reg)) {
+		pr_err(PREFIX "Failed to get DAC regulator from %s: %ld\n",
+			dev_name(&omap3pandora_snd_device->dev),
+			PTR_ERR(omap3pandora_dac_reg));
+		ret = PTR_ERR(omap3pandora_dac_reg);
+		goto fail3;
+	}
+
+	return 0;
+
+fail3:
+	platform_device_del(omap3pandora_snd_device);
+fail2:
+	platform_device_put(omap3pandora_snd_device);
+fail1:
+	gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO);
+fail0:
+	gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO);
+	return ret;
+}
+module_init(omap3pandora_soc_init);
+
+static void __exit omap3pandora_soc_exit(void)
+{
+	regulator_put(omap3pandora_dac_reg);
+	platform_device_unregister(omap3pandora_snd_device);
+	gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO);
+	gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO);
+}
+module_exit(omap3pandora_soc_exit);
+
+MODULE_AUTHOR("Grazvydas Ignotas <notasas@gmail.com>");
+MODULE_DESCRIPTION("ALSA SoC OMAP3 Pandora");
+MODULE_LICENSE("GPL");
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/omap4-hdmi-card.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap4-hdmi-card.c
new file mode 100644
index 0000000..28d689b
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/omap4-hdmi-card.c
@@ -0,0 +1,121 @@
+/*
+ * omap4-hdmi-card.c
+ *
+ * OMAP ALSA SoC machine driver for TI OMAP4 HDMI
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Ricardo Neri <ricardo.neri@ti.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <asm/mach-types.h>
+#include <video/omapdss.h>
+
+#define DRV_NAME "omap4-hdmi-audio"
+
+static int omap4_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params)
+{
+	int i;
+	struct omap_overlay_manager *mgr = NULL;
+	struct device *dev = substream->pcm->card->dev;
+
+	/* Find DSS HDMI device */
+	for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
+		mgr = omap_dss_get_overlay_manager(i);
+		if (mgr && mgr->device
+			&& mgr->device->type == OMAP_DISPLAY_TYPE_HDMI)
+			break;
+	}
+
+	if (i == omap_dss_get_num_overlay_managers()) {
+		dev_err(dev, "HDMI display device not found!\n");
+		return -ENODEV;
+	}
+
+	/* Make sure HDMI is power-on to avoid L3 interconnect errors */
+	if (mgr->device->state != OMAP_DSS_DISPLAY_ACTIVE) {
+		dev_err(dev, "HDMI display is not active!\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops omap4_hdmi_dai_ops = {
+	.hw_params = omap4_hdmi_dai_hw_params,
+};
+
+static struct snd_soc_dai_link omap4_hdmi_dai = {
+	.name = "HDMI",
+	.stream_name = "HDMI",
+	.cpu_dai_name = "hdmi-audio-dai",
+	.platform_name = "omap-pcm-audio",
+	.codec_name = "omapdss_hdmi",
+	.codec_dai_name = "hdmi-audio-codec",
+	.ops = &omap4_hdmi_dai_ops,
+};
+
+static struct snd_soc_card snd_soc_omap4_hdmi = {
+	.name = "OMAP4HDMI",
+	.owner = THIS_MODULE,
+	.dai_link = &omap4_hdmi_dai,
+	.num_links = 1,
+};
+
+static __devinit int omap4_hdmi_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &snd_soc_omap4_hdmi;
+	int ret;
+
+	card->dev = &pdev->dev;
+
+	ret = snd_soc_register_card(card);
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+		card->dev = NULL;
+		return ret;
+	}
+	return 0;
+}
+
+static int __devexit omap4_hdmi_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+	card->dev = NULL;
+	return 0;
+}
+
+static struct platform_driver omap4_hdmi_driver = {
+	.driver = {
+		.name = "omap4-hdmi-audio",
+		.owner = THIS_MODULE,
+	},
+	.probe = omap4_hdmi_probe,
+	.remove = __devexit_p(omap4_hdmi_remove),
+};
+
+module_platform_driver(omap4_hdmi_driver);
+
+MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
+MODULE_DESCRIPTION("OMAP4 HDMI machine ASoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/osk5912.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/osk5912.c
new file mode 100644
index 0000000..b1a9d64
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/osk5912.c
@@ -0,0 +1,189 @@
+/*
+ * osk5912.c  --  SoC audio for OSK 5912
+ *
+ * Copyright (C) 2008 Mistral Solutions
+ *
+ * Contact: Arun KS  <arunks@mistralsolutions.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <plat/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/tlv320aic23.h"
+
+#define CODEC_CLOCK 	12000000
+
+static struct clk *tlv320aic23_mclk;
+
+static int osk_startup(struct snd_pcm_substream *substream)
+{
+	return clk_enable(tlv320aic23_mclk);
+}
+
+static void osk_shutdown(struct snd_pcm_substream *substream)
+{
+	clk_disable(tlv320aic23_mclk);
+}
+
+static int osk_hw_params(struct snd_pcm_substream *substream,
+			 struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int err;
+
+	/* Set the codec system clock for DAC and ADC */
+	err =
+	    snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
+
+	if (err < 0) {
+		printk(KERN_ERR "can't set codec system clock\n");
+		return err;
+	}
+
+	return err;
+}
+
+static struct snd_soc_ops osk_ops = {
+	.startup = osk_startup,
+	.hw_params = osk_hw_params,
+	.shutdown = osk_shutdown,
+};
+
+static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_LINE("Line In", NULL),
+	SND_SOC_DAPM_MIC("Mic Jack", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	{"Headphone Jack", NULL, "LHPOUT"},
+	{"Headphone Jack", NULL, "RHPOUT"},
+
+	{"LLINEIN", NULL, "Line In"},
+	{"RLINEIN", NULL, "Line In"},
+
+	{"MICIN", NULL, "Mic Jack"},
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link osk_dai = {
+	.name = "TLV320AIC23",
+	.stream_name = "AIC23",
+	.cpu_dai_name = "omap-mcbsp.1",
+	.codec_dai_name = "tlv320aic23-hifi",
+	.platform_name = "omap-pcm-audio",
+	.codec_name = "tlv320aic23-codec",
+	.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBM_CFM,
+	.ops = &osk_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_card_osk = {
+	.name = "OSK5912",
+	.owner = THIS_MODULE,
+	.dai_link = &osk_dai,
+	.num_links = 1,
+
+	.dapm_widgets = tlv320aic23_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
+static struct platform_device *osk_snd_device;
+
+static int __init osk_soc_init(void)
+{
+	int err;
+	u32 curRate;
+	struct device *dev;
+
+	if (!(machine_is_omap_osk()))
+		return -ENODEV;
+
+	osk_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!osk_snd_device)
+		return -ENOMEM;
+
+	platform_set_drvdata(osk_snd_device, &snd_soc_card_osk);
+	err = platform_device_add(osk_snd_device);
+	if (err)
+		goto err1;
+
+	dev = &osk_snd_device->dev;
+
+	tlv320aic23_mclk = clk_get(dev, "mclk");
+	if (IS_ERR(tlv320aic23_mclk)) {
+		printk(KERN_ERR "Could not get mclk clock\n");
+		err = PTR_ERR(tlv320aic23_mclk);
+		goto err2;
+	}
+
+	/*
+	 * Configure 12 MHz output on MCLK.
+	 */
+	curRate = (uint) clk_get_rate(tlv320aic23_mclk);
+	if (curRate != CODEC_CLOCK) {
+		if (clk_set_rate(tlv320aic23_mclk, CODEC_CLOCK)) {
+			printk(KERN_ERR "Cannot set MCLK for AIC23 CODEC\n");
+			err = -ECANCELED;
+			goto err3;
+		}
+	}
+
+	printk(KERN_INFO "MCLK = %d [%d]\n",
+	       (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK);
+
+	return 0;
+
+err3:
+	clk_put(tlv320aic23_mclk);
+err2:
+	platform_device_del(osk_snd_device);
+err1:
+	platform_device_put(osk_snd_device);
+
+	return err;
+
+}
+
+static void __exit osk_soc_exit(void)
+{
+	clk_put(tlv320aic23_mclk);
+	platform_device_unregister(osk_snd_device);
+}
+
+module_init(osk_soc_init);
+module_exit(osk_soc_exit);
+
+MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
+MODULE_DESCRIPTION("ALSA SoC OSK 5912");
+MODULE_LICENSE("GPL");
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/overo.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/overo.c
new file mode 100644
index 0000000..6ac3e0c
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/overo.c
@@ -0,0 +1,122 @@
+/*
+ * overo.c  --  SoC audio for Gumstix Overo
+ *
+ * Author: Steve Sakoman <steve@sakoman.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <plat/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+
+static int overo_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret;
+
+	/* Set the codec system clock for DAC and ADC */
+	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+					    SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set codec system clock\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops overo_ops = {
+	.hw_params = overo_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link overo_dai = {
+	.name = "TWL4030",
+	.stream_name = "TWL4030",
+	.cpu_dai_name = "omap-mcbsp.2",
+	.codec_dai_name = "twl4030-hifi",
+	.platform_name = "omap-pcm-audio",
+	.codec_name = "twl4030-codec",
+	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBM_CFM,
+	.ops = &overo_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_card_overo = {
+	.name = "overo",
+	.owner = THIS_MODULE,
+	.dai_link = &overo_dai,
+	.num_links = 1,
+};
+
+static struct platform_device *overo_snd_device;
+
+static int __init overo_soc_init(void)
+{
+	int ret;
+
+	if (!(machine_is_overo() || machine_is_cm_t35())) {
+		pr_debug("Incomatible machine!\n");
+		return -ENODEV;
+	}
+	printk(KERN_INFO "overo SoC init\n");
+
+	overo_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!overo_snd_device) {
+		printk(KERN_ERR "Platform device allocation failed\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(overo_snd_device, &snd_soc_card_overo);
+
+	ret = platform_device_add(overo_snd_device);
+	if (ret)
+		goto err1;
+
+	return 0;
+
+err1:
+	printk(KERN_ERR "Unable to add platform device\n");
+	platform_device_put(overo_snd_device);
+
+	return ret;
+}
+module_init(overo_soc_init);
+
+static void __exit overo_soc_exit(void)
+{
+	platform_device_unregister(overo_snd_device);
+}
+module_exit(overo_soc_exit);
+
+MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
+MODULE_DESCRIPTION("ALSA SoC overo");
+MODULE_LICENSE("GPL");
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/rx51.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/rx51.c
new file mode 100644
index 0000000..2712dd2
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/rx51.c
@@ -0,0 +1,451 @@
+/*
+ * rx51.c  --  SoC audio for Nokia RX-51
+ *
+ * Copyright (C) 2008 - 2009 Nokia Corporation
+ *
+ * Contact: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *          Eduardo Valentin <eduardo.valentin@nokia.com>
+ *          Jarkko Nikula <jarkko.nikula@bitmer.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <plat/mcbsp.h>
+#include "../codecs/tpa6130a2.h"
+
+#include <asm/mach-types.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+
+#define RX51_TVOUT_SEL_GPIO		40
+#define RX51_JACK_DETECT_GPIO		177
+#define RX51_ECI_SW_GPIO		182
+/*
+ * REVISIT: TWL4030 GPIO base in RX-51. Now statically defined to 192. This
+ * gpio is reserved in arch/arm/mach-omap2/board-rx51-peripherals.c
+ */
+#define RX51_SPEAKER_AMP_TWL_GPIO	(192 + 7)
+
+enum {
+	RX51_JACK_DISABLED,
+	RX51_JACK_TVOUT,		/* tv-out with stereo output */
+	RX51_JACK_HP,			/* headphone: stereo output, no mic */
+	RX51_JACK_HS,			/* headset: stereo output with mic */
+};
+
+static int rx51_spk_func;
+static int rx51_dmic_func;
+static int rx51_jack_func;
+
+static void rx51_ext_control(struct snd_soc_dapm_context *dapm)
+{
+	int hp = 0, hs = 0, tvout = 0;
+
+	switch (rx51_jack_func) {
+	case RX51_JACK_TVOUT:
+		tvout = 1;
+		hp = 1;
+		break;
+	case RX51_JACK_HS:
+		hs = 1;
+	case RX51_JACK_HP:
+		hp = 1;
+		break;
+	}
+
+	if (rx51_spk_func)
+		snd_soc_dapm_enable_pin(dapm, "Ext Spk");
+	else
+		snd_soc_dapm_disable_pin(dapm, "Ext Spk");
+	if (rx51_dmic_func)
+		snd_soc_dapm_enable_pin(dapm, "DMic");
+	else
+		snd_soc_dapm_disable_pin(dapm, "DMic");
+	if (hp)
+		snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
+	else
+		snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
+	if (hs)
+		snd_soc_dapm_enable_pin(dapm, "HS Mic");
+	else
+		snd_soc_dapm_disable_pin(dapm, "HS Mic");
+
+	gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout);
+
+	snd_soc_dapm_sync(dapm);
+}
+
+static int rx51_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+
+	snd_pcm_hw_constraint_minmax(runtime,
+				     SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
+	rx51_ext_control(&card->dapm);
+
+	return 0;
+}
+
+static int rx51_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+
+	/* Set the codec system clock for DAC and ADC */
+	return snd_soc_dai_set_sysclk(codec_dai, 0, 19200000,
+				      SND_SOC_CLOCK_IN);
+}
+
+static struct snd_soc_ops rx51_ops = {
+	.startup = rx51_startup,
+	.hw_params = rx51_hw_params,
+};
+
+static int rx51_get_spk(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = rx51_spk_func;
+
+	return 0;
+}
+
+static int rx51_set_spk(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+
+	if (rx51_spk_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	rx51_spk_func = ucontrol->value.integer.value[0];
+	rx51_ext_control(&card->dapm);
+
+	return 1;
+}
+
+static int rx51_spk_event(struct snd_soc_dapm_widget *w,
+			  struct snd_kcontrol *k, int event)
+{
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		gpio_set_value_cansleep(RX51_SPEAKER_AMP_TWL_GPIO, 1);
+	else
+		gpio_set_value_cansleep(RX51_SPEAKER_AMP_TWL_GPIO, 0);
+
+	return 0;
+}
+
+static int rx51_hp_event(struct snd_soc_dapm_widget *w,
+			 struct snd_kcontrol *k, int event)
+{
+	struct snd_soc_codec *codec = w->dapm->codec;
+
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		tpa6130a2_stereo_enable(codec, 1);
+	else
+		tpa6130a2_stereo_enable(codec, 0);
+
+	return 0;
+}
+
+static int rx51_get_input(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = rx51_dmic_func;
+
+	return 0;
+}
+
+static int rx51_set_input(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+
+	if (rx51_dmic_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	rx51_dmic_func = ucontrol->value.integer.value[0];
+	rx51_ext_control(&card->dapm);
+
+	return 1;
+}
+
+static int rx51_get_jack(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = rx51_jack_func;
+
+	return 0;
+}
+
+static int rx51_set_jack(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+
+	if (rx51_jack_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	rx51_jack_func = ucontrol->value.integer.value[0];
+	rx51_ext_control(&card->dapm);
+
+	return 1;
+}
+
+static struct snd_soc_jack rx51_av_jack;
+
+static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = {
+	{
+		.gpio = RX51_JACK_DETECT_GPIO,
+		.name = "avdet-gpio",
+		.report = SND_JACK_HEADSET,
+		.invert = 1,
+		.debounce_time = 200,
+	},
+};
+
+static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = {
+	SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event),
+	SND_SOC_DAPM_MIC("DMic", NULL),
+	SND_SOC_DAPM_HP("Headphone Jack", rx51_hp_event),
+	SND_SOC_DAPM_MIC("HS Mic", NULL),
+	SND_SOC_DAPM_LINE("FM Transmitter", NULL),
+};
+
+static const struct snd_soc_dapm_widget aic34_dapm_widgetsb[] = {
+	SND_SOC_DAPM_SPK("Earphone", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	{"Ext Spk", NULL, "HPLOUT"},
+	{"Ext Spk", NULL, "HPROUT"},
+	{"Headphone Jack", NULL, "LLOUT"},
+	{"Headphone Jack", NULL, "RLOUT"},
+	{"FM Transmitter", NULL, "LLOUT"},
+	{"FM Transmitter", NULL, "RLOUT"},
+
+	{"DMic Rate 64", NULL, "Mic Bias 2V"},
+	{"Mic Bias 2V", NULL, "DMic"},
+};
+
+static const struct snd_soc_dapm_route audio_mapb[] = {
+	{"b LINE2R", NULL, "MONO_LOUT"},
+	{"Earphone", NULL, "b HPLOUT"},
+
+	{"LINE1L", NULL, "b Mic Bias 2.5V"},
+	{"b Mic Bias 2.5V", NULL, "HS Mic"}
+};
+
+static const char *spk_function[] = {"Off", "On"};
+static const char *input_function[] = {"ADC", "Digital Mic"};
+static const char *jack_function[] = {"Off", "TV-OUT", "Headphone", "Headset"};
+
+static const struct soc_enum rx51_enum[] = {
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function),
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function),
+};
+
+static const struct snd_kcontrol_new aic34_rx51_controls[] = {
+	SOC_ENUM_EXT("Speaker Function", rx51_enum[0],
+		     rx51_get_spk, rx51_set_spk),
+	SOC_ENUM_EXT("Input Select",  rx51_enum[1],
+		     rx51_get_input, rx51_set_input),
+	SOC_ENUM_EXT("Jack Function", rx51_enum[2],
+		     rx51_get_jack, rx51_set_jack),
+	SOC_DAPM_PIN_SWITCH("FM Transmitter"),
+};
+
+static const struct snd_kcontrol_new aic34_rx51_controlsb[] = {
+	SOC_DAPM_PIN_SWITCH("Earphone"),
+};
+
+static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int err;
+
+	/* Set up NC codec pins */
+	snd_soc_dapm_nc_pin(dapm, "MIC3L");
+	snd_soc_dapm_nc_pin(dapm, "MIC3R");
+	snd_soc_dapm_nc_pin(dapm, "LINE1R");
+
+	/* Add RX-51 specific controls */
+	err = snd_soc_add_card_controls(rtd->card, aic34_rx51_controls,
+				   ARRAY_SIZE(aic34_rx51_controls));
+	if (err < 0)
+		return err;
+
+	/* Add RX-51 specific widgets */
+	snd_soc_dapm_new_controls(dapm, aic34_dapm_widgets,
+				  ARRAY_SIZE(aic34_dapm_widgets));
+
+	/* Set up RX-51 specific audio path audio_map */
+	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
+
+	err = tpa6130a2_add_controls(codec);
+	if (err < 0)
+		return err;
+	snd_soc_limit_volume(codec, "TPA6130A2 Headphone Playback Volume", 42);
+
+	err = omap_mcbsp_st_add_controls(rtd);
+	if (err < 0)
+		return err;
+
+	/* AV jack detection */
+	err = snd_soc_jack_new(codec, "AV Jack",
+			       SND_JACK_HEADSET | SND_JACK_VIDEOOUT,
+			       &rx51_av_jack);
+	if (err)
+		return err;
+	err = snd_soc_jack_add_gpios(&rx51_av_jack,
+				     ARRAY_SIZE(rx51_av_jack_gpios),
+				     rx51_av_jack_gpios);
+
+	return err;
+}
+
+static int rx51_aic34b_init(struct snd_soc_dapm_context *dapm)
+{
+	int err;
+
+	err = snd_soc_add_card_controls(dapm->card, aic34_rx51_controlsb,
+				   ARRAY_SIZE(aic34_rx51_controlsb));
+	if (err < 0)
+		return err;
+
+	err = snd_soc_dapm_new_controls(dapm, aic34_dapm_widgetsb,
+					ARRAY_SIZE(aic34_dapm_widgetsb));
+	if (err < 0)
+		return 0;
+
+	return snd_soc_dapm_add_routes(dapm, audio_mapb,
+				       ARRAY_SIZE(audio_mapb));
+}
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link rx51_dai[] = {
+	{
+		.name = "TLV320AIC34",
+		.stream_name = "AIC34",
+		.cpu_dai_name = "omap-mcbsp.2",
+		.codec_dai_name = "tlv320aic3x-hifi",
+		.platform_name = "omap-pcm-audio",
+		.codec_name = "tlv320aic3x-codec.2-0018",
+		.dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
+			   SND_SOC_DAIFMT_CBM_CFM,
+		.init = rx51_aic34_init,
+		.ops = &rx51_ops,
+	},
+};
+
+static struct snd_soc_aux_dev rx51_aux_dev[] = {
+	{
+		.name = "TLV320AIC34b",
+		.codec_name = "tlv320aic3x-codec.2-0019",
+		.init = rx51_aic34b_init,
+	},
+};
+
+static struct snd_soc_codec_conf rx51_codec_conf[] = {
+	{
+		.dev_name = "tlv320aic3x-codec.2-0019",
+		.name_prefix = "b",
+	},
+};
+
+/* Audio card */
+static struct snd_soc_card rx51_sound_card = {
+	.name = "RX-51",
+	.owner = THIS_MODULE,
+	.dai_link = rx51_dai,
+	.num_links = ARRAY_SIZE(rx51_dai),
+	.aux_dev = rx51_aux_dev,
+	.num_aux_devs = ARRAY_SIZE(rx51_aux_dev),
+	.codec_conf = rx51_codec_conf,
+	.num_configs = ARRAY_SIZE(rx51_codec_conf),
+};
+
+static struct platform_device *rx51_snd_device;
+
+static int __init rx51_soc_init(void)
+{
+	int err;
+
+	if (!machine_is_nokia_rx51())
+		return -ENODEV;
+
+	err = gpio_request_one(RX51_TVOUT_SEL_GPIO,
+			       GPIOF_DIR_OUT | GPIOF_INIT_LOW, "tvout_sel");
+	if (err)
+		goto err_gpio_tvout_sel;
+	err = gpio_request_one(RX51_ECI_SW_GPIO,
+			       GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "eci_sw");
+	if (err)
+		goto err_gpio_eci_sw;
+
+	rx51_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!rx51_snd_device) {
+		err = -ENOMEM;
+		goto err1;
+	}
+
+	platform_set_drvdata(rx51_snd_device, &rx51_sound_card);
+
+	err = platform_device_add(rx51_snd_device);
+	if (err)
+		goto err2;
+
+	return 0;
+err2:
+	platform_device_put(rx51_snd_device);
+err1:
+	gpio_free(RX51_ECI_SW_GPIO);
+err_gpio_eci_sw:
+	gpio_free(RX51_TVOUT_SEL_GPIO);
+err_gpio_tvout_sel:
+
+	return err;
+}
+
+static void __exit rx51_soc_exit(void)
+{
+	snd_soc_jack_free_gpios(&rx51_av_jack, ARRAY_SIZE(rx51_av_jack_gpios),
+				rx51_av_jack_gpios);
+
+	platform_device_unregister(rx51_snd_device);
+	gpio_free(RX51_ECI_SW_GPIO);
+	gpio_free(RX51_TVOUT_SEL_GPIO);
+}
+
+module_init(rx51_soc_init);
+module_exit(rx51_soc_exit);
+
+MODULE_AUTHOR("Nokia Corporation");
+MODULE_DESCRIPTION("ALSA SoC Nokia RX-51");
+MODULE_LICENSE("GPL");
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/sdp3430.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/sdp3430.c
new file mode 100644
index 0000000..0e28322
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/sdp3430.c
@@ -0,0 +1,279 @@
+/*
+ * sdp3430.c  --  SoC audio for TI OMAP3430 SDP
+ *
+ * Author: Misael Lopez Cruz <x0052729@ti.com>
+ *
+ * Based on:
+ * Author: Steve Sakoman <steve@sakoman.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/twl.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <plat/mcbsp.h>
+
+/* Register descriptions for twl4030 codec part */
+#include <linux/mfd/twl4030-audio.h>
+#include <linux/module.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+
+/* TWL4030 PMBR1 Register */
+#define TWL4030_INTBR_PMBR1		0x0D
+/* TWL4030 PMBR1 Register GPIO6 mux bit */
+#define TWL4030_GPIO6_PWM0_MUTE(value)	(value << 2)
+
+static struct snd_soc_card snd_soc_sdp3430;
+
+static int sdp3430_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret;
+
+	/* Set the codec system clock for DAC and ADC */
+	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+					    SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set codec system clock\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops sdp3430_ops = {
+	.hw_params = sdp3430_hw_params,
+};
+
+/* Headset jack */
+static struct snd_soc_jack hs_jack;
+
+/* Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin hs_jack_pins[] = {
+	{
+		.pin = "Headset Mic",
+		.mask = SND_JACK_MICROPHONE,
+	},
+	{
+		.pin = "Headset Stereophone",
+		.mask = SND_JACK_HEADPHONE,
+	},
+};
+
+/* Headset jack detection gpios */
+static struct snd_soc_jack_gpio hs_jack_gpios[] = {
+	{
+		.gpio = (OMAP_MAX_GPIO_LINES + 2),
+		.name = "hsdet-gpio",
+		.report = SND_JACK_HEADSET,
+		.debounce_time = 200,
+	},
+};
+
+/* SDP3430 machine DAPM */
+static const struct snd_soc_dapm_widget sdp3430_twl4030_dapm_widgets[] = {
+	SND_SOC_DAPM_MIC("Ext Mic", NULL),
+	SND_SOC_DAPM_SPK("Ext Spk", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_HP("Headset Stereophone", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	/* External Mics: MAINMIC, SUBMIC with bias*/
+	{"MAINMIC", NULL, "Mic Bias 1"},
+	{"SUBMIC", NULL, "Mic Bias 2"},
+	{"Mic Bias 1", NULL, "Ext Mic"},
+	{"Mic Bias 2", NULL, "Ext Mic"},
+
+	/* External Speakers: HFL, HFR */
+	{"Ext Spk", NULL, "HFL"},
+	{"Ext Spk", NULL, "HFR"},
+
+	/* Headset Mic: HSMIC with bias */
+	{"HSMIC", NULL, "Headset Mic Bias"},
+	{"Headset Mic Bias", NULL, "Headset Mic"},
+
+	/* Headset Stereophone (Headphone): HSOL, HSOR */
+	{"Headset Stereophone", NULL, "HSOL"},
+	{"Headset Stereophone", NULL, "HSOR"},
+};
+
+static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int ret;
+
+	/* SDP3430 connected pins */
+	snd_soc_dapm_enable_pin(dapm, "Ext Mic");
+	snd_soc_dapm_enable_pin(dapm, "Ext Spk");
+	snd_soc_dapm_disable_pin(dapm, "Headset Mic");
+	snd_soc_dapm_disable_pin(dapm, "Headset Stereophone");
+
+	/* TWL4030 not connected pins */
+	snd_soc_dapm_nc_pin(dapm, "AUXL");
+	snd_soc_dapm_nc_pin(dapm, "AUXR");
+	snd_soc_dapm_nc_pin(dapm, "CARKITMIC");
+	snd_soc_dapm_nc_pin(dapm, "DIGIMIC0");
+	snd_soc_dapm_nc_pin(dapm, "DIGIMIC1");
+
+	snd_soc_dapm_nc_pin(dapm, "OUTL");
+	snd_soc_dapm_nc_pin(dapm, "OUTR");
+	snd_soc_dapm_nc_pin(dapm, "EARPIECE");
+	snd_soc_dapm_nc_pin(dapm, "PREDRIVEL");
+	snd_soc_dapm_nc_pin(dapm, "PREDRIVER");
+	snd_soc_dapm_nc_pin(dapm, "CARKITL");
+	snd_soc_dapm_nc_pin(dapm, "CARKITR");
+
+	/* Headset jack detection */
+	ret = snd_soc_jack_new(codec, "Headset Jack",
+				SND_JACK_HEADSET, &hs_jack);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
+				hs_jack_pins);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios),
+				hs_jack_gpios);
+
+	return ret;
+}
+
+static int sdp3430_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	unsigned short reg;
+
+	/* Enable voice interface */
+	reg = codec->driver->read(codec, TWL4030_REG_VOICE_IF);
+	reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN;
+	codec->driver->write(codec, TWL4030_REG_VOICE_IF, reg);
+
+	return 0;
+}
+
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link sdp3430_dai[] = {
+	{
+		.name = "TWL4030 I2S",
+		.stream_name = "TWL4030 Audio",
+		.cpu_dai_name = "omap-mcbsp.2",
+		.codec_dai_name = "twl4030-hifi",
+		.platform_name = "omap-pcm-audio",
+		.codec_name = "twl4030-codec",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			   SND_SOC_DAIFMT_CBM_CFM,
+		.init = sdp3430_twl4030_init,
+		.ops = &sdp3430_ops,
+	},
+	{
+		.name = "TWL4030 PCM",
+		.stream_name = "TWL4030 Voice",
+		.cpu_dai_name = "omap-mcbsp.3",
+		.codec_dai_name = "twl4030-voice",
+		.platform_name = "omap-pcm-audio",
+		.codec_name = "twl4030-codec",
+		.dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
+			   SND_SOC_DAIFMT_CBM_CFM,
+		.init = sdp3430_twl4030_voice_init,
+		.ops = &sdp3430_ops,
+	},
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_sdp3430 = {
+	.name = "SDP3430",
+	.owner = THIS_MODULE,
+	.dai_link = sdp3430_dai,
+	.num_links = ARRAY_SIZE(sdp3430_dai),
+
+	.dapm_widgets = sdp3430_twl4030_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(sdp3430_twl4030_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
+static struct platform_device *sdp3430_snd_device;
+
+static int __init sdp3430_soc_init(void)
+{
+	int ret;
+	u8 pin_mux;
+
+	if (!machine_is_omap_3430sdp())
+		return -ENODEV;
+	printk(KERN_INFO "SDP3430 SoC init\n");
+
+	sdp3430_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!sdp3430_snd_device) {
+		printk(KERN_ERR "Platform device allocation failed\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(sdp3430_snd_device, &snd_soc_sdp3430);
+
+	/* Set TWL4030 GPIO6 as EXTMUTE signal */
+	twl_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux,
+						TWL4030_INTBR_PMBR1);
+	pin_mux &= ~TWL4030_GPIO6_PWM0_MUTE(0x03);
+	pin_mux |= TWL4030_GPIO6_PWM0_MUTE(0x02);
+	twl_i2c_write_u8(TWL4030_MODULE_INTBR, pin_mux,
+						TWL4030_INTBR_PMBR1);
+
+	ret = platform_device_add(sdp3430_snd_device);
+	if (ret)
+		goto err1;
+
+	return 0;
+
+err1:
+	printk(KERN_ERR "Unable to add platform device\n");
+	platform_device_put(sdp3430_snd_device);
+
+	return ret;
+}
+module_init(sdp3430_soc_init);
+
+static void __exit sdp3430_soc_exit(void)
+{
+	snd_soc_jack_free_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios),
+				hs_jack_gpios);
+
+	platform_device_unregister(sdp3430_snd_device);
+}
+module_exit(sdp3430_soc_exit);
+
+MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
+MODULE_DESCRIPTION("ALSA SoC SDP3430");
+MODULE_LICENSE("GPL");
+
diff --git a/ap/os/linux/linux-3.4.x/sound/soc/omap/zoom2.c b/ap/os/linux/linux-3.4.x/sound/soc/omap/zoom2.c
new file mode 100644
index 0000000..920e0d9
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/sound/soc/omap/zoom2.c
@@ -0,0 +1,219 @@
+/*
+ * zoom2.c  --  SoC audio for Zoom2
+ *
+ * Author: Misael Lopez Cruz <x0052729@ti.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/board-zoom.h>
+#include <plat/mcbsp.h>
+
+/* Register descriptions for twl4030 codec part */
+#include <linux/mfd/twl4030-audio.h>
+#include <linux/module.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+
+#define ZOOM2_HEADSET_MUX_GPIO		(OMAP_MAX_GPIO_LINES + 15)
+
+static int zoom2_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret;
+
+	/* Set the codec system clock for DAC and ADC */
+	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+					SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set codec system clock\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops zoom2_ops = {
+	.hw_params = zoom2_hw_params,
+};
+
+/* Zoom2 machine DAPM */
+static const struct snd_soc_dapm_widget zoom2_twl4030_dapm_widgets[] = {
+	SND_SOC_DAPM_MIC("Ext Mic", NULL),
+	SND_SOC_DAPM_SPK("Ext Spk", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_HP("Headset Stereophone", NULL),
+	SND_SOC_DAPM_LINE("Aux In", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	/* External Mics: MAINMIC, SUBMIC with bias*/
+	{"MAINMIC", NULL, "Mic Bias 1"},
+	{"SUBMIC", NULL, "Mic Bias 2"},
+	{"Mic Bias 1", NULL, "Ext Mic"},
+	{"Mic Bias 2", NULL, "Ext Mic"},
+
+	/* External Speakers: HFL, HFR */
+	{"Ext Spk", NULL, "HFL"},
+	{"Ext Spk", NULL, "HFR"},
+
+	/* Headset Stereophone:  HSOL, HSOR */
+	{"Headset Stereophone", NULL, "HSOL"},
+	{"Headset Stereophone", NULL, "HSOR"},
+
+	/* Headset Mic: HSMIC with bias */
+	{"HSMIC", NULL, "Headset Mic Bias"},
+	{"Headset Mic Bias", NULL, "Headset Mic"},
+
+	/* Aux In: AUXL, AUXR */
+	{"Aux In", NULL, "AUXL"},
+	{"Aux In", NULL, "AUXR"},
+};
+
+static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+	/* TWL4030 not connected pins */
+	snd_soc_dapm_nc_pin(dapm, "CARKITMIC");
+	snd_soc_dapm_nc_pin(dapm, "DIGIMIC0");
+	snd_soc_dapm_nc_pin(dapm, "DIGIMIC1");
+	snd_soc_dapm_nc_pin(dapm, "EARPIECE");
+	snd_soc_dapm_nc_pin(dapm, "PREDRIVEL");
+	snd_soc_dapm_nc_pin(dapm, "PREDRIVER");
+	snd_soc_dapm_nc_pin(dapm, "CARKITL");
+	snd_soc_dapm_nc_pin(dapm, "CARKITR");
+
+	return 0;
+}
+
+static int zoom2_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	unsigned short reg;
+
+	/* Enable voice interface */
+	reg = codec->driver->read(codec, TWL4030_REG_VOICE_IF);
+	reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN;
+	codec->driver->write(codec, TWL4030_REG_VOICE_IF, reg);
+
+	return 0;
+}
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link zoom2_dai[] = {
+	{
+		.name = "TWL4030 I2S",
+		.stream_name = "TWL4030 Audio",
+		.cpu_dai_name = "omap-mcbsp.2",
+		.codec_dai_name = "twl4030-hifi",
+		.platform_name = "omap-pcm-audio",
+		.codec_name = "twl4030-codec",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			   SND_SOC_DAIFMT_CBM_CFM,
+		.init = zoom2_twl4030_init,
+		.ops = &zoom2_ops,
+	},
+	{
+		.name = "TWL4030 PCM",
+		.stream_name = "TWL4030 Voice",
+		.cpu_dai_name = "omap-mcbsp.3",
+		.codec_dai_name = "twl4030-voice",
+		.platform_name = "omap-pcm-audio",
+		.codec_name = "twl4030-codec",
+		.dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
+			   SND_SOC_DAIFMT_CBM_CFM,
+		.init = zoom2_twl4030_voice_init,
+		.ops = &zoom2_ops,
+	},
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_zoom2 = {
+	.name = "Zoom2",
+	.owner = THIS_MODULE,
+	.dai_link = zoom2_dai,
+	.num_links = ARRAY_SIZE(zoom2_dai),
+
+	.dapm_widgets = zoom2_twl4030_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(zoom2_twl4030_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
+static struct platform_device *zoom2_snd_device;
+
+static int __init zoom2_soc_init(void)
+{
+	int ret;
+
+	if (!machine_is_omap_zoom2())
+		return -ENODEV;
+	printk(KERN_INFO "Zoom2 SoC init\n");
+
+	zoom2_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!zoom2_snd_device) {
+		printk(KERN_ERR "Platform device allocation failed\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(zoom2_snd_device, &snd_soc_zoom2);
+	ret = platform_device_add(zoom2_snd_device);
+	if (ret)
+		goto err1;
+
+	BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0);
+	gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0);
+
+	BUG_ON(gpio_request(ZOOM2_HEADSET_EXTMUTE_GPIO, "ext_mute") < 0);
+	gpio_direction_output(ZOOM2_HEADSET_EXTMUTE_GPIO, 0);
+
+	return 0;
+
+err1:
+	printk(KERN_ERR "Unable to add platform device\n");
+	platform_device_put(zoom2_snd_device);
+
+	return ret;
+}
+module_init(zoom2_soc_init);
+
+static void __exit zoom2_soc_exit(void)
+{
+	gpio_free(ZOOM2_HEADSET_MUX_GPIO);
+	gpio_free(ZOOM2_HEADSET_EXTMUTE_GPIO);
+
+	platform_device_unregister(zoom2_snd_device);
+}
+module_exit(zoom2_soc_exit);
+
+MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
+MODULE_DESCRIPTION("ALSA SoC Zoom2");
+MODULE_LICENSE("GPL");
+