ASoC: sdp4430 - add ABE support to machine driver

Add full support for ABE Frontend and Backend DAIs.

Signed-off-by: Liam Girdwood <lrg@ti.com>
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
index 7292087..c8c2e10 100644
--- a/sound/soc/omap/sdp4430.c
+++ b/sound/soc/omap/sdp4430.c
@@ -25,25 +25,35 @@
 
 #include <sound/core.h>
 #include <sound/pcm.h>
+#include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/soc-dapm.h>
 #include <sound/jack.h>
+#include <sound/soc-dsp.h>
 
 #include <asm/mach-types.h>
 #include <plat/hardware.h>
 #include <plat/mux.h>
 
+#include "omap-mcpdm.h"
+#include "omap-abe.h"
 #include "omap-pcm.h"
+#include "omap-mcbsp.h"
+#include "omap-dmic.h"
 #include "../codecs/twl6040.h"
 
 static int twl6040_power_mode;
+static int mcbsp_cfg;
 
-static int sdp4430_hw_params(struct snd_pcm_substream *substream,
+static int sdp4430_mcpdm_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 clk_id, freq;
-	int ret;
+	struct snd_soc_pcm_runtime *modem_rtd;
+	struct snd_pcm_substream *modem_substream[2];
+	struct snd_soc_dsp_params *dsp_params;
+	int clk_id, freq, ret, stream = substream->stream;
 
 	if (twl6040_power_mode) {
 		clk_id = TWL6040_SYSCLK_SEL_HPPLL;
@@ -60,13 +70,144 @@
 		printk(KERN_ERR "can't set codec system clock\n");
 		return ret;
 	}
+	list_for_each_entry(dsp_params, &rtd->dsp[stream].fe_clients, list_fe) {
+
+		if (dsp_params->fe->cpu_dai->id != ABE_FRONTEND_DAI_MODEM)
+			continue;
+
+		if (!mcbsp_cfg) {
+			modem_substream[stream] =
+				snd_soc_get_dai_substream(rtd->card,
+							OMAP_ABE_BE_MM_EXT1,
+							substream->stream);
+			if (modem_substream[stream] == NULL)
+				return -ENODEV;
+
+			modem_rtd = modem_substream[stream]->private_data;
+
+			/* Set cpu DAI configuration */
+			ret = snd_soc_dai_set_fmt(modem_rtd->cpu_dai,
+					  SND_SOC_DAIFMT_I2S |
+					  SND_SOC_DAIFMT_NB_NF |
+					  SND_SOC_DAIFMT_CBM_CFM);
+			mcbsp_cfg = 1;
+		}
+		if (ret < 0) {
+			printk(KERN_ERR "can't set Modem cpu DAI configuration\n");
+			return ret;
+		}
+	}
 	return ret;
 }
 
