diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 95441bf..63eac69 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -13,6 +13,9 @@
  * 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.
+ *
+ * Ref: spruh77a, chapter "Multichannel Audio Serial Port (McASP)"
+ *
  */
 
 #include <linux/init.h>
@@ -188,6 +191,7 @@
 /*
  * DAVINCI_MCASP_ACLKXCTL_REG - Transmit Clock Control Register Bits
  */
+#define ACLKXDIV_MASK	0b11111
 #define ACLKXDIV(val)	(val)
 #define ACLKXE		BIT(5)
 #define TX_ASYNC	BIT(6)
@@ -291,36 +295,73 @@
 
 #define DAVINCI_MCASP_NUM_SERIALIZER	16
 
-static inline void mcasp_set_bits(void __iomem *reg, u32 val)
+/* HACK: Whether we are playing or recording, to manage clock generation */
+static int playing = 0;
+static int recording = 0;
+static void * base = NULL;
+
+#define stringify(x)  #x
+
+#define mcasp_set_bits(b, x, v) { \
+	pr_debug("%s: setting %s to %s\n", __func__, #x, #v); \
+	mcasp_set_bits2(b + x, v); }
+
+#define mcasp_clr_bits(b, x, v) { \
+	pr_debug("%s: clring %s to %s\n", __func__, #x, #v); \
+	mcasp_clr_bits2(b + x, v); }
+
+#define mcasp_mod_bits(b, x, v, m) { \
+	pr_debug("%s: modding %s with %s mask %s\n", __func__, #x, #v, #m); \
+	mcasp_mod_bits2(b + x, v, m); }
+
+#define mcasp_set_reg(b, x, v) { \
+	pr_debug("%s: setting %s to %s\n", __func__, #x, #v); \
+	mcasp_set_reg2(b + x, v); }
+
+#define mcasp_set_ctl_reg(b, x, v) { \
+	pr_debug("%s: setting %s to %s\n", __func__, #x, #v); \
+	mcasp_set_ctl_reg2(b + x, v); }
+
+static inline void mcasp_set_bits2(void __iomem *reg, u32 val)
 {
-	__raw_writel(__raw_readl(reg) | val, reg);
+	u32 v = __raw_readl(reg);
+	if ((v & val) != val) { // bits to set
+		pr_debug("%s: %04x %x -> %x\n", __func__, (reg-base), v, v|val);
+		__raw_writel(v | val, reg);
+	}
 }
 
-static inline void mcasp_clr_bits(void __iomem *reg, u32 val)
+static inline void mcasp_clr_bits2(void __iomem *reg, u32 val)
 {
-	__raw_writel((__raw_readl(reg) & ~(val)), reg);
+	u32 v = __raw_readl(reg);
+	if ((val & v) != 0) { // bits to clear
+		pr_debug("%s: %04x %x -> %x\n", __func__, (reg-base), v, v&(~val));
+		__raw_writel((v & ~(val)), reg);
+	}
 }
 
-static inline void mcasp_mod_bits(void __iomem *reg, u32 val, u32 mask)
+static inline void mcasp_mod_bits2(void __iomem *reg, u32 val, u32 mask)
 {
 	__raw_writel((__raw_readl(reg) & ~mask) | val, reg);
 }
 
-static inline void mcasp_set_reg(void __iomem *reg, u32 val)
+static inline void mcasp_set_reg2(void __iomem *reg, u32 val)
 {
 	__raw_writel(val, reg);
 }
 
 static inline u32 mcasp_get_reg(void __iomem *reg)
 {
-	return (unsigned int)__raw_readl(reg);
+	u32 v = __raw_readl(reg);
+	pr_debug("%s: %04x = %x\n", __func__, (reg-base), v);
+	return v;
 }
 
-static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
+static inline void mcasp_set_ctl_reg2(void __iomem *regs, u32 val)
 {
 	int i = 0;
 
-	mcasp_set_bits(regs, val);
+	mcasp_set_bits2(regs, val);
 
 	/* programming GBLCTL needs to read back from GBLCTL and verfiy */
 	/* loop count is to avoid the lock-up */
@@ -333,19 +374,94 @@ static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
 		printk(KERN_ERR "GBLCTL write error\n");
 }
 
