diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 69b3f3c..8dd5a83 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -12,12 +12,14 @@
  *
  *  Revision history
  *    12th Aug 2005   Initial version.
+ *    25th Oct 2005   Working Codec, Interface and Platform registration.
  *
  *  TODO:
- *   o Check return values for interface and codec calbacks
+ *   o Add machine layer.
  *   o Should probably add hw rules to enforce rates, etc.
  *   o Testing.....
  *   o Add more codecs and platforms to ensure good API coverage.
+ *   o Support TDM on PCM and I2S
  */
 
 #include <linux/module.h>
@@ -37,7 +39,7 @@
 #include <sound/soc-dpm.h>
 #include <sound/initval.h>
 
-#define SND_SOC_VERSION "0.2"
+#define SND_SOC_VERSION "0.3"
 
 #define iface_name(x) \
 	(((x) == SND_SOC_AC97) ? "ac97" : \
@@ -78,7 +80,6 @@ int snd_soc_test_bits(snd_soc_codec_t *c
 	return change;
 }
 
-
 static int soc_match_hw(snd_soc_hw_mode_t *c, snd_soc_hw_mode_t *i, int rate, int fs)
 {
 	if (c->rate != i->rate)
@@ -104,12 +105,15 @@ static int soc_match_hw(snd_soc_hw_mode_
 	return 0;
 }
 
+/* Check that common hw capabilities exist between the codec and interface for
+ * the given hw params */
 static int soc_check_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params)
 {
 	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
 	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
 	int fs = 2048, i, j, match = 0;	
 	
+	/* try and match interface <--> codec table entries */
 	for (i = 0; i < pcm_c->hw.num_hmodes; i++) {
 		for (j = 0; j < pcm_i->hw.num_hmodes; j++) {
 			if (soc_match_hw(&pcm_c->hw.hmodes[i], &pcm_i->hw.hmodes[j], 
@@ -123,7 +127,7 @@ static int soc_check_hw_params(snd_pcm_s
 	}
 	
 	if (!match) {
-		printk(KERN_ERR "Can't match codec and interface capabilities\n");
+		printk(KERN_ERR "soc: can't match codec and interface capabilities\n");
 		return -EINVAL;
 	}
 	
@@ -136,20 +140,25 @@ static int soc_check_hw_params(snd_pcm_s
 	pcm_c->hw_runtime.hformat = pcm_i->hw_runtime.hformat;
 	pcm_c->hw_runtime.hbits = pcm_i->hw_runtime.hbits;
 	
-	printk(KERN_INFO "codec rate %d fs %d format %x\n", pcm_c->hw_runtime.rate, 
+	/* for debug atm */
+	printk(KERN_INFO "soc: codec rate %d fs %d format %x\n", pcm_c->hw_runtime.rate, 
 		pcm_c->hw_runtime.fs, pcm_c->hw_runtime.hformat);
-	printk(KERN_INFO "iface rate %d fs %d format %x\n", pcm_i->hw_runtime.rate, 
+	printk(KERN_INFO "soc: iface rate %d fs %d format %x\n", pcm_i->hw_runtime.rate, 
 		pcm_i->hw_runtime.fs, pcm_i->hw_runtime.hformat);
-	printk(KERN_INFO "audio rate %d chn %d\n", params_rate(params), params_channels(params));	
+	printk(KERN_INFO "soc: audio rate %d chn %d\n", params_rate(params), params_channels(params));	
 	
 	return 0;
 }
 
+/*
+ * Initialize the runtime->hw record, private data can be allocated
+ */
 static int soc_pcm_open(snd_pcm_substream_t *substream)
 {
 	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
 	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
 	snd_pcm_runtime_t *runtime = substream->runtime;
+	int ret = 0;
 
 	/* Check that the codec and SoC audio interface's are compatible */
 	if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -167,36 +176,65 @@ static int soc_pcm_open(snd_pcm_substrea
 		runtime->hw.channels_min = max(pcm_c->capture.channels_min, pcm_i->capture.channels_min);
 		runtime->hw.channels_max = min(pcm_c->capture.channels_max, pcm_i->capture.channels_max);
 	}
+	
+	/* will the codec and interface work together ? */
 	snd_pcm_limit_hw_rates(runtime);
 	if (!runtime->hw.rates) {
-		printk(KERN_ERR "%s <-> %s No matching rates\n", pcm_c->name, pcm_i->name);
+		printk(KERN_ERR "soc: %s <-> %s No matching rates\n", pcm_c->name, pcm_i->name);
 		return -ENODEV;
 	}
 	if(!runtime->hw.formats) {
-		printk(KERN_ERR "%s <-> %s No matching formats\n", pcm_c->name, pcm_i->name);
+		printk(KERN_ERR "soc: %s <-> %s No matching formats\n", pcm_c->name, pcm_i->name);
 		return -ENODEV;
 	}
 	if(!runtime->hw.channels_min || !runtime->hw.channels_max) {
-		printk(KERN_ERR "%s <-> %s No matching channels\n", pcm_c->name, pcm_i->name);
+		printk(KERN_ERR "soc: %s <-> %s No matching channels\n", pcm_c->name, pcm_i->name);
 		return -ENODEV;
 	}
-	printk(KERN_INFO "%s <-> %s info:\n", pcm_c->name, pcm_i->name);
-	printk(KERN_INFO "rates %x n\nmin ch %d max ch %d\nmin rate %d max rate %d\n",
+	printk(KERN_INFO "soc: %s <-> %s info:\n", pcm_c->name, pcm_i->name);
+	printk(KERN_INFO "soc: rate mask 0x%x \nsoc: min ch %d max ch %d\nsoc: min rate %d max rate %d\n",
 		runtime->hw.rates, runtime->hw.channels_min,
 		runtime->hw.channels_max, runtime->hw.rate_min, runtime->hw.rate_max);
+
+	if(pcm_i->ops.startup) {
+		if((ret = pcm_i->ops.startup(substream)) < 0) {
+			printk(KERN_ERR "soc: can't open interface %s\n", pcm_i->name);
+			goto ops_err;
+		}
+	}
+
+	if(platform->pcm_ops->open) {
+		if((ret = platform->pcm_ops->open(substream)) < 0) {
+			printk(KERN_ERR "soc: can't open platform %s\n", platform->name);
+			goto platform_err;
+		}
+	}
+
+	if(pcm_c->ops.startup) {
+		if((ret = pcm_c->ops.startup(substream)) < 0) {
+			printk(KERN_ERR "soc: can't open codec %s\n", pcm_c->name);
+			goto pcm_err;
+		}
+	}
+
+	return ret;
+
+pcm_err:
+	if(pcm_c->ops.shutdown)
+		pcm_c->ops.shutdown(substream);
 	
-	if(pcm_i->ops.startup)
-		pcm_i->ops.startup(substream);
-	
-	if(platform->pcm_ops->open)
-		platform->pcm_ops->open(substream);
-	
-	if(pcm_c->ops.startup)
-		pcm_c->ops.startup(substream);
+platform_err:
+	if(platform->pcm_ops->close)
+		platform->pcm_ops->close(substream);
 
-	return 0;
+ops_err:
+	if(pcm_i->ops.shutdown)
+		pcm_i->ops.shutdown(substream);	
+	
+	return ret;
 }
 
+/* private data can be freed here */
 static int soc_pcm_close(snd_pcm_substream_t *substream)
 {
 	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
@@ -214,46 +252,60 @@ static int soc_pcm_close(snd_pcm_substre
 	return 0;
 }
 
+/* called when pcm is prepared, can set format, sample rate; 
+ * atomic, can be called multiple times, can refer to runtime info*/
 static int soc_pcm_prepare(snd_pcm_substream_t *substream)
 {
 	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
 	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
+	int ret = 0;
 	
 	if(platform->pcm_ops->prepare)
-		platform->pcm_ops->prepare(substream);
+		if((ret = platform->pcm_ops->prepare(substream)) < 0)
+			return ret;
 	
 	if(pcm_c->ops.prepare)
-		pcm_c->ops.prepare(substream);
+		if((ret = pcm_c->ops.prepare(substream)) < 0)
+			return ret;
 	
 	if(pcm_i->ops.prepare)
-		pcm_i->ops.prepare(substream);
+		if((ret = pcm_i->ops.prepare(substream)) < 0)
+			return ret;
 
-	return 0;
+	return ret;
 }
 
 static int soc_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
 {
 	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
 	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
+	int ret = 0;
 
 	if(pcm_c->ops.trigger)
-		pcm_c->ops.trigger(substream, cmd);
+		if((ret = pcm_c->ops.trigger(substream, cmd)) < 0)
+			return ret;
 	
 	if(pcm_i->ops.trigger)
-		pcm_i->ops.trigger(substream, cmd);
+		if((ret = pcm_i->ops.trigger(substream, cmd)) < 0)
+			return ret;
 	
 	if(platform->pcm_ops->trigger)
-		platform->pcm_ops->trigger(substream, cmd);
+		if((ret = platform->pcm_ops->trigger(substream, cmd)) < 0)
+			return ret;
 
-	return 0;
+	return ret;
 }
 
+/* called when hw params is set by app, can be called multiple times
+ * alloc buffers (using snd_pcm_lib_* ), non-atomic, hw setup
+ */
 static int soc_pcm_hw_params(snd_pcm_substream_t *substream,
 				snd_pcm_hw_params_t *params)
 {
 	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
 	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
-	int ret;
+	snd_soc_codec_t *codec = (snd_soc_codec_t*)pcm_i->card->private_data;
+	int ret = 0;
 
 	/* prepare hw non AC97 only */
 	if(pcm_i->type != SND_SOC_AC97) {
@@ -261,23 +313,62 @@ static int soc_pcm_hw_params(snd_pcm_sub
 			return ret;
 	}
 	
-	if(pcm_c->ops.hw_params)
-		pcm_c->ops.hw_params(substream, params);
+	if(pcm_c->ops.hw_params) {
+		if((ret = pcm_c->ops.hw_params(substream, params)) < 0) {
+			printk(KERN_ERR "soc: can't set codec %s hw params\n", pcm_c->name);
+			goto codec_err;
+		}
+	}
 	
-	if(pcm_i->ops.hw_params)
-		pcm_i->ops.hw_params(substream, params);
+	if(pcm_i->ops.hw_params) {
+		if((ret = pcm_i->ops.hw_params(substream, params)) < 0) {
+			printk(KERN_ERR "soc: can't set interface %s hw params\n", pcm_i->name);
+			goto interface_err;
+		}
+	}
+	
+	if(platform->pcm_ops->hw_params) {
+		if((ret = platform->pcm_ops->hw_params(substream, params)) < 0) {
+			printk(KERN_ERR "soc: can't set platform %s hw params\n", platform->name);
+			goto platform_err;
+		}
+	}
 	
-	if(platform->pcm_ops->hw_params)
-		platform->pcm_ops->hw_params(substream, params);
+	snd_soc_dpm_codec_event(codec, SND_SOC_DPM_CODEC_ON);
+	if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		snd_soc_dpm_stream_event(codec, pcm_c->playback.sname, SND_SOC_DPM_STREAM_START);
+	else
+		snd_soc_dpm_stream_event(codec, pcm_c->capture.sname, SND_SOC_DPM_STREAM_START);
+	return ret;
 	
-	return 0;
+platform_err:
+	if(platform->pcm_ops->hw_free)
+		platform->pcm_ops->hw_free(substream);
+	
+interface_err:
+	if(pcm_i->ops.hw_free)
+		pcm_i->ops.hw_free(substream);
+	
+codec_err:
+	if(pcm_c->ops.hw_free)
+		pcm_c->ops.hw_free(substream);
+	snd_soc_dpm_codec_event(codec, SND_SOC_DPM_CODEC_OFF);
+	if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		snd_soc_dpm_stream_event(codec, pcm_c->playback.sname, SND_SOC_DPM_STREAM_STOP);
+	else
+		snd_soc_dpm_stream_event(codec, pcm_c->capture.sname, SND_SOC_DPM_STREAM_STOP);
+	
+	
+	return ret;
 }
 
+/* free buffers, can be called multiple times */
 static int soc_pcm_hw_free(snd_pcm_substream_t *substream)
 {
 	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
 	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
-	
+	snd_soc_codec_t *codec = (snd_soc_codec_t*)pcm_i->card->private_data;
+
 	if(pcm_c->ops.hw_free)
 		pcm_c->ops.hw_free(substream);
 	
@@ -287,6 +378,12 @@ static int soc_pcm_hw_free(snd_pcm_subst
 	if(platform->pcm_ops->hw_free)
 		platform->pcm_ops->hw_free(substream);
 	
+	snd_soc_dpm_codec_event(codec, SND_SOC_DPM_CODEC_OFF);
+	if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		snd_soc_dpm_stream_event(codec, pcm_c->playback.sname, SND_SOC_DPM_STREAM_STOP);
+	else
+		snd_soc_dpm_stream_event(codec, pcm_c->capture.sname, SND_SOC_DPM_STREAM_STOP);
+	
 	return 0;
 }
 
@@ -347,11 +444,14 @@ static int soc_probe_codec(snd_soc_codec
 	
 	/* register a sound card */
 	codec->card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, codec->owner, 0);
-	if (!codec->card)
+	if (!codec->card) {
+		printk(KERN_ERR "soc: can't create sound card for codec %s\n", codec->name);
 		return -ENODEV;
+	}
 
 	platform_device_register(&codec->pdev);
 	codec->card->dev = &codec->pdev.dev;
+	codec->card->private_data = codec;
 	strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
 		
 	if((ret = codec->probe(codec)) < 0)
@@ -364,16 +464,18 @@ static int soc_probe_codec(snd_soc_codec
 	snprintf(codec->card->longname, sizeof(codec->card->longname),
 		 "%s (%s)", codec->longname, "SoC");
 	
-	if((ret = snd_card_register(codec->card)) < 0)
+	if((ret = snd_card_register(codec->card)) < 0) {
+		printk(KERN_ERR "soc: failed to register soundcard for codec %s\n", codec->name);
 		goto err;
+	}
 		
 	if(codec->interface->probe)
 		if((ret = codec->interface->probe(codec->interface)) < 0)
 			goto err;
-
+			
+	snd_soc_dpm_sys_add(&codec->pdev.dev);
 	snd_card_set_pm_callback(codec->card, soc_suspend, soc_resume, codec);		     
 	codec->probed = 1;
-
 	return 0;
 	
 err:
@@ -424,6 +526,7 @@ static int soc_remove_codec(snd_soc_code
 	if(codec->interface->remove)
 		codec->interface->remove(codec->interface);
 	codec->remove(codec);
+	snd_soc_dpm_sys_remove(&codec->pdev.dev);
 	
 	/* free any DPM objects */
 	soc_free_dpm_widgets(codec);
@@ -433,16 +536,18 @@ static int soc_remove_codec(snd_soc_code
 
 int snd_soc_register_codec(snd_soc_codec_t *codec)
 {
+	int ret = 0;
+
 	down(&soc_sem);
 	INIT_LIST_HEAD(&codec->list);
 	INIT_LIST_HEAD(&codec->dpm_widgets);
 	INIT_LIST_HEAD(&codec->dpm_paths);
 	list_add(&codec->list, &codecs);
 
-	up(&soc_sem);
 	if (platform)
-		return soc_probe_codec(codec);
+		ret = soc_probe_codec(codec);
 	
+	up(&soc_sem);
 	return 0;
 }
 
@@ -467,8 +572,8 @@ void snd_soc_unregister_interface(snd_so
 {
 	down(&soc_sem);
 	list_del_init(&iface->list);
-	//if (platform && iface->remove) 
-	//	iface->remove(iface);
+	if (platform && iface->remove) 
+		iface->remove(iface);
 	up(&soc_sem);	
 }
 
@@ -479,7 +584,7 @@ int snd_soc_register_platform(snd_soc_pl
 	struct list_head *l;
 	snd_soc_codec_t *c;
 	int ret;
-		
+	
 	down(&soc_sem);
 	if(platform) {
 		up(&soc_sem);
@@ -493,10 +598,10 @@ int snd_soc_register_platform(snd_soc_pl
 	soc_pdrv.name = p->name;
 	soc_pdrv.probe = p->probe;
 	soc_pdrv.remove = p->remove;
-	up(&soc_sem);	
 		
 	if((ret = driver_register(&soc_pdrv)) < 0) {
-		printk(KERN_ERR "SoC: Failed to register platform %s\n", p->name);
+		printk(KERN_ERR "soc: failed to register platform %s\n", p->name);
+		up(&soc_sem);
 		return ret;
 	}
 	
@@ -504,8 +609,9 @@ int snd_soc_register_platform(snd_soc_pl
 		c = list_entry(l, snd_soc_codec_t, list);
 		ret = soc_probe_codec(c);
 		if (ret < 0)
-			printk(KERN_ERR "SoC: Probe of codec %s failed\n", c->name);
+			printk(KERN_ERR "soc: probe of codec %s failed\n", c->name);
 	}
+	up(&soc_sem);
 	
 	return 0;
 }
@@ -520,11 +626,8 @@ void snd_soc_unregister_platform(snd_soc
 		c = list_entry(l, snd_soc_codec_t, list);
 		soc_remove_codec(c);
 	}
-	up(&soc_sem);
 	
 	driver_unregister(&soc_pdrv);
-	
-	down(&soc_sem);
 	platform = NULL;
 	up(&soc_sem);	
 }
@@ -538,7 +641,7 @@ int snd_soc_pcm_new(snd_soc_codec_t *cod
 	struct list_head *l;
 	snd_soc_pcm_interface_t *i = NULL;
 	char name[32];
-		
+	
 	down(&soc_sem);
 	list_for_each(l, &interfaces) {
 		i = list_entry(l, snd_soc_pcm_interface_t, list);
@@ -557,9 +660,10 @@ int snd_soc_pcm_new(snd_soc_codec_t *cod
 	i->pcm_c = pcm_c;
 	codec->interface = i;
 	sprintf(name, "%s-%s-%d", pcm_c->name, iface_name(iface_type), num);
-	ret = snd_pcm_new(card, name, dev_no, play, capt, &pcm);
-	if (ret)
+	if((ret = snd_pcm_new(card, name, dev_no, play, capt, &pcm)) < 0) {
+		printk(KERN_ERR "soc: can't create pcm for codec %s\n", codec->name);
 		goto err;
+	}
 
 	pcm->private_data = pcm_c;
 	if (play)
@@ -568,13 +672,16 @@ int snd_soc_pcm_new(snd_soc_codec_t *cod
 	if (capt)
 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
 
-	if((ret = platform->pcm_new(card, pcm_c, play, capt, pcm)) < 0)
+	if((ret = platform->pcm_new(card, pcm_c, play, capt, pcm)) < 0) {
+		printk(KERN_ERR "soc: platform pcm constructor failed\n");
 		goto err;
+	}
+	
 	codec->pcm = pcm;
 	if (rpcm)
 		*rpcm = pcm;
 
-	printk(KERN_INFO "%s <-> %s mapping ok\n", pcm_c->name, i->name);
+	printk(KERN_INFO "soc: %s <-> %s mapping ok\n", pcm_c->name, i->name);
 	up(&soc_sem);
 	return 0;
 	
@@ -592,7 +699,6 @@ int snd_soc_iface_query(int iface_type, 
 	struct list_head *l;
 	snd_soc_pcm_interface_t *i;
 
-	down(&soc_sem);
 	list_for_each(l, &interfaces) {
 		i = list_entry(l, snd_soc_pcm_interface_t, list);
 		if (i->type == iface_type && i->id == num){
@@ -600,7 +706,7 @@ int snd_soc_iface_query(int iface_type, 
 			return 0;
 		}
 	}
-	up(&soc_sem);
+
 	return -ENODEV;
 }
 
@@ -752,7 +858,7 @@ int snd_soc_put_volsw(snd_kcontrol_t * k
 
 static int __init snd_soc_init(void) 
 {
-	printk(KERN_INFO "version %s liam.girdwood@wolfsonmicro.com\n", SND_SOC_VERSION);
+	printk(KERN_INFO "soc: version %s liam.girdwood@wolfsonmicro.com\n", SND_SOC_VERSION);
 	return 0;
 }
 
diff --git a/sound/soc/soc-dpm.c b/sound/soc/soc-dpm.c
index 13d423d..91ab5af 100644
--- a/sound/soc/soc-dpm.c
+++ b/sound/soc/soc-dpm.c
@@ -1,5 +1,5 @@
 /*
- * soc-dpm.c  --  ALSA Soc Dynamic Power Management
+ * soc-dpm.c  --  ALSA SoC Dynamic Power Management
  *
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Author: Liam Girdwood
@@ -12,6 +12,24 @@
  *
  *  Revision history
  *    12th Aug 2005   Initial version.
+ *    25th Oct 2005   Implemented path power domain.
+ *
+ *  Features:
+ *    o Changes power status of internal codec blocks depending on the 
+ *      dynamic configuration of codec internal audio paths and active
+ *      DAC's/ADC's.
+ * 
+ *  Todo:
+ *    o Codec dpm event notification. e.g. mute DAC's to stop pops
+ *    o sysfs dpm status.
+ *    o VMID selection.
+ *    o Platform power domain - could this be tied into machine layer ???
+ *    o DPM power change sequencing - order dpm "ons" to minimise pops.
+ *    o DPM power change volume stepping - mute or have volume at minimum
+ *      then gradually increase to preset level to minimise pops.
+ *    o Support for analogue bias optimisation.
+ *    o Support for reduced codec oversampling rates.
+ *    o Support for reduced codec bias currents.
  */
 
 #include <linux/module.h>
@@ -30,7 +48,12 @@
 #include <sound/soc-dpm.h>
 #include <sound/initval.h>
 
-static snd_soc_dpm_widget_t *snd_soc_cnew_widget(const snd_soc_dpm_widget_t *_widget)
+
+static int dpm_status = 0;
+module_param(dpm_status, int, 0);
+MODULE_PARM_DESC(dpm_status, "enable DPM sysfs entries");
+
+static snd_soc_dpm_widget_t *dpm_cnew_widget(const snd_soc_dpm_widget_t *_widget)
 {
 	snd_soc_dpm_widget_t* widget;
 	widget = kmalloc(sizeof(snd_soc_dpm_widget_t), GFP_KERNEL);
@@ -41,26 +64,6 @@ static snd_soc_dpm_widget_t *snd_soc_cne
 	return widget;
 }
 
-int snd_soc_dpm_new_control(snd_soc_codec_t *codec, const snd_soc_dpm_widget_t *widget)
-{
-	snd_soc_dpm_widget_t *w;
-	
-	if ((w = snd_soc_cnew_widget(widget)) == NULL)
-		return -ENOMEM;
-
-	w->codec = codec;
-	INIT_LIST_HEAD(&w->inputs);
-	INIT_LIST_HEAD(&w->outputs);
-	INIT_LIST_HEAD(&w->list);
-	list_add(&w->list, &codec->dpm_widgets);
-	
-	// liam - remove when implemented
-	w->active = 1; // liam - set by stream ops
-	w->connected = 1; // liam - set by .asoundrc extension
-	
-	return 0;
-}
-
 static void dpm_set_path_status(snd_soc_dpm_widget_t *w, 
 	snd_soc_dpm_path_t *p, int i)
 {	
@@ -106,7 +109,8 @@ static void dpm_set_path_status(snd_soc_
 		case snd_soc_dpm_adc:
 		case snd_soc_dpm_input:
 		case snd_soc_dpm_dac:
-		case snd_soc_dpm_codec:
+		case snd_soc_dpm_clock:
+		case snd_soc_dpm_vref:	
 			p->connect = 1;
 		break;
 	}
@@ -119,8 +123,6 @@ static int dpm_connect_mux(snd_soc_codec
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	int i;
 	
-//printk("control name %s\n", dest->kcontrols[0].name);
-	
 	for (i = 0; i < e->mask; i++) {
 		if (!(strcmp(control_name, e->texts[i]))) {
 			list_add(&path->list, &codec->dpm_paths);
@@ -128,7 +130,6 @@ static int dpm_connect_mux(snd_soc_codec
 			list_add(&path->list_in, &src->outputs);
 			path->name = (char*)e->texts[i];
 			dpm_set_path_status(dest, path, 0);
-//			printk("path name %s\n", path->name);
 			return 0;
 		}
 	}
@@ -194,7 +195,6 @@ int snd_soc_dpm_connect_input(snd_soc_co
 		list_add(&path->list, &codec->dpm_paths);
 		list_add(&path->list_out, &dest->inputs);
 		list_add(&path->list_in, &src->outputs);
-//printk("src %s %p --> dest %s %p\n", src->name, src, dest->name, dest);
 		path->connect = 1;
 		return 0;
 	}
@@ -202,10 +202,11 @@ int snd_soc_dpm_connect_input(snd_soc_co
 	switch(dest->id) {
 		case snd_soc_dpm_adc:
 		case snd_soc_dpm_dac:
-		case snd_soc_dpm_codec:
 		case snd_soc_dpm_volume:
 		case snd_soc_dpm_input:
 		case snd_soc_dpm_output:
+		case snd_soc_dpm_clock:
+		case snd_soc_dpm_vref:	
 			list_add(&path->list, &codec->dpm_paths);
 			list_add(&path->list_out, &dest->inputs);
 			list_add(&path->list_in, &src->outputs);
@@ -223,19 +224,23 @@ int snd_soc_dpm_connect_input(snd_soc_co
 	return 0;
 
 err:
-	printk(KERN_WARNING "No match for %s --> %s --> %s\n", src_name, 
+	printk(KERN_WARNING "soc: no dpm match for %s --> %s --> %s\n", src_name, 
 		control_name, dest_name); 
 	kfree(path);
 	return ret;
 }
 
 
-static int snd_soc_dpm_update_bits(snd_soc_dpm_widget_t *widget, int power)
+static int dpm_update_bits(snd_soc_dpm_widget_t *widget, int power)
 {
 	int change;
 	unsigned short old, new;
 	snd_soc_codec_t *codec = widget->codec;
 	
+	if(widget->reg < 0 || widget->id == snd_soc_dpm_input ||
+		widget->id == snd_soc_dpm_output)
+		return 0;
+	
 	if(power)
 		power = 1;
 	
@@ -243,70 +248,79 @@ static int snd_soc_dpm_update_bits(snd_s
 	new = (old & ~(0x1 << widget->shift)) | (power << widget->shift);
 	
 	change = old != new;
-	//printk("test power %d block %s change %d\n", power, widget->name, change);
-	if (change) {
+	if (change)
 		snd_soc_write(codec, widget->reg, new);
-		printk("**power block %s %d\n", widget->name, power);
-	}
+
 	return change;
 }
 
-/*
- * Create DPM kcontrols
- */
-#warning NEED to Sync with startup values and create paths and correct PM status
-int snd_soc_dpm_sync(snd_soc_codec_t *codec)
+static int dpm_sync_mixer(snd_soc_codec_t *codec, snd_soc_dpm_widget_t *w)
 {
-	snd_soc_dpm_path_t *path;
-	snd_soc_dpm_widget_t *w = NULL;
-	struct list_head *lw, *lp;
-	int i, err;
+	int i, ret = 0;
 	char name[32];
-		
-	list_for_each(lw, &codec->dpm_widgets)
-	{
-		w = list_entry(lw, snd_soc_dpm_widget_t, list);
-		
-		/* add kcontrol */
-		for (i = 0; i < w->num_kcontrols; i++) {
+	struct list_head *lp;
+	snd_soc_dpm_path_t *path;
+	
+	/* add kcontrol */
+	for (i = 0; i < w->num_kcontrols; i++) {
 			
-			/* match name */
-			list_for_each(lp, &w->inputs)
-			{
-				path = list_entry(lp, snd_soc_dpm_path_t, list_out);
-				if (path->name == (char*)w->kcontrols[i].name) {
-					/* add dpm control with long name */
-					snprintf(name, 32, "%s %s", w->name, w->kcontrols[i].name);
-					path->long_name = kstrdup (name, GFP_KERNEL);
-					path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, path->long_name);
-					if ((err = snd_ctl_add(codec->card, path->kcontrol)) < 0)
-						return err;
-				}	
+		/* match name */
+		list_for_each(lp, &w->inputs)
+		{
+			path = list_entry(lp, snd_soc_dpm_path_t, list_out);
+			
+			if (path->name != (char*)w->kcontrols[i].name) 
+				continue;
+				
+			/* add dpm control with long name */
+			snprintf(name, 32, "%s %s", w->name, w->kcontrols[i].name);
+			path->long_name = kstrdup (name, GFP_KERNEL);
+			if(path->long_name == NULL)
+				return -ENOMEM;
+			
+			path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, path->long_name);
+			if ((ret = snd_ctl_add(codec->card, path->kcontrol)) < 0) {
+				printk(KERN_ERR "soc: failed to add dpm kcontrol %s\n", path->long_name);
+				kfree(path->long_name);
+				path->long_name = NULL;
+				return ret;
 			}
 		}
 	}
-	return 0;
+	return ret;
 }
 
-/*
- * Reset 'checked' bit for each path
- */
-static void snd_soc_dpm_clear_paths(snd_soc_codec_t *codec)
+static int dpm_sync_mux(snd_soc_codec_t *codec, snd_soc_dpm_widget_t *w)
 {
-	snd_soc_dpm_path_t *p = NULL;
-	struct list_head *l = NULL;
-		
-	list_for_each(l, &codec->dpm_paths)
+	struct list_head *lp;
+	snd_soc_dpm_path_t *path = NULL;
+	snd_kcontrol_t *kcontrol;
+	int ret = 0;
+	
+	if(!w->num_kcontrols) {
+		printk(KERN_ERR "soc: mux %s has no controls\n", w->name);
+		return -EINVAL;
+	}
+	
+	kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
+	if ((ret = snd_ctl_add(codec->card, kcontrol)) < 0) {
+		printk(KERN_ERR "soc: failed to add kcontrol %s\n", w->name);
+		return ret;
+	}
+
+	list_for_each(lp, &w->inputs)
 	{
-		p = list_entry(l, snd_soc_dpm_path_t, list);
-		p->checked = 0;		
+		path = list_entry(lp, snd_soc_dpm_path_t, list_out);
+		path->kcontrol = kcontrol;
 	}
+	
+	return ret;
 }
 
 /*
- * Reset 'checked' bit for each path
+ * Reset 'walked' bit for each path
  */
-static void snd_soc_dpm_clear_walk(snd_soc_codec_t *codec)
+static void dpm_clear_walk(snd_soc_codec_t *codec)
 {
 	snd_soc_dpm_path_t *p = NULL;
 	struct list_head *l = NULL;
@@ -335,10 +349,8 @@ static int is_connected_output_ep(snd_so
 	list_for_each(lp, &widget->outputs)
 	{
 		path = list_entry(lp, snd_soc_dpm_path_t, list_in);
-		if(path->walked) {
-			con++;
+		if(path->walked)
 			continue;
-		}
 	
 		if (path->out && path->connect) {
 			path->walked = 1;
@@ -366,10 +378,8 @@ static int is_connected_input_ep(snd_soc
 	list_for_each(lp, &widget->inputs)
 	{
 		path = list_entry(lp, snd_soc_dpm_path_t, list_out);
-		if(path->walked) {
-			con++;
+		if(path->walked)
 			continue;
-		}
 	
 		if (path->in && path->connect) {
 			path->walked = 1;
@@ -380,207 +390,78 @@ static int is_connected_input_ep(snd_soc
 	return con;
 }
 
-
-/*
- * Check each widgets input and output paths and determine it's new power
- * state.
- */
-static int snd_soc_dpm_check_widget(snd_soc_dpm_widget_t *widget, int power)
+static int dpm_power_widgets(snd_soc_codec_t *codec)
 {
-	snd_soc_dpm_path_t *path = NULL;
-	struct list_head *lp;
-	int in = 0, out = 0;
+	snd_soc_dpm_widget_t *w;
+	struct list_head *l;
+	int in, out, pm;
 	
-//printk("w name %s id %d pwr %d reg %d\n", widget->name, widget->id, power, widget->reg); 	
-
-	switch(widget->id) {
-		case snd_soc_dpm_dac: /* end point */
-			
-			widget->active = 1; // liam - set by stream ops
-		
-			out = is_connected_output_ep(widget);
-			snd_soc_dpm_clear_walk(widget->codec);
-		//	printk("dac widget %s in %d out %d pwr %d\n", widget->name, in, out, power);
-			if(!out)
-				power = widget->active = 0;
-			else
-				power = widget->active;
-		
-			list_for_each(lp, &widget->outputs)
-			{
-				path = list_entry(lp, snd_soc_dpm_path_t, list_in);
-				if(path->checked)
-					continue;
-		
-				if (path->out && path->connect) {
-					path->checked = 1;
-					snd_soc_dpm_check_widget(path->out, power);
-				}
-			}
-			
-			break;
-		case snd_soc_dpm_input: /* end point */
-			
-			widget->connected = 1; // liam - set by .asoundrc extension
-		
-			out = is_connected_output_ep(widget);
-			snd_soc_dpm_clear_walk(widget->codec);
-		//	printk("in widget %s in %d out %d pwr %d\n", widget->name, in, out, power);
-			if(!out)
-				power = 0;
-			
-			list_for_each(lp, &widget->outputs)
-			{
-				path = list_entry(lp, snd_soc_dpm_path_t, list_in);
-				if(path->checked)
-					continue; 	
-				
-				if (path->out && path->connect) {
-					path->checked = 1;
-					snd_soc_dpm_check_widget(path->out, power);
-				}
-			}
-			
-			break;
-		case snd_soc_dpm_adc: /* end point */
-			
-			widget->active = 1; //liam - set by stream ops
+	list_for_each(l, &codec->dpm_widgets)
+	{
+		w = list_entry(l, snd_soc_dpm_widget_t, list);
 		
-			in = is_connected_input_ep(widget);
-			snd_soc_dpm_clear_walk(widget->codec);
-		//	printk("adc widget %s in %d out %d pwr %d\n", widget->name, in, out, power);
-			if(!in)
-				power = widget->active = 0;
-			else
-				power = widget->active;
-			
-			list_for_each(lp, &widget->inputs)
-			{
-				path = list_entry(lp, snd_soc_dpm_path_t, list_out);
-				
-				if(path->checked)
-					continue;
-			
-				if (path->in && path->connect) {
-					path->checked = 1;
-					snd_soc_dpm_check_widget(path->in, power);
-				}
-			}
-			
-			break;
-		case snd_soc_dpm_output: /* end point */
-			
-			widget->connected = 1; // liam - set by .asoundrc extension
+		if(w->id == snd_soc_dpm_vref || w->id == snd_soc_dpm_clock)
+			continue;
 		
-			in = is_connected_input_ep(widget);
-			snd_soc_dpm_clear_walk(widget->codec);
-		//	printk("out widget %s in %d out %d pwr %d\n", widget->name, in, out, power);
-			if(!in)
-				power = 0;
-			
-			list_for_each(lp, &widget->inputs)
-			{
-				path = list_entry(lp, snd_soc_dpm_path_t, list_out);
-				
-				if(path->checked)
-					continue;
-			
-				if (path->in && path->connect) {
-					path->checked = 1;
-					snd_soc_dpm_check_widget(path->in, power);
-				}
-			}
-			break;
-		case snd_soc_dpm_volume:
-		case snd_soc_dpm_mixer:
-		case snd_soc_dpm_codec:
-		case snd_soc_dpm_mux:
-			in = is_connected_input_ep(widget);
-			out = is_connected_output_ep(widget);
-			snd_soc_dpm_clear_walk(widget->codec);
-			if(!in || !out)
-				power = 0;
-			else
-				power = 1;
-//printk("widget %s in %d out %d pwr %d\n", widget->name, in, out, power);		
-			list_for_each(lp, &widget->inputs)
-			{
-				path = list_entry(lp, snd_soc_dpm_path_t, list_out);
-			//	printk("  in* %s\n", path->in->name);
-				if(path->checked)
-					continue;
+		if(w->id == snd_soc_dpm_adc && w->active) {
+			in = is_connected_input_ep(w);
+			dpm_clear_walk(w->codec);
+			pm = (in != 0) ? 1 : 0;
+			dpm_update_bits(w, pm);
+			continue;
+		}
 		
-				if (path->in && path->connect) {
-					path->checked = 1;
-			//		printk("  in %s\n", path->in->name);
-					snd_soc_dpm_check_widget(path->in, power);
-				}
-			}
-			list_for_each(lp, &widget->outputs)
-			{
-				path = list_entry(lp, snd_soc_dpm_path_t, list_in);
-	//			printk("  out* %s path to %s\n", path->name, path->out->name);
-				if(path->checked)
-					continue;
-				
-				if (path->out) {
-					path->checked = 1;
-		//			printk("  out %s path to %s\n", path->name, path->out->name);
-					snd_soc_dpm_check_widget(path->out, power);
-				}
-			}
-			break;
-	}
-	//printk("in %d out %d\n", in, out);
-	snd_soc_dpm_update_bits(widget, power);
-	return power;
-}
-
-#if 0
-static snd_soc_dpm_widget_t * snd_soc_dpm_find_stream(snd_soc_codec_t *codec, 
-	char* name)
-{
-	snd_soc_dpm_widget_t *w = NULL;
-	struct list_head *l = NULL;
+		if(w->id == snd_soc_dpm_dac && w->active) {
+			out = is_connected_output_ep(w);
+			dpm_clear_walk(w->codec);
+			pm = (out != 0) ? 1 : 0;
+			dpm_update_bits(w, pm);
+			continue;
+		}
 		
-	list_for_each(l, &codec->dpm_widgets)
-	{
-		w = list_entry(l, snd_soc_dpm_widget_t, list);
-		if (!strcmp(name, w->name))
-			return w;			
+		in = is_connected_input_ep(w);
+		dpm_clear_walk(w->codec);
+		out = is_connected_output_ep(w);
+		dpm_clear_walk(w->codec);
+		pm = (out != 0 && in != 0) ? 1 : 0;
+		dpm_update_bits(w, pm);
+		//printk("widget %s\n in %d out %d pm %s\n", w->name, in, out, pm ? "On":"Off");	
 	}
-	
-	return NULL;
+	return 0;
 }
-#endif
 
 static int dpm_mux_update_power(snd_soc_dpm_widget_t *widget, 
 	snd_kcontrol_t *kcontrol, int mask, int val, struct soc_enum* e)
 {
-	int i = 0;
-
+	struct list_head *l;
+	snd_soc_dpm_path_t *path;
+	
 	if(widget->id != snd_soc_dpm_mux)
 		return -ENODEV; 
 		
 	if (!snd_soc_test_bits(widget->codec, e->reg, mask, val))
 		return 0;
+	
+	/* find dpm widget path assoc with kcontrol */
+	list_for_each(l, &widget->codec->dpm_paths)
+	{
+		path = list_entry(l, snd_soc_dpm_path_t, list);
+		if (path->kcontrol != kcontrol)
+			continue;
 		
-	/* we now need to match the string in the enum to the path */
-//	for (i = 0; i < e->mask; i++) {
-//		if (!(strcmp(p->name, e->texts[i]))) {
-			
-//			dpm_set_path_status(dest, path, 0);
-//			printk("path name %s\n", path->name);
-//			return 0;
-//		}
-//	}
-						
-	snd_soc_dpm_clear_paths(widget->codec);
+		/* we now need to match the string in the enum to the path */
+		if (!(strcmp(path->name, e->texts[val])))
+			path->connect = 1; /* new connection */
+		else
+			path->connect = 0; /* old connection must be powered down */
+	}
+	
+	dpm_power_widgets(widget->codec);			
 	return 0;
 }
 
 static int dpm_mixer_update_power(snd_soc_dpm_widget_t *widget, 
-	snd_kcontrol_t *kcontrol, int reg, int val_mask, int val)
+	snd_kcontrol_t *kcontrol, int reg, int val_mask, int val, int invert)
 {
 	struct list_head *l;
 	snd_soc_dpm_path_t *path;
@@ -599,23 +480,81 @@ static int dpm_mixer_update_power(snd_so
 			continue;
 			
 		/* found, now check type */
-		if (val) { // liam - need to check invert bit
-			/* new connection */
-			printk("\n\n\nnew connection\n");
-			path->connect = 1;
-			snd_soc_dpm_check_widget(widget, 1);
-		} else {
-			/* old connection must be powered down */
-			printk("\n\n\nbreak connection\n");
-			path->connect = 0;
-			snd_soc_dpm_check_widget(path->in, 0);
-			printk("\n\n\nbreak connection2\n");
-			snd_soc_dpm_check_widget(widget, 0);
-		}
+		if (val)
+			path->connect = invert ? 0:1; /* new connection */
+		else
+			path->connect = invert ? 1:0; /* old connection must be powered down */
 		break;
 	}
 	
-	snd_soc_dpm_clear_paths(widget->codec);
+	dpm_power_widgets(widget->codec);
+	return 0;
+}
+
+#if 0
+#define DPM_STATUS_ATTR(name) \
+static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf)   \
+{ \
+	snd_soc_codec_t *codec = (snd_soc_codec_t*)dev->driver_data; \
+	snd_soc_dpm_widget_t *w = NULL; 	\
+	struct list_head *l = NULL; 	\
+	int count = 0; 	\
+					\
+	list_for_each(l, &codec->dpm_widgets) \
+	{ \
+		w = list_entry(l, snd_soc_dpm_widget_t, list); \
+		count += sprintf(buf, "%s: %s\n", w->name, w->power ? "On":"Off");	\
+	} \
+	return count;\
+} \
+static DEVICE_ATTR(name, 0444, name##_show, NULL)
+		     
+DPM_STATUS_ATTR(dpm_status);
+#endif
+
+int snd_soc_dpm_sys_add(struct device *dev) 
+{
+	int ret = 0;
+	
+//	if (dpm_status)
+//		ret = device_create_file(dev, &dev_attr_dpm_status);
+	return ret;
+}	     
+
+void snd_soc_dpm_sys_remove(struct device *dev) 
+{
+	//if (dpm_status)
+	//	device_remove_file(dev, &dev_attr_dpm_status);
+} 
+
+int snd_soc_dpm_sync(snd_soc_codec_t *codec)
+{
+	snd_soc_dpm_widget_t *w = NULL;
+	struct list_head *lw;
+	
+	list_for_each(lw, &codec->dpm_widgets)
+	{
+		w = list_entry(lw, snd_soc_dpm_widget_t, list);
+
+		switch(w->id) {
+			case snd_soc_dpm_mixer:
+				dpm_sync_mixer(codec, w);
+				break;
+			case snd_soc_dpm_mux:
+				dpm_sync_mux(codec, w);
+				break;
+			case snd_soc_dpm_adc:
+			case snd_soc_dpm_dac:
+			case snd_soc_dpm_volume:
+			case snd_soc_dpm_input:
+			case snd_soc_dpm_output:
+			case snd_soc_dpm_clock:
+			case snd_soc_dpm_vref:				
+				break;
+		}
+	}
+	
+	dpm_power_widgets(codec);
 	return 0;
 }
 
@@ -663,7 +602,7 @@ int snd_soc_dpm_put_volsw(snd_kcontrol_t
 		val |= val2 << rshift;
 	}
 	
-	dpm_mixer_update_power(widget, kcontrol, reg, val_mask, val);
+	dpm_mixer_update_power(widget, kcontrol, reg, val_mask, val, invert);
 	return snd_soc_update_bits(widget->codec, reg, val_mask, val);
 }
 
@@ -707,6 +646,95 @@ int snd_soc_dpm_put_enum_double(snd_kcon
 	return snd_soc_update_bits(widget->codec, e->reg, mask, val);
 }
 
+int snd_soc_dpm_new_control(snd_soc_codec_t *codec, const snd_soc_dpm_widget_t *widget)
+{
+	snd_soc_dpm_widget_t *w;
+	
+	if ((w = dpm_cnew_widget(widget)) == NULL)
+		return -ENOMEM;
+
+	w->codec = codec;
+	INIT_LIST_HEAD(&w->inputs);
+	INIT_LIST_HEAD(&w->outputs);
+	INIT_LIST_HEAD(&w->list);
+	list_add(&w->list, &codec->dpm_widgets);
+	
+	// liam - remove when implemented
+	w->connected = 1; // liam - set by .asoundrc extension or machine layer
+	
+	return 0;
+}
+
+int snd_soc_dpm_stream_event(snd_soc_codec_t *codec, char * stream, int event)
+{
+	snd_soc_dpm_widget_t *w;
+	struct list_head *l = NULL;	
+	
+	list_for_each(l, &codec->dpm_widgets)
+	{
+		w = list_entry(l, snd_soc_dpm_widget_t, list);
+
+		if (!w->sname)
+			continue;
+		
+		if (strstr(w->sname, stream)) {
+			switch(event) {
+				case SND_SOC_DPM_STREAM_START:
+					w->active = 1;
+					break;
+				case SND_SOC_DPM_STREAM_STOP:
+				case SND_SOC_DPM_STREAM_SUSPEND:	
+					w->active = 0;
+					break;
+				case SND_SOC_DPM_STREAM_PAUSE_PUSH:
+					break;
+				case SND_SOC_DPM_STREAM_PAUSE_RELEASE:
+					break;
+			}
+		}					
+	}
+	
+	dpm_power_widgets(codec);
+	return 0;
+}
+
+int snd_soc_dpm_codec_event(snd_soc_codec_t *codec, int event)
+{
+	snd_soc_dpm_widget_t *w;
+	struct list_head *l = NULL;	
+	int pm = 0, active = 0;
+
+	if(event == SND_SOC_DPM_CODEC_ON) {
+		if(codec->active_streams)
+			return 0;
+		pm = 1;
+		active = 1;
+	
+	} else if(event == SND_SOC_DPM_CODEC_OFF){
+		if(!codec->active_streams)
+			return 0;
+		pm = 0;
+		active = -1;
+	}
+
+	list_for_each(l, &codec->dpm_widgets)
+	{
+		int tpm = pm;
+		w = list_entry(l, snd_soc_dpm_widget_t, list);
+		if(w->id == snd_soc_dpm_vref || w->id == snd_soc_dpm_clock) {
+			codec->active_streams += active;
+			
+			if(w->invert)
+				tpm = (pm ? 0:1);
+			
+			dpm_update_bits(w, tpm);
+			//printk("active %d name %s state %d\n", codec->active_streams, w->name, tpm);	
+		}
+	}
+
+	return 0;
+}
+
 EXPORT_SYMBOL_GPL(snd_soc_dpm_put_volsw);
 EXPORT_SYMBOL_GPL(snd_soc_dpm_get_volsw);
 EXPORT_SYMBOL_GPL(snd_soc_dpm_connect_input);
@@ -714,6 +742,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dpm_new_contro
 EXPORT_SYMBOL_GPL(snd_soc_dpm_sync);
 EXPORT_SYMBOL_GPL(snd_soc_dpm_put_enum_double);
 EXPORT_SYMBOL_GPL(snd_soc_dpm_get_enum_double);
+EXPORT_SYMBOL_GPL(snd_soc_dpm_stream_event);
+EXPORT_SYMBOL_GPL(snd_soc_dpm_codec_event);
 
 /* Module information */ 
 MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 42afeee..0bff291 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -34,7 +34,7 @@
 #include "wm8753.h"
 
 #define AUDIO_NAME "wm8753"
-#define WM8753_VERSION "0.1"
+#define WM8753_VERSION "0.2"
 
 
 /*
@@ -371,32 +371,32 @@ static const char* wm8753_adc_filter[] =
 static const char* wm8753_mic_sel[] = {"Mic 1", "Mic 2", "Mic 3"};
 
 static const struct soc_enum wm8753_enum[] = {
-SOC_ENUM_SINGLE(WM8753_BASS, 7, 2, wm8753_base),
-SOC_ENUM_SINGLE(WM8753_BASS, 4, 6, wm8753_base_filter),
-SOC_ENUM_SINGLE(WM8753_TREBLE, 6, 2, wm8753_treble),
-SOC_ENUM_SINGLE(WM8753_ALC1, 7, 4, wm8753_alc_func),
-SOC_ENUM_SINGLE(WM8753_NGATE, 1, 2, wm8753_ng_type),
-SOC_ENUM_SINGLE(WM8753_3D, 7, 2, wm8753_3d_func),
-SOC_ENUM_SINGLE(WM8753_3D, 6, 2, wm8753_3d_uc),
-SOC_ENUM_SINGLE(WM8753_3D, 5, 2, wm8753_3d_lc),
-SOC_ENUM_SINGLE(WM8753_DAC, 1, 4, wm8753_deemp),
-SOC_ENUM_SINGLE(WM8753_DAC, 4, 4, wm8753_mono_mix),
-SOC_ENUM_SINGLE(WM8753_DAC, 6, 2, wm8753_dac_phase),
-SOC_ENUM_SINGLE(WM8753_INCTL1, 3, 4, wm8753_line_mix),
-SOC_ENUM_SINGLE(WM8753_INCTL1, 2, 2, wm8753_mono_mux),
-SOC_ENUM_SINGLE(WM8753_INCTL1, 1, 2, wm8753_right_mux),
-SOC_ENUM_SINGLE(WM8753_INCTL1, 0, 2, wm8753_left_mux),
-SOC_ENUM_SINGLE(WM8753_INCTL2, 6, 4, wm8753_rxmsel),
-SOC_ENUM_SINGLE(WM8753_INCTL2, 4, 4, wm8753_sidetone_mux),
-SOC_ENUM_SINGLE(WM8753_OUTCTL, 7, 4, wm8753_mono2_src),
-SOC_ENUM_SINGLE(WM8753_OUTCTL, 0, 3, wm8753_out3),
-SOC_ENUM_SINGLE(WM8753_OUTCTL, 0, 3, wm8753_out4),
-SOC_ENUM_SINGLE(WM8753_ADCIN, 2, 3, wm8753_radcsel),
-SOC_ENUM_SINGLE(WM8753_ADCIN, 0, 3, wm8753_ladcsel),
-SOC_ENUM_SINGLE(WM8753_ADCIN, 4, 4, wm8753_mono_adc),
-SOC_ENUM_SINGLE(WM8753_ADC, 2, 4, wm8753_adc_hp),
-SOC_ENUM_SINGLE(WM8753_ADC, 4, 2, wm8753_adc_filter),
-SOC_ENUM_SINGLE(WM8753_MICBIAS, 6, 3, wm8753_mic_sel),
+SOC_ENUM_SINGLE(WM8753_BASS, 7, 2, wm8753_base),		// 0
+SOC_ENUM_SINGLE(WM8753_BASS, 4, 6, wm8753_base_filter),	// 1
+SOC_ENUM_SINGLE(WM8753_TREBLE, 6, 2, wm8753_treble), 	// 2
+SOC_ENUM_SINGLE(WM8753_ALC1, 7, 4, wm8753_alc_func),	// 3
+SOC_ENUM_SINGLE(WM8753_NGATE, 1, 2, wm8753_ng_type),	// 4
+SOC_ENUM_SINGLE(WM8753_3D, 7, 2, wm8753_3d_func),		// 5
+SOC_ENUM_SINGLE(WM8753_3D, 6, 2, wm8753_3d_uc),			// 6
+SOC_ENUM_SINGLE(WM8753_3D, 5, 2, wm8753_3d_lc),			// 7
+SOC_ENUM_SINGLE(WM8753_DAC, 1, 4, wm8753_deemp),		// 8
+SOC_ENUM_SINGLE(WM8753_DAC, 4, 4, wm8753_mono_mix),		// 9
+SOC_ENUM_SINGLE(WM8753_DAC, 6, 2, wm8753_dac_phase),	// 10
+SOC_ENUM_SINGLE(WM8753_INCTL1, 3, 4, wm8753_line_mix),	// 11
+SOC_ENUM_SINGLE(WM8753_INCTL1, 2, 2, wm8753_mono_mux),	// 12
+SOC_ENUM_SINGLE(WM8753_INCTL1, 1, 2, wm8753_right_mux),	// 13
+SOC_ENUM_SINGLE(WM8753_INCTL1, 0, 2, wm8753_left_mux),	// 14
+SOC_ENUM_SINGLE(WM8753_INCTL2, 6, 4, wm8753_rxmsel),	// 15
+SOC_ENUM_SINGLE(WM8753_INCTL2, 4, 4, wm8753_sidetone_mux),// 16
+SOC_ENUM_SINGLE(WM8753_OUTCTL, 7, 4, wm8753_mono2_src),	// 17
+SOC_ENUM_SINGLE(WM8753_OUTCTL, 0, 3, wm8753_out3),		// 18
+SOC_ENUM_SINGLE(WM8753_ADCTL2, 7, 3, wm8753_out4),		// 19
+SOC_ENUM_SINGLE(WM8753_ADCIN, 2, 3, wm8753_radcsel),	// 20
+SOC_ENUM_SINGLE(WM8753_ADCIN, 0, 3, wm8753_ladcsel),	// 21
+SOC_ENUM_SINGLE(WM8753_ADCIN, 4, 4, wm8753_mono_adc),	// 22
+SOC_ENUM_SINGLE(WM8753_ADC, 2, 4, wm8753_adc_hp),		// 23
+SOC_ENUM_SINGLE(WM8753_ADC, 4, 2, wm8753_adc_filter),	// 24
+SOC_ENUM_SINGLE(WM8753_MICBIAS, 6, 3, wm8753_mic_sel),	// 25
 };
 
 static const snd_kcontrol_new_t wm8753_snd_controls[] = {
@@ -455,9 +455,8 @@ SOC_SINGLE("Capture Right Volume", WM875
 SOC_SINGLE("Capture Right ZC Switch", WM8753_RINVOL, 6, 1, 0),
 SOC_SINGLE("Capture Right Switch", WM8753_RINVOL, 7, 1, 1),
 
-SOC_ENUM("Capture Mono Mix", wm8753_enum[20]),
-SOC_ENUM("Capture Filter Select", wm8753_enum[22]),
-SOC_ENUM("Capture Filter Cut-off", wm8753_enum[21]),
+SOC_ENUM("Capture Filter Select", wm8753_enum[23]),
+SOC_ENUM("Capture Filter Cut-off", wm8753_enum[24]),
 SOC_SINGLE("Capture Filter Switch", WM8753_ADC, 0, 1, 1),
 
 SOC_SINGLE("ALC Target Volume", WM8753_ALC1, 0, 7, 0),
@@ -548,7 +547,7 @@ SOC_DPM_ENUM("Source", wm8753_enum[19]),
 
 /* ADC Mono Mix */
 static const snd_kcontrol_new_t wm8753_adc_mono_controls[] = {
-SOC_DPM_ENUM("Source", wm8753_enum[9]),
+SOC_DPM_ENUM("Source", wm8753_enum[22]),
 };
 
 /* ST Record mixer */
@@ -560,12 +559,12 @@ SOC_DPM_SINGLE("Right Switch", WM8753_RE
 
 /* Left ADC mux */
 static const snd_kcontrol_new_t wm8753_adc_left_controls[] = {
-SOC_DPM_ENUM("Source", wm8753_enum[20]),
+SOC_DPM_ENUM("Source", wm8753_enum[21]),
 };
 
 /* Right ADC mux */
 static const snd_kcontrol_new_t wm8753_adc_right_controls[] = {
-SOC_DPM_ENUM("Source", wm8753_enum[21]),
+SOC_DPM_ENUM("Source", wm8753_enum[20]),
 };
 
 /* MIC mux */
@@ -612,6 +611,8 @@ SOC_DPM_ENUM("Source", wm8753_enum[25]),
 };
 
 static const snd_soc_dpm_widget_t wm8753_dpm_widgets[] = {
+SND_SOC_DPM_VREF("WM8753 VRef", WM8753_PWR1, 6, 0),
+SND_SOC_DPM_CLOCK("WM8753 Clock", WM8753_PWR1, 0, 1),
 SND_SOC_DPM_MIXER("Left Mixer", WM8753_PWR4, 0, 0, &wm8753_left_mixer_controls[0], 
 	ARRAY_SIZE(wm8753_left_mixer_controls)),
 SND_SOC_DPM_VOLUME("Left Out 1", WM8753_PWR3, 8, 0, NULL, 0),
@@ -688,9 +689,6 @@ SND_SOC_DPM_INPUT("MIC2N"),
 SND_SOC_DPM_INPUT("MIC2"),
 };
 
-/*
- * VERY EXPERIMENTAL - 
- */
 static int wm8753_add_widgets(snd_soc_codec_t *codec)
 {
 	int i;
@@ -854,7 +852,7 @@ static int wm8753_add_widgets(snd_soc_co
 	snd_soc_dpm_connect_input(codec, "ACOP", NULL, "ALC Mixer");
 	
 	/* ACIN --> ACOP */
-	// liam - make this a mod param
+	// liam - make this a mod param OR better still machine layer
 	snd_soc_dpm_connect_input(codec, "ACIN", NULL, "ACOP");
 	
 	snd_soc_dpm_sync(codec);
@@ -868,7 +866,6 @@ static int wm8753_add_widgets(snd_soc_co
 static u32 wm8753_config_pll(int pll, u32 speed)
 {
 	u16 clk;
-	printk("config pll %d %d\n", pll, speed);
 
     if (pll == 1) {
 		clk = wm8753_read_reg_cache(WM8753_CLOCK) & 0x0010;
@@ -952,51 +949,6 @@ static u32 wm8753_config_pll(int pll, u3
 	return speed;
 }
 
-
-/*
- * Power up the codec -- WE ARE NOW ALMOST DOING THIS IN DPM
- */
-static int wm8753_power_up(snd_pcm_substream_t *substream)
-{	
-	u16 pwr = 0xfc;
-	
-	/* set Vmid to 5kOhm, enable VREF and VDAC */
-	if (wm8753_2w_write(wm8753.i2c, WM8753_PWR1, 0x0100 | pwr) != 0)
-		return -EIO;
-
-	/* enable MIC1 preamp, ALC mix and left ADC */
-	//if (wm8753_2w_write(wm8753.i2c, WM8753_PWR2, 0x01ff) != 0)	
-	//	return -EIO;
-	
-	/* enable LOUT 1, ROUT1, MONO1 */
-	//if (wm8753_2w_write(wm8753.i2c, WM8753_PWR3, 0x01ff) != 0)
-	//	return -EIO;
-	
-	/* enable left, mono mixer */
-	//if (wm8753_2w_write(wm8753.i2c, WM8753_PWR4, 0x0000) != 0)
-	//	return -EIO;
-	
-	/* let WM8753 powerup and then set Vmid to 50kOhm */
-	mdelay(1);
-	if (wm8753_2w_write(wm8753.i2c, WM8753_PWR1, pwr) != 0)
-		return -EIO;
-	
-	return 0;
-}
-
-/* WE CAN USE DPM IN NEAR FUTURE */
-static int wm8753_power_down(snd_pcm_substream_t *substream)
-{
-	if ((wm8753_2w_write(wm8753.i2c, WM8753_PWR1, 0x0100) != 0) &&
-		(wm8753_2w_write(wm8753.i2c, WM8753_PWR2, 0x0000) != 0) &&
-		(wm8753_2w_write(wm8753.i2c, WM8753_PWR3, 0x0000) != 0) &&
-		(wm8753_2w_write(wm8753.i2c, WM8753_PWR4, 0x0000) != 0)) {
-			err("could not powerdown WM8753");
-			return -EIO;
-		}
-	return 0;
-}
-
 static int wm8753_pcm_voice_startup(snd_pcm_substream_t *substream)
 {
 	//snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1006,7 +958,7 @@ static int wm8753_pcm_voice_startup(snd_
 
 static void wm8753_pcm_voice_shutdown(snd_pcm_substream_t *substream)
 {
-	wm8753_power_down(substream);
+
 }
 
 static int wm8753_pcm_voice_prepare(snd_pcm_substream_t *substream)
@@ -1090,13 +1042,13 @@ static int wm8753_pcm_voice_prepare(snd_
 
 static int wm8753_pcm_hifi_startup(snd_pcm_substream_t *substream)
 {
-	wm8753_power_up(substream);
+
 	return 0;
 }
 
 static void wm8753_pcm_hifi_shutdown(snd_pcm_substream_t *substream)
 {	
-	wm8753_power_down(substream);
+
 }
 
 static int wm8753_pcm_hifi_prepare(snd_pcm_substream_t *substream)
@@ -1258,7 +1210,7 @@ static int wm8753_probe(snd_soc_codec_t 
 		err("no interfaces selected");
 		return -ENODEV;
 	}
-	
+
 	/* check platform for interfaces */
 	if(voice && snd_soc_iface_query(SND_SOC_SSP, 1)) {
 		err("voice interface not available");
@@ -1290,6 +1242,9 @@ static int wm8753_probe(snd_soc_codec_t 
 		return ret;
 	}
 	
+	/* set vmid to 50k - liam move to dpm */
+	wm8753_2w_write(wm8753.i2c, WM8753_PWR1, 0x0080);
+	
 	/* set the update bits */
 	reg = wm8753_read_reg_cache(WM8753_LDAC);
 	wm8753_2w_write(wm8753.i2c, WM8753_LDAC, reg | 0x0100);
@@ -1307,7 +1262,7 @@ static int wm8753_probe(snd_soc_codec_t 
 	wm8753_2w_write(wm8753.i2c, WM8753_LINVOL, reg | 0x0100);
 	reg = wm8753_read_reg_cache(WM8753_RINVOL);
 	wm8753_2w_write(wm8753.i2c, WM8753_RINVOL, reg | 0x0100);
-	
+
 	wm8753_add_controls(&wm8753_soc_codec);
 	wm8753_add_widgets(&wm8753_soc_codec);
 
@@ -1319,6 +1274,8 @@ static int wm8753_probe(snd_soc_codec_t 
  */
 static void wm8753_remove(snd_soc_codec_t *codec)
 {
+	/* power down vmid - liam move to dpm */
+	wm8753_2w_write(wm8753.i2c, WM8753_PWR1, 0x0000);
 	i2c_del_driver(&wm8753_i2c_driver);
 }
 
@@ -1344,7 +1301,6 @@ static int __init wm8753_init(void)
 
 static void __exit wm8753_exit(void)
 {
-	printk("%s %s %d\n",  __FILE__, __FUNCTION__, __LINE__);
 	snd_soc_unregister_codec(&wm8753_soc_codec);
 }
 
diff --git a/sound/soc/codecs/wm8753.h b/sound/soc/codecs/wm8753.h
index ec7451b..c7f2a6b 100644
--- a/sound/soc/codecs/wm8753.h
+++ b/sound/soc/codecs/wm8753.h
@@ -78,27 +78,4 @@
 #define WM8753_BIASCTL	0x3d
 #define WM8753_ADCTL2	0x3f
 
-/* Voice DAC sample rates */
-#define WM8753_VD8K		(0x6 << 6)
-#define WM8753_VD12K	(0x5 << 6)
-#define WM8753_VD16K	(0x2 << 6)
-#define WM8753_VD24K	(0x4 << 6)
-#define WM8753_VD48K	(0x0 << 6)
-
-
-/* Hifi ADC/DAC sample rates */
-#define WM8753_A8D8		0x0006
-#define WM8753_A8D48	0x0004
-#define WM8753_A12D12	0x0008
-#define WM8753_A16D16	0x000a
-#define WM8753_A24D24	0x001c
-#define WM8753_A32D32	0x000c
-#define WM8753_A48D8	0x0002
-#define WM8753_A48D48	0x0000
-#define WM8753_A96D96	0x000e
-
-struct wm8753_mixer_t {
-	int dev_mixer;
-};
-
 #endif
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 5dffc04..15c156d 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -108,20 +108,13 @@ static u32 get_sadiv(int rate)
 
 static int pxa2xx_i2s_startup(snd_pcm_substream_t *substream)
 {	
+	SACR0 |= SACR0_RST;
+	SACR0 = 0;
 	return 0;
 }
 
-/* do we need 2 waits..... - needs more testing */
-static int pxa_i2s_wait_ready(void)
-{
-	int i;
-	/* flush the Rx FIFO */
-	for(i = 0; i < 16; i++)
-		SADR;
-	return 0;
-}
-
-static int pxa_i2s_wait_close(void)
+/* wait for I2S controller to be ready */
+static int pxa_i2s_wait(void)
 {
 	int i;
 	/* flush the Rx FIFO */
@@ -145,7 +138,7 @@ static int pxa2xx_i2s_hw_params(snd_pcm_
 	pxa_gpio_mode(gpio_bus[master].frm);
 	pxa_gpio_mode(gpio_bus[master].clk);
 	pxa_set_cken(CKEN8_I2S, 1);
-	pxa_i2s_wait_ready();
+	pxa_i2s_wait();
 	
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		if (params_channels(params) == 2)
@@ -158,36 +151,6 @@ static int pxa2xx_i2s_hw_params(snd_pcm_
 		else
 			pcm_i->platform_data = &pxa2xx_i2s_pcm_mono_in;
 	}
-	printk("hw sub rate %d chn %d\n", params_rate(params), params_channels(params));
-	return 0;
-}
-
-static void pxa2xx_i2s_shutdown(snd_pcm_substream_t *substream)
-{
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		SACR1 |= SACR1_DRPL;
-		SAIMR &= ~SAIMR_TFS;
-	} else {
-		SACR1 |= SACR1_DREC;
-		SAIMR &= ~SAIMR_RFS;
-	}
-
-	if (SACR1 & (SACR1_DREC | SACR1_DRPL)) {
-		pxa_i2s_wait_close();
-		SACR0 &= ~SACR0_ENB;
-		pxa_set_cken(CKEN8_I2S, 0);
-	}
-}
-
-static int pxa2xx_i2s_prepare(snd_pcm_substream_t *substream)
-{
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
-	int master = 0;
-	
-	if(pcm_i->hw_runtime.hformat & SND_SOC_HWFMT_CBS_CFS)
-		master = 1;
 	
 	/* is port used by another stream */
 	if (SACR0 & SACR0_ENB) {
@@ -226,6 +189,24 @@ static int pxa2xx_i2s_prepare(snd_pcm_su
 	return 0;
 }
 
+static void pxa2xx_i2s_shutdown(snd_pcm_substream_t *substream)
+{
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		SACR1 |= SACR1_DRPL;
+		SAIMR &= ~SAIMR_TFS;
+	} else {
+		SACR1 |= SACR1_DREC;
+		SAIMR &= ~SAIMR_RFS;
+	}
+
+	if (SACR1 & (SACR1_DREC | SACR1_DRPL)) {
+		pxa_i2s_wait();
+		SACR0 &= ~SACR0_ENB;
+		pxa_set_cken(CKEN8_I2S, 0);
+	}
+}
+
 #ifdef CONFIG_PM
 static int pxa2xx_i2s_suspend(snd_soc_pcm_interface_t *interface, pm_message_t state)
 {
@@ -252,21 +233,10 @@ static int pxa2xx_i2s_resume(snd_soc_pcm
 #define pxa2xx_i2s_resume	NULL
 #endif
 
-static int pxa2xx_i2s_probe(snd_soc_pcm_interface_t *interface)
-{
-	return 0;
-}
-
-static void pxa2xx_i2s_remove(snd_soc_pcm_interface_t *interface)
-{
-}
-
 static snd_soc_pcm_interface_t pxa_i2s_interface[] = {
 	{	.name = "pxa2xx-i2s",
 		.id = 0,
 		.type = SND_SOC_I2S,
-		.probe = pxa2xx_i2s_probe,
-		.remove = pxa2xx_i2s_remove,
 		.suspend = pxa2xx_i2s_suspend,
 		.resume = pxa2xx_i2s_resume,
 		.playback = {
@@ -286,7 +256,6 @@ static snd_soc_pcm_interface_t pxa_i2s_i
 		.ops = {
 			.startup = pxa2xx_i2s_startup,
 			.shutdown = pxa2xx_i2s_shutdown,
-			.prepare = pxa2xx_i2s_prepare,
 			.hw_params = pxa2xx_i2s_hw_params,},
 		.hw = {
 			.num_hmodes = ARRAY_SIZE(pxa2xx_i2s),
diff --git a/sound/soc/pxa/pxa2xx-ssp.c b/sound/soc/pxa/pxa2xx-ssp.c
index 7df14f4..fd1102c 100644
--- a/sound/soc/pxa/pxa2xx-ssp.c
+++ b/sound/soc/pxa/pxa2xx-ssp.c
@@ -275,6 +275,8 @@ static int pxa2xx_ssp_hw_params(snd_pcm_
 	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
 	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
 	int master = 0, dma = 0;
+	u32 ssp_mode = 0, ssp_setup = 0, psp_mode = 0;
+	int bits = generic_ffs(pcm_i->hw_runtime.hbits);
 	
 	if(pcm_i->hw_runtime.hformat & SND_SOC_HWFMT_CBS_CFS)
 		master = 1;
@@ -284,23 +286,12 @@ static int pxa2xx_ssp_hw_params(snd_pcm_
 	pxa_gpio_mode(ssp_gpios[pcm_i->id][master].frm);
 	pxa_gpio_mode(ssp_gpios[pcm_i->id][master].clk);
 	
-	
 	if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
 		dma = 1;
 	if (params_channels(params) == 2)
 		dma += 2;
 	pcm_i->platform_data = ssp_dma_params[pcm_i->id][dma];
 	
-	return 0;
-}
-
-static int pxa2xx_ssp_prepare(snd_pcm_substream_t *substream)
-{
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
-	u32 ssp_mode = 0, ssp_setup = 0, psp_mode = 0;
-	int bits = generic_ffs(pcm_i->hw_runtime.hbits);
-	
 	ssp_mode = SSCR0_PSP | SSCR0_DataSize(bits);
 	ssp_setup = SSCR1_RxTresh(14) | SSCR1_TxTresh(1) | SSCR1_TRAIL |
 				SSCR1_TSRE | SSCR1_RSRE | SSCR1_TIE | SSCR1_RIE;
@@ -331,26 +322,14 @@ static int pxa2xx_ssp_prepare(snd_pcm_su
 	ssp_config(&ssp[pcm_i->id], ssp_mode, ssp_setup, psp_mode,
 					SSCR0_SerClkDiv(pcm_i->hw_runtime.priv1));
 	ssp_enable(&ssp[pcm_i->id]);
-	
-	return 0;
-}
 
-static int pxa2xx_ssp_probe(snd_soc_pcm_interface_t *interface)
-{
 	return 0;
 }
 
-static void pxa2xx_ssp_remove(snd_soc_pcm_interface_t *interface)
-{
-}
-
-
 static snd_soc_pcm_interface_t pxa_ssp_interfaces[] = {
 	{	.name = "pxa2xx-ssp1",
 		.id = 0,
 		.type = SND_SOC_SSP,
-		.probe = pxa2xx_ssp_probe,
-		.remove = pxa2xx_ssp_remove,
 		.suspend = pxa2xx_ssp_suspend,
 		.resume = pxa2xx_ssp_resume,
 		.playback = {
@@ -368,7 +347,6 @@ static snd_soc_pcm_interface_t pxa_ssp_i
 		.ops = {
 			.startup = pxa2xx_ssp_startup,
 			.shutdown = pxa2xx_ssp_shutdown,
-			.prepare = pxa2xx_ssp_prepare,
 			.hw_params = pxa2xx_ssp_hw_params,},
 		.hw = {
 			.hmodes = &pxa2xx_ssp[0],
@@ -377,8 +355,6 @@ static snd_soc_pcm_interface_t pxa_ssp_i
 	{	.name = "pxa2xx-ssp2",
 		.id = 1,
 		.type = SND_SOC_SSP,
-		.probe = pxa2xx_ssp_probe,
-		.remove = pxa2xx_ssp_remove,
 		.suspend = pxa2xx_ssp_suspend,
 		.resume = pxa2xx_ssp_resume,
 		.playback = {
@@ -396,7 +372,6 @@ static snd_soc_pcm_interface_t pxa_ssp_i
 		.ops = {
 			.startup = pxa2xx_ssp_startup,
 			.shutdown = pxa2xx_ssp_shutdown,
-			.prepare = pxa2xx_ssp_prepare,
 			.hw_params = pxa2xx_ssp_hw_params,},
 		.hw = {
 			.hmodes = &pxa2xx_ssp[0],
@@ -405,8 +380,6 @@ static snd_soc_pcm_interface_t pxa_ssp_i
 	{	.name = "pxa2xx-ssp3",
 		.id = 2,
 		.type = SND_SOC_SSP,
-		.probe = pxa2xx_ssp_probe,
-		.remove = pxa2xx_ssp_remove,
 		.suspend = pxa2xx_ssp_suspend,
 		.resume = pxa2xx_ssp_resume,
 		.playback = {
@@ -424,7 +397,6 @@ static snd_soc_pcm_interface_t pxa_ssp_i
 		.ops = {
 			.startup = pxa2xx_ssp_startup,
 			.shutdown = pxa2xx_ssp_shutdown,
-			.prepare = pxa2xx_ssp_prepare,
 			.hw_params = pxa2xx_ssp_hw_params,},
 		.hw = {
 			.hmodes = &pxa2xx_ssp[0],
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index 5cfad9c..ff691c3 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -248,7 +248,7 @@ static int pxa2xx_pcm_open(snd_pcm_subst
 
 	if (platform_ops && platform_ops->startup)
 		platform_ops->startup(substream, platform_ops->priv);
-	return ret;
+	return 0;
 
  err1:
 	kfree(rtd);
diff --git a/include/sound/soc.h b/include/sound/soc.h
index eb7c2a3..f244a67 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -101,12 +101,24 @@ typedef struct snd_soc_pcm_stream snd_so
 typedef struct snd_soc_ops snd_soc_ops_t;
 typedef struct snd_soc_hw_bus snd_soc_hw_bus_t;
 typedef struct snd_soc_hw_mode snd_soc_hw_mode_t;
+typedef struct snd_soc_machine snd_soc_machine_t;
 
 /*
  * Queries SoC layer for available interface
  */
 int snd_soc_iface_query(int iface_type, int num);
 
+/*
+ * SoC registration objects:-
+ * 
+ *  o Codec (n)
+ *  o Platform (1)
+ *  o Interface (n)
+ *  o Machine (1)
+ * 
+ * Only 1 Platform and Machine may be registered with the SoC layer. However there is
+ * no limit on the number of codecs and interfaces that can be registered.
+ */
 int snd_soc_register_codec(snd_soc_codec_t *codec);
 void snd_soc_unregister_codec(snd_soc_codec_t *codec);
 
@@ -116,12 +128,18 @@ void snd_soc_unregister_platform(snd_soc
 int snd_soc_register_interface(snd_soc_pcm_interface_t *iface);
 void snd_soc_unregister_interface(snd_soc_pcm_interface_t *iface);
 
+int snd_soc_register_machine(snd_soc_machine_t *machine);
+void snd_soc_unregister_machine(snd_soc_machine_t *machine);
+
+/* pcm constructor */
 int snd_soc_pcm_new(snd_soc_codec_t *codec, int dev_no, snd_soc_pcm_codec_t *pcm_c, 
 		snd_pcm_t **rpcm, int play, int capt, int iface_type, int num);
 
 int snd_soc_set_runtime_hw(snd_pcm_substream_t *substream, 
 	const snd_pcm_hardware_t *hw);
 
+
+/* codec register bit access */
 int snd_soc_update_bits(snd_soc_codec_t *codec, unsigned short reg,
 				unsigned short mask, unsigned short value);
 				
@@ -192,6 +210,7 @@ struct snd_soc_pcm_codec {
 	snd_soc_hw_mode_t hw_runtime;
 	snd_soc_ops_t ops;
 	snd_soc_pcm_interface_t *pcm_i;
+	snd_soc_codec_t *codec; // liam - check
 	
 	/* private data */
 	void *priv;
@@ -242,12 +261,15 @@ struct snd_soc_codec {
 	int (*suspend)(snd_soc_codec_t *codec, pm_message_t state);
 	int (*resume)(snd_soc_codec_t *codec);
 	
+	/* runtime */
 	snd_card_t *card;
 	snd_pcm_t *pcm;
 	struct platform_device pdev;
-	snd_soc_pcm_interface_t *interface;
+	snd_soc_pcm_interface_t *interface; // liam - this needs to be 1:n
 	void *private_data;
+	int active_streams;
 	
+	/* codec IO */
 	unsigned int (*read)(u16);
 	int (*write)(u16, unsigned int);
 	
@@ -267,6 +289,17 @@ struct snd_soc_platform {
 	snd_pcm_ops_t *pcm_ops;
 };
 
+/* SoC machine interface */
+struct snd_soc_machine {
+	char *name;
+	
+	int	(*probe)(struct device * dev);
+	int	(*remove)(struct device * dev);
+	struct bus_type	* bus;
+	snd_pcm_ops_t *pcm_ops;
+};
+
+/* enamerated kcontrol */
 struct soc_enum {
 	unsigned short reg;
 	unsigned char shift_l;
diff --git a/include/sound/soc-dpm.h b/include/sound/soc-dpm.h
index df6094d..49cd2c5 100644
--- a/include/sound/soc-dpm.h
+++ b/include/sound/soc-dpm.h
@@ -25,8 +25,8 @@
  * 	1. Codec domain - VREF, VMID
  *     Usually controlled at codec probe/remove, although can be set
  *     at stream time if power is not needed for sidetone, etc.
- *  2. Platform domain - physically connected inputs and outputs
- *     Is platform and user action specific, is set in the .asoundrc file and
+ *  2. Platform/Machine domain - physically connected inputs and outputs
+ *     Is platform/machine and user action specific, is set in the .asoundrc file and
  *     by userspace e.g when HP are inserted
  *  3. Path domain - Internal codec path mixers
  *     Are automatically set when mixer and mux settings are
@@ -35,10 +35,14 @@
  *     Enabled when stream playback/capture is started.  
  */
 
-/* codec domain */  
-#define SND_SOC_DPM_CODEC(wname) \
-{.id = snd_soc_dpm_codec, .name = wname}
-  
+/* codec domain - vmid handled by the codec driver atm */  
+#define SND_SOC_DPM_VREF(wname, preg, pshift, pinvert) \
+{.id = snd_soc_dpm_vref, .name = wname, .reg = preg, .shift = pshift, \
+ .invert = pinvert, .kcontrols = NULL, .num_kcontrols = 0}
+#define SND_SOC_DPM_CLOCK(wname, preg, pshift, pinvert) \
+{.id = snd_soc_dpm_clock, .name = wname, .reg = preg, .shift = pshift, \
+ .invert = pinvert, .kcontrols = NULL, .num_kcontrols = 0}
+ 
 /* platform domain */
 #define SND_SOC_DPM_INPUT(wname) \
 {.id = snd_soc_dpm_input, .name = wname, .kcontrols = NULL, \
@@ -81,7 +85,16 @@
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_soc_info_enum_double, \
   .get = snd_soc_dpm_get_enum_double, .put = snd_soc_dpm_put_enum_double, \
   .private_value = (unsigned long)&xenum }
+
+#define SND_SOC_DPM_STREAM_START		0x1
+#define SND_SOC_DPM_STREAM_STOP			0x2
+#define SND_SOC_DPM_STREAM_SUSPEND		0x4
+#define SND_SOC_DPM_STREAM_PAUSE_PUSH	0x8
+#define SND_SOC_DPM_STREAM_PAUSE_RELEASE	0x10  
   
+#define SND_SOC_DPM_CODEC_ON	0x1
+#define SND_SOC_DPM_CODEC_OFF	0x2
+
 typedef struct snd_soc_dpm_widget snd_soc_dpm_widget_t;
 typedef enum snd_soc_dpm_type snd_soc_dpm_type_t;
 typedef struct snd_soc_dpm_path snd_soc_dpm_path_t;
@@ -94,6 +107,10 @@ int snd_soc_dpm_new_control(snd_soc_code
 int snd_soc_dpm_connect_input(snd_soc_codec_t *codec, char *target_name, 
 	char *control_name, char *src_name);
 int snd_soc_dpm_sync(snd_soc_codec_t *codec);
+int snd_soc_dpm_stream_event(snd_soc_codec_t *codec, char * stream, int event);
+int snd_soc_dpm_codec_event(snd_soc_codec_t *codec, int event);
+void snd_soc_dpm_sys_remove(struct device *dev);
+int snd_soc_dpm_sys_add(struct device *dev);
 
 enum snd_soc_dpm_type {
 	snd_soc_dpm_input = 0,
@@ -103,7 +120,8 @@ enum snd_soc_dpm_type {
 	snd_soc_dpm_volume,
 	snd_soc_dpm_adc,
 	snd_soc_dpm_dac,
-	snd_soc_dpm_codec,
+	snd_soc_dpm_clock,
+	snd_soc_dpm_vref,
 };
 
 struct snd_soc_dpm_path {
@@ -113,9 +131,8 @@ struct snd_soc_dpm_path {
 	snd_soc_dpm_widget_t *out;
 	snd_kcontrol_t *kcontrol;
 	
-	u8 connect:1; /* applies to widget inputs only */
-	u8 checked:1;   /* path has been checked */
-	u8 walked:1;		/* path has been walked */
+	u8 connect:1;	/* applies to widget inputs only */
+	u8 walked:1;	/* path has been walked */
 	
 	struct list_head list_in;
 	struct list_head list_out;
@@ -130,7 +147,7 @@ struct snd_soc_dpm_widget {
 	struct list_head list;
 	
 	/* dpm control */
-	unsigned short reg;
+	short reg;						/* negative reg = no direct dpm */
 	unsigned char shift;
 	unsigned char status;			/* block rules status */ 
 	unsigned char power:1;			/* block power status */