-static struct snd_soc_ops sdp4430_ops = {
-	.hw_params = sdp4430_hw_params,
+static struct snd_soc_ops sdp4430_mcpdm_ops = {
+	.hw_params = sdp4430_mcpdm_hw_params,
 };
 
+static int sdp4430_mcbsp_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;
+	unsigned int be_id;
+
+        be_id = rtd->dai_link->be_id;
+
+	if (be_id == OMAP_ABE_DAI_MM_FM) {
+		/* Set cpu DAI configuration */
+		ret = snd_soc_dai_set_fmt(cpu_dai,
+				  SND_SOC_DAIFMT_I2S |
+				  SND_SOC_DAIFMT_NB_NF |
+				  SND_SOC_DAIFMT_CBM_CFM);
+	} else if (be_id == OMAP_ABE_DAI_BT_VX) {
+	        ret = snd_soc_dai_set_fmt(cpu_dai,
+                                  SND_SOC_DAIFMT_DSP_B |
+                                  SND_SOC_DAIFMT_NB_IF |
+                                  SND_SOC_DAIFMT_CBM_CFM);
+	}
+
+	if (ret < 0) {
+		printk(KERN_ERR "can't set cpu DAI configuration\n");
+		return ret;
+	}
+
+	/*
+	 * TODO: where does this clock come from (external source??) -
+	 * do we need to enable it.
+	 */
+	/* Set McBSP clock to external */
+	ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK,
+				     64 * params_rate(params),
+				     SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set cpu system clock\n");
+		return ret;
+	}
+	return 0;
+}
+
+static struct snd_soc_ops sdp4430_mcbsp_ops = {
+	.hw_params = sdp4430_mcbsp_hw_params,
+};
+
+static int sdp4430_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_clkdiv(cpu_dai, OMAP_DMIC_CLKDIV, 8);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set DMIC cpu clock divider\n");
+		return ret;
+	}
+	return 0;
+}
+
+static struct snd_soc_ops sdp4430_dmic_ops = {
+	.hw_params = sdp4430_dmic_hw_params,
+};
+
+static int mcbsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *channels = hw_param_interval(params,
+                                       SNDRV_PCM_HW_PARAM_CHANNELS);
+	unsigned int be_id = rtd->dai_link->be_id;
+
+	if (be_id == OMAP_ABE_DAI_MM_FM)
+		channels->min = 2;
+	else if (be_id == OMAP_ABE_DAI_BT_VX)
+		channels->min = 1;
+	snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
+	                            SNDRV_PCM_HW_PARAM_FIRST_MASK],
+	                            SNDRV_PCM_FORMAT_S16_LE);
+	return 0;
+}
+
+static int dmic_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+			SNDRV_PCM_HW_PARAM_RATE);
+
+	/* The ABE will covert the FE rate to 96k */
+	rate->min = rate->max = 96000;
+
+	snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
+	                            SNDRV_PCM_HW_PARAM_FIRST_MASK],
+	                            SNDRV_PCM_FORMAT_S32_LE);
+	return 0;
+}
+
 /* Headset jack */
 static struct snd_soc_jack hs_jack;
 
@@ -176,6 +317,14 @@
 	snd_soc_dapm_enable_pin(dapm, "Headset Mic");
 	snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
 
+	/* allow audio paths from the audio modem to run during suspend */
+	snd_soc_dapm_ignore_suspend(dapm, "Ext Mic");
+	snd_soc_dapm_ignore_suspend(dapm, "Ext Spk");
+	snd_soc_dapm_ignore_suspend(dapm, "AFML");
+	snd_soc_dapm_ignore_suspend(dapm, "AFMR");
+	snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
+	snd_soc_dapm_ignore_suspend(dapm, "Headset Stereophone");
+
 	ret = snd_soc_dapm_sync(dapm);
 	if (ret)
 		return ret;
@@ -197,26 +346,469 @@
 	return ret;
 }
 