-static void mcasp_start_rx(struct davinci_audio_dev *dev)
+
+static ssize_t mcasp_sysfs_report(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
 {
-	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
-	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
-	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
-	mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
+	char const * cmd;
+
+	struct davinci_audio_dev *adev;
+	adev = dev_get_drvdata(dev);
 
-	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
-	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
-	mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
+	cmd = "reg rxstat";
+	if (count >= strlen(cmd) && strcmp(buf, cmd) == 0) {
+		pr_info("%s: %s is %x\n",
+		 __func__,
+		 stringify(DAVINCI_MCASP_RXSTAT_REG),
+		 mcasp_get_reg(adev->base + DAVINCI_MCASP_RXSTAT_REG));
+	}
+	cmd = "reg txstat";
+	if (count >= strlen(cmd) && strcmp(buf, cmd) == 0) {
+		pr_info("%s: %s is %x\n",
+		 __func__,
+		 stringify(DAVINCI_MCASP_TXSTAT_REG),
+		 mcasp_get_reg(adev->base + DAVINCI_MCASP_TXSTAT_REG));
+	}
 
-	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
-	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
+	return count;
+}
+
+static DEVICE_ATTR(read, S_IWUSR, NULL, mcasp_sysfs_report);
+
+static struct attribute *mcasp_drv_attributes[] = {
+	&dev_attr_read.attr,
+	NULL
+};
+
+static const struct attribute_group mcasp_drv_attr_group = {
+	.attrs = mcasp_drv_attributes,
+};
+
+/* Transmit/Receive Section Initialization
+ *
+ * Done according to "Transmit/Receive Section Initialization"
+ * and "Register Bit Restrictions" in SPRUH77A.
+ *
+ */
+
+static void mcasp_start_tx(struct davinci_audio_dev *dev);
+
+static void mcasp_start_rx(struct davinci_audio_dev *dev)
+{
+	pr_debug("%s: starting rx\n", __func__);
+	
+	if (!playing) {
+		pr_debug("%s: also starting tx\n", __func__);
+		mcasp_start_tx(dev);
+	}
+
+	// 1)
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_GBLCTLR_REG, 0);
+	
+	// 2b)
+	if (dev->rxnumevt)	/* enable FIFO */
+		mcasp_set_bits(dev->base, DAVINCI_MCASP_RFIFOCTL,
+							FIFO_ENABLE);
+	
+	// 4)
+	mcasp_set_ctl_reg(dev->base, DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
+
+	// 5)
+	mcasp_set_ctl_reg(dev->base, DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
+
+	// 7)
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_RXSTAT_REG, 0xFFFF);
+	mcasp_set_ctl_reg(dev->base, DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
+
+	// TODO understand
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_RXBUF_REG, 0);
+
+	// 9)
+	mcasp_set_ctl_reg(dev->base, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
+
+	// 10)
+	mcasp_set_ctl_reg(dev->base, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
+
+	// TODO why a second time ?
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_RXBUF_REG, 0);
+	mcasp_set_ctl_reg(dev->base, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
+	mcasp_set_ctl_reg(dev->base, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
 }
 
 static void mcasp_start_tx(struct davinci_audio_dev *dev)
@@ -353,14 +469,40 @@ static void mcasp_start_tx(struct davinci_audio_dev *dev)
 	u8 offset = 0, i;
 	u32 cnt;
 
-	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
-	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
-	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
-	mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
+	if (recording) {
+		pr_debug("%s: recording already in progress, not performing\n",
+		 __func__);
+		//return;
+	}
+	pr_debug("%s: starting tx\n", __func__);
+	
+	// 1)
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_GBLCTLX_REG, 0);
+	
+	// 2a)
+	if (dev->txnumevt)	/* enable FIFO */
+		mcasp_set_bits(dev->base, DAVINCI_MCASP_WFIFOCTL,
+							FIFO_ENABLE);
+
+	// 4)
+	mcasp_set_ctl_reg(dev->base, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
+
+	// 5)
+	mcasp_set_ctl_reg(dev->base, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
+
+	// 7)
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_TXSTAT_REG, 0xFFFF);
+	mcasp_set_ctl_reg(dev->base, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
+
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_TXBUF_REG, 0);
 
-	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
-	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
-	mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
+	// 9)
+	mcasp_set_ctl_reg(dev->base, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
+
+	// 10)
+	mcasp_set_ctl_reg(dev->base, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
+
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_TXBUF_REG, 0);
 	for (i = 0; i < dev->num_serializer; i++) {
 		if (dev->serial_dir[i] == TX_MODE) {
 			offset = i;
@@ -373,48 +515,59 @@ static void mcasp_start_tx(struct davinci_audio_dev *dev)
 	while (!(mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(offset)) &
 		 TXSTATE) && (cnt < 100000))
 		cnt++;
+	
+	if (cnt == 100000) {
+		pr_err("%s: tx not ready!\n", __func__);
+	}
 
-	mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_TXBUF_REG, 0);
 }
 
 static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream)
 {
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		if (dev->txnumevt)	/* enable FIFO */
-			mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
-								FIFO_ENABLE);
 		mcasp_start_tx(dev);
+		playing = 1;
 	} else {
-		if (dev->rxnumevt)	/* enable FIFO */
-			mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
-								FIFO_ENABLE);
 		mcasp_start_rx(dev);
+		recording = 1;
 	}
 }
 
 static void mcasp_stop_rx(struct davinci_audio_dev *dev)
 {
-	mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0);
-	mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
+	recording = 0;
+	pr_debug("%s\n", __func__);
+	if (dev->rxnumevt)	/* disable FIFO */
+		mcasp_clr_bits(dev->base, DAVINCI_MCASP_RFIFOCTL,
+							FIFO_ENABLE);
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_GBLCTLR_REG, 0);
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_RXSTAT_REG, 0xFFFF);
+	if (!playing) {
+		pr_debug("%s: not playing, shutting down tx too\n", __func__);
+		mcasp_set_reg(dev->base, DAVINCI_MCASP_GBLCTLX_REG, 0);
+	}
 }
 
 static void mcasp_stop_tx(struct davinci_audio_dev *dev)
 {
-	mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0);
-	mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
+	playing = 0;
+	pr_debug("%s\n", __func__);
+	if (dev->txnumevt)	/* disable FIFO */
+		mcasp_clr_bits(dev->base, DAVINCI_MCASP_WFIFOCTL,
+							FIFO_ENABLE);
+	if (!recording) {
+		pr_debug("%s: not recording, shutting down\n", __func__);
+		mcasp_set_reg(dev->base, DAVINCI_MCASP_GBLCTLX_REG, 0);
+	}
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_TXSTAT_REG, 0xFFFF);
 }
 
 static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream)
 {
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		if (dev->txnumevt)	/* disable FIFO */
-			mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
-								FIFO_ENABLE);
 		mcasp_stop_tx(dev);
 	} else {
-		if (dev->rxnumevt)	/* disable FIFO */
-			mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
-								FIFO_ENABLE);
 		mcasp_stop_rx(dev);
 	}
 }
