--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -42,10 +42,20 @@ config SND_S3C24XX_SOC_JIVE_WM8750
 	tristate "SoC I2S Audio support for Jive"
 	depends on SND_S3C24XX_SOC && MACH_JIVE
 	select SND_SOC_WM8750
+	select SND_SOC_WM8750_SPI
 	select SND_S3C2412_SOC_I2S
 	help
 	  Sat Y if you want to add support for SoC audio on the Jive.
 
+config SND_S3C24XX_SOC_NEO1973_GTA02_WM8753
+	tristate "SoC I2S Audio support for Openmoko Freerunner - WM8753"
+	depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA02
+	select SND_S3C24XX_SOC_I2S
+	select SND_SOC_WM8753
+	help
+	  Say Y if you want to add support for SoC audio on Openmoko Freerunner
+	  with the WM8753 codec
+
 config SND_S3C24XX_SOC_SMDK2443_WM9710
 	tristate "SoC AC97 Audio support for SMDK2443 - WM9710"
 	depends on SND_S3C24XX_SOC && MACH_SMDK2443
--- a/sound/soc/s3c24xx/Makefile
+++ b/sound/soc/s3c24xx/Makefile
@@ -19,9 +19,11 @@ snd-soc-neo1973-wm8753-objs := neo1973_w
 snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
 snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
 snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
+snd-soc-neo1973-gta02-wm8753-objs := gta02_wm8753.o
 
 obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o
 obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
 obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
 obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
 obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
+obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753) += snd-soc-neo1973-gta02-wm8753.o
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -284,11 +284,14 @@ static int s3c24xx_i2s_trigger(struct sn
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		if (!s3c24xx_snd_is_clkmaster()) {
-			ret = s3c24xx_snd_lrsync();
-			if (ret)
-				goto exit_err;
-		}
+		if (!s3c24xx_snd_is_clkmaster())
+			/* we ignore the return code, if it sync'd then fine,
+			 * if it didn't sync, which happens after resume the
+			 * first time when there was a live stream at suspend,
+			 * just let it timeout, the stream picks up OK after
+			 * that and LRCK is evidently working again.
+			 */
+			s3c24xx_snd_lrsync();
 
 		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 			s3c24xx_snd_rxctrl(1);
@@ -308,7 +311,6 @@ static int s3c24xx_i2s_trigger(struct sn
 		break;
 	}
 
-exit_err:
 	return ret;
 }
 
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -75,11 +75,18 @@ static void s3c24xx_pcm_enqueue(struct s
 {
 	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
 	dma_addr_t pos = prtd->dma_pos;
+	unsigned int limit;
 	int ret;
 
 	pr_debug("Entered %s\n", __func__);
 
-	while (prtd->dma_loaded < prtd->dma_limit) {
+	if (s3c_dma_has_circular()) {
+		limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
+	} else
+		limit = prtd->dma_limit;
+
+
+	while (prtd->dma_loaded < limit) {
 		unsigned long len = prtd->dma_period;
 
 		pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
@@ -123,7 +130,7 @@ static void s3c24xx_audio_buffdone(struc
 		snd_pcm_period_elapsed(substream);
 
 	spin_lock(&prtd->lock);
-	if (prtd->state & ST_RUNNING) {
+	if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
 		prtd->dma_loaded--;
 		s3c24xx_pcm_enqueue(substream);
 	}
@@ -164,6 +171,11 @@ static int s3c24xx_pcm_hw_params(struct 
 			printk(KERN_ERR "failed to get dma channel\n");
 			return ret;
 		}
+
+		/* use the circular buffering if we have it available. */
+		if (s3c_dma_has_circular())
+			s3c2410_dma_setflags(prtd->params->channel,
+					     S3C2410_DMAF_CIRCULAR);
 	}
 
 	s3c2410_dma_set_buffdone_fn(prtd->params->channel,
@@ -218,24 +230,17 @@ static int s3c24xx_pcm_prepare(struct sn
 	 * sync to pclk, half-word transfers to the IIS-FIFO. */
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		s3c2410_dma_devconfig(prtd->params->channel,
-				S3C2410_DMASRC_MEM, S3C2410_DISRCC_INC |
-				S3C2410_DISRCC_APB, prtd->params->dma_addr);
-
-		s3c2410_dma_config(prtd->params->channel,
-				prtd->params->dma_size,
-				S3C2410_DCON_SYNC_PCLK |
-				S3C2410_DCON_HANDSHAKE);
+				      S3C2410_DMASRC_MEM,
+				      prtd->params->dma_addr);
 	} else {
-		s3c2410_dma_config(prtd->params->channel,
-				prtd->params->dma_size,
-				S3C2410_DCON_HANDSHAKE |
-				S3C2410_DCON_SYNC_PCLK);
-
 		s3c2410_dma_devconfig(prtd->params->channel,
-					S3C2410_DMASRC_HW, 0x3,
-					prtd->params->dma_addr);
+				      S3C2410_DMASRC_HW,
+				      prtd->params->dma_addr);
 	}
 
+	s3c2410_dma_config(prtd->params->channel,
+			   prtd->params->dma_size);
+
 	/* flush the DMA channel */
 	s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH);
 	prtd->dma_loaded = 0;