+/* TODO: make this a separate BT CODEC driver or DUMMY */
+static struct snd_soc_dai_driver dai[] = {
+{
+	.name = "Bluetooth",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
+					SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
+					SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	},
+},
+/* TODO: make this a separate FM CODEC driver or DUMMY */
+{
+	.name = "FM Digital",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	},
+},
+{
+	.name = "HDMI",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 8,
+		.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+				SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
+	},
+},
+};
+
+static const char *mm1_be[] = {
+		OMAP_ABE_BE_PDM_DL1,
+		OMAP_ABE_BE_PDM_UL1,
+		OMAP_ABE_BE_PDM_DL2,
+		OMAP_ABE_BE_BT_VX,
+		OMAP_ABE_BE_MM_EXT0,
+		OMAP_ABE_BE_DMIC0,
+		OMAP_ABE_BE_DMIC1,
+		OMAP_ABE_BE_DMIC2,
+};
+
+struct snd_soc_dsp_link fe_media = {
+	.supported_be	= mm1_be,
+	.num_be			= ARRAY_SIZE(mm1_be),
+	.fe_playback_channels	= 2,
+	.fe_capture_channels	= 8,
+	.trigger =
+		{SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
+};
+
+static const char *mm2_be[] = {
+		OMAP_ABE_BE_PDM_UL1,
+		OMAP_ABE_BE_BT_VX,
+		OMAP_ABE_BE_MM_EXT0,
+		OMAP_ABE_BE_DMIC0,
+		OMAP_ABE_BE_DMIC1,
+		OMAP_ABE_BE_DMIC2,
+};
+
+struct snd_soc_dsp_link fe_media_capture = {
+	.supported_be	= mm2_be,
+	.num_be			= ARRAY_SIZE(mm2_be),
+	.fe_capture_channels	= 8,
+	.trigger =
+		{SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
+};
+
+static const char *tones_be[] = {
+		OMAP_ABE_BE_PDM_DL1,
+		OMAP_ABE_BE_PDM_DL2,
+		OMAP_ABE_BE_BT_VX,
+		OMAP_ABE_BE_MM_EXT0,
+};
+
+struct snd_soc_dsp_link fe_tones = {
+	.supported_be	= tones_be,
+	.num_be			= ARRAY_SIZE(tones_be),
+	.fe_playback_channels	= 2,
+	.trigger =
+		{SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
+};
+
+static const char *vib_be[] = {
+		OMAP_ABE_BE_PDM_VIB,
+};
+
+struct snd_soc_dsp_link fe_vib = {
+	.supported_be	= vib_be,
+	.num_be			= ARRAY_SIZE(vib_be),
+	.fe_playback_channels	= 2,
+	.trigger =
+		{SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
+};
+
+static const char *modem_be[] = {
+		OMAP_ABE_BE_PDM_DL1,
+		OMAP_ABE_BE_PDM_UL1,
+		OMAP_ABE_BE_PDM_DL2,
+		OMAP_ABE_BE_BT_VX,
+		OMAP_ABE_BE_DMIC0,
+		OMAP_ABE_BE_DMIC1,
+		OMAP_ABE_BE_DMIC2,
+};
+
+struct snd_soc_dsp_link fe_modem = {
+	.supported_be	= modem_be,
+	.num_be			= ARRAY_SIZE(modem_be),
+	.fe_playback_channels	= 2,
+	.fe_capture_channels	= 2,
+	.trigger =
+		{SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
+};
+
+static const char *mm_lp_be[] = {
+		OMAP_ABE_BE_PDM_DL1,
+		OMAP_ABE_BE_PDM_DL2,
+		OMAP_ABE_BE_BT_VX,
+		OMAP_ABE_BE_MM_EXT0,
+};
+
+struct snd_soc_dsp_link fe_lp_media = {
+	.supported_be	= mm_lp_be,
+	.num_be			= ARRAY_SIZE(mm_lp_be),
+	.fe_playback_channels	= 2,
+	.trigger =
+		{SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
+};
 /* Digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link sdp4430_dai = {
-	.name = "TWL6040",
-	.stream_name = "TWL6040",
-	.cpu_dai_name ="omap-mcpdm-dai",
-	.codec_dai_name = "twl6040-hifi",
-	.platform_name = "omap-pcm-audio",
-	.codec_name = "twl6040-codec",
-	.init = sdp4430_twl6040_init,
-	.ops = &sdp4430_ops,
+static struct snd_soc_dai_link sdp4430_dai[] = {
+
+/*
+ * Frontend DAIs - i.e. userspace visible interfaces (ALSA PCMs)
+ */
+
+	{
+		.name = "SDP4430 Media",
+		.stream_name = "Multimedia",
+
+		/* ABE components - MM-UL & MM_DL */
+		.cpu_dai_name = "MultiMedia1",
+		.platform_name = "omap-pcm-audio",
+
+		.dynamic = 1, /* BE is dynamic */
+		.dsp_link = &fe_media,
+	},
+	{
+		.name = "SDP4430 Media Capture",
+		.stream_name = "Multimedia Capture",
+
+		/* ABE components - MM-UL2 */
+		.cpu_dai_name = "MultiMedia2",
+		.platform_name = "omap-pcm-audio",
+
+		.dynamic = 1, /* BE is dynamic */
+		.dsp_link = &fe_media_capture,
+	},
+	{
+		.name = "SDP4430 Voice",
+		.stream_name = "Voice",
+
+		/* ABE components - VX-UL & VX-DL */
+		.cpu_dai_name = "Voice",
+		.platform_name = "omap-pcm-audio",
+
+		.dynamic = 1, /* BE is dynamic */
+		.dsp_link = &fe_media,
+		.no_host_mode = SND_SOC_DAI_LINK_OPT_HOST,
+	},
+	{
+		.name = "SDP4430 Tones Playback",
+		.stream_name = "Tone Playback",
+
+		/* ABE components - TONES_DL */
+		.cpu_dai_name = "Tones",
+		.platform_name = "omap-pcm-audio",
+
+		.dynamic = 1, /* BE is dynamic */
+		.dsp_link = &fe_tones,
+	},
+	{
+		.name = "SDP4430 Vibra Playback",
+		.stream_name = "VIB-DL",
+
+		/* ABE components - DMIC UL 2 */
+		.cpu_dai_name = "Vibra",
+		.platform_name = "omap-pcm-audio",
+
+		.dynamic = 1, /* BE is dynamic */
+		.dsp_link = &fe_vib,
+	},
+	{
+		.name = "SDP4430 MODEM",
+		.stream_name = "MODEM",
+
+		/* ABE components - MODEM <-> McBSP2 */
+		.cpu_dai_name = "MODEM",
+		.platform_name = "aess",
+
+		.dynamic = 1, /* BE is dynamic */
+		.dsp_link = &fe_modem,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = "SDP4430 Media LP",
+		.stream_name = "Multimedia",
+
+		/* ABE components - MM-DL (mmap) */
+		.cpu_dai_name = "MultiMedia1 LP",
+		.platform_name = "aess",
+
+		.dynamic = 1, /* BE is dynamic */
+		.dsp_link = &fe_lp_media,
+	},
+	{
+		.name = "Legacy McBSP",
+		.stream_name = "Multimedia",
+
+		/* ABE components - MCBSP2 - MM-EXT */
+		.cpu_dai_name = "omap-mcbsp-dai.1",
+		.platform_name = "omap-pcm-audio",
+
+		/* FM */
+		.codec_dai_name = "FM Digital",
+
+		.no_codec = 1, /* TODO: have a dummy CODEC */
+		.ops = &sdp4430_mcbsp_ops,
+	},
+	{
+		.name = "Legacy McPDM",
+		.stream_name = "Headset Playback",
+
+		/* ABE components - DL1 */
+		.cpu_dai_name = "mcpdm-dl",
+		.platform_name = "omap-pcm-audio",
+
+		/* Phoenix - DL1 DAC */
+		.codec_dai_name =  "twl6040-dl1",
+		.codec_name = "twl6040-codec",
+
+		.ops = &sdp4430_mcpdm_ops,
+	},
+	{
+		.name = "Legacy DMIC",
+		.stream_name = "DMIC Capture",
+
+		/* ABE components - DMIC0 */
+		.cpu_dai_name = "omap-dmic-dai-0",
+		.platform_name = "omap-pcm-audio",
+
+		/* DMIC codec */
+		.codec_dai_name = "dmic-hifi",
+		.codec_name = "dmic-codec.0",
+
+		.ops = &sdp4430_dmic_ops,
+	},
+
+/*
+ * Backend DAIs - i.e. dynamically matched interfaces, invisible to userspace.
+ * Matched to above interfaces at runtime, based upon use case.
+ */
+
+	{
+		.name = OMAP_ABE_BE_PDM_DL1,
+		.stream_name = "HS Playback",
+
+		/* ABE components - DL1 */
+		.cpu_dai_name = "mcpdm-dl1",
+		.platform_name = "aess",
+
+		/* Phoenix - DL1 DAC */
+		.codec_dai_name =  "twl6040-dl1",
+		.codec_name = "twl6040-codec",
+
+		.no_pcm = 1, /* don't create ALSA pcm for this */
+		.init = sdp4430_twl6040_init,
+		.ops = &sdp4430_mcpdm_ops,
+		.be_id = OMAP_ABE_DAI_PDM_DL1,
+	},
+	{
+		.name = OMAP_ABE_BE_PDM_UL1,
+		.stream_name = "Analog Capture",
+
+		/* ABE components - UL1 */
+		.cpu_dai_name = "mcpdm-ul1",
+		.platform_name = "aess",
+
+		/* Phoenix - UL ADC */
+		.codec_dai_name =  "twl6040-ul",
+		.codec_name = "twl6040-codec",
+
+		.no_pcm = 1, /* don't create ALSA pcm for this */
+		.ops = &sdp4430_mcpdm_ops,
+		.be_id = OMAP_ABE_DAI_PDM_UL,
+	},
+	{
+		.name = OMAP_ABE_BE_PDM_DL2,
+		.stream_name = "HF Playback",
+
+		/* ABE components - DL2 */
+		.cpu_dai_name = "mcpdm-dl2",
+		.platform_name = "aess",
+
+		/* Phoenix - DL2 DAC */
+		.codec_dai_name =  "twl6040-dl2",
+		.codec_name = "twl6040-codec",
+
+		.no_pcm = 1, /* don't create ALSA pcm for this */
+		.ops = &sdp4430_mcpdm_ops,
+		.be_id = OMAP_ABE_DAI_PDM_DL2,
+	},
+	{
+		.name = OMAP_ABE_BE_PDM_VIB,
+		.stream_name = "Vibra",
+
+		/* ABE components - VIB1 DL */
+		.cpu_dai_name = "mcpdm-vib",
+		.platform_name = "aess",
+
+		/* Phoenix - PDM to PWM */
+		.codec_dai_name =  "twl6040-vib",
+		.codec_name = "twl6040-codec",
+
+		.no_pcm = 1, /* don't create ALSA pcm for this */
+		.ops = &sdp4430_mcpdm_ops,
+		.be_id = OMAP_ABE_DAI_PDM_VIB,
+	},
+	{
+		.name = OMAP_ABE_BE_BT_VX,
+		.stream_name = "BT",
+
+		/* ABE components - MCBSP1 - BT-VX */
+		.cpu_dai_name = "omap-mcbsp-dai.0",
+		.platform_name = "aess",
+
+		/* Bluetooth */
+		.codec_dai_name = "Bluetooth",
+
+		.no_pcm = 1, /* don't create ALSA pcm for this */
+		.no_codec = 1, /* TODO: have a dummy CODEC */
+		.be_hw_params_fixup = mcbsp_be_hw_params_fixup,
+		.ops = &sdp4430_mcbsp_ops,
+		.be_id = OMAP_ABE_DAI_BT_VX,
+	},
+	{
+		.name = OMAP_ABE_BE_MM_EXT0,
+		.stream_name = "FM",
+
+		/* ABE components - MCBSP2 - MM-EXT */
+		.cpu_dai_name = "omap-mcbsp-dai.1",
+		.platform_name = "aess",
+
+		/* FM */
+		.codec_dai_name = "FM Digital",
+
+		.no_pcm = 1, /* don't create ALSA pcm for this */
+		.no_codec = 1, /* TODO: have a dummy CODEC */
+		.be_hw_params_fixup = mcbsp_be_hw_params_fixup,
+		.ops = &sdp4430_mcbsp_ops,
+		.be_id = OMAP_ABE_DAI_MM_FM,
+	},
+	{
+		.name = OMAP_ABE_BE_MM_EXT1,
+		.stream_name = "MODEM",
+
+		/* ABE components - MCBSP2 - MM-EXT */
+		.cpu_dai_name = "omap-mcbsp-dai.1",
+		.platform_name = "aess",
+
+		/* MODEM */
+		.codec_dai_name = "MODEM",
+
+		.no_pcm = 1, /* don't create ALSA pcm for this */
+		.no_codec = 1, /* TODO: have a dummy CODEC */
+		.be_hw_params_fixup = mcbsp_be_hw_params_fixup,
+		.ops = &sdp4430_mcbsp_ops,
+		.be_id = OMAP_ABE_DAI_MODEM,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = OMAP_ABE_BE_DMIC0,
+		.stream_name = "DMIC0",
+
+		/* ABE components - DMIC UL 1 */
+		.cpu_dai_name = "omap-dmic-abe-dai-0",
+		.platform_name = "aess",
+
+		/* DMIC 0 */
+		.codec_dai_name = "dmic-hifi",
+		.codec_name = "dmic-codec.0",
+		.ops = &sdp4430_dmic_ops,
+
+		.no_pcm = 1, /* don't create ALSA pcm for this */
+		.be_hw_params_fixup = dmic_be_hw_params_fixup,
+		.be_id = OMAP_ABE_DAI_DMIC0,
+	},
+	{
+		.name = OMAP_ABE_BE_DMIC1,
+		.stream_name = "DMIC1",
+
+		/* ABE components - DMIC UL 1 */
+		.cpu_dai_name = "omap-dmic-abe-dai-1",
+		.platform_name = "aess",
+
+		/* DMIC 1 */
+		.codec_dai_name = "dmic-hifi",
+		.codec_name = "dmic-codec.1",
+		.ops = &sdp4430_dmic_ops,
+
+		.no_pcm = 1, /* don't create ALSA pcm for this */
+		.be_hw_params_fixup = dmic_be_hw_params_fixup,
+		.be_id = OMAP_ABE_DAI_DMIC1,
+	},
+	{
+		.name = OMAP_ABE_BE_DMIC2,
+		.stream_name = "DMIC2",
+
+		/* ABE components - DMIC UL 2 */
+		.cpu_dai_name = "omap-dmic-abe-dai-2",
+		.platform_name = "aess",
+
+		/* DMIC 2 */
+		.codec_dai_name = "dmic-hifi",
+		.codec_name = "dmic-codec.2",
+		.ops = &sdp4430_dmic_ops,
+
+		.no_pcm = 1, /* don't create ALSA pcm for this */
+		.be_hw_params_fixup = dmic_be_hw_params_fixup,
+		.be_id = OMAP_ABE_DAI_DMIC2,
+	},
 };
 
 /* Audio machine driver */
 static struct snd_soc_card snd_soc_sdp4430 = {
 	.name = "SDP4430",
-	.dai_link = &sdp4430_dai,
-	.num_links = 1,
+	.dai_link = sdp4430_dai,
+	.num_links = ARRAY_SIZE(sdp4430_dai),
 };
 
 static struct platform_device *sdp4430_snd_device;
+struct i2c_adapter *adapter;
 
 static int __init sdp4430_soc_init(void)
 {
@@ -232,15 +824,15 @@
 		return -ENOMEM;
 	}
 
+	ret = snd_soc_register_dais(&sdp4430_snd_device->dev, dai, ARRAY_SIZE(dai));
+	if (ret < 0)
+		goto err;
 	platform_set_drvdata(sdp4430_snd_device, &snd_soc_sdp4430);
 
 	ret = platform_device_add(sdp4430_snd_device);
 	if (ret)
 		goto err;
 
-	/* Codec starts in HP mode */
-	twl6040_power_mode = 1;
-
 	return 0;
 
 err: