Patch submitted again.

Fixed a lot of coding style problems, debugging information now using "pr_debug()"
and problem of freeing both dma's when closing pcm.

Signed-off-by: Javier Martin <javier.martin@vista-silicon.com>

diff --git a/sound/soc/imx/imx27-pcm.c b/sound/soc/imx/imx27-pcm.c
new file mode 100644
index 0000000..ea00983
--- /dev/null
+++ b/sound/soc/imx/imx27-pcm.c
@@ -0,0 +1,555 @@
+/*
+ * linux/sound/arm/mx27-pcm.c -- ALSA SoC interface for the Freescale i.MX27 CPU
+ *
+ * Copyright 2009 Vista Silicon S.L.
+ * Author: Javier Martin
+ *         javier.martin@vista-silicon.com
+ *
+ * Based on mxc-pcm.c by	Liam Girdwood, (C) 2006 Wolfson Microelectronics PLC.
+ * and on mxc-alsa-mc13783 (C) 2006 Freescale.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <asm/dma.h>
+#include <asm/hardware.h>
+
+#include "imx27-pcm.h"
+
+/* Just for debugging */
+#include "imx27-ssi.h"
+
+/* Taken from drivers/mxc/ssi/registers.h just provisionally */
+#define    MXC_SSI1STX0		0x00
+#define    MXC_SSI1SRX0		0x08
+#define    MXC_SSI2STX0		0x00
+#define    MXC_SSI2SRX0		0x08
+
+static const struct snd_pcm_hardware mx27_pcm_hardware = {
+	.info			= (SNDRV_PCM_INFO_INTERLEAVED |
+				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				   SNDRV_PCM_INFO_MMAP |
+				   SNDRV_PCM_INFO_MMAP_VALID),
+	.formats		= SNDRV_PCM_FMTBIT_S16_LE,
+	.buffer_bytes_max	= 32 * 1024,
+	.period_bytes_min	= 64,
+	.period_bytes_max	= 8 * 1024,
+	.periods_min		= 2,
+	.periods_max		= 255,
+	.fifo_size		= 0,
+};
+
+struct mx27_runtime_data {
+	int dma_ch_tx; //DMA channel number for tx
+	int dma_ch_rx; //DMA channel number for rx
+	int active; //Is the stream active?
+	unsigned int period; //Period number
+	unsigned int periods; //¿?
+	int tx_spin; //¿?
+	spinlock_t dma_lock; //DMA spinlock
+	struct mx27_pcm_dma_param *dma_params; //FIXME this is SDMA api
+};
+
+/**
+  * This function stops the current dma transfer for playback
+  * and clears the dma pointers.
+  *
+  * @param	substream	pointer to the structure of the current stream.
+  *
+  */
+static int audio_stop_dma(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct mx27_runtime_data *prtd = runtime->private_data;
+	unsigned int dma_size = frames_to_bytes(runtime, runtime->period_size);
+	unsigned int offset  = dma_size * prtd->periods;
+	unsigned long flags;
+
+	spin_lock_irqsave(&prtd->dma_lock, flags);
+
+	pr_debug("MX27 : audio_stop_dma active = 0\n");
+
+	prtd->active = 0;
+	prtd->period = 0;
+	prtd->periods = 0;
+
+	/* this stops the dma channel and clears the buffer ptrs */
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (mxc_dma_disable(prtd->dma_ch_tx) < 0)
+			printk(KERN_ERR "audio_stop_dma: error when stopping dma transfer in channel %d \n",
+				prtd->dma_ch_tx);
+	} else {
+		if (mxc_dma_disable(prtd->dma_ch_rx) < 0)
+			printk(KERN_ERR "audio_stop_dma: error when stopping dma transfer in channel %d \n",
+				prtd->dma_ch_rx);
+	}
+	spin_unlock_irqrestore(&prtd->dma_lock, flags);
+
+	return 0;
+}
+
+/**
+  * This function is called whenever a new audio block needs to be
+  * transferred to the codec. The function receives the address and the size
+  * of the new block and start a new DMA transfer.
+  *
+  * @param	substream	pointer to the structure of the current stream.
+  *
+  */
+static int dma_new_period(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime =  substream->runtime;
+	struct mx27_runtime_data *prtd = runtime->private_data;
+	unsigned int dma_size;
+	unsigned int offset;
+	int ret = 0;
+	mxc_dma_requestbuf_t dma_request;
+
+
+	if (prtd->active) {
+		memset(&dma_request, 0, sizeof(mxc_dma_requestbuf_t));;
+		dma_size = frames_to_bytes(runtime, runtime->period_size);
+
+		pr_debug("dma_new_period: prtd->period (%x) runtime->periods (%d)\n",
+			prtd->period, runtime->periods);
+		pr_debug("dma_new_period: runtime->period_size (%d) dma_size (%d)\n",
+			(unsigned int)runtime->period_size,
+			runtime->dma_bytes);
+
+		offset = dma_size * prtd->period;
+		snd_assert(dma_size <= mx27_pcm_hardware.period_bytes_max);
+
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			pr_debug("\ndma_new_period (playback): runtime->dma_area = %x\noffset = %x\ndma_size = %x\n",
+				runtime->dma_area, offset, dma_size);
+			pr_debug("\ndma_new_period : dma_addr is %x\n",
+				 (runtime->dma_addr + offset));
+
+			dma_request.src_addr = (dma_addr_t)(runtime->dma_addr + offset);
+#ifdef CONFIG_SND_SOC_MX27_SSI1
+
+			dma_request.dst_addr = (dma_addr_t) (SSI1_BASE_ADDR + MXC_SSI1STX0);
+
+			pr_debug("dst_addr is %x\n", dma_request.dst_addr);
+			pr_debug("src_addr is %x\n", dma_request.src_addr);
+#else
+			dma_request.dst_addr =
+			    (dma_addr_t) (SSI2_BASE_ADDR + MXC_SSI2STX0);
+#endif
+		} else {
+			pr_debug("\ndma_new_period (capture): runtime->dma_area = %x\noffset = %x\ndma_size = %x\n",
+				runtime->dma_area, offset, dma_size);
+			pr_debug("\ndma_new_period: dma_addr is %x\n",
+				(runtime->dma_addr + offset));
+
+			dma_request.dst_addr = (dma_addr_t) (runtime->dma_addr + offset);
+#ifdef CONFIG_SND_SOC_MX27_SSI1
+			dma_request.src_addr =
+			    (dma_addr_t) (SSI1_BASE_ADDR + MXC_SSI1SRX0);
+#else
+			dma_request.src_addr =
+			    (dma_addr_t) (SSI2_BASE_ADDR + MXC_SSI2SRX0);
+#endif
+		}
+
+		dma_request.num_of_bytes = dma_size;
+		pr_debug("dma_new_period: Start DMA offset (%d) size (%d)\n",
+			 offset, runtime->dma_bytes);
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			pr_debug("dma_new_period: configuring tx dma\n");
+			ret = mxc_dma_config(prtd->dma_ch_tx, &dma_request, 1,
+				MXC_DMA_MODE_WRITE);
+			if (ret < 0) {
+				printk("dma_new_period: buffer could not be added for playback transfer\n");
+				return ret;
+			}
+
+			pr_debug("dma_new_period: enable  tx dma transfer\n");
+			ret = mxc_dma_enable(prtd->dma_ch_tx);
+			if (ret < 0) {
+				printk("dma_new_period: cannot queue DMA buffer\
+							(%i)\n", ret);
+				return ret;
+			}
+		} else {
+			ret = mxc_dma_config(prtd->dma_ch_rx, &dma_request, 1, MXC_DMA_MODE_READ);
+			if (ret < 0) {
+				printk("dma_new_period: buffer could not be added for capture transfer\n");
+				return ret;
+			}
+
+			pr_debug("dma_new_period: enable  dma transfer\n");
+			ret = mxc_dma_enable(prtd->dma_ch_rx);
+			if(ret<0) {
+				printk("dma_new_period: cannot queue DMA buffer\
+							(%i)\n", ret);
+				return ret;
+			}
+		}
+
+		pr_debug("dma_new_period: transfer enabled\n src_addr = %x\n dst_addr = %x\n num_of_byes = %d\n", (void *) dma_request.src_addr, (void *) dma_request.dst_addr, dma_request.num_of_bytes);
+
+		prtd->tx_spin = 1; /* FGA little trick to retrieve DMA pos */
+		prtd->period++;
+		prtd->period %= runtime->periods;
+    }
+	return ret;
+}
+
+
+/**
+  * This is a callback which will be called
+  * when a TX transfer finishes. The call occurs
+  * in interrupt context.
+  *
+  * @param	dat	pointer to the structure of the current stream.
+  *
+  */
+static void audio_dma_irq(void *data, int error, unsigned int count)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_pcm_runtime *runtime;
+	struct mx27_runtime_data *prtd;
+	unsigned int dma_size;
+	unsigned int previous_period;
+	unsigned int offset;
+
+	substream = data;
+	runtime = substream->runtime;
+	prtd = runtime->private_data;
+	previous_period  = prtd->periods;
+	dma_size = frames_to_bytes(runtime, runtime->period_size);
+	offset = dma_size * previous_period;
+
+	prtd->tx_spin = 0;
+	prtd->periods++;
+	prtd->periods %= runtime->periods;
+
+	pr_debug("audio_dma_irq: irq per %d offset %x\n", prtd->periods, offset);
+
+	/*
+	  * If we are getting a callback for an active stream then we inform
+	  * the PCM middle layer we've finished a period
+	  */
+ 	if (prtd->active)
+		snd_pcm_period_elapsed(substream);
+
+	/*
+	  * Trig next DMA transfer
+	  */
+	dma_new_period(substream);
+}
+
+/**
+  * This function configures the hardware to allow audio
+  * playback operations. It is called by ALSA framework.
+  *
+  * @param	substream	pointer to the structure of the current stream.
+  *
+  * @return              0 on success, -1 otherwise.
+  */
+static int
+snd_mxc_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime =  substream->runtime;
+	struct mx27_runtime_data *prtd = runtime->private_data;
+
+	prtd->period = 0;
+	prtd->periods = 0;
+
+	return 0;
+}
+
+static int mxc_pcm_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *hw_params)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct mx27_runtime_data *prtd = runtime->private_data;
+	int ret;
+
+	if((ret=snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
+	{
+		printk("imx27-pcm: failed to malloc pcm pages\n");
+		return ret;
+	}
+
+	pr_debug("mxc_pcm_hw_params: snd_pcm_lib_malloc pages has return OK\n");
+	pr_debug("IMX27: snd_imx27_audio_hw_params runtime->dma_addr 0x(%x)\n",
+		 (unsigned int)runtime->dma_addr);
+	pr_debug("IMX27: snd_imx27_audio_hw_params runtime->dma_area 0x(%x)\n",
+		 (unsigned int)runtime->dma_area);
+	pr_debug("IMX27: snd_imx27_audio_hw_params runtime->dma_bytes 0x(%x)\n",
+		 (unsigned int)runtime->dma_bytes);
+
+	return ret;
+}
+
+static int mxc_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct mx27_runtime_data *prtd = runtime->private_data;
+	
+
+	if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		mxc_dma_free(prtd->dma_ch_tx);
+	else
+		mxc_dma_free(prtd->dma_ch_rx);
+
+	snd_pcm_lib_free_pages(substream);
+
+	return 0;
+}
+
+static int mxc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct mx27_runtime_data *prtd = substream->runtime->private_data;
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		prtd->tx_spin = 0;
+		/* requested stream startup */
+		prtd->active = 1;
+		pr_debug("mxc_pcm_trigger: starting dma_new_period\n");
+        	ret = dma_new_period(substream);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		/* requested stream shutdown */
+		pr_debug("mxc_pcm_trigger: stopping dma transfer\n");
+		ret = audio_stop_dma(substream);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static snd_pcm_uframes_t mxc_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct mx27_runtime_data *prtd = runtime->private_data;
+	unsigned int offset = 0;
+
+	pr_debug("mxc_pcm_pointer:\n runtime->period_size=%d\n prtd->periods=%d\n runtime->buffer_size=%d\n prtd->tx_spin=%d\n",
+		runtime->period_size, prtd->periods, runtime->buffer_size, prtd->tx_spin);
+	/* tx_spin value is used here to check if a transfer is active */
+	if (prtd->tx_spin){
+		offset = (runtime->period_size * (prtd->periods)) +
+						(runtime->period_size >> 1);
+		if (offset >= runtime->buffer_size)
+			offset = runtime->period_size >> 1;
+	} else {
+		offset = (runtime->period_size * (prtd->periods));
+		if (offset >= runtime->buffer_size)
+			offset = 0;
+	}
+	pr_debug("mxc_pcm_pointer: pointer offset %x\n", offset);
+	
+	return offset;
+}
+
+//Alocation of substream->runtime->private_data
+static int mxc_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct mx27_runtime_data *prtd;
+	int ret;
+
+	snd_soc_set_runtime_hwparams(substream, &mx27_pcm_hardware);
+
+	if ((ret = snd_pcm_hw_constraint_integer(runtime,
+					SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+		return ret;
+
+	if ((prtd = kzalloc(sizeof(struct mx27_runtime_data), GFP_KERNEL)) == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	runtime->private_data = prtd;
+
+	if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+	{
+		
+#ifdef CONFIG_SND_SOC_MX27_SSI1
+		pr_debug("mxc_pcm_open: Requesting MXC_DMA_SSI1_16BIT_TX0 dma channel\n");
+		prtd->dma_ch_tx  = mxc_dma_request(MXC_DMA_SSI1_16BIT_TX0, "ALSA TX DMA");
+#else
+		prtd->dma_ch_tx = mxc_dma_request(MXC_DMA_SSI2_16BIT_TX0, "ALSA TX DMA");
+#endif
+		if(prtd->dma_ch_tx < 0)
+		{ 
+			printk("error requesting a write(dma to device) dma channel\n");
+			return ret;
+		}
+
+		/* Set dma callback */
+		pr_debug("mxc_pcm_open: Setting tx dma callback function\n");
+		ret = mxc_dma_callback_set(prtd->dma_ch_tx, (mxc_dma_callback_t) audio_dma_irq, (void *)substream);
+		if(ret < 0) {
+			printk("error setting dma callback function\n");
+			return ret;
+		}
+
+		return 0;
+	} else {
+#ifdef CONFIG_SND_SOC_MX27_SSI1
+		pr_debug("mxc_pcm_open: Requesting MXC_DMA_SSI1_16BIT_RX0 dma channel\n");
+		prtd->dma_ch_rx  = mxc_dma_request(MXC_DMA_SSI1_16BIT_RX0, "ALSA RX DMA");
+#else
+		prtd->dma_ch_rx = mxc_dma_request(MXC_DMA_SSI2_16BIT_RX0, "ALSA RX DMA");
+#endif
+		if (prtd->dma_ch_rx < 0) { 
+			printk("error requesting a read(dma from device) dma channel\n");
+			return ret;
+		}
+
+		//Set dma callback
+		pr_debug("mxc_pcm_open: Setting rx dma callback function\n");
+		if (mxc_dma_callback_set(prtd->dma_ch_rx, (mxc_dma_callback_t) audio_dma_irq, (void *)substream)<0)
+			printk("error setting dma callback function\n");
+
+		return 0;
+	}
+
+
+
+ out:
+	return ret;
+}
+
+static int mxc_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct mxc_runtime_data *prtd = runtime->private_data;
+
+	kfree(prtd);
+
+	return 0;
+}
+
+static int
+mxc_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);
+}
+
+struct snd_pcm_ops mxc_pcm_ops = {
+	.open		= mxc_pcm_open,
+	.close		= mxc_pcm_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= mxc_pcm_hw_params,
+	.hw_free	= mxc_pcm_hw_free,
+	.prepare	= snd_mxc_prepare,
+	.trigger	= mxc_pcm_trigger,
+	.pointer	= mxc_pcm_pointer,
+	.mmap		= mxc_pcm_mmap,
+};
+
+static u64 mxc_pcm_dmamask = 0xffffffff;
+
+static int imx31_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 = mx27_pcm_hardware.buffer_bytes_max;
+	buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	buf->dev.dev = pcm->card->dev;
+	buf->private_data = NULL;
+
+	//Reserve uncached-buffered memory area for DMA
+	buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+					   &buf->addr, GFP_KERNEL);
+
+	pr_debug("imx27_pcm: preallocate_dma_buffer: area=%p, addr=%p, size=%d\n", (void *) buf->area, (void *) buf->addr, size);
+
+	if (!buf->area)
+		return -ENOMEM;
+		
+	buf->bytes = size;
+	return 0;
+}
+
+static void imx31_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;
+	}
+}
+
+int mxc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
+	struct snd_pcm *pcm)
+{
+	int ret = 0;
+
+	if (!card->dev->dma_mask)
+		card->dev->dma_mask = &mxc_pcm_dmamask;
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = 0xffffffff;
+
+	if (dai->playback.channels_min) {
+		ret = imx31_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_PLAYBACK);
+		printk("mxc_pcm_new: preallocate playback buffer\n");
+		if (ret)
+			goto out;
+	}
+
+	if (dai->capture.channels_min) {
+		ret = imx31_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_CAPTURE);
+		printk("mxc_pcm_new: preallocate capture buffer\n");
+		if (ret)
+			goto out;
+	}
+ out:
+	return ret;
+}
+
+struct snd_soc_platform imx27_soc_platform = {
+	.name		= "mxc-audio",
+	.pcm_ops 	= &mxc_pcm_ops,
+	.pcm_new	= mxc_pcm_new,
+	.pcm_free	= imx31_pcm_free_dma_buffers,
+};
+
+EXPORT_SYMBOL_GPL(imx27_soc_platform);
+
+MODULE_AUTHOR("Javier Martin");
+MODULE_DESCRIPTION("Freescale i.MX27 PCM DMA module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/imx/imx27-pcm.h b/sound/soc/imx/imx27-pcm.h
new file mode 100644
index 0000000..9852cff
--- /dev/null
+++ b/sound/soc/imx/imx27-pcm.h
@@ -0,0 +1,97 @@
+/*
+ * mxc-pcm.h :- ASoC platform header for Freescale i.MX
+ *
+ * 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 _MXC_PCM_H
+#define _MXC_PCM_H
+
+#include <asm/arch/dma.h>
+
+/* AUDMUX regs definition - MOVE to asm/arch when stable 
+#define AUDMUX_IO_BASE_ADDR	IO_ADDRESS(AUDMUX_BASE_ADDR)
+
+#define DAM_PTCR1	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x00)))
+#define DAM_PDCR1	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x04)))
+#define DAM_PTCR2	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x08)))
+#define DAM_PDCR2	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x0C)))
+#define DAM_PTCR3	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x10)))
+#define DAM_PDCR3	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x14)))
+#define DAM_PTCR4	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x18)))
+#define DAM_PDCR4	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x1C)))
+#define DAM_PTCR5	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x20)))
+#define DAM_PDCR5	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x24)))
+#define DAM_PTCR6	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x28)))
+#define DAM_PDCR6	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x2C)))
+#define DAM_PTCR7	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x30)))
+#define DAM_PDCR7	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x34)))
+#define DAM_CNMCR	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x38)))
+#define DAM_PTCR(a)	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + a*8)))
+#define DAM_PDCR(a)	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 4 + a*8)))
+
+
+#define AUDMUX_PTCR_TFSDIR		(1 << 31)
+#define AUDMUX_PTCR_TFSSEL(x, y)		((x << 30) | (((y - 1) & 0x7) << 27))
+#define AUDMUX_PTCR_TCLKDIR		(1 << 26)
+#define AUDMUX_PTCR_TCSEL(x, y)		((x << 25) | (((y - 1) & 0x7) << 22))
+#define AUDMUX_PTCR_RFSDIR		(1 << 21)
+#define AUDMUX_PTCR_RFSSEL(x, y)		((x << 20) | (((y - 1) & 0x7) << 17))
+#define AUDMUX_PTCR_RCLKDIR		(1 << 16)
+#define AUDMUX_PTCR_RCSEL(x, y)		((x << 15) | (((y - 1) & 0x7) << 12))
+#define AUDMUX_PTCR_SYN		(1 << 11)
+
+#define AUDMUX_FROM_TXFS	0
+#define AUDMUX_FROM_RXFS	1
+
+#define AUDMUX_PDCR_RXDSEL(x)		(((x - 1) & 0x7) << 13)
+#define AUDMUX_PDCR_TXDXEN		(1 << 12)
+#define AUDMUX_PDCR_MODE(x)		(((x) & 0x3) << 8)
+#define AUDMUX_PDCR_INNMASK(x)		(((x) & 0xff) << 0)
+
+#define AUDMUX_CNMCR_CEN		(1 << 18)
+#define AUDMUX_CNMCR_FSPOL		(1 << 17)
+#define AUDMUX_CNMCR_CLKPOL		(1 << 16)
+#define AUDMUX_CNMCR_CNTHI(x)		(((x) & 0xff) << 8)
+#define AUDMUX_CNMCR_CNTLOW(x)		(((x) & 0xff) << 0)
+*/
+
+/* Previous defines are only valid for imx31 */
+#define AUDMUX_IO_BASE_ADDR	IO_ADDRESS(AUDMUX_BASE_ADDR)
+
+#define DAM_HPCR1	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x00)))
+#define DAM_HPCR2	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x04)))
+#define DAM_HPCR3	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x08)))
+#define DAM_PPCR1	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x10)))
+#define DAM_PPCR2	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x14)))
+#define DAM_PPCR3	(*((volatile u32 *)(AUDMUX_IO_BASE_ADDR + 0x1C)))
+
+#define AUDMUX_HPCR_TFSDIR	(1 << 31)
+#define AUDMUX_HPCR_TCLKDIR	(1 << 30)
+#define AUDMUX_HPCR_TFCSEL(x)	(((x) & 0xff) << 26)
+#define AUDMUX_HPCR_RXDSEL(x)	(((x) & 0x7) << 13)
+#define AUDMUX_HPCR_SYN		(1 << 12)
+
+#define AUDMUX_PPCR_TFSDIR	(1 << 31)
+#define AUDMUX_PPCR_TCLKDIR	(1 << 30)
+#define AUDMUX_PPCR_TFCSEL(x)	(((x) & 0xff) << 26)
+#define AUDMUX_PPCR_RXDSEL(x)	(((x) & 0x7) << 13)
+#define AUDMUX_PPCR_SYN		(1 << 12)
+
+
+
+struct mx27_pcm_dma_params {
+	char *name;			/* stream identifier */
+	mxc_dma_requestbuf_t buf_params; /*DMA buffer params */
+
+};
+
+extern struct snd_soc_dai mxc_ssi_dai[3];
+
+/* platform data */
+extern struct snd_soc_platform imx27_soc_platform;
+
+
+#endif