@@ -428,39 +581,54 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBS_CFS:
 		/* codec is clock and frame slave */
-		mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
-		mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+		mcasp_set_bits(base, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+		mcasp_set_bits(base, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
 
-		mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
-		mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
+		mcasp_set_bits(base, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+		mcasp_set_bits(base, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-		mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
+		mcasp_set_bits(base, DAVINCI_MCASP_PDIR_REG,
 				ACLKX | AHCLKX | AFSX);
 		break;
 	case SND_SOC_DAIFMT_CBM_CFS:
 		/* codec is clock master and frame slave */
-		mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
-		mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+		mcasp_clr_bits(base, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+		mcasp_set_bits(base, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
 
-		mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
-		mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
+		mcasp_clr_bits(base, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+		mcasp_set_bits(base, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-		mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG,
+		mcasp_clr_bits(base, DAVINCI_MCASP_PDIR_REG,
 				ACLKX | ACLKR);
-		mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
+		mcasp_set_bits(base, DAVINCI_MCASP_PDIR_REG,
 				AFSX | AFSR);
 		break;
 	case SND_SOC_DAIFMT_CBM_CFM:
 		/* codec is clock and frame master */
-		mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
-		mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+		mcasp_clr_bits(base, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+		mcasp_clr_bits(base, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
 
-		mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
-		mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
+		mcasp_clr_bits(base, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+		mcasp_clr_bits(base, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-		mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG,
+		mcasp_clr_bits(base, DAVINCI_MCASP_PDIR_REG,
 				ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR);
 		break;
+	
+	case SND_SOC_DAIFMT_EM_CBS_CFS:
+		/* external master clock, cpu generates bit and frame clocks */
+		mcasp_clr_bits(base, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
+		mcasp_set_bits(base, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+		mcasp_set_bits(base, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
+		
+		mcasp_clr_bits(base, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+		mcasp_set_bits(base, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+		mcasp_set_bits(base, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+
+		mcasp_clr_bits(base, DAVINCI_MCASP_PDIR_REG, AHCLKX | AHCLKR);
+		mcasp_set_bits(base, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
+		mcasp_set_bits(base, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
+		break;
 
 	default:
 		return -EINVAL;
@@ -468,35 +636,35 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 
 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 	case SND_SOC_DAIFMT_IB_NF:
-		mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-		mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+		mcasp_clr_bits(base, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+		mcasp_clr_bits(base, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
 
-		mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-		mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+		mcasp_set_bits(base, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+		mcasp_clr_bits(base, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
 		break;
 
 	case SND_SOC_DAIFMT_NB_IF:
-		mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-		mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+		mcasp_set_bits(base, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+		mcasp_set_bits(base, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
 
-		mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-		mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+		mcasp_clr_bits(base, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+		mcasp_set_bits(base, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
 		break;
 
 	case SND_SOC_DAIFMT_IB_IF:
-		mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-		mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+		mcasp_clr_bits(base, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+		mcasp_set_bits(base, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
 
-		mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-		mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+		mcasp_set_bits(base, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+		mcasp_set_bits(base, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
 		break;
 
 	case SND_SOC_DAIFMT_NB_NF:
-		mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-		mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+		mcasp_set_bits(base, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+		mcasp_clr_bits(base, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
 
-		mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-		mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+		mcasp_clr_bits(base, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+		mcasp_clr_bits(base, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
 		break;
 
 	default:
@@ -559,16 +727,16 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev,
 		return -EINVAL;
 	}
 
-	mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
+	mcasp_mod_bits(dev->base, DAVINCI_MCASP_RXFMT_REG,
 					RXSSZ(fmt), RXSSZ(0x0F));
-	mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
+	mcasp_mod_bits(dev->base, DAVINCI_MCASP_TXFMT_REG,
 					TXSSZ(fmt), TXSSZ(0x0F));
-	mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXROT(rotate),
+	mcasp_mod_bits(dev->base, DAVINCI_MCASP_TXFMT_REG, TXROT(rotate),
 							TXROT(7));
-	mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXROT(rotate),
+	mcasp_mod_bits(dev->base, DAVINCI_MCASP_RXFMT_REG, RXROT(rotate),
 							RXROT(7));
-	mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask);
-	mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, mask);
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_TXMASK_REG, mask);
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_RXMASK_REG, mask);
 
 	return 0;
 }
@@ -580,30 +748,30 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
 	u8 rx_ser = 0;
 
 	/* Default configuration */
-	mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
+	mcasp_set_bits(dev->base, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
 
 	/* All PINS as McASP */
-	mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, 0x00000000);
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_PFUNC_REG, 0x00000000);
 
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
-		mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG,
+		mcasp_set_reg(dev->base, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
+		mcasp_clr_bits(dev->base, DAVINCI_MCASP_XEVTCTL_REG,
 				TXDATADMADIS);
 	} else {
-		mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
-		mcasp_clr_bits(dev->base + DAVINCI_MCASP_REVTCTL_REG,
+		mcasp_set_reg(dev->base, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
+		mcasp_clr_bits(dev->base, DAVINCI_MCASP_REVTCTL_REG,
 				RXDATADMADIS);
 	}
 
 	for (i = 0; i < dev->num_serializer; i++) {
-		mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
+		mcasp_set_bits(dev->base, DAVINCI_MCASP_XRSRCTL_REG(i),
 					dev->serial_dir[i]);
 		if (dev->serial_dir[i] == TX_MODE) {
-			mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
+			mcasp_set_bits(dev->base, DAVINCI_MCASP_PDIR_REG,
 					AXR(i));
 			tx_ser++;
 		} else if (dev->serial_dir[i] == RX_MODE) {
-			mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
+			mcasp_clr_bits(dev->base, DAVINCI_MCASP_PDIR_REG,
 					AXR(i));
 			rx_ser++;
 		}
@@ -613,9 +781,9 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
 		if (dev->txnumevt * tx_ser > 64)
 			dev->txnumevt = 1;
 
-		mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, tx_ser,
+		mcasp_mod_bits(dev->base, DAVINCI_MCASP_WFIFOCTL, tx_ser,
 								NUMDMA_MASK);
-		mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
+		mcasp_mod_bits(dev->base, DAVINCI_MCASP_WFIFOCTL,
 				((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK);
 	}
 
@@ -623,9 +791,9 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
 		if (dev->rxnumevt * rx_ser > 64)
 			dev->rxnumevt = 1;
 
-		mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, rx_ser,
+		mcasp_mod_bits(dev->base, DAVINCI_MCASP_RFIFOCTL, rx_ser,
 								NUMDMA_MASK);
-		mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
+		mcasp_mod_bits(dev->base, DAVINCI_MCASP_RFIFOCTL,
 				((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
 	}
 }
@@ -639,40 +807,59 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
 	for (i = 0; i < active_slots; i++)
 		mask |= (1 << i);
 
-	mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
+	/* Synchronous Transmit and Receive Operation */
+	mcasp_clr_bits(dev->base, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
+
+	/* HACK: set clock divider, no support for frequencies != 32k
+	 *
+	 * We want 32kHz FCLK with 32bits (left, right) transferred for
+	 * every frame, so it makes a 1.024MHz BCLK (/8).
+	 */
+	mcasp_mod_bits(dev->base, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXDIV(8-1),
+	 ACLKXDIV_MASK);
 
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		/* bit stream is MSB first  with no delay */
+		/* bit stream is MSB first with no delay */
 		/* DSP_B mode */
-		mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
+		/* HACK: disable master transmit clock generation
+		mcasp_set_bits(dev->base, DAVINCI_MCASP_AHCLKXCTL_REG,
 				AHCLKXE);
-		mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
-		mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
+		*/
+		mcasp_set_reg(dev->base, DAVINCI_MCASP_TXTDM_REG, mask);
+		mcasp_set_bits(dev->base, DAVINCI_MCASP_TXFMT_REG, TXORD);
 
-		if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
-			mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
+		if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32)) {
+			mcasp_mod_bits(dev->base, DAVINCI_MCASP_TXFMCTL_REG,
 					FSXMOD(dev->tdm_slots), FSXMOD(0x1FF));
-		else
+		}
+		else {
 			printk(KERN_ERR "playback tdm slot %d not supported\n",
 				dev->tdm_slots);
+		}
+
+		mcasp_clr_bits(dev->base, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
 
-		mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
 	} else {
 		/* bit stream is MSB first with no delay */
 		/* DSP_B mode */
-		mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
-		mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
+		/* HACK: disable master receive clock generation
+		mcasp_set_bits(dev->base, DAVINCI_MCASP_AHCLKRCTL_REG,
 				AHCLKRE);
-		mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);
+		*/
+		mcasp_set_reg(dev->base, DAVINCI_MCASP_RXTDM_REG, mask);
+		mcasp_set_bits(dev->base, DAVINCI_MCASP_RXFMT_REG, RXORD);
 
-		if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
-			mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
+		if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32)) {
+			mcasp_mod_bits(dev->base, DAVINCI_MCASP_RXFMCTL_REG,
 					FSRMOD(dev->tdm_slots), FSRMOD(0x1FF));
-		else
+		}
+		else {
 			printk(KERN_ERR "capture tdm slot %d not supported\n",
 				dev->tdm_slots);
+		}
+
+		mcasp_clr_bits(dev->base, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
 
-		mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
 	}
 }
 
@@ -680,34 +867,34 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
 static void davinci_hw_dit_param(struct davinci_audio_dev *dev)
 {
 	/* Set the PDIR for Serialiser as output */
-	mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AFSX);
+	mcasp_set_bits(dev->base, DAVINCI_MCASP_PDIR_REG, AFSX);
 
 	/* TXMASK for 24 bits */
-	mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0x00FFFFFF);
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_TXMASK_REG, 0x00FFFFFF);
 
 	/* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
 	   and LSB first */
-	mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
+	mcasp_set_bits(dev->base, DAVINCI_MCASP_TXFMT_REG,
 						TXROT(6) | TXSSZ(15));
 
 	/* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */
-	mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_TXFMCTL_REG,
 						AFSXE | FSXMOD(0x180));
 
 	/* Set the TX tdm : for all the slots */
-	mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF);
+	mcasp_set_reg(dev->base, DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF);
 
 	/* Set the TX clock controls : div = 1 and internal */
-	mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
+	mcasp_set_bits(dev->base, DAVINCI_MCASP_ACLKXCTL_REG,
 						ACLKXE | TX_ASYNC);
 
-	mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
+	mcasp_clr_bits(dev->base, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
 
 	/* Only 44100 and 48000 are valid, both have the same setting */
-	mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3));
+	mcasp_set_bits(dev->base, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3));
 
 	/* Enable the DIT */
-	mcasp_set_bits(dev->base + DAVINCI_MCASP_TXDITCTL_REG, DITEN);
+	mcasp_set_bits(dev->base, DAVINCI_MCASP_TXDITCTL_REG, DITEN);
 }
 
 static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
@@ -719,8 +906,14 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
 					&dev->dma_params[substream->stream];
 	int word_length;
 	u8 fifo_level;
+	
+	pr_debug("-> %s %p %s(%d)\n", __func__, substream,
+	 current->comm, current->pid);
 
 	davinci_hw_common_param(dev, substream->stream);
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && !playing)
+		davinci_hw_common_param(dev, SNDRV_PCM_STREAM_PLAYBACK);
+
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		fifo_level = dev->txnumevt;
 	else
@@ -728,8 +921,11 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
 
 	if (dev->op_mode == DAVINCI_MCASP_DIT_MODE)
 		davinci_hw_dit_param(dev);
-	else
+	else {
 		davinci_hw_param(dev, substream->stream);
+		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && !playing)
+			davinci_hw_param(dev, SNDRV_PCM_STREAM_PLAYBACK);
+	}
 
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_U8:
@@ -763,6 +959,9 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
 	dma_params->fifo_level = fifo_level;
 	davinci_config_channel_size(dev, word_length);
 
+	pr_debug("<- %s %p %s(%d)\n", __func__, substream,
+	 current->comm, current->pid);
+
 	return 0;
 }
 
@@ -772,6 +971,9 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
 	struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
 	int ret = 0;
 
+	pr_debug("-> %s %p %d %s(%d)\n", __func__, substream, cmd,
+	 current->comm, current->pid);
+
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_START:
@@ -800,6 +1002,9 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
 	default:
 		ret = -EINVAL;
 	}
+	
+	pr_debug("<- %s %p %d %s(%d) %d\n", __func__, substream, cmd,
+	 current->comm, current->pid, ret);
 
 	return ret;
 }
@@ -808,8 +1013,15 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
 				 struct snd_soc_dai *dai)
 {
 	struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
+	
+	pr_debug("-> %s %p %s(%d)\n", __func__, substream,
+	 current->comm, current->pid);
 
 	snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
+	
+	pr_debug("<- %s %p %s(%d) %d\n", __func__, substream,
+	 current->comm, current->pid, 0);
+
 	return 0;
 }
 
@@ -899,6 +1111,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 		ret = -ENOMEM;
 		goto err_release_clk;
 	}
+	base = dev->base;
 
 	dev->op_mode = pdata->op_mode;
 	dev->tdm_slots = pdata->tdm_slots;
@@ -943,6 +1156,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 	dma_data->channel = res->start;
 	dev_set_drvdata(&pdev->dev, dev);
 	ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]);
+	
+	ret = sysfs_create_group(&pdev->dev.kobj, &mcasp_drv_attr_group);
 
 	if (ret != 0)
 		goto err_release_clk;
@@ -958,6 +1173,8 @@ static int davinci_mcasp_remove(struct platform_device *pdev)
 {
 	struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev);
 
+	sysfs_remove_group(&pdev->dev.kobj, &mcasp_drv_attr_group);
+
 	snd_soc_unregister_dai(&pdev->dev);
 	clk_disable(dev->clk);
 	clk_put(dev->clk);
