diff -urN a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
--- a/sound/soc/codecs/ac97.c	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/codecs/ac97.c	2005-11-30 14:56:30.000000000 +0000
@@ -18,7 +18,7 @@
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/kernel.h>
-
+#include <linux/device.h>
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -26,31 +26,10 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 
-static int ac97_soc_add_widgets(struct snd_soc_codec * codec)
-{
-	return 0;
-}
-
-static void ac97_soc_device_release(struct device * dev)
-{
-}
-
-static int ac97_soc_suspend(struct snd_soc_codec *codec, pm_message_t state)
-{
-	//snd_soc_pcm_interface_t *i = codec->interface;
-	//snd_ac97_suspend(i->ac97);
-	return 0;
-}	
-
-static int ac97_soc_resume(struct snd_soc_codec *codec)
-{
-	//snd_soc_pcm_interface_t *i = codec->interface;
-	//snd_ac97_resume(i->ac97);
-	return 0;
-}
+#define AC97_VERSION "0.2"
 
 static struct snd_soc_pcm_codec ac97_soc_client = {
-	.name = "AC97 Audio",
+	.name = "AC97 HiFi",
 	.playback = {
 		.sname = "AC97 Playback",
 		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
@@ -65,55 +44,62 @@
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 		.channels_min = 1,
 		.channels_max = 2,},
+	.nplayback = 1,
+	.ncapture = 1,
 };
 
-static struct snd_soc_codec ac97_soc_codec;
-static snd_pcm_t *pcm_ac97;
-
-static int ac97_soc_probe(struct snd_soc_codec *codec)
+static int ac97_soc_probe(struct device *dev)
 {
-	int ret;
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	ac97_bus_ops_t* soc_ac97_ops = (ac97_bus_ops_t*)codec->control_data;
+	ac97_bus_t *ac97_bus;
+	ac97_template_t ac97_template;
+	int ret = 0;
 	
-//	if((ret = snd_soc_pcm_new(codec, 0, &ac97_soc_client, 
-//		&pcm_ac97, 1, 1, SND_SOC_AC97, 0)) < 0)
-//		return ret;
-	
-	ac97_soc_add_widgets(&ac97_soc_codec);
+	codec->name = "AC97";
+	codec->owner = THIS_MODULE;
+	codec->pcms = &ac97_soc_client;
+	codec->npcms = 1;
+
+	/* register pcms */
+	if((ret = snd_soc_register_pcms(codec)) < 0) {
+		return ret;
+	}
+
+	ret = snd_ac97_bus(codec->card, 0, soc_ac97_ops, NULL, &ac97_bus);
+	if (ret)
+		return ret;
+	memset(&ac97_template, 0, sizeof(ac97_template));
+	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
 
+	snd_soc_register_card(codec);
 	return ret;
 }
 
-/* 
- * unregister interfaces and clean up
- */
-static void ac97_soc_remove(struct snd_soc_codec *codec)
+static int ac97_soc_remove(struct device *dev)
 {
-
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	snd_soc_free_pcms(codec);
+	return 0;
 }
 
-static struct snd_soc_codec ac97_soc_codec = {
-	.name = "SoC AC97",
-	.longname = "ALSA SoC Generic AC97 Codec",
-	.owner = THIS_MODULE,
-	.pdev = {
-		.name		= "SoC AC97 Codec",
-		.id		= -1,
-		.dev		= {.release = ac97_soc_device_release},
-	},
-	.probe = ac97_soc_probe,
-	.remove = ac97_soc_remove,
-	.suspend = ac97_soc_suspend,
-	.resume = ac97_soc_resume,
-};	
+static struct device_driver ac97_soc_driver = {
+	.name = 	"AC97", 
+	.bus = 		&soc_bus_type, 
+	.owner = 	THIS_MODULE, 
+	.probe = 	ac97_soc_probe, 
+	.remove = 	ac97_soc_remove,
+};
 
 static int __init ac97_init(void)
-{	
-	return snd_soc_register_codec(&ac97_soc_codec);
+{
+	printk(KERN_INFO "SoC AC97 Audio Codec %s\n", AC97_VERSION);
+	return driver_register(&ac97_soc_driver);
 }
 
 static void __exit ac97_exit(void)
 {
-	snd_soc_unregister_codec(&ac97_soc_codec);
+	driver_unregister(&ac97_soc_driver);
 }
 
 module_init(ac97_init);
diff -urN a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
--- a/sound/soc/codecs/wm8731.c	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/codecs/wm8731.c	2005-11-28 11:29:32.000000000 +0000
@@ -18,8 +18,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/i2c.h>
 #include <linux/pm.h>
+#include <linux/device.h>
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -31,8 +31,7 @@
 #include "wm8731.h"
 
 #define AUDIO_NAME "wm8731"
-#define WM8731_VERSION "0.4"
-
+#define WM8731_VERSION "0.5"
 
 /*
  * Debug
@@ -50,17 +49,6 @@
 #define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg)
 
-#define I2C_DRIVERID_WM8731 0xf2fe
-
-static unsigned short normal_i2c[] = { 0x1a, 0x1b,
-                                       I2C_CLIENT_END };
-
-/* Magic definition of all other variables and things */
-I2C_CLIENT_INSMOD;
-
-static struct i2c_driver wm8731_i2c_driver;
-static struct i2c_client client_template;
-
 /*
  * wm8731 register cache
  * We can't read the WM8731 register space when we are
@@ -149,17 +137,16 @@
 	unsigned int value)
 {
 	u8 data[2];
-	struct i2c_client* i2c = (struct i2c_client*)codec->control_data;
+	
 	/* data is 
-	 *   D15..D9 WM8731 register offset
+	 *   D15..D9 WM8753 register offset
 	 *   D8...D0 register data
 	 */
 	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
 	data[1] = value & 0x00ff;
 
 	wm8731_write_reg_cache (codec, reg, value);
-
-	if (i2c_master_send(i2c, data, 2) == 2)
+	if (codec->hw_write(codec->control_data, data, 2) == 2)
 		return 0;
 	else
 		return -1;
@@ -360,10 +347,6 @@
 	return 0;
 }
 
-static void wm8731_device_release(struct device * dev)
-{
-}
-
 static int wm8731_dpm_event(struct snd_soc_codec *codec, int event)
 {
 	switch (event) {
@@ -419,81 +402,31 @@
 		.hmodes = &wm8731_hwfmt[0],
 	},
 };
-
-/*
- * initialise the WM8731 driver
- * register the mixer and dsp interfaces with the kernel 
- */
-static int wm8731_probe(struct snd_soc_codec *codec)
+static int wm8731_suspend(struct device *dev, pm_message_t state)
 {
-	int reg;
-	
-	wm8731_reset(codec);
-
-	wm8731_dpm_event(codec, SNDRV_CTL_POWER_D3hot);
-	
-	/* set the update bits */
-	reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V);
-	wm8731_write(codec, WM8731_LOUT1V, reg | 0x0100);
-	reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V);
-	wm8731_write(codec, WM8731_ROUT1V, reg | 0x0100);
-	reg = wm8731_read_reg_cache(codec, WM8731_LINVOL);
-	wm8731_write(codec, WM8731_LINVOL, reg | 0x0100);
-	reg = wm8731_read_reg_cache(codec, WM8731_RINVOL);
-	wm8731_write(codec, WM8731_RINVOL, reg | 0x0100);
-
-	wm8731_add_controls(codec);
-	wm8731_add_widgets(codec);
-
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	wm8731_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
 	return 0;
 }
 
-/* 
- * unregister interfaces and clean up
- */
-static void wm8731_remove(struct snd_soc_codec *codec)
+static int wm8731_resume(struct device *dev)
 {
-	wm8731_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	wm8731_dpm_event(codec, SNDRV_CTL_POWER_D3hot);
+	return 0;
 }
 
 /*
- * Attach WM8731 2 wire client 
+ * initialise the WM8731 driver
+ * register the mixer and dsp interfaces with the kernel 
  */
-static int wm8731_i2c_probe(struct i2c_adapter *adap, int addr, int kind)
-{		
-	int ret = 0;
-	struct snd_soc_codec *codec;
-	struct i2c_client *i2c;
-
-	client_template.adapter = adap;
-	client_template.addr = addr;
-	
-	if ((codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL)) == NULL)
-		return -ENOMEM;
- 
-	if ((i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL)) == NULL){
-		kfree(codec);
-		return -ENOMEM;
-	}
-	memcpy(i2c, &client_template, sizeof(struct i2c_client));
-	codec->control_data = i2c;
-	i2c->dev.platform_data = codec;
-
-	if((ret = i2c_attach_client(i2c)) < 0) {
-		err("failed to attach codec at addr %x\n", addr);
-		kfree(i2c);
-		kfree(codec);
-		return ret;
-	}
+static int wm8731_probe(struct device *dev)
+{
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	int reg, ret = 0;
 
 	codec->name = "WM8731";
-	codec->longname = "WM8731 Portable Codec";
 	codec->owner = THIS_MODULE;
-	codec->pdev.name = "alsa-wm8731";
-	codec->pdev.id = -1;
-	codec->pdev.dev.release = wm8731_device_release;
-	codec->probe = wm8731_probe;
-	codec->remove = wm8731_remove;
 	codec->read = wm8731_read_reg_cache;
 	codec->write = wm8731_write;
 	codec->dpm_event = wm8731_dpm_event;
@@ -503,67 +436,65 @@
 			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8731_reg), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	memcpy(codec->reg_cache, wm8731_reg, sizeof(u16) * ARRAY_SIZE(wm8731_reg));
+	
+	wm8731_reset(codec);
+
+	/* charge output caps */
+	wm8731_dpm_event(codec, SNDRV_CTL_POWER_D2);
 
-	if((ret = snd_soc_register_codec(codec)) < 0) {
-		err("can't register codec");
-		i2c_del_driver(&wm8731_i2c_driver);
-		kfree(i2c);
+	/* register pcms */
+	if((ret = snd_soc_register_pcms(codec)) < 0) {
+		wm8731_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
 		kfree(codec->reg_cache);
-		kfree(codec);
+		return ret;
 	}
+	
+	/* set the update bits */
+	reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V);
+	wm8731_write(codec, WM8731_LOUT1V, reg | 0x0100);
+	reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V);
+	wm8731_write(codec, WM8731_ROUT1V, reg | 0x0100);
+	reg = wm8731_read_reg_cache(codec, WM8731_LINVOL);
+	wm8731_write(codec, WM8731_LINVOL, reg | 0x0100);
+	reg = wm8731_read_reg_cache(codec, WM8731_RINVOL);
+	wm8731_write(codec, WM8731_RINVOL, reg | 0x0100);
 
-	return ret;
-}
-
-static int wm8731_i2c_detach(struct i2c_client *client)
-{
-	struct snd_soc_codec *codec = 
-		(struct snd_soc_codec*)client->dev.platform_data;
+	wm8731_add_controls(codec);
+	wm8731_add_widgets(codec);
+	snd_soc_register_card(codec);
 
-	i2c_detach_client(client);
-	snd_soc_unregister_codec(codec);
-	kfree(codec->reg_cache);
-	kfree(codec->control_data);
-	kfree(codec);
 	return 0;
 }
 
-static int wm8731_i2c_attach(struct i2c_adapter *adap)
+/* power down chip */
+static int wm8731_remove(struct device *dev)
 {
-	return i2c_probe(adap, &addr_data, wm8731_i2c_probe);
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	wm8731_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
+	snd_soc_free_pcms(codec);
+	kfree(codec->reg_cache);
+	return 0;
 }
 
-/* WM8731 2 Wire layer */ 
-static struct i2c_driver wm8731_i2c_driver = {
-	.name =           "i2c wm8731 driver",
-	.id =             I2C_DRIVERID_WM8731,
-	.flags =          I2C_DF_NOTIFY,
-	.attach_adapter = wm8731_i2c_attach,
-	.detach_client =  wm8731_i2c_detach,
-	.command =        NULL,
-};
-
-static struct i2c_client client_template = {
-	.name =   "WM8731",
-	.flags =  I2C_CLIENT_ALLOW_USE,
-	.driver = &wm8731_i2c_driver,
+static struct device_driver wm8731_driver = {
+	.name = 	"WM8731", 
+	.bus = 		&soc_bus_type, 
+	.owner = 	THIS_MODULE, 
+	.probe = 	wm8731_probe, 
+	.remove = 	wm8731_remove, 
+	.suspend = 	wm8731_suspend, 
+	.resume =	wm8731_resume, 
 };
 
 static int __init wm8731_init(void)
-{	
-	int ret = 0;
-	
+{
 	info("WM8731 Audio Codec %s", WM8731_VERSION);
-
-	if ((ret = i2c_add_driver(&wm8731_i2c_driver)) != 0)
-		err("can't add i2c driver");
-	
-	return ret;
+	return driver_register(&wm8731_driver);
 }
 
 static void __exit wm8731_exit(void)
 {
-	i2c_del_driver(&wm8731_i2c_driver);
+	driver_unregister(&wm8731_driver);
 }
 
 module_init(wm8731_init);
diff -urN a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
--- a/sound/soc/codecs/wm8750.c	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/codecs/wm8750.c	2005-11-28 11:30:00.000000000 +0000
@@ -17,8 +17,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
-#include <linux/i2c.h>
-
+#include <linux/device.h>
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -30,7 +29,7 @@
 #include "wm8750.h"
 
 #define AUDIO_NAME "WM8750"
-#define WM8750_VERSION "0.4"
+#define WM8750_VERSION "0.5"
 
 /*
  * Debug
@@ -48,20 +47,6 @@
 #define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg)
 
-
-/* 
- * WM8750 2 wire address is determined by CSB pin state during powerup */
-#define I2C_DRIVERID_WM8750 0xfde
-
-static unsigned short normal_i2c[] = {  0x1a, 0x1b,
-                                       I2C_CLIENT_END };
-
-/* Magic definition of all other variables and things */
-I2C_CLIENT_INSMOD;
-
-static struct i2c_driver wm8750_i2c_driver;
-static struct i2c_client client_template;
-	
 /*
  * wm8750 register cache
  * We can't read the WM8750 register space when we 
@@ -173,17 +158,16 @@
 	unsigned int value)
 {
 	u8 data[2];
-	struct i2c_client *i2c = (struct i2c_client*)codec->control_data;
-
+	
 	/* data is 
-	 *   D15..D9 WM8750 register offset
+	 *   D15..D9 WM8753 register offset
 	 *   D8...D0 register data
 	 */
 	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
 	data[1] = value & 0x00ff;
 
 	wm8750_write_reg_cache (codec, reg, value);
-	if (i2c_master_send(i2c, data, 2) == 2)
+	if (codec->hw_write(codec->control_data, data, 2) == 2)
 		return 0;
 	else
 		return -1;
@@ -637,10 +621,6 @@
 	return 0;
 }
 
-static void wm8750_device_release(struct device * dev)
-{
-}
-
 static int wm8750_dpm_event(struct snd_soc_codec *codec, int event)
 {
 	u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3f;
@@ -698,21 +678,53 @@
 	},
 };
 
+static int wm8750_suspend(struct device *dev, pm_message_t state)
+{
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	wm8750_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
+	return 0;
+}
+
+static int wm8750_resume(struct device *dev)
+{
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	wm8750_dpm_event(codec, SNDRV_CTL_POWER_D3hot);
+	return 0;
+}
+
 /*
  * initialise the WM8750 driver
  * register the mixer and dsp interfaces with the kernel 
  */
-static int wm8750_probe(struct snd_soc_codec *codec)
+static int wm8750_probe(struct device *dev)
 {
-	int reg;
-	
-	info("WM8750 Audio Codec %s", WM8750_VERSION);
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	int reg, ret = 0;
+
+	codec->name = "WM8750";
+	codec->owner = THIS_MODULE;
+	codec->read = wm8750_read_reg_cache;
+	codec->write = wm8750_write;
+	codec->dpm_event = wm8750_dpm_event;
+	codec->pcms = &wm8750_pcm_client;
+	codec->npcms = 1;
+	if ((codec->reg_cache = 
+			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8750_reg), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+	memcpy(codec->reg_cache, wm8750_reg, sizeof(u16) * ARRAY_SIZE(wm8750_reg));
 	
 	wm8750_reset(codec);
-	
+
 	/* charge output caps */
 	wm8750_dpm_event(codec, SNDRV_CTL_POWER_D2);
 
+	/* register pcms */
+	if((ret = snd_soc_register_pcms(codec)) < 0) {
+		wm8750_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
+		kfree(codec->reg_cache);
+		return ret;
+	}
+
 	/* set the update bits */
 	reg = wm8750_read_reg_cache(codec, WM8750_LDAC);
 	wm8750_write(codec, WM8750_LDAC, reg | 0x0100);
@@ -733,6 +745,7 @@
 
 	wm8750_add_controls(codec);
 	wm8750_add_widgets(codec);
+	snd_soc_register_card(codec);
 	
 	/* wait for caps to finish charging - liam make this thread */
 	ssleep(1);
@@ -741,122 +754,35 @@
 	return 0;
 }
 
-/* 
- * unregister interfaces and clean up
- */
-static void wm8750_remove(struct snd_soc_codec *codec)
+/* power down chip */
+static int wm8750_remove(struct device *dev)
 {
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
 	wm8750_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
-}
-
-/*
- * Attach WM8750 2 wire client 
- */
-static int wm8750_i2c_probe(struct i2c_adapter *adap, int addr, int kind)
-{		
-	int ret = 0;
-	struct snd_soc_codec *codec;
-	struct i2c_client *i2c;
-
-	client_template.adapter = adap;
-	client_template.addr = addr;
-	
-	if ((codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL)) == NULL)
-		return -ENOMEM;
- 
-	if ((i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL)) == NULL){
-		kfree(codec);
-		return -ENOMEM;
-	}
-	memcpy(i2c, &client_template, sizeof(struct i2c_client));
-	codec->control_data = i2c;
-	i2c->dev.platform_data = codec;
-
-	if((ret = i2c_attach_client(i2c)) < 0) {
-		err("failed to attach codec at addr %x\n", addr);
-		kfree(i2c);
-		kfree(codec);
-		return ret;
-	}
-
-	codec->name = "WM8750";
-	codec->longname = "WM8750 Portable Codec";
-	codec->owner = THIS_MODULE;
-	codec->pdev.name = "alsa-wm8750";
-	codec->pdev.id = -1;
-	codec->pdev.dev.release = wm8750_device_release;
-	codec->probe = wm8750_probe;
-	codec->remove = wm8750_remove;
-	codec->read = wm8750_read_reg_cache;
-	codec->write = wm8750_write;
-	codec->dpm_event = wm8750_dpm_event;
-	codec->pcms = &wm8750_pcm_client;
-	codec->npcms = 1;
-	if ((codec->reg_cache = 
-			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8750_reg), GFP_KERNEL)) == NULL)
-		return -ENOMEM;
-	memcpy(codec->reg_cache, wm8750_reg, sizeof(u16) * ARRAY_SIZE(wm8750_reg));
-
-	if((ret = snd_soc_register_codec(codec)) < 0) {
-		err("can't register codec");
-		i2c_del_driver(&wm8750_i2c_driver);
-		kfree(i2c);
-		kfree(codec->reg_cache);
-		kfree(codec);
-	}
-
-	return ret;
-}
-
-static int wm8750_i2c_detach(struct i2c_client *client)
-{
-	struct snd_soc_codec *codec = 
-		(struct snd_soc_codec*)client->dev.platform_data;
-			
-	i2c_detach_client(client);
-	snd_soc_unregister_codec(codec);
-	kfree(codec->control_data);
+	snd_soc_free_pcms(codec);
 	kfree(codec->reg_cache);
-	kfree(codec);
 	return 0;
 }
 
-static int wm8750_i2c_attach(struct i2c_adapter *adap)
-{
-	return i2c_probe(adap, &addr_data, wm8750_i2c_probe);
-}
-
-/* WM8750 2 Wire layer */ 
-static struct i2c_driver wm8750_i2c_driver = {
-	.name =           "i2c wm8750 driver",
-	.id =             I2C_DRIVERID_WM8750,
-	.flags =          I2C_DF_NOTIFY,
-	.attach_adapter = wm8750_i2c_attach,
-	.detach_client =  wm8750_i2c_detach,
-	.command =        NULL,
-};
-
-static struct i2c_client client_template = {
-	.name =   "WM8750",
-	.flags =  I2C_CLIENT_ALLOW_USE,
-	.driver = &wm8750_i2c_driver,
+static struct device_driver wm8750_driver = {
+	.name = 	"WM8750", 
+	.bus = 		&soc_bus_type, 
+	.owner = 	THIS_MODULE, 
+	.probe = 	wm8750_probe, 
+	.remove = 	wm8750_remove, 
+	.suspend = 	wm8750_suspend, 
+	.resume =	wm8750_resume, 
 };
 
 static int __init wm8750_init(void)
-{	
-	int ret = 0;
-
+{
 	info("WM8750 Audio Codec %s", WM8750_VERSION);
-
-	if ((ret = i2c_add_driver(&wm8750_i2c_driver)) != 0)
-		err("can't add i2c driver");
-	
-	return ret;
+	return driver_register(&wm8750_driver);
 }
 
 static void __exit wm8750_exit(void)
 {
-	i2c_del_driver(&wm8750_i2c_driver);
+	driver_unregister(&wm8750_driver);
 }
 
 module_init(wm8750_init);
diff -urN a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
--- a/sound/soc/codecs/wm8753.c	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/codecs/wm8753.c	2005-11-29 16:30:48.000000000 +0000
@@ -21,8 +21,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/i2c.h>
 #include <linux/pm.h>
+#include <linux/platform_device.h>
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -34,7 +34,7 @@
 #include "wm8753.h"
 
 #define AUDIO_NAME "wm8753"
-#define WM8753_VERSION "0.5"
+#define WM8753_VERSION "0.6"
 
 /*
  * Debug
@@ -52,27 +52,6 @@
 #define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg)
 
-
-
-/* 
- * WM8753 2 wire address is determined by GPIO5
- * state during powerup.
- *    low  = WM8753_2W_ADDR1
- *    high = WM8753_2W_ADDR2
- */
-#define WM8753_2W_ADDR1	0x1a
-#define WM8753_2W_ADDR2	0x1b
-#define I2C_DRIVERID_WM8753 0xfefe /* liam -  need a proper id */
-
-static unsigned short normal_i2c[] = { WM8753_2W_ADDR1, WM8753_2W_ADDR2,
-                                       I2C_CLIENT_END };
-
-/* Magic definition of all other variables and things */
-I2C_CLIENT_INSMOD;
-
-static struct i2c_driver wm8753_i2c_driver;
-static struct i2c_client client_template;
-
 /*
  * wm8753 register cache
  * We can't read the WM8753 register space when we 
@@ -238,8 +217,6 @@
 	cache[reg - 1] = value;
 }
 
-static struct i2c_client client_template;
-
 /*
  * write to the WM8753 register space
  */
@@ -247,7 +224,7 @@
 	unsigned int value)
 {
 	u8 data[2];
-	struct i2c_client *i2c = (struct i2c_client*)codec->control_data;
+	
 	/* data is 
 	 *   D15..D9 WM8753 register offset
 	 *   D8...D0 register data
@@ -256,7 +233,7 @@
 	data[1] = value & 0x00ff;
 
 	wm8753_write_reg_cache (codec, reg, value);
-	if (i2c_master_send(i2c, data, 2) == 2)
+	if (codec->hw_write(codec->control_data, data, 2) == 2)
 		return 0;
 	else
 		return -1;
@@ -762,16 +739,16 @@
 static int wm8753_add_widgets(struct snd_soc_codec *codec)
 {
 	int i;
-	
+
 	for(i = 0; i < ARRAY_SIZE(wm8753_dpm_widgets); i++) {
 		snd_soc_dpm_new_control(codec, &wm8753_dpm_widgets[i]);
 	}
-	
+
 	/* set up audio path interconnects */
 	for(i = 0; intercon[i][0] != NULL; i++) {
 		snd_soc_dpm_connect_input(codec, intercon[i][0], intercon[i][1], intercon[i][2]);
 	}
-	
+
 	snd_soc_dpm_sync(codec);
 	return 0;
 }
@@ -951,7 +928,7 @@
 	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
 	struct snd_soc_codec *codec = pcm_c->codec;
 	u16 hifi = 0, ioctl, srate;
-	
+		
 	/* enable PLL */
 	wm8753_config_pll(codec, 1, pcm_c->hw_runtime.priv1);
 	
@@ -1039,10 +1016,6 @@
 	return 0;
 }
 
-static void wm8753_device_release(struct device * dev)
-{
-}
-
 static int wm8753_dpm_event(struct snd_soc_codec *codec, int event)
 {
 	u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3f;
@@ -1065,7 +1038,7 @@
 			wm8753_write(codec, WM8753_PWR1, 0x0001);
 			break;
 	}
-	
+	codec->dpm_state = event;
 	return 0;
 }
 
@@ -1112,19 +1085,53 @@
 		.hmodes = &wm8753_hifi[0],},},
 };
 
+static int wm8753_suspend(struct device *dev, pm_message_t state)
+{
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	wm8753_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
+	return 0;
+}
+
+static int wm8753_resume(struct device *dev)
+{
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	wm8753_dpm_event(codec, SNDRV_CTL_POWER_D3hot);
+	return 0;
+}
+
 /*
  * initialise the WM8753 driver
  * register the mixer and dsp interfaces with the kernel 
  */
-static int wm8753_probe(struct snd_soc_codec *codec)
+static int wm8753_probe(struct device *dev)
 {
-	int reg;
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	int reg, ret = 0;
 
-	wm8753_reset(codec);
+	codec->name = "WM8753";
+	codec->owner = THIS_MODULE;
+	codec->read = wm8753_read_reg_cache;
+	codec->write = wm8753_write;
+	codec->dpm_event = wm8753_dpm_event;
+	codec->pcms = wm8753_pcm_clients;
+	codec->npcms = 2;
+	if ((codec->reg_cache = 
+			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8753_reg), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+	memcpy(codec->reg_cache, wm8753_reg, sizeof(u16) * ARRAY_SIZE(wm8753_reg));
 	
+	wm8753_reset(codec);
+
 	/* charge output caps */
 	wm8753_dpm_event(codec, SNDRV_CTL_POWER_D2);
-	
+
+	/* register pcms */
+	if((ret = snd_soc_register_pcms(codec)) < 0) {
+		wm8753_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
+		kfree(codec->reg_cache);
+		return ret;
+	}
+
 	/* set the update bits */
 	reg = wm8753_read_reg_cache(codec, WM8753_LDAC);
 	wm8753_write(codec, WM8753_LDAC, reg | 0x0100);
@@ -1145,130 +1152,44 @@
 
 	wm8753_add_controls(codec);
 	wm8753_add_widgets(codec);
-	
+	snd_soc_register_card(codec);
+
 	/* wait for caps to finish charging - liam make this thread */
 	ssleep(1);
 	wm8753_dpm_event(codec, SNDRV_CTL_POWER_D3hot);
 
-	return 0;
-}
-
-/* 
- * unregister interfaces and clean up
- */
-static void wm8753_remove(struct snd_soc_codec *codec)
-{
-	/* power down chip */
-	wm8753_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
-}
-
-/*
- * Attach WM8753 2 wire client 
- */
-static int wm8753_i2c_probe(struct i2c_adapter *adap, int addr, int kind)
-{		
-	int ret = 0;
-	struct snd_soc_codec *codec;
-	struct i2c_client *i2c;
-
-	client_template.adapter = adap;
-	client_template.addr = addr;
-	
-	if ((codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL)) == NULL)
-		return -ENOMEM;
- 
-	if ((i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL)) == NULL){
-		kfree(codec);
-		return -ENOMEM;
-	}
-	memcpy(i2c, &client_template, sizeof(struct i2c_client));
-	codec->control_data = i2c;
-	i2c->dev.platform_data = codec;
-
-	if((ret = i2c_attach_client(i2c)) < 0) {
-		err("failed to attach codec at addr %x\n", addr);
-		kfree(i2c);
-		kfree(codec);
-		return ret;
-	}
-
-	codec->name = "WM8753";
-	codec->longname = "WM8753 Portable Codec";
-	codec->owner = THIS_MODULE;
-	codec->pdev.name = "alsa-wm8753";
-	codec->pdev.id = -1;
-	codec->pdev.dev.release = wm8753_device_release;
-	codec->probe = wm8753_probe;
-	codec->remove = wm8753_remove;
-	codec->read = wm8753_read_reg_cache;
-	codec->write = wm8753_write;
-	codec->dpm_event = wm8753_dpm_event;
-	codec->pcms = wm8753_pcm_clients;
-	codec->npcms = 2;
-	if ((codec->reg_cache = 
-			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8753_reg), GFP_KERNEL)) == NULL)
-		return -ENOMEM;
-	memcpy(codec->reg_cache, wm8753_reg, sizeof(u16) * ARRAY_SIZE(wm8753_reg));
-
-	if((ret = snd_soc_register_codec(codec)) < 0) {
-		err("can't register codec");
-		i2c_del_driver(&wm8753_i2c_driver);
-		kfree(i2c);
-		kfree(codec->reg_cache);
-		kfree(codec);
-	}
-
 	return ret;
 }
 
-static int wm8753_i2c_detach(struct i2c_client *client)
+/* power down chip */
+static int wm8753_remove(struct device *dev)
 {
-	struct snd_soc_codec *codec = 
-		(struct snd_soc_codec*)client->dev.platform_data;
-
-	i2c_detach_client(client);
-	snd_soc_unregister_codec(codec);
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	wm8753_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
+	snd_soc_free_pcms(codec);
 	kfree(codec->reg_cache);
-	kfree(codec);
 	return 0;
 }
 
-static int wm8753_i2c_attach(struct i2c_adapter *adap)
-{
-	return i2c_probe(adap, &addr_data, wm8753_i2c_probe);
-}
-
-/* WM8753 2 Wire layer */ 
-static struct i2c_driver wm8753_i2c_driver = {
-	.name =           "i2c wm8753 driver",
-	.id =             I2C_DRIVERID_WM8753,
-	.flags =          I2C_DF_NOTIFY,
-	.attach_adapter = wm8753_i2c_attach,
-	.detach_client =  wm8753_i2c_detach,
-	.command =        NULL,
-};
-
-static struct i2c_client client_template = {
-	.name =   "WM8753",
-	.flags =  I2C_CLIENT_ALLOW_USE,
-	.driver = &wm8753_i2c_driver,
+static struct device_driver wm8753_driver = {
+	.name = 	"WM8753", 
+	.bus = 		&soc_bus_type, 
+	.owner = 	THIS_MODULE, 
+	.probe = 	wm8753_probe, 
+	.remove = 	wm8753_remove, 
+	.suspend = 	wm8753_suspend, 
+	.resume =	wm8753_resume, 
 };
 
 static int __init wm8753_init(void)
-{	
-	int ret = 0;
-	
+{
 	info("WM8753 Audio Codec %s", WM8753_VERSION);
-
-	if ((ret = i2c_add_driver(&wm8753_i2c_driver)) != 0)
-		err("can't add i2c driver");
-	
-	return ret;
+	return driver_register(&wm8753_driver);
 }
 
 static void __exit wm8753_exit(void)
 {
-	i2c_del_driver(&wm8753_i2c_driver);
+	driver_unregister(&wm8753_driver);
 }
 
 module_init(wm8753_init);
diff -urN a/sound/soc/codecs/wm8772.c b/sound/soc/codecs/wm8772.c
--- a/sound/soc/codecs/wm8772.c	1970-01-01 01:00:00.000000000 +0100
+++ b/sound/soc/codecs/wm8772.c	2005-11-26 12:53:06.000000000 +0000
@@ -0,0 +1,861 @@
+/*
+ * wm8772.c  --  WM8772 Soc Audio driver
+ *
+ * Copyright 2003 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ * Notes:
+ *  The WM8753 is a low power, high quality stereo codec with integrated PCM
+ *  codec designed for portable digital telephony applications.
+ */
+ 
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dpm.h>
+#include <sound/initval.h>
+
+#include "wm8772.h"
+
+#define AUDIO_NAME "WM8772"
+#define WM8750_VERSION "0.1"
+
+/*
+ * Debug
+ */
+ 
+#define PFX AUDIO_NAME
+#define WM8750_DEBUG 0
+
+#ifdef WM8772_DEBUG
+#define dbg(format, arg...) printk(KERN_DEBUG PFX ": " format "\n" , ## arg)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif
+#define err(format, arg...) printk(KERN_ERR PFX ": " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg)
+
+
+/* 
+ * WM8750 2 wire address is determined by CSB pin state during powerup */
+#define I2C_DRIVERID_WM8772 0xfde
+
+static unsigned short normal_i2c[] = {  0x1a, 0x1b,
+                                       I2C_CLIENT_END };
+
+/* Magic definition of all other variables and things */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver wm8750_i2c_driver;
+static struct i2c_client client_template;
+	
+/*
+ * wm8772 register cache
+ * We can't read the WM8772 register space when we 
+ * are using 2 wire for device control, so we cache them instead. 
+ */
+static const u16 wm8772_reg[] = {
+	0x0097, 0x0097, 0x0079, 0x0079,  /*  0 */
+	0x0000, 0x0008, 0x0000, 0x000a,  /*  4 */
+	0x0000, 0x0000, 0x00ff, 0x00ff,  /*  8 */
+	0x000f, 0x000f, 0x0000, 0x0000,  /* 12 */
+	0x0000, 0x007b, 0x0000, 0x0032,  /* 16 */
+	0x0000, 0x00c3, 0x00c3, 0x00c0,  /* 20 */
+	0x0000, 0x0000, 0x0000, 0x0000,  /* 24 */
+	0x0000, 0x0000, 0x0000, 0x0000,  /* 28 */
+	0x0000, 0x0000, 0x0050, 0x0050,  /* 32 */
+};
+
+#define WM8772_HWFMT \
+	(SND_SOC_HWFMT_I2S | SND_SOC_HWFMT_LEFT_J | SND_SOC_HWFMT_RIGHT_J | \
+	SND_SOC_HWFMT_CBS_CFS | SND_SOC_HWFMT_CBM_CFM |\
+	SND_SOC_HWFMT_NB_NF | SND_SOC_HWFMT_NB_IF | SND_SOC_HWFMT_IB_NF | \
+	SND_SOC_HWFMT_IB_IF)
+
+/* priv1 is srate register setting */
+static struct snd_soc_hw_mode wm8750_hwfmt[] = {
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 8000,   64, 0x000c},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 8000,   96, 0x000e},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 8000,  128, 0x004c},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 8000,  192, 0x004e},
+
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 11025, 64,  0x0030},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 11025, 96,  0x0032},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 11025, 128, 0x0070},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 11025, 192, 0x0072},
+
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 12000, 64,  0x0010},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 12000, 96,  0x0012},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 12000, 128, 0x0050},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 12000, 192, 0x0052},
+
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 16000, 64,  0x0014},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 16000, 96,  0x0016},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 16000, 128, 0x0054},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 16000, 192, 0x0056},
+
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 22050, 64,  0x0034},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 22050, 96,  0x0036},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 22050, 128, 0x0074},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 22050, 192, 0x0076},
+
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 24000, 64,  0x0038},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 24000, 96,  0x003a},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 24000, 128, 0x0078},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 24000, 192, 0x007a},
+
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 32000,  64, 0x0018},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 32000,  96, 0x001a},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 32000, 128, 0x0058},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 32000, 192, 0x005a},
+
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 44100,  64, 0x0020},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 44100,  96, 0x0022},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 44100, 128, 0x0060},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 44100, 192, 0x0062},
+
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 48000,  64, 0x0000},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 48000,  96, 0x0002},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 48000, 128, 0x0040},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 48000, 192, 0x0042},
+
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 88200,  32, 0x003c},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 88200,  48, 0x003e},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 88200,  64, 0x007c},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 88200,  96, 0x007e},
+
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 96000,  32, 0x001c},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 96000,  48, 0x001e},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 96000,  64, 0x005c},
+	{WM8750_HWFMT, SND_SOC_HWBITS(16), 96000,  96, 0x005e},
+};
+
+/*
+ * read wm8750 register cache
+ */
+static inline unsigned int wm8750_read_reg_cache(struct snd_soc_codec * codec, 
+	unsigned int reg)
+{
+	u16 *cache = codec->reg_cache;
+	if (reg > WM8750_CACHE_REGNUM)
+		return -1;
+	return cache[reg];
+}
+
+/*
+ * write wm8750 register cache
+ */
+static inline void wm8750_write_reg_cache(struct snd_soc_codec * codec, 
+	unsigned int reg, unsigned int value)
+{
+	u16 *cache = codec->reg_cache;
+	if (reg > WM8750_CACHE_REGNUM)
+		return;
+	cache[reg] = value;
+}
+
+static int wm8750_write(struct snd_soc_codec * codec, unsigned int reg, 
+	unsigned int value)
+{
+	u8 data[2];
+	struct i2c_client *i2c = (struct i2c_client*)codec->control_data;
+
+	/* data is 
+	 *   D15..D9 WM8750 register offset
+	 *   D8...D0 register data
+	 */
+	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+	data[1] = value & 0x00ff;
+
+	wm8750_write_reg_cache (codec, reg, value);
+	if (i2c_master_send(i2c, data, 2) == 2)
+		return 0;
+	else
+		return -1;
+}
+
+#define wm8750_reset(c)	wm8750_write(c, WM8750_RESET, 0)
+
+/*
+ * WM8750 Controls
+ */
+static const char* wm8750_bass[] = {"Linear Control", "Adaptive Boost"};
+static const char* wm8750_bass_filter[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" };
+static const char* wm8750_treble[] = {"8kHz", "4kHz"};
+static const char* wm8750_3d_lc[] = {"200Hz", "500Hz"};
+static const char* wm8750_3d_uc[] = {"2.2kHz", "1.5kHz"};
+static const char* wm8750_3d_func[] = {"Capture", "Playback"};
+static const char* wm8750_alc_func[] = {"Off", "Right", "Left", "Stereo"};
+static const char* wm8750_ng_type[] = {"Constant PGA Gain", "Mute ADC Output"};
+static const char* wm8750_line_mux[] = {"Line 1", "Line 2", "Line 3", "PGA", "Differential"};
+static const char* wm8750_pga_sel[] = {"Line 1", "Line 2", "Line 3", "Differential"};
+static const char* wm8750_out3[] = {"VREF", "ROUT1 + Vol", "MonoOut", "ROUT1"};
+static const char* wm8750_diff_sel[] = {"Line 1", "Line 2"};
+static const char* wm8750_adcpol[] = {"Normal", "L Invert", "R Invert", "L + R Invert"};
+static const char* wm8750_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
+static const char* wm8750_mono_mux[] = {"Stereo", "Mono (Left)", "Mono (Right)", "Digital Mono"};
+
+static const struct soc_enum wm8750_enum[] = {
+SOC_ENUM_SINGLE(WM8750_BASS, 7, 2, wm8750_bass),
+SOC_ENUM_SINGLE(WM8750_BASS, 6, 2, wm8750_bass_filter),
+SOC_ENUM_SINGLE(WM8750_TREBLE, 6, 2, wm8750_treble),
+SOC_ENUM_SINGLE(WM8750_3D, 5, 2, wm8750_3d_lc),
+SOC_ENUM_SINGLE(WM8750_3D, 6, 2, wm8750_3d_uc),
+SOC_ENUM_SINGLE(WM8750_3D, 7, 2, wm8750_3d_func),
+SOC_ENUM_SINGLE(WM8750_ALC1, 7, 4, wm8750_alc_func),
+SOC_ENUM_SINGLE(WM8750_NGATE, 1, 2, wm8750_ng_type),
+SOC_ENUM_SINGLE(WM8750_LOUTM1, 0, 5, wm8750_line_mux),
+SOC_ENUM_SINGLE(WM8750_ROUTM1, 0, 5, wm8750_line_mux),
+SOC_ENUM_SINGLE(WM8750_LADCIN, 6, 4, wm8750_pga_sel), /* 10 */
+SOC_ENUM_SINGLE(WM8750_RADCIN, 6, 4, wm8750_pga_sel),
+SOC_ENUM_SINGLE(WM8750_ADCTL2, 7, 4, wm8750_out3),
+SOC_ENUM_SINGLE(WM8750_ADCIN, 8, 2, wm8750_diff_sel),
+SOC_ENUM_SINGLE(WM8750_ADCDAC, 5, 4, wm8750_adcpol),
+SOC_ENUM_SINGLE(WM8750_ADCDAC, 1, 4, wm8750_deemph),
+SOC_ENUM_SINGLE(WM8750_ADCIN, 6, 4, wm8750_mono_mux), /* 16 */
+
+};
+
+static const snd_kcontrol_new_t wm8750_snd_controls[] = {
+
+SOC_SINGLE("Left Capture Volume", WM8750_LINVOL, 0, 63, 0),
+SOC_SINGLE("Left Capture ZC Switch", WM8750_LINVOL, 6, 1, 0),
+SOC_SINGLE("Left Capture Switch", WM8750_LINVOL, 7, 1, 1),
+SOC_SINGLE("Right Capture Volume", WM8750_RINVOL, 0, 63, 0),
+SOC_SINGLE("Right Capture ZC Switch", WM8750_RINVOL, 6, 1, 0),
+SOC_SINGLE("Right Capture Switch", WM8750_RINVOL, 7, 1, 1),
+
+SOC_SINGLE("Left Out1 Playback ZC Switch", WM8750_LOUT1V, 7, 1, 0),
+SOC_SINGLE("Right Out1 Playback ZC Switch", WM8750_ROUT1V, 7, 1, 0),
+
+SOC_SINGLE("Left Out2 Playback ZC Switch", WM8750_LOUT2V, 7, 1, 0),
+SOC_SINGLE("Right Out2 Playback ZC Switch", WM8750_ROUT2V, 7, 1, 0),
+
+SOC_ENUM("Playback De-emphasis", wm8750_enum[15]),
+
+SOC_ENUM("Capture Polarity", wm8750_enum[14]),
+SOC_SINGLE("Playback 6dB Attenuate", WM8750_ADCDAC, 7, 1, 0),
+SOC_SINGLE("Capture 6dB Attenuate", WM8750_ADCDAC, 8, 1, 0),
+
+SOC_SINGLE("Left PCM Volume", WM8750_LDAC, 0, 255, 0),
+SOC_SINGLE("Right PCM Volume", WM8750_RDAC, 0, 255, 0),
+
+SOC_ENUM("Bass Boost", wm8750_enum[0]),
+SOC_ENUM("Bass Filter", wm8750_enum[1]),
+SOC_SINGLE("Bass Volume", WM8750_BASS, 0, 15, 1),
+
+SOC_SINGLE("Treble Volume", WM8750_TREBLE, 0, 15, 0),
+SOC_ENUM("Treble Cut-off", wm8750_enum[2]),
+
+SOC_SINGLE("3D Switch", WM8750_3D, 0, 1, 0),
+SOC_SINGLE("3D Volume", WM8750_3D, 1, 15, 0),
+SOC_ENUM("3D Lower Cut-off", wm8750_enum[3]),
+SOC_ENUM("3D Upper Cut-off", wm8750_enum[4]),
+SOC_ENUM("3D Mode", wm8750_enum[5]),
+
+SOC_SINGLE("ALC Capture Target Volume", WM8750_ALC1, 0, 7, 0),
+SOC_SINGLE("ALC Capture Max Volume", WM8750_ALC1, 4, 7, 0),
+SOC_ENUM("ALC Capture Function", wm8750_enum[6]),
+SOC_SINGLE("ALC Capture ZC Switch", WM8750_ALC2, 7, 1, 0),
+SOC_SINGLE("ALC Capture Hold Time", WM8750_ALC2, 0, 15, 0),
+SOC_SINGLE("ALC Capture Decay Time", WM8750_ALC3, 4, 15, 0),
+SOC_SINGLE("ALC Capture Attack Time", WM8750_ALC3, 0, 15, 0),
+SOC_SINGLE("ALC Capture NG Threshold", WM8750_NGATE, 3, 31, 0),
+SOC_ENUM("ALC Capture NG Type", wm8750_enum[4]),
+SOC_SINGLE("ALC Capture NG Switch", WM8750_NGATE, 0, 1, 0),
+
+SOC_SINGLE("Left ADC Capture Volume", WM8750_LADC, 0, 255, 0),
+SOC_SINGLE("Right ADC Capture Volume", WM8750_RADC, 0, 255, 0),
+
+SOC_SINGLE("ZC Timeout Switch", WM8750_ADCTL1, 0, 1, 0),
+SOC_SINGLE("Playback Invert Switch", WM8750_ADCTL1, 1, 1, 0),
+
+SOC_SINGLE("Right Out2 Playback Invert Switch", WM8750_ADCTL2, 4, 1, 0),
+
+
+/* Unimplemented */
+/* ADCDAC Bit 0 - ADCHPD */
+/* ADCDAC Bit 4 - HPOR */
+/* ADCTL1 Bit 2,3 - DATSEL */
+/* ADCTL1 Bit 4,5 - DMONOMIX */
+/* ADCTL1 Bit 6,7 - VSEL */
+/* ADCTL2 Bit 2 - LRCM */
+/* ADCTL2 Bit 3 - TRI */
+/* ADCTL3 Bit 5 - HPFLREN */
+/* ADCTL3 Bit 6 - VROI */
+/* ADCTL3 Bit 7,8 - ADCLRM */
+/* ADCIN Bit 4 - LDCM */ 
+/* ADCIN Bit 5 - RDCM */
+
+SOC_SINGLE("Left Mic Boost", WM8750_LADCIN, 4, 3, 0),
+SOC_SINGLE("Right Mic Boost", WM8750_RADCIN, 4, 3, 0),
+
+SOC_SINGLE("Left Bypass Left Playback Volume", WM8750_LOUTM1, 4, 7, 1),
+SOC_SINGLE("Right Bypass Left Playback Volume", WM8750_LOUTM2, 4, 7, 1),
+
+SOC_SINGLE("Left Bypass Right Playback Volume", WM8750_ROUTM1, 4, 7, 1),
+SOC_SINGLE("Right Bypass Right Playback Volume", WM8750_ROUTM2, 4, 7, 1),
+
+SOC_SINGLE("Left Bypass Mono Playback Volume", WM8750_MOUTM1, 4, 7, 1),
+SOC_SINGLE("Right Bypass Mono Playback Volume", WM8750_MOUTM2, 4, 7, 1), 
+
+SOC_SINGLE("Mono Playback ZC Switch", WM8750_MOUTV, 7, 1, 0),
+
+};
+
+/* add non dpm controls */
+static int wm8750_add_controls(struct snd_soc_codec *codec)
+{
+	int err, i;
+
+	for (i = 0; i < ARRAY_SIZE(wm8750_snd_controls); i++) {
+		if ((err = snd_ctl_add(codec->card, snd_soc_cnew(&wm8750_snd_controls[i],codec, NULL))) < 0)
+			return err;
+	}
+	return 0;
+}
+
+/*
+ * DPM Controls
+ */
+
+/* Left Mixer */
+static const snd_kcontrol_new_t wm8750_left_mixer_controls[] = {
+SOC_DPM_SINGLE("Playback Switch", WM8750_LOUTM1, 8, 1, 0),
+SOC_DPM_SINGLE("Left Bypass Switch", WM8750_LOUTM1, 7, 1, 0),
+SOC_DPM_SINGLE("Right Playback Switch", WM8750_LOUTM2, 8, 1, 0),
+SOC_DPM_SINGLE("Right Bypass Switch", WM8750_LOUTM2, 7, 1, 0),
+};
+
+/* Right Mixer */
+static const snd_kcontrol_new_t wm8750_right_mixer_controls[] = {
+SOC_DPM_SINGLE("Left Playback Switch", WM8750_ROUTM1, 8, 1, 0),
+SOC_DPM_SINGLE("Left Bypass Switch", WM8750_ROUTM1, 7, 1, 0),
+SOC_DPM_SINGLE("Playback Switch", WM8750_ROUTM2, 8, 1, 0),
+SOC_DPM_SINGLE("Right Bypass Switch", WM8750_ROUTM2, 7, 1, 0),
+};
+
+/* Mono Mixer */
+static const snd_kcontrol_new_t wm8750_mono_mixer_controls[] = {
+SOC_DPM_SINGLE("Left Playback Switch", WM8750_MOUTM1, 8, 1, 0),
+SOC_DPM_SINGLE("Left Bypass Switch", WM8750_MOUTM1, 7, 1, 0),
+SOC_DPM_SINGLE("Right Playback Switch", WM8750_MOUTM2, 8, 1, 0),
+SOC_DPM_SINGLE("Right Bypass Switch", WM8750_MOUTM2, 7, 1, 0),
+};
+
+/* Left Line Mux */
+static const snd_kcontrol_new_t wm8750_left_line_controls =
+SOC_DPM_ENUM("Route", wm8750_enum[8]);
+
+/* Right Line Mux */
+static const snd_kcontrol_new_t wm8750_right_line_controls =
+SOC_DPM_ENUM("Route", wm8750_enum[9]);
+
+/* Left PGA Mux */
+static const snd_kcontrol_new_t wm8750_left_pga_controls =
+SOC_DPM_ENUM("Route", wm8750_enum[10]);
+
+/* Right PGA Mux */
+static const snd_kcontrol_new_t wm8750_right_pga_controls =
+SOC_DPM_ENUM("Route", wm8750_enum[11]);
+
+/* Out 3 Mux */
+static const snd_kcontrol_new_t wm8750_out3_controls =
+SOC_DPM_ENUM("Route", wm8750_enum[12]);
+
+/* Differential Mux */
+static const snd_kcontrol_new_t wm8750_diffmux_controls =
+SOC_DPM_ENUM("Route", wm8750_enum[13]);
+
+/* Mono ADC Mux */
+static const snd_kcontrol_new_t wm8750_monomux_controls =
+SOC_DPM_ENUM("Route", wm8750_enum[16]);
+
+/* LOUT 1 Volume */
+static const snd_kcontrol_new_t wm8750_lout1_vol_controls =
+SOC_DPM_SINGLE("Left Out1 Playback Volume", WM8750_LOUT1V, 0, 127, 0);
+
+/* ROUT 1 Volume */
+static const snd_kcontrol_new_t wm8750_rout1_vol_controls =
+SOC_DPM_SINGLE("Right Out1 Playback Volume", WM8750_ROUT1V, 0, 127, 0);
+
+/* LOUT 2 Volume */
+static const snd_kcontrol_new_t wm8750_lout2_vol_controls =
+SOC_DPM_SINGLE("Left Out2 Playback Volume", WM8750_LOUT2V, 0, 127, 0);
+
+/* ROUT 2 Volume */
+static const snd_kcontrol_new_t wm8750_rout2_vol_controls =
+SOC_DPM_SINGLE("Right Out2 Playback Volume", WM8750_ROUT2V, 0, 127, 0);
+
+/* Mono Volume */
+static const snd_kcontrol_new_t wm8750_mout_vol_controls =
+SOC_DPM_SINGLE("Mono Playback Volume", WM8750_MOUTV, 0, 127, 0);
+
+static const struct snd_soc_dpm_widget wm8750_dpm_widgets[] = {
+	SND_SOC_DPM_CLOCK("WM8750 Clock", WM8750_PWR1, 0, 1),
+	SND_SOC_DPM_MUTE("DAC Mute", WM8750_ADCDAC, 3, 0),
+	SND_SOC_DPM_MIXER("Left Mixer", -1, 0, 0, &wm8750_left_mixer_controls[0], ARRAY_SIZE(wm8750_left_mixer_controls)),
+	SND_SOC_DPM_MIXER("Right Mixer", -1, 0, 0, &wm8750_right_mixer_controls[0], ARRAY_SIZE(wm8750_right_mixer_controls)),
+	SND_SOC_DPM_MIXER("Mono Mixer", WM8750_PWR2, 2, 0, &wm8750_mono_mixer_controls[0], ARRAY_SIZE(wm8750_mono_mixer_controls)),
+
+	SND_SOC_DPM_VOLUME("Right Out 2", WM8750_PWR2, 3, 0, &wm8750_rout2_vol_controls, 1),
+	SND_SOC_DPM_VOLUME("Left Out 2", WM8750_PWR2, 4, 0, &wm8750_lout2_vol_controls, 1),
+	SND_SOC_DPM_VOLUME("Right Out 1", WM8750_PWR2, 5, 0, &wm8750_rout1_vol_controls, 1),
+	SND_SOC_DPM_VOLUME("Left Out 1", WM8750_PWR2, 6, 0, &wm8750_lout1_vol_controls, 1),
+	SND_SOC_DPM_DAC("Right DAC", "Right Playback", WM8750_PWR2, 7, 0, NULL, 0),
+	SND_SOC_DPM_DAC("Left DAC", "Left Playback", WM8750_PWR2, 8, 0, NULL, 0),
+
+	//"Mic Bias", WM8750_PWR1, 1, 0
+	SND_SOC_DPM_ADC("Right ADC", "Right Capture", WM8750_PWR1, 2, 0, NULL, 0),
+	SND_SOC_DPM_ADC("Left ADC", "Left Capture", WM8750_PWR1, 3, 0, NULL, 0),
+
+	SND_SOC_DPM_MUX("Left PGA Mux", WM8750_PWR1, 5, 0, &wm8750_left_pga_controls),
+	SND_SOC_DPM_MUX("Right PGA Mux", WM8750_PWR1, 4, 0, &wm8750_right_pga_controls),
+	SND_SOC_DPM_MUX("Left Line Mux", -1, 0, 0, &wm8750_left_line_controls),
+	SND_SOC_DPM_MUX("Right Line Mux", -1, 0, 0, &wm8750_right_line_controls),
+
+	SND_SOC_DPM_MUX("Out3 Mux", -1, 0, 0, &wm8750_out3_controls),
+	SND_SOC_DPM_VOLUME("Out 3", WM8750_PWR2, 1, 0, NULL, 0),
+	SND_SOC_DPM_VOLUME("Mono Out 1", WM8750_PWR2, 2, 0, &wm8750_mout_vol_controls, 1),
+	
+	SND_SOC_DPM_MUX("Differential Mux", -1, 0, 0, &wm8750_diffmux_controls),
+	SND_SOC_DPM_MUX("Left ADC Mux", -1, 0, 0, &wm8750_monomux_controls),
+	SND_SOC_DPM_MUX("Right ADC Mux", -1, 0, 0, &wm8750_monomux_controls),
+
+	SND_SOC_DPM_OUTPUT("LOUT1"),
+	SND_SOC_DPM_OUTPUT("ROUT1"),
+	SND_SOC_DPM_OUTPUT("LOUT2"),
+	SND_SOC_DPM_OUTPUT("ROUT2"),
+	SND_SOC_DPM_OUTPUT("MONO"),
+	SND_SOC_DPM_OUTPUT("OUT3"),
+
+	SND_SOC_DPM_INPUT("LINPUT1"),
+	SND_SOC_DPM_INPUT("LINPUT2"),
+	SND_SOC_DPM_INPUT("LINPUT3"),
+	SND_SOC_DPM_INPUT("RINPUT1"),
+	SND_SOC_DPM_INPUT("RINPUT2"),
+	SND_SOC_DPM_INPUT("RINPUT3"),
+};
+
+static int wm8750_add_widgets(struct snd_soc_codec *codec)
+{
+	int i;
+	
+	for(i = 0; i < ARRAY_SIZE(wm8750_dpm_widgets); i++) {
+		snd_soc_dpm_new_control(codec, &wm8750_dpm_widgets[i]);
+	}
+	
+	/* left mixer */
+	snd_soc_dpm_connect_input(codec, "Left Mixer", "Playback Switch", "Left DAC");
+	snd_soc_dpm_connect_input(codec, "Left Mixer", "Left Bypass Switch", "Left Line Mux");
+	snd_soc_dpm_connect_input(codec, "Left Mixer", "Right Playback Switch", "Right DAC");
+	snd_soc_dpm_connect_input(codec, "Left Mixer", "Right Bypass Switch", "Right Line Mux");
+
+	/* right mixer */
+	snd_soc_dpm_connect_input(codec, "Right Mixer", "Left Playback Switch", "Left DAC");
+	snd_soc_dpm_connect_input(codec, "Right Mixer", "Left Bypass Switch", "Left Line Mux");
+	snd_soc_dpm_connect_input(codec, "Right Mixer", "Playback Switch", "Right DAC");
+	snd_soc_dpm_connect_input(codec, "Right Mixer", "Right Bypass Switch", "Right Line Mux");
+
+	/* left out 1 */
+	snd_soc_dpm_connect_input(codec, "Left Out 1", NULL, "Left Mixer");
+	snd_soc_dpm_connect_input(codec, "LOUT1", NULL, "Left Out 1");
+
+	/* left out 2 */
+	snd_soc_dpm_connect_input(codec, "Left Out 2", NULL, "Left Mixer");
+	snd_soc_dpm_connect_input(codec, "LOUT2", NULL, "Left Out 2");
+	
+	/* right out 1 */
+	snd_soc_dpm_connect_input(codec, "Right Out 1", NULL, "Right Mixer");
+	snd_soc_dpm_connect_input(codec, "ROUT1", NULL, "Right Out 1");
+
+	/* right out 2 */
+	snd_soc_dpm_connect_input(codec, "Right Out 2", NULL, "Right Mixer");
+	snd_soc_dpm_connect_input(codec, "ROUT2", NULL, "Right Out 2");
+
+	/* mono mixer */
+	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Left Playback Switch", "Left DAC");
+	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Left Bypass Switch", "Left Line Mux");
+	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Right Playback Switch", "Right DAC");
+	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Right Bypass Switch", "Right Line Mux");
+	
+	/* mono out */
+	snd_soc_dpm_connect_input(codec, "Mono Out 1", NULL, "Mono Mixer");
+	snd_soc_dpm_connect_input(codec, "MONO1", NULL, "Mono Out 1");
+
+	/* out 3 */
+	snd_soc_dpm_connect_input(codec, "Out3 Mux", "VREF", "VREF");
+	snd_soc_dpm_connect_input(codec, "Out3 Mux", "ROUT1 + Vol", "ROUT1");
+	snd_soc_dpm_connect_input(codec, "Out3 Mux", "ROUT1", "Right Mixer");
+	snd_soc_dpm_connect_input(codec, "Out3 Mux", "MonoOut", "MONO1");
+
+	snd_soc_dpm_connect_input(codec, "Out 3", NULL, "Out3 Mux");
+	snd_soc_dpm_connect_input(codec, "OUT3", NULL, "Out 3");
+
+	/* Left Line Mux */
+	snd_soc_dpm_connect_input(codec, "Left Line Mux", "Line 1", "LINPUT1");
+	snd_soc_dpm_connect_input(codec, "Left Line Mux", "Line 2", "LINPUT2");
+	snd_soc_dpm_connect_input(codec, "Left Line Mux", "Line 3", "LINPUT3");
+	snd_soc_dpm_connect_input(codec, "Left Line Mux", "PGA", "Left PGA Mux");
+	snd_soc_dpm_connect_input(codec, "Left Line Mux", "Differential", "Differential Mux");
+
+	/* Right Line Mux */
+	snd_soc_dpm_connect_input(codec, "Right Line Mux", "Line 1", "RINPUT1");
+	snd_soc_dpm_connect_input(codec, "Right Line Mux", "Line 2", "RINPUT2");
+	snd_soc_dpm_connect_input(codec, "Right Line Mux", "Line 3", "RINPUT3");
+	snd_soc_dpm_connect_input(codec, "Right Line Mux", "PGA", "Right PGA Mux");
+	snd_soc_dpm_connect_input(codec, "Right Line Mux", "Differential", "Differential Mux");
+
+	/* Left PGA Mux */
+	snd_soc_dpm_connect_input(codec, "Left PGA Mux", "Line 1", "LINPUT1");
+	snd_soc_dpm_connect_input(codec, "Left PGA Mux", "Line 2", "LINPUT2");
+	snd_soc_dpm_connect_input(codec, "Left PGA Mux", "Line 3", "LINPUT3");
+	snd_soc_dpm_connect_input(codec, "Left PGA Mux", "Differential", "Differential Mux");
+
+	/* Right PGA Mux */
+	snd_soc_dpm_connect_input(codec, "Right PGA Mux", "Line 1", "RINPUT1");
+	snd_soc_dpm_connect_input(codec, "Right PGA Mux", "Line 2", "RINPUT2");
+	snd_soc_dpm_connect_input(codec, "Right PGA Mux", "Line 3", "RINPUT3");
+	snd_soc_dpm_connect_input(codec, "Right PGA Mux", "Differential", "Differential Mux");
+
+	/* Differential Mux */
+	snd_soc_dpm_connect_input(codec, "Differential Mux", "Line 1", "LINPUT1");
+	snd_soc_dpm_connect_input(codec, "Differential Mux", "Line 1", "RINPUT1");
+	snd_soc_dpm_connect_input(codec, "Differential Mux", "Line 2", "LINPUT2");
+	snd_soc_dpm_connect_input(codec, "Differential Mux", "Line 2", "RINPUT2");
+
+	/* Left ADC Mux */
+	snd_soc_dpm_connect_input(codec, "Left ADC Mux", "Stereo", "Left PGA Mux");
+	snd_soc_dpm_connect_input(codec, "Left ADC Mux", "Mono (Left)", "Left PGA Mux");
+	snd_soc_dpm_connect_input(codec, "Left ADC Mux", "Digital Mono", "Left PGA Mux");
+
+	/* Right ADC Mux */
+	snd_soc_dpm_connect_input(codec, "Right ADC Mux", "Stereo", "Right PGA Mux");
+	snd_soc_dpm_connect_input(codec, "Right ADC Mux", "Mono (Right)", "Right PGA Mux");
+	snd_soc_dpm_connect_input(codec, "Right ADC Mux", "Digital Mono", "Right PGA Mux");
+
+	/* ADC */
+	snd_soc_dpm_connect_input(codec, "Left ADC", NULL, "Left ADC Mux");
+	snd_soc_dpm_connect_input(codec, "Right ADC", NULL, "Right ADC Mux");
+
+	snd_soc_dpm_sync(codec);
+	return 0;
+}
+
+
+static int wm8750_pcm_prepare(snd_pcm_substream_t *substream)
+{
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
+	struct snd_soc_codec *codec = pcm_c->codec;
+	u16 iface = 0;
+	
+	/* set master/slave audio interface */
+	switch(pcm_c->hw_runtime.hformat & SND_SOC_CLOCK_MASK) {
+		case SND_SOC_HWFMT_CBM_CFM:
+			iface |= 0x0040;
+			break;
+		case SND_SOC_HWFMT_CBS_CFS:
+			break;
+	}
+	
+	/* interface format */
+	switch(pcm_c->hw_runtime.hformat & SND_SOC_FORMAT_MASK) {
+		case SND_SOC_HWFMT_I2S:
+			iface |= 0x0002;
+			break;
+		case SND_SOC_HWFMT_RIGHT_J:
+			break;
+		case SND_SOC_HWFMT_LEFT_J:
+			iface |= 0x0001;
+			break;
+		case SND_SOC_HWFMT_DSP_A:
+			iface |= 0x0003;
+			break;
+		case SND_SOC_HWFMT_DSP_B:
+			iface |= 0x0013;
+			break;
+	}
+		
+	/* bit size */
+	switch(pcm_c->hw_runtime.hbits) {
+		case SND_SOC_HWBITS(16):
+			break;
+		case SND_SOC_HWBITS(20):
+			iface |= 0x0004;
+			break;
+		case SND_SOC_HWBITS(24):
+			iface |= 0x0008;
+			break;
+		case SND_SOC_HWBITS(32):
+			iface |= 0x000c;
+			break;
+	}
+
+	/* clock inversion */
+	switch(pcm_c->hw_runtime.hformat & SND_SOC_INV_MASK) {
+		case SND_SOC_HWFMT_NB_NF:
+			break;
+		case SND_SOC_HWFMT_IB_IF:
+			iface |= 0x0090;
+			break;
+		case SND_SOC_HWFMT_IB_NF:
+			iface |= 0x0080;
+			break;
+		case SND_SOC_HWFMT_NB_IF:
+			iface |= 0x0010;
+			break;
+	}
+	
+	/* set rate */
+	wm8750_write(codec, WM8750_SRATE, pcm_c->hw_runtime.priv1);
+	wm8750_write(codec, WM8750_IFACE, iface);
+	
+	return 0;
+}
+
+static void wm8750_device_release(struct device * dev)
+{
+}
+
+static int wm8750_dpm_event(struct snd_soc_codec *codec, int event)
+{
+	u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3f;
+	
+	switch (event) {
+		case SNDRV_CTL_POWER_D0: /* full On */
+			/* set vmid to 50k and unmute dac */
+			wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
+			break;
+		case SNDRV_CTL_POWER_D1: /* partial On */
+		case SNDRV_CTL_POWER_D2: /* partial On */
+			/* set vmid to 5k for quick power up */
+			wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x01c0);
+			break;
+		case SNDRV_CTL_POWER_D3hot: /* Off, with power */
+			/* mute dac and set vmid to 500k, enable VREF */
+			wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x0140);
+			break;
+		case SNDRV_CTL_POWER_D3cold: /* Off, without power */
+			wm8750_write(codec, WM8750_PWR1, 0x0000);
+			break;
+	}
+	
+	return 0;
+}
+
+static struct snd_soc_pcm_codec wm8750_pcm_client = {
+	.name = "WM8750",
+	.playback = {
+		.sname = "Playback",
+		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
+		SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100 |
+		SNDRV_PCM_RATE_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 2,
+	},
+	.nplayback = 1,
+	.capture = {
+		.sname = "Capture",
+		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | 
+		SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100 |
+		SNDRV_PCM_RATE_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 2,
+	},
+	.ncapture = 1,
+	.ops = {
+		.prepare = wm8750_pcm_prepare,
+	},
+	.hw = {
+		.num_hmodes = ARRAY_SIZE(wm8750_hwfmt),
+		.hmodes = &wm8750_hwfmt[0],
+	},
+};
+
+/*
+ * initialise the WM8750 driver
+ * register the mixer and dsp interfaces with the kernel 
+ */
+static int wm8750_probe(struct snd_soc_codec *codec)
+{
+	int reg;
+	
+	info("WM8750 Audio Codec %s", WM8750_VERSION);
+	
+	wm8750_reset(codec);
+	
+	/* charge output caps */
+	wm8750_dpm_event(codec, SNDRV_CTL_POWER_D2);
+
+	/* set the update bits */
+	reg = wm8750_read_reg_cache(codec, WM8750_LDAC);
+	wm8750_write(codec, WM8750_LDAC, reg | 0x0100);
+	reg = wm8750_read_reg_cache(codec, WM8750_RDAC);
+	wm8750_write(codec, WM8750_RDAC, reg | 0x0100);
+	reg = wm8750_read_reg_cache(codec, WM8750_LOUT1V);
+	wm8750_write(codec, WM8750_LOUT1V, reg | 0x0100);
+	reg = wm8750_read_reg_cache(codec, WM8750_ROUT1V);
+	wm8750_write(codec, WM8750_ROUT1V, reg | 0x0100);
+	reg = wm8750_read_reg_cache(codec, WM8750_LOUT2V);
+	wm8750_write(codec, WM8750_LOUT2V, reg | 0x0100);
+	reg = wm8750_read_reg_cache(codec, WM8750_ROUT2V);
+	wm8750_write(codec, WM8750_ROUT2V, reg | 0x0100);
+	reg = wm8750_read_reg_cache(codec, WM8750_LINVOL);
+	wm8750_write(codec, WM8750_LINVOL, reg | 0x0100);
+	reg = wm8750_read_reg_cache(codec, WM8750_RINVOL);
+	wm8750_write(codec, WM8750_RINVOL, reg | 0x0100);
+
+	wm8750_add_controls(codec);
+	wm8750_add_widgets(codec);
+	
+	/* wait for caps to finish charging - liam make this thread */
+	ssleep(1);
+	wm8750_dpm_event(codec, SNDRV_CTL_POWER_D3hot);
+
+	return 0;
+}
+
+/* 
+ * unregister interfaces and clean up
+ */
+static void wm8750_remove(struct snd_soc_codec *codec)
+{
+	wm8750_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
+}
+
+/*
+ * Attach WM8750 2 wire client 
+ */
+static int wm8750_i2c_probe(struct i2c_adapter *adap, int addr, int kind)
+{		
+	int ret = 0;
+	struct snd_soc_codec *codec;
+	struct i2c_client *i2c;
+
+	client_template.adapter = adap;
+	client_template.addr = addr;
+	
+	if ((codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+ 
+	if ((i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL)) == NULL){
+		kfree(codec);
+		return -ENOMEM;
+	}
+	memcpy(i2c, &client_template, sizeof(struct i2c_client));
+	codec->control_data = i2c;
+	i2c->dev.platform_data = codec;
+
+	if((ret = i2c_attach_client(i2c)) < 0) {
+		err("failed to attach codec at addr %x\n", addr);
+		kfree(i2c);
+		kfree(codec);
+		return ret;
+	}
+
+	codec->name = "WM8750";
+	codec->longname = "WM8750 Portable Codec";
+	codec->owner = THIS_MODULE;
+	codec->pdev.name = "alsa-wm8750";
+	codec->pdev.id = -1;
+	codec->pdev.dev.release = wm8750_device_release;
+	codec->probe = wm8750_probe;
+	codec->remove = wm8750_remove;
+	codec->read = wm8750_read_reg_cache;
+	codec->write = wm8750_write;
+	codec->dpm_event = wm8750_dpm_event;
+	codec->pcms = &wm8750_pcm_client;
+	codec->npcms = 1;
+	if ((codec->reg_cache = 
+			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8750_reg), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+	memcpy(codec->reg_cache, wm8750_reg, sizeof(u16) * ARRAY_SIZE(wm8750_reg));
+
+	if((ret = snd_soc_register_codec(codec)) < 0) {
+		err("can't register codec");
+		i2c_del_driver(&wm8750_i2c_driver);
+		kfree(i2c);
+		kfree(codec->reg_cache);
+		kfree(codec);
+	}
+
+	return ret;
+}
+
+static int wm8750_i2c_detach(struct i2c_client *client)
+{
+	struct snd_soc_codec *codec = 
+		(struct snd_soc_codec*)client->dev.platform_data;
+			
+	i2c_detach_client(client);
+	snd_soc_unregister_codec(codec);
+	kfree(codec->control_data);
+	kfree(codec->reg_cache);
+	kfree(codec);
+	return 0;
+}
+
+static int wm8750_i2c_attach(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, wm8750_i2c_probe);
+}
+
+/* WM8750 2 Wire layer */ 
+static struct i2c_driver wm8750_i2c_driver = {
+	.name =           "i2c wm8750 driver",
+	.id =             I2C_DRIVERID_WM8750,
+	.flags =          I2C_DF_NOTIFY,
+	.attach_adapter = wm8750_i2c_attach,
+	.detach_client =  wm8750_i2c_detach,
+	.command =        NULL,
+};
+
+static struct i2c_client client_template = {
+	.name =   "WM8750",
+	.flags =  I2C_CLIENT_ALLOW_USE,
+	.driver = &wm8750_i2c_driver,
+};
+
+static int __init wm8750_init(void)
+{	
+	int ret = 0;
+
+	info("WM8750 Audio Codec %s", WM8750_VERSION);
+
+	if ((ret = i2c_add_driver(&wm8750_i2c_driver)) != 0)
+		err("can't add i2c driver");
+	
+	return ret;
+}
+
+static void __exit wm8750_exit(void)
+{
+	i2c_del_driver(&wm8750_i2c_driver);
+}
+
+module_init(wm8750_init);
+module_exit(wm8750_exit);
+
+MODULE_DESCRIPTION("Soc WM8750 driver");
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_LICENSE("GPL");
diff -urN a/sound/soc/codecs/wm8772.h b/sound/soc/codecs/wm8772.h
--- a/sound/soc/codecs/wm8772.h	1970-01-01 01:00:00.000000000 +0100
+++ b/sound/soc/codecs/wm8772.h	2005-11-26 12:53:06.000000000 +0000
@@ -0,0 +1,34 @@
+/*
+ * wm8772.h  --  audio driver for WM8772
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef _WM8772_H
+#define _WM8772_H
+
+/* WM8772 register space */
+
+#define WM8731_LINVOL   0x00
+#define WM8731_RINVOL   0x01
+#define WM8731_LOUT1V   0x02
+#define WM8731_ROUT1V   0x03
+#define WM8731_APANA    0x04
+#define WM8731_APDIGI   0x05
+#define WM8731_PWR      0x06
+#define WM8731_IFACE    0x07
+#define WM8731_SRATE    0x08
+#define WM8731_ACTIVE   0x09
+#define WM8731_RESET	0x0f
+
+#define WM8731_CACHEREGNUM 	10
+
+#endif
diff -urN a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
--- a/sound/soc/codecs/wm8971.c	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/codecs/wm8971.c	2005-11-28 11:36:04.000000000 +0000
@@ -19,8 +19,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/i2c.h>
 #include <linux/pm.h>
+#include <linux/device.h>
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -32,7 +32,7 @@
 #include "wm8971.h"
 
 #define AUDIO_NAME "wm8971"
-#define WM8971_VERSION "0.2"
+#define WM8971_VERSION "0.3"
 
 
 #define PFX AUDIO_NAME
@@ -48,23 +48,6 @@
 #define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg)
 
 
-#define WM8971_2W_ADDR1			0x1a
-#define	WM8971_2W_ADDR2			0x1b
-
-#define I2C_DRIVERID_WM8971		0xfdfd		/* need to get a real ID */
-
-
-static unsigned short normal_i2c[] = { WM8971_2W_ADDR1, WM8971_2W_ADDR2, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };	/* (required for kernel 2.6.10) */
-
-
-/* magic definition of all other variables and things */
-I2C_CLIENT_INSMOD;
-
-static struct i2c_driver wm8971_i2c_driver;
-static struct i2c_client client_template;
-
-
 #define	WM8971_REG_COUNT		43
 
 /*
@@ -150,8 +133,6 @@
 	{WM8971_HWFMT, SND_SOC_HWBITS(16), 96000,  96, 0x005e},
 };
 
-
-
 static inline unsigned int wm8971_read_reg_cache(struct snd_soc_codec * codec, 
 	unsigned int reg)
 {
@@ -174,15 +155,19 @@
 	unsigned int value)
 {
 	u8 data[2];
-	struct i2c_client *i2c = (struct i2c_client*)codec->control_data;
-
-	/* D15..D9 is WM8971 register offset, D8..D0 is register data */
+	
+	/* data is 
+	 *   D15..D9 WM8753 register offset
+	 *   D8...D0 register data
+	 */
 	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
 	data[1] = value & 0x00ff;
 
 	wm8971_write_reg_cache (codec, reg, value);
-
-	return (i2c_master_send(i2c, data, 2) == 2) ? 0 : -1;
+	if (codec->hw_write(codec->control_data, data, 2) == 2)
+		return 0;
+	else
+		return -1;
 }
 
 #define wm8971_reset(c)	wm8971_write(c, WM8971_RESET, 0)
@@ -566,7 +551,6 @@
 			break;
 	}
 	
-	
 	/* set rate */
 	wm8971_write(codec, WM8971_SRATE, pcm_c->hw_runtime.priv1);
 	wm8971_write(codec, WM8971_AUDIO, iface);
@@ -574,10 +558,6 @@
 	return 0;
 }
 
-static void wm8971_device_release(struct device * dev)
-{
-}
-
 static int wm8971_dpm_event(struct snd_soc_codec *codec, int event)
 {
 	u16 pwr_reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3f;
@@ -604,8 +584,7 @@
 	return 0;
 }
 
-static struct snd_soc_pcm_codec wm8971_pcm_client[] = {
-	{
+static struct snd_soc_pcm_codec wm8971_pcm_client = {
 	.name = "WM8971",
 	.playback = {
 		.sname = "Playback",
@@ -626,27 +605,59 @@
 		.channels_min = 1,
 		.channels_max = 2,
 	},
-		.ncapture = 1,
-		.ops = {
-			.prepare = wm8971_pcm_prepare,
-		},
-		.hw = {
-			.num_hmodes = ARRAY_SIZE(wm8971_audio),
-			.hmodes = &wm8971_audio[0],
-		},
+	.ncapture = 1,
+	.ops = {
+		.prepare = wm8971_pcm_prepare,
+	},
+	.hw = {
+		.num_hmodes = ARRAY_SIZE(wm8971_audio),
+		.hmodes = &wm8971_audio[0],
 	},
 };
 
-static int wm8971_probe(struct snd_soc_codec *codec)
+static int wm8971_suspend(struct device *dev, pm_message_t state)
 {
-	int reg;
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	wm8971_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
+	return 0;
+}
 
-	/* reset the WM8971 */
+static int wm8971_resume(struct device *dev)
+{
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	wm8971_dpm_event(codec, SNDRV_CTL_POWER_D3hot);
+	return 0;
+}
+
+static int wm8971_probe(struct device *dev)
+{
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	int reg, ret = 0;
+
+	codec->name = "WM8971";
+	codec->owner = THIS_MODULE;
+	codec->read = wm8971_read_reg_cache;
+	codec->write = wm8971_write;
+	codec->dpm_event = wm8971_dpm_event;
+	codec->pcms = &wm8971_pcm_client;
+	codec->npcms = 1;
+	if ((codec->reg_cache = 
+			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8971_reg), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+	memcpy(codec->reg_cache, wm8971_reg, sizeof(u16) * ARRAY_SIZE(wm8971_reg));
+	
 	wm8971_reset(codec);
 
 	/* charge output caps */
 	wm8971_dpm_event(codec, SNDRV_CTL_POWER_D2);
 
+	/* register pcms */
+	if((ret = snd_soc_register_pcms(codec)) < 0) {
+		wm8971_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
+		kfree(codec->reg_cache);
+		return ret;
+	}
+
 	/* set the update bits */
 	reg = wm8971_read_reg_cache(codec, WM8971_LDAC);
 	wm8971_write(codec, WM8971_LDAC, reg | 0x0100);
@@ -670,6 +681,7 @@
 
 	wm8971_add_controls(codec);
 	wm8971_add_widgets(codec);
+	snd_soc_register_card(codec);
 	
 	/* wait for caps to finish charging - liam make this thread */
 	ssleep(1);
@@ -678,125 +690,37 @@
 	return 0;
 }
 
-
-static void wm8971_remove(struct snd_soc_codec *codec)
+/* power down chip */
+static int wm8971_remove(struct device *dev)
 {
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
 	wm8971_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
-}
-
-
-/*
- * Attach WM8750 2 wire client 
- */
-static int wm8971_i2c_probe(struct i2c_adapter *adap, int addr, int kind)
-{		
-	int ret = 0;
-	struct snd_soc_codec *codec;
-	struct i2c_client *i2c;
-		
-	client_template.adapter = adap;
-	client_template.addr = addr;
-	
-	if ((codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL)) == NULL)
-		return -ENOMEM;
- 
-	if ((i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL)) == NULL){
-		kfree(codec);
-		return -ENOMEM;
-	}
-	memcpy(i2c, &client_template, sizeof(struct i2c_client));
-	codec->control_data = i2c;
-	i2c->dev.platform_data = codec;
-
-	if((ret = i2c_attach_client(i2c)) < 0) {
-		err("failed to attach codec at addr %x\n", addr);
-		kfree(i2c);
-		kfree(codec);
-		return ret;
-	}
-
-	codec->name = "WM8971";
-	codec->longname = "WM8971 Portable Codec";
-	codec->owner = THIS_MODULE;
-	codec->pdev.name = "alsa-wm8971";
-	codec->pdev.id = -1;
-	codec->pdev.dev.release = wm8971_device_release;
-	codec->probe = wm8971_probe;
-	codec->remove = wm8971_remove;
-	codec->read = wm8971_read_reg_cache;
-	codec->write = wm8971_write;
-	codec->dpm_event = wm8971_dpm_event;
-	codec->pcms = wm8971_pcm_client;
-	codec->npcms = 1;
-	if ((codec->reg_cache = 
-			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8971_reg), GFP_KERNEL)) == NULL)
-		return -ENOMEM;
-	memcpy(codec->reg_cache, wm8971_reg, sizeof(u16) * ARRAY_SIZE(wm8971_reg));
-
-	if((ret = snd_soc_register_codec(codec)) < 0) {
-		err("can't register codec");
-		i2c_del_driver(&wm8971_i2c_driver);
-		kfree(i2c);
-		kfree(codec->reg_cache);
-		kfree(codec);
-	}
-
-	return ret;
-}
-
-static int wm8971_i2c_detach(struct i2c_client *client)
-{
-	struct snd_soc_codec *codec = 
-		(struct snd_soc_codec*)client->dev.platform_data;
-	
-	i2c_detach_client(client);
-	snd_soc_unregister_codec(codec);
-	kfree(codec->control_data);
+	snd_soc_free_pcms(codec);
 	kfree(codec->reg_cache);
-	kfree(codec);
 	return 0;
 }
 
-static int wm8971_i2c_attach(struct i2c_adapter *adap)
-{
-	return i2c_probe(adap, &addr_data, wm8971_i2c_probe);
-}
-
-/* WM8971 2 Wire layer */ 
-static struct i2c_driver wm8971_i2c_driver = {
-	.name =           "i2c wm8971 driver",
-	.id =             I2C_DRIVERID_WM8971,
-	.flags =          I2C_DF_NOTIFY,
-	.attach_adapter = wm8971_i2c_attach,
-	.detach_client =  wm8971_i2c_detach,
-	.command =        NULL,
-};
-
-static struct i2c_client client_template = {
-	.name =   "WM8971",
-	.flags =  I2C_CLIENT_ALLOW_USE,
-	.driver = &wm8971_i2c_driver,
+static struct device_driver wm8971_driver = {
+	.name = 	"WM8971", 
+	.bus = 		&soc_bus_type, 
+	.owner = 	THIS_MODULE, 
+	.probe = 	wm8971_probe, 
+	.remove = 	wm8971_remove, 
+	.suspend = 	wm8971_suspend, 
+	.resume =	wm8971_resume, 
 };
 
 static int __init wm8971_init(void)
 {
-	int ret = 0;
-
 	info("WM8971 Audio Codec %s", WM8971_VERSION);
-
-	if ((ret = i2c_add_driver(&wm8971_i2c_driver)) != 0)
-		err("can't add i2c driver");
-
-	return ret;
+	return driver_register(&wm8971_driver);
 }
 
-
 static void __exit wm8971_exit(void)
 {
-	i2c_del_driver(&wm8971_i2c_driver);
+	driver_unregister(&wm8971_driver);
 }
 
-
 module_init(wm8971_init);
 module_exit(wm8971_exit);
 
diff -urN a/sound/soc/codecs/wm9713-voice.c b/sound/soc/codecs/wm9713-voice.c
--- a/sound/soc/codecs/wm9713-voice.c	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/codecs/wm9713-voice.c	2005-11-28 14:25:04.000000000 +0000
@@ -36,7 +36,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/wm97xx.h>
+#include <linux/device.h>
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -44,22 +44,7 @@
 #include <sound/soc.h>
 #include <sound/initval.h>
 
-#define NAME		"wm9713-voice"
-#define VERSION		"0.1"
-
-/*
- * Debug
- */ 
-#if 0
-#define dbg(format, arg...) printk(KERN_DEBUG TS_NAME ": " format "\n" , ## arg)
-#else	/* 
- */
-#define dbg(format, arg...)
-#endif	/* 
- */
-#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
+#define WM9713_VERSION		"0.3"
 
 #define WM9713_PCM_8K		(0xb << 8)
 #define WM9713_PCM_12K		(0x7 << 8)
@@ -85,32 +70,20 @@
 	{WM9713_VOICE_HWFMT, 	SND_SOC_HWBITS(16),		16000,	256,	WM9713_PCM_16K,},
 	{WM9713_VOICE_HWFMT, 	SND_SOC_HWBITS(16),		8000,	256,	WM9713_PCM_8K,},
 };
-	
-struct wm9713_pcm {
-	int pcm_rate;
-	struct wm97xx *wm;
-	snd_pcm_t *pcm_voice;
-};
-
-static struct wm9713_pcm wm9713;
 
 static int wm9713_voice_startup(snd_pcm_substream_t *substream)
 {
 	int reg;
-
-	/* power up clock control and voice DAC */
+#if 0
+	/* power up clock control and voice DAC - move to dpm */
 	reg = wm97xx_reg_read(wm9713.wm, AC97_POWERDOWN); 
 	wm97xx_reg_write(wm9713.wm, AC97_POWERDOWN, reg & ~0x2000);
 	reg = wm97xx_reg_read(wm9713.wm, AC97_EXTENDED_MID); 
 	wm97xx_reg_write(wm9713.wm, AC97_EXTENDED_MID, reg & ~0x1000);
-
+#endif
 	return 0;
 }
 
-static void wm9713_voice_shutdown(snd_pcm_substream_t *substream)
-{
-}
-
 static int wm9713_voice_prepare(snd_pcm_substream_t *substream)
 {
 	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
@@ -170,15 +143,15 @@
 			break;
 	}
 	/* enable PCM interface in master mode */
-	wm97xx_reg_write(wm9713.wm, AC97_CENTER_LFE_MASTER, reg);
+//	wm97xx_reg_write(wm9713.wm, AC97_CENTER_LFE_MASTER, reg);
 	
 	/* sample rate */
-	reg = wm97xx_reg_read(wm9713.wm, AC97_HANDSET_RATE) &0xe0ff;
-	wm97xx_reg_write(wm9713.wm, AC97_HANDSET_RATE, reg | pcm_c->hw_runtime.priv1);
+//	reg = wm97xx_reg_read(wm9713.wm, AC97_HANDSET_RATE) &0xe0ff;
+//	wm97xx_reg_write(wm9713.wm, AC97_HANDSET_RATE, reg | pcm_c->hw_runtime.priv1);
 	return 0;
 }
 
-static struct snd_soc_pcm_codec wm9713_voice_client = {
+static struct snd_soc_pcm_codec wm9713_pcm_client = {
 	.name = "WM9713 Voice",
 	.playback = {
 		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
@@ -195,7 +168,7 @@
 		.channels_max = 1,},
 	.ops = {
 		.startup = wm9713_voice_startup,
-		.shutdown = wm9713_voice_shutdown,
+	//	.shutdown = wm9713_voice_shutdown,
 		.prepare = wm9713_voice_prepare,},
 	.hw = {
 		.num_hmodes = ARRAY_SIZE(wm9713_voice),
@@ -203,75 +176,88 @@
 		},
 };
 
-static void wm9713_device_release(struct device * dev)
+
+static int wm9713_suspend(struct device *dev, pm_message_t state)
 {
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+//	wm9713_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
+	return 0;
 }
 
-static struct snd_soc_codec wm9713_soc_codec;
-
-static int wm9713_soc_probe(struct snd_soc_codec *codec)
+static int wm9713_resume(struct device *dev)
 {
-	int ret;
-
-	//ret = snd_soc_pcm_new(codec, 0, &wm9713_voice_client, 
-	//		&wm9713.pcm_voice, 1, 1, SND_SOC_SSP, 1);
-	return ret;
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+//	wm9713_dpm_event(codec, SNDRV_CTL_POWER_D3hot);
+	return 0;
 }
 
-static void wm9713_soc_remove(struct snd_soc_codec *codec)
+static int wm9713_probe(struct device *dev)
 {
-}
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	int reg, ret = 0;
 
-static struct snd_soc_codec wm9713_soc_codec = {
-	.name = "WM9713 Voice",
-	.longname = "WM9713 Portable Voice Codec",
-	.owner = THIS_MODULE,
-	.pdev = {
-		.name		= "alsa-wm9713",
-		.id		= -1,
-		.dev		= {.release = wm9713_device_release},
-	},
-	.probe = wm9713_soc_probe,
-	.remove = wm9713_soc_remove,
-};
+	codec->name = "WM9713";
+	codec->owner = THIS_MODULE;
+//	codec->read = wm9713_read_reg_cache;
+//	codec->write = wm9713_write;
+//	codec->dpm_event = wm9713_dpm_event;
+	codec->pcms = &wm9713_pcm_client;
+	codec->npcms = 1;
+
+	/* charge output caps */
+//	wm8753_dpm_event(codec, SNDRV_CTL_POWER_D2);
+
+	/* register pcms */
+	if((ret = snd_soc_register_pcms(codec)) < 0) {
+		//wm8753_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
+		return ret;
+	}
 
-static int wm97xx_wm9713_probe(struct wm97xx* wm)
-{	
-	if (wm->ac97 == NULL)
-		return -ENODEV;
-	
-	wm9713.wm = wm;
-	return snd_soc_register_codec(&wm9713_soc_codec);
+
+	snd_soc_register_card(codec);
+
+	/* wait for caps to finish charging - liam make this thread */
+	//ssleep(1);
+	//wm8753_dpm_event(codec, SNDRV_CTL_POWER_D3hot);
+
+	return ret;
 }
 
-static void wm97xx_wm9713_remove(struct wm97xx* wm)
+/* power down chip */
+static int wm9713_remove(struct device *dev)
 {
-	snd_soc_unregister_codec(&wm9713_soc_codec);
-	wm9713.wm = NULL;
+	struct snd_soc_codec* codec = (struct snd_soc_codec*)dev->platform_data;
+	//wm9713_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
+	snd_soc_free_pcms(codec);
+	return 0;
 }
 
-static struct wm97xx_platform_drv pxa_wm9713 = {
-	.id = 0x4c13,
-	.mask = 0xffff,
-	.probe = 	wm97xx_wm9713_probe,
-	.remove = 	wm97xx_wm9713_remove,
+
+static struct device_driver wm9713_driver = {
+	.name = 	"WM9713", 
+	.bus = 		&soc_bus_type, 
+	.owner = 	THIS_MODULE, 
+	.probe = 	wm9713_probe, 
+	.remove = 	wm9713_remove, 
+	.suspend = 	wm9713_suspend, 
+	.resume =	wm9713_resume, 
 };
 
-static int __init pxa_wm9713_init(void)
+static int __init wm9713_init(void)
 {
-	wm97xx_register_platform_drv(&pxa_wm9713);
-	return 0;
+	printk(KERN_INFO "WM9713 Audio Codec %s", WM9713_VERSION);
+	return driver_register(&wm9713_driver);
 }
 
-static void __exit pxa_wm9713_exit(void)
+static void __exit wm9713_exit(void)
 {
-	wm97xx_unregister_platform_drv(&pxa_wm9713);
+	driver_unregister(&wm9713_driver);
 }
 
 /* Module information */
 MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
-MODULE_DESCRIPTION("pxa2xx WM9713 PCM driver");
+MODULE_DESCRIPTION("WM9713 voice driver");
 MODULE_LICENSE("GPL");
 
-module_init(pxa_wm9713_init);
-module_exit(pxa_wm9713_exit);
+module_init(wm9713_init);
+module_exit(wm9713_exit);
diff -urN a/sound/soc/Makefile b/sound/soc/Makefile
--- a/sound/soc/Makefile	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/Makefile	2005-11-26 12:53:05.000000000 +0000
@@ -1,5 +1,5 @@
 
-snd-soc-core-objs := soc-core.o soc-dpm.o
+snd-soc-core-objs := soc-core.o soc-dpm.o soc-bus.o
 
 obj-$(CONFIG_SND_SOC)	+= snd-soc-core.o
 obj-$(CONFIG_SND_SOC)	+= pxa/ codecs/
diff -urN a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
--- a/sound/soc/pxa/corgi.c	1970-01-01 01:00:00.000000000 +0100
+++ b/sound/soc/pxa/corgi.c	2005-11-30 18:57:55.000000000 +0000
@@ -0,0 +1,384 @@
+/*
+ * corgi.c  --  SoC audio for Corgi
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Copyright 2005 Openedhand Ltd.
+ * 
+ * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ *          Richard Purdie <richard@openedhand.com>
+ * 
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  Revision history
+ *    30th Nov 2005   Initial version.
+ * 
+ * TODO:
+ *   Fill in (or delete) the gaps.
+ * 
+ */
+ 
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dpm.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/mainstone.h>
+#include <asm/arch/audio.h>
+
+#include "../codecs/wm8731.h"
+#include "pxa2xx-pcm.h"
+
+/*
+ * Debug
+ */
+ 
+#define PFX "corgi-soc"
+#define CORGI_DEBUG 0
+
+#ifdef CORGI_DEBUG
+#define dbg(format, arg...) printk(KERN_DEBUG PFX ": " format "\n" , ## arg)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif
+#define err(format, arg...) printk(KERN_ERR PFX ": " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg)
+
+/* 
+ * WM8731 2 wire address is determined by GPIO5
+ * state during powerup.
+ *    low  = 0x1a
+ *    high = 0x1b
+ */
+#define WM8731_2W_ADDR	0x1a
+#define I2C_DRIVERID_CORGI 0xfefe /* liam -  need a proper id */
+
+static unsigned short normal_i2c[] = { WM8731_2W_ADDR, I2C_CLIENT_END };
+
+/* Magic definition of all other variables and things */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver wm8731_i2c_driver;
+static struct i2c_client client_template;
+
+static struct snd_soc_machine corgi;
+
+static int corgi_startup(snd_pcm_substream_t *substream)
+{
+	return 0;
+}
+
+static void corgi_shutdown(snd_pcm_substream_t *substream)
+{
+}
+
+/* corgi pcm ops */
+static struct snd_soc_ops corgi_ops = {
+	.startup = corgi_startup,
+	.shutdown = corgi_shutdown,
+};
+
+static int corgi_suspend(struct device* dev, pm_message_t state)
+{
+	return 0;
+}
+
+static int corgi_resume(struct device* dev)
+{
+	return 0;
+}
+
+static int corgi_probe(struct device* dev)
+{
+	return 0;
+}
+
+static int corgi_remove(struct device* dev)
+{
+	return 0;
+}
+
+#ifdef TODO
+
+/*
+ * need to change this for corgi 
+ */
+
+/* example external dpm event callback */
+int external_amp_event(struct snd_soc_codec *codec, int event)
+{
+	return 0;
+}
+
+/* example machine dpm widgets */
+static const struct snd_soc_dpm_widget wm8753_dpm_widgets[] = {
+SND_SOC_DPM_HP("Headphone Jack"),
+SND_SOC_DPM_MIC("Mic1 Jack"),
+SND_SOC_DPM_AMP("Ext Amp", external_amp_event),
+};
+
+/* example machine interconnections */
+static const char* intercon[][3] = {
+	
+	/* headphone connected to LOUT1, ROUT1 */
+	{"Headphone Jack", NULL, "LOUT1"},
+	{"Headphone Jack", NULL, "ROUT1"},
+	
+	/* ext speaker connected to LOUT2, ROUT2 via amp */
+	{"Ext Amp", NULL, "LOUT2"},
+	{"Ext Amp", NULL, "ROUT2"},
+	
+	/* mic is connected to mic1 - with bias */
+	{"MIC1", NULL, "Mic Bias"},
+	{"MIC1N", NULL, "Mic Bias"},
+	{"Mic Bias", NULL, "Mic1 Jack"},
+	{"Mic Bias", NULL, "Mic1 Jack"},
+	
+	{"ACIN", NULL, "ACOP"},
+	{NULL, NULL, NULL},
+};
+
+/* example unconnected codec pins */
+static const struct snd_soc_dpm_pin wm8753_mainstone_pins[] = {
+	{"RXP", 0},
+	{"RXN", 0},
+	{"MIC2", 0},
+};
+
+/* headphone detect support on my board */
+static const char * hp_pol[] = {"Headphone", "Speaker"};
+static const struct soc_enum wm8753_enum =
+	SOC_ENUM_SINGLE(WM8753_OUTCTL, 1, 2, hp_pol);
+
+static const snd_kcontrol_new_t wm8753_mainstone_controls[] = {
+	SOC_SINGLE("Headphone Detect Switch", WM8753_OUTCTL, 6, 1, 0),
+	SOC_ENUM("Headphone Detect Polarity", wm8753_enum),
+};
+
+/*
+ * This is an example machine initialisation for a wm8753 connected to a 
+ * Mainstone II. It is missing logic to detect hp/mic insertions and logic
+ * to re-route the audio in such an event.
+ */
+
+static int corgi_wm8731_init(struct snd_soc_codec *codec)
+{
+	int i, err;
+	
+	/* set up mainstone codec pins */
+	for (i = 0; i < ARRAY_SIZE(wm8753_mainstone_pins); i++)
+		snd_soc_dpm_set_connection(codec, &wm8753_mainstone_pins[i]);
+	
+	/* add mainstone specific controls */
+	for (i = 0; i < ARRAY_SIZE(wm8753_mainstone_controls); i++) {
+		if ((err = snd_ctl_add(codec->card, snd_soc_cnew(&wm8753_mainstone_controls[i],codec, NULL))) < 0)
+			return err;
+	}
+
+	/* add mainstone specific widgets */
+	for(i = 0; i < ARRAY_SIZE(wm8753_dpm_widgets); i++) {
+		snd_soc_dpm_new_control(codec, &wm8753_dpm_widgets[i]);
+	}
+	
+	/* set up mainstone specific audio path interconnects */
+	for(i = 0; intercon[i][0] != NULL; i++) {
+		snd_soc_dpm_connect_input(codec, intercon[i][0], intercon[i][1], intercon[i][2]);
+	}
+	
+	snd_soc_dpm_sync(codec);
+	return 0;
+}
+#endif
+
+static struct snd_soc_machine_config codecs[] = {
+{
+	.name = "WM8731", 
+	.sname = "WM8731 HiFi", 
+	.iface = &pxa_i2s_interface,
+//	.init = corgi_wm8731_init, -- see above
+},
+};
+
+static void corgi_device_release(struct device * dev)
+{
+	kfree(dev);
+}
+
+
+/*
+ * Attach WM8731 2 wire client 
+ */
+static int corgi_codec_probe(struct i2c_adapter *adap, int addr, int kind)
+{		
+	int ret = 0;
+	struct snd_soc_codec *codec;
+	struct i2c_client *i2c;
+	struct device *dev;
+
+	if(addr != WM8731_2W_ADDR)
+		return -ENODEV;
+
+	client_template.adapter = adap;
+	client_template.addr = addr;
+	
+	if ((codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+ 
+	if ((i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL)) == NULL){
+		kfree(codec);
+		return -ENOMEM;
+	}
+	memcpy(i2c, &client_template, sizeof(struct i2c_client));
+	codec->control_data = i2c;
+
+	if((ret = i2c_attach_client(i2c)) < 0) {
+		err("failed to attach codec at addr %x\n", addr);
+		kfree(i2c);
+		kfree(codec);
+		return ret;
+	}
+	
+	if((dev = kzalloc(sizeof(struct device), GFP_KERNEL)) == NULL) {
+		i2c_del_driver(&wm8731_i2c_driver);
+		kfree(i2c);
+		kfree(codec);
+		return -ENOMEM;
+	}
+
+	dev->bus = &soc_bus_type;
+	dev->parent = &i2c->dev;
+	dev->release = corgi_device_release;
+	snprintf(dev->bus_id, BUS_ID_SIZE, "WM8731");
+	i2c->dev.platform_data = dev;
+	dev->platform_data = codec;
+	codec->longname = "Corgi Audio Codec";
+	codec->dev = dev;
+	codec->machine = &corgi;
+	codec->hw_write = (hw_write_t)i2c_master_send;
+	INIT_LIST_HEAD(&codec->dpm_widgets);
+	INIT_LIST_HEAD(&codec->dpm_paths);
+
+	if((ret = device_register(dev)) < 0) {
+		err("can't register codec");
+		i2c_del_driver(&wm8731_i2c_driver);
+		kfree(i2c);
+		kfree(dev);
+		kfree(codec);
+	}
+
+	return ret;
+}
+
+static int corgi_i2c_detach(struct i2c_client *client)
+{
+	struct device *dev = (struct device*)client->dev.platform_data;
+	struct snd_soc_codec *codec = 
+		(struct snd_soc_codec*)dev->platform_data;
+
+	device_unregister(dev);
+	i2c_detach_client(client);
+	kfree(codec);
+	kfree(client);
+	return 0;
+}
+
+static int corgi_i2c_attach(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, corgi_codec_probe);
+}
+
+/* corgi i2c codec control layer */ 
+static struct i2c_driver corgi_i2c_driver = {
+	.name =           "Corgi i2c codec driver",
+	.id =             I2C_DRIVERID_CORGI,
+	.flags =          I2C_DF_NOTIFY,
+	.attach_adapter = corgi_i2c_attach,
+	.detach_client =  corgi_i2c_detach,
+	.command =        NULL,
+};
+
+static struct i2c_client client_template = {
+	.name =   "WM8731",
+	.flags =  I2C_CLIENT_ALLOW_USE,
+	.driver = &corgi_i2c_driver,
+};
+
+static int __init corgi_i2c_init(void)
+{
+	int ret = 0;
+	
+	if ((ret = i2c_add_driver(&corgi_i2c_driver)) != 0)
+		printk(KERN_ERR "can't add i2c driver");
+		
+	return ret;
+}
+
+static struct snd_soc_machine corgi = {
+	.name = "Corgi",
+	.probe = corgi_probe,
+	.remove = corgi_remove,
+	.suspend = corgi_suspend,
+	.resume = corgi_resume,
+	.ops = &corgi_ops,
+	.platform = &pxa2xx_soc_platform,
+	.config = codecs,
+	.nconfigs = ARRAY_SIZE(codecs),
+};
+
+static int __init corgi_init(void) 
+{
+	int ret;
+	struct device *dev;
+
+	pxa_i2s_interface.machine = &corgi;
+	
+	if((dev = kzalloc(sizeof(struct device), GFP_KERNEL)) == NULL) 
+		return -ENOMEM;
+	
+	if((ret = snd_soc_register_machine(&corgi)) < 0) {
+		printk(KERN_ERR "can't register corgi soc audio\n");
+		return ret;
+	}
+
+	corgi.dev = dev;
+	dev->bus = &soc_bus_type;
+	dev->parent = NULL;
+	dev->release = corgi_device_release;
+	dev->platform_data = &corgi;
+	snprintf(dev->bus_id, BUS_ID_SIZE, "corgi-audio");
+
+	if((ret = device_register(dev)) < 0) {
+		err("can't register mainstone audio device");
+		kfree(dev);
+		snd_soc_unregister_machine(&corgi);
+	}
+	
+	corgi_i2c_init();
+	return ret;
+}
+
+static void __exit corgi_exit(void) 
+{
+	device_unregister(corgi.dev);
+	i2c_del_driver(&corgi_i2c_driver);
+	snd_soc_unregister_machine(&corgi);
+}
+
+module_init(corgi_init);
+module_exit(corgi_exit);
+
+/* Module information */ 
+MODULE_AUTHOR("Richard Purdie");
+MODULE_DESCRIPTION("ALSA SoC Corgi");
+MODULE_LICENSE("GPL");
diff -urN a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
--- a/sound/soc/pxa/Kconfig	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/pxa/Kconfig	2005-11-30 16:18:14.000000000 +0000
@@ -8,39 +8,51 @@
 	  to select the audio interfaces to support below.
 
 config SND_PXA2xx_SOC_AC97
-	tristate "SoC AC97 driver for the Intel PXA2xx chip"
-	depends on SND_PXA2xx_SOC
+	bool
 	select SND_AC97_CODEC
-	select SND_PCM
-	help
-	  Say Y or M if you want to add support for AC97 codecs attached to
-	  the PXA2xx AC97 interface.
 	  
 config SND_PXA2xx_SOC_I2S
-	tristate "SoC I2S driver for the Intel PXA2xx chip"
-	depends on SND_PXA2xx_SOC
-	select SND_PCM
-	help
-	  Say Y or M if you want to add support for I2S codecs attached to
-	  the PXA2xx I2S interface.
-	  
+	bool
+
 config SND_PXA2xx_SOC_SSP
-	tristate "SoC SSP driver for the Intel PXA2xx chip"
-	depends on SND_PXA2xx_SOC
-	select SND_PCM
+	bool
 	select PXA_SSP
-	help
-	  Say Y or M if you want to add support for PCM codecs attached to
-	  the PXA2xx SSP interface.
 
-# Supported machines
-menu "PXA2xx machine support"
-depends on SND_PXA2xx_SOC
 
+# Supported machines
+choice
+	prompt "PXA Audio Machine"
+	depends on SND_PXA2xx_SOC
+	default SND_PXA2xx_SOC_MAINSTONE
+	
 config SND_PXA2xx_SOC_MAINSTONE
-	tristate "SoC Audio support for Intel Mainstone"
+	bool "SoC AC97 Audio support for Intel Mainstone"
 	depends on SND_PXA2xx_SOC
+	select SND_PXA2xx_SOC_AC97
 	help
-	  Say Y or M if you want to add support for SoC audio on Mainstone.
+	  Say Y if you want to add support for SoC audio on Mainstone.
+
+config SND_PXA2xx_SOC_MAINSTONE_TEST
+	bool "SoC I2S/SSP Audio support for Intel Mainstone - testing"
+	depends on SND_PXA2xx_SOC
+	select SND_PXA2xx_SOC_I2S
+	select SND_PXA2xx_SOC_SSP
+	help
+	  Say Y if you want to add support for SoC audio on Mainstone.
+
+config SND_PXA2xx_SOC_TOSA
+	bool "SoC AC97 Audio support for tosa"
+	depends on SND_PXA2xx_SOC
+	select SND_PXA2xx_SOC_AC97
+	help
+	  Say Y if you want to add support for SoC audio on tosa.
 	  
-endmenu
+config SND_PXA2xx_SOC_CORGI
+	bool "SoC Audio support for corgi"
+	depends on SND_PXA2xx_SOC
+	select SND_PXA2xx_SOC_I2S
+	help
+	  Say Y if you want to add support for SoC audio on corgi.
+	  
+
+endchoice
diff -urN a/sound/soc/pxa/mainstone.c b/sound/soc/pxa/mainstone.c
--- a/sound/soc/pxa/mainstone.c	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/pxa/mainstone.c	2005-11-30 18:42:44.000000000 +0000
@@ -22,6 +22,8 @@
 #include <linux/moduleparam.h>
 #include <linux/version.h>
 #include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -33,6 +35,43 @@
 #include <asm/arch/audio.h>
 
 #include "../codecs/wm8753.h"
+#include "pxa2xx-pcm.h"
+
+/*
+ * Debug
+ */
+ 
+#define PFX "mainstone-soc"
+#define MAINSTONE_DEBUG 0
+
+#ifdef MAINSTONE_DEBUG
+#define dbg(format, arg...) printk(KERN_DEBUG PFX ": " format "\n" , ## arg)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif
+#define err(format, arg...) printk(KERN_ERR PFX ": " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg)
+
+#ifdef CONFIG_SND_PXA2xx_SOC_MAINSTONE_TEST
+/* 
+ * WM8753 2 wire address is determined by GPIO5
+ * state during powerup.
+ *    low  = 0x1a
+ *    high = 0x1b
+ */
+#define WM8753_2W_ADDR	0x1a
+#define I2C_DRIVERID_MAINSTONE 0xfefe /* liam -  need a proper id */
+
+static unsigned short normal_i2c[] = { WM8753_2W_ADDR, I2C_CLIENT_END };
+
+/* Magic definition of all other variables and things */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver wm8753_i2c_driver;
+static struct i2c_client client_template;
+#endif
+static struct snd_soc_machine mainstone;
 
 static int mainstone_startup(snd_pcm_substream_t *substream)
 {
@@ -66,31 +105,32 @@
 
 static long mst_audio_suspend_mask;
 
-static int mainstone_suspend(struct snd_soc_machine *machine, pm_message_t state)
+static int mainstone_suspend(struct device* dev, pm_message_t state)
 {
 	mst_audio_suspend_mask = MST_MSCWR2;
 	MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
 	return 0;
 }
 
-static int mainstone_resume(struct snd_soc_machine *machine)
+static int mainstone_resume(struct device* dev)
 {
 	MST_MSCWR2 &= mst_audio_suspend_mask | ~MST_MSCWR2_AC97_SPKROFF;
 	return 0;
 }
 
-static int mainstone_probe(struct snd_soc_machine *machine)
+static int mainstone_probe(struct device* dev)
 {
 	MST_MSCWR2 &= ~MST_MSCWR2_AC97_SPKROFF;
 	return 0;
 }
 
-static int mainstone_remove(struct snd_soc_machine *machine)
+static int mainstone_remove(struct device* dev)
 {
 	MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
 	return 0;
 }
 
+#ifdef CONFIG_SND_PXA2xx_SOC_MAINSTONE_TEST
 /* example external dpm event callback */
 int external_amp_event(struct snd_soc_codec *codec, int event)
 {
@@ -161,7 +201,7 @@
 		if ((err = snd_ctl_add(codec->card, snd_soc_cnew(&wm8753_mainstone_controls[i],codec, NULL))) < 0)
 			return err;
 	}
-	
+
 	/* add mainstone specific widgets */
 	for(i = 0; i < ARRAY_SIZE(wm8753_dpm_widgets); i++) {
 		snd_soc_dpm_new_control(codec, &wm8753_dpm_widgets[i]);
@@ -171,29 +211,156 @@
 	for(i = 0; intercon[i][0] != NULL; i++) {
 		snd_soc_dpm_connect_input(codec, intercon[i][0], intercon[i][1], intercon[i][2]);
 	}
-	snd_soc_dpm_sync(codec);
 	
+	snd_soc_dpm_sync(codec);
 	return 0;
 }
+#endif
 
 /* I've added all my different configs here atm for easier testing on ms II */
 static struct snd_soc_machine_config codecs[] = {
+#ifdef CONFIG_SND_PXA2xx_SOC_MAINSTONE
+{
+	.name = "AC97", 
+	.sname = "AC97 HiFi", 
+	.iface = &pxa_ac97_interface,
+},
+#endif
+#ifdef CONFIG_SND_PXA2xx_SOC_MAINSTONE_TEST
 {
 	.name = "WM8753", 
 	.sname = "WM8753 HiFi", 
-	.interface = SND_SOC_I2S, 
-	.int_num = 0,
+	.iface = &pxa_i2s_interface,
 	.init = mainstone_wm8753_init,
 },
+{
+	.name = "WM8753", 
+	.sname = "WM8753 Voice", 
+	.iface = &pxa_ssp_interface[1],
+},
+#endif
 #if 0
 	{.name = "WM8971", .sname = "WM8971", SND_SOC_I2S, 0},
 	{.name = "WM8750", .sname = "WM8750", SND_SOC_I2S, 0},
 	{.name = "WM8731", .sname = "WM8731", SND_SOC_I2S, 0},
-	{.name = "WM8753", .sname = "WM8753 Voice", SND_SOC_SSP, 1},
-	{.name = "AC97", .sname = "AC97 Audio", SND_SOC_AC97, 0},
 #endif
 };
 
+static void mainstone_device_release(struct device * dev)
+{
+	kfree(dev);
+}
+
+#ifdef CONFIG_SND_PXA2xx_SOC_MAINSTONE_TEST
+/*
+ * Attach WM8753 2 wire client 
+ */
+static int mainstone_codec_probe(struct i2c_adapter *adap, int addr, int kind)
+{		
+	int ret = 0;
+	struct snd_soc_codec *codec;
+	struct i2c_client *i2c;
+	struct device *dev;
+
+	if(addr != WM8753_2W_ADDR)
+		return -ENODEV;
+
+	client_template.adapter = adap;
+	client_template.addr = addr;
+	
+	if ((codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+ 
+	if ((i2c = kzalloc(sizeof(struct i2c_client), GFP_KERNEL)) == NULL){
+		kfree(codec);
+		return -ENOMEM;
+	}
+	memcpy(i2c, &client_template, sizeof(struct i2c_client));
+	codec->control_data = i2c;
+
+	if((ret = i2c_attach_client(i2c)) < 0) {
+		err("failed to attach codec at addr %x\n", addr);
+		kfree(i2c);
+		kfree(codec);
+		return ret;
+	}
+	
+	if((dev = kzalloc(sizeof(struct device), GFP_KERNEL)) == NULL) {
+		i2c_del_driver(&wm8753_i2c_driver);
+		kfree(i2c);
+		kfree(codec);
+		return -ENOMEM;
+	}
+
+	dev->bus = &soc_bus_type;
+	dev->parent = &i2c->dev;
+	dev->release = mainstone_device_release;
+	snprintf(dev->bus_id, BUS_ID_SIZE, "WM8753");
+	i2c->dev.platform_data = dev;
+	dev->platform_data = codec;
+	codec->longname = "Mainstone Audio Codec";
+	codec->dev = dev;
+	codec->machine = &mainstone;
+	codec->hw_write = (hw_write_t)i2c_master_send;
+	INIT_LIST_HEAD(&codec->dpm_widgets);
+	INIT_LIST_HEAD(&codec->dpm_paths);
+
+	if((ret = device_register(dev)) < 0) {
+		err("can't register codec");
+		i2c_del_driver(&wm8753_i2c_driver);
+		kfree(i2c);
+		kfree(dev);
+		kfree(codec);
+	}
+
+	return ret;
+}
+
+static int mainstone_i2c_detach(struct i2c_client *client)
+{
+	struct device *dev = (struct device*)client->dev.platform_data;
+	struct snd_soc_codec *codec = 
+		(struct snd_soc_codec*)dev->platform_data;
+
+	device_unregister(dev);
+	i2c_detach_client(client);
+	kfree(codec);
+	kfree(client);
+	return 0;
+}
+
+static int mainstone_i2c_attach(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, mainstone_codec_probe);
+}
+
+/* Mainstone i2c codec control layer */ 
+static struct i2c_driver mainstone_i2c_driver = {
+	.name =           "Mainstone i2c codec driver",
+	.id =             I2C_DRIVERID_MAINSTONE,
+	.flags =          I2C_DF_NOTIFY,
+	.attach_adapter = mainstone_i2c_attach,
+	.detach_client =  mainstone_i2c_detach,
+	.command =        NULL,
+};
+
+static struct i2c_client client_template = {
+	.name =   "WM8753",
+	.flags =  I2C_CLIENT_ALLOW_USE,
+	.driver = &mainstone_i2c_driver,
+};
+
+static int __init mainstone_i2c_init(void)
+{
+	int ret = 0;
+	
+	if ((ret = i2c_add_driver(&mainstone_i2c_driver)) != 0)
+		printk(KERN_ERR "can't add i2c driver");
+		
+	return ret;
+}
+#endif
+
 static struct snd_soc_machine mainstone = {
 	.name = "Mainstone",
 	.probe = mainstone_probe,
@@ -201,22 +368,126 @@
 	.suspend = mainstone_suspend,
 	.resume = mainstone_resume,
 	.ops = &mainstone_ops,
+	.platform = &pxa2xx_soc_platform,
 	.config = codecs,
 	.nconfigs = ARRAY_SIZE(codecs),
 };
 
-static int __init snd_soc_init(void) 
+#ifdef CONFIG_SND_PXA2xx_SOC_MAINSTONE
+static unsigned int mainstone_ac97_read(struct snd_soc_codec *codec, 
+	unsigned int reg)
+{
+	return pxa2xx_ac97_ops.read(codec->ac97, reg);
+}
+
+static int mainstone_ac97_write(struct snd_soc_codec *codec, unsigned int reg,
+	unsigned int val)
+{
+	pxa2xx_ac97_ops.write(codec->ac97, reg, val);
+	return 0;
+}
+
+static struct device *ac97_dev;
+
+static int __init mainstone_ac97_init(void)
+{
+	int ret = 0;
+	struct snd_soc_codec *codec;
+	
+	if ((codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+ 
+	codec->control_data = &pxa2xx_ac97_ops;
+	if((ac97_dev = kzalloc(sizeof(struct device), GFP_KERNEL)) == NULL) {
+		kfree(codec);
+		return -ENOMEM;
+	}
+
+	ac97_dev->bus = &soc_bus_type;
+	ac97_dev->parent = NULL;
+	ac97_dev->release = mainstone_device_release;
+	snprintf(ac97_dev->bus_id, BUS_ID_SIZE, "AC97");
+	ac97_dev->platform_data = codec;
+	codec->longname = "Mainstone Audio Codec";
+	codec->dev = ac97_dev;
+	codec->machine = &mainstone;
+	codec->write = mainstone_ac97_write;
+	codec->read = mainstone_ac97_read;
+	INIT_LIST_HEAD(&codec->dpm_widgets);
+	INIT_LIST_HEAD(&codec->dpm_paths);
+
+	if((ret = device_register(ac97_dev)) < 0) {
+		err("can't register codec");
+		kfree(ac97_dev);
+		kfree(codec);
+	}
+
+	return ret;
+}
+#endif
+
+static int __init mainstone_init(void) 
 {
-	return snd_soc_register_machine(&mainstone);
+	int ret;
+	struct device *dev;
+		
+#ifdef CONFIG_SND_PXA2xx_SOC_AC97
+	pxa_ac97_interface.machine = &mainstone;
+#endif
+#ifdef CONFIG_SND_PXA2xx_SOC_I2S
+	pxa_i2s_interface.machine = &mainstone;
+#endif
+#ifdef CONFIG_SND_PXA2xx_SOC_SSP
+	pxa_ssp_interface[0].machine = &mainstone;
+	pxa_ssp_interface[1].machine = &mainstone;
+	pxa_ssp_interface[2].machine = &mainstone;
+#endif
+	
+	if((dev = kzalloc(sizeof(struct device), GFP_KERNEL)) == NULL) 
+		return -ENOMEM;
+	
+	if((ret = snd_soc_register_machine(&mainstone)) < 0) {
+		printk(KERN_ERR "can't register mainstone soc audio\n");
+		return ret;
+	}
+
+	mainstone.dev = dev;
+	dev->bus = &soc_bus_type;
+	dev->parent = NULL;
+	dev->release = mainstone_device_release;
+	dev->platform_data = &mainstone;
+	snprintf(dev->bus_id, BUS_ID_SIZE, "mainstone-audio");
+
+	if((ret = device_register(dev)) < 0) {
+		err("can't register mainstone audio device");
+		kfree(dev);
+		snd_soc_unregister_machine(&mainstone);
+	}
+	
+#ifdef CONFIG_SND_PXA2xx_SOC_MAINSTONE_TEST
+	mainstone_i2c_init();
+#endif
+#ifdef CONFIG_SND_PXA2xx_SOC_MAINSTONE
+	mainstone_ac97_init();
+#endif
+	return ret;
 }
 
-static void __exit snd_soc_exit(void) 
+static void __exit mainstone_exit(void) 
 {
+	device_unregister(mainstone.dev);
+#ifdef CONFIG_SND_PXA2xx_SOC_MAINSTONE_TEST
+	i2c_del_driver(&mainstone_i2c_driver);
+#endif
+#ifdef CONFIG_SND_PXA2xx_SOC_MAINSTONE
+	kfree(ac97_dev->platform_data);
+	device_unregister(ac97_dev);
+#endif
 	snd_soc_unregister_machine(&mainstone);
 }
 
-module_init(snd_soc_init); 
-module_exit(snd_soc_exit);
+module_init(mainstone_init);
+module_exit(mainstone_exit);
 
 /* Module information */ 
 MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
diff -urN a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
--- a/sound/soc/pxa/Makefile	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/pxa/Makefile	2005-11-30 17:52:03.000000000 +0000
@@ -1,13 +1,38 @@
+snd-soc-pxa2xx-objs := pxa2xx-pcm.o
+snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o
+snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o
+snd-soc-pxa2xx-ssp-objs := pxa2xx-ssp.o
+snd-soc-mainstone-objs := mainstone.o
+snd-soc-tosa-objs := tosa.o
+snd-soc-corgi-objs := corgi.o
+snd-soc-mainstone-test-objs := mainstone.o
 
-snd-pxa2xx-soc-objs := pxa2xx-pcm.o 
-snd-pxa2xx-soc-ac97-objs := pxa2xx-ac97.o 
-snd-pxa2xx-soc-i2s-objs := pxa2xx-i2s.o 
-snd-pxa2xx-soc-ssp-objs := pxa2xx-ssp.o
-snd-pxa2xx-soc-mainstone-objs := mainstone.o
-
-obj-$(CONFIG_SND_PXA2xx_SOC) += snd-pxa2xx-soc.o
-obj-$(CONFIG_SND_PXA2xx_SOC_AC97) += snd-pxa2xx-soc-ac97.o
-obj-$(CONFIG_SND_PXA2xx_SOC_I2S) += snd-pxa2xx-soc-i2s.o
-obj-$(CONFIG_SND_PXA2xx_SOC_SSP) += snd-pxa2xx-soc-ssp.o
+obj-$(CONFIG_SND_PXA2xx_SOC) += snd-soc-pxa2xx.o
 
-obj-$(CONFIG_SND_PXA2xx_SOC_MAINSTONE) += snd-pxa2xx-soc-mainstone.o
\ No newline at end of file
+ifeq ($(CONFIG_SND_PXA2xx_SOC_AC97),y)
+obj-$(CONFIG_SND_PXA2xx_SOC) += snd-soc-pxa2xx-ac97.o
+endif
+
+ifeq ($(CONFIG_SND_PXA2xx_SOC_I2S),y)
+obj-$(CONFIG_SND_PXA2xx_SOC) += snd-soc-pxa2xx-i2s.o
+endif
+
+ifeq ($(CONFIG_SND_PXA2xx_SOC_SSP),y)
+obj-$(CONFIG_SND_PXA2xx_SOC) += snd-soc-pxa2xx-ssp.o
+endif
+
+ifeq ($(CONFIG_SND_PXA2xx_SOC_MAINSTONE),y)
+obj-$(CONFIG_SND_PXA2xx_SOC) += snd-soc-mainstone.o
+endif
+
+ifeq ($(CONFIG_SND_PXA2xx_SOC_MAINSTONE_TEST),y)
+obj-$(CONFIG_SND_PXA2xx_SOC) += snd-soc-mainstone.o
+endif
+
+ifeq ($(CONFIG_SND_PXA2xx_SOC_TOSA),y)
+obj-$(CONFIG_SND_PXA2xx_SOC) += snd-soc-tosa.o
+endif
+
+ifeq ($(CONFIG_SND_PXA2xx_SOC_CORGI),y)
+obj-$(CONFIG_SND_PXA2xx_SOC) += snd-soc-corgi.o
+endif
\ No newline at end of file
diff -urN a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
--- a/sound/soc/pxa/pxa2xx-ac97.c	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/pxa/pxa2xx-ac97.c	2005-11-30 15:51:24.000000000 +0000
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/wait.h>
 #include <linux/delay.h>
@@ -50,7 +50,7 @@
 static unsigned short pxa2xx_ac97_read(ac97_t *ac97, unsigned short reg)
 {
 	unsigned short val = -1;
-	volatile unsigned long *reg_addr;
+	volatile u32 *reg_addr;
 
 	down(&car_mutex);
 
@@ -99,7 +99,7 @@
 
 static void pxa2xx_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
 {
-	volatile unsigned long *reg_addr;
+	volatile u32 *reg_addr;
 
 	down(&car_mutex);
 
@@ -198,7 +198,7 @@
 	return IRQ_NONE;
 }
 
-static ac97_bus_ops_t pxa2xx_ac97_ops = {
+ac97_bus_ops_t pxa2xx_ac97_ops = {
 	.read	= pxa2xx_ac97_read,
 	.write	= pxa2xx_ac97_write,
 	.reset	= pxa2xx_ac97_reset,
@@ -238,32 +238,29 @@
 
 #ifdef CONFIG_PM
 
-static int pxa2xx_ac97_suspend(struct snd_soc_pcm_interface *interface, pm_message_t state)
+static int pxa2xx_ac97_suspend(struct device *dev, pm_message_t state)
 {
-	snd_card_t *card = interface->card;
-	
-	if (card->power_state != SNDRV_CTL_POWER_D3cold) {
-		pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
-		
-		if (platform_ops && platform_ops->suspend)
-			platform_ops->suspend(platform_ops->priv);
-		GCR |= GCR_ACLINK_OFF;
-		pxa_set_cken(CKEN2_AC97, 0);
-	}
-	
+	GCR |= GCR_ACLINK_OFF;
+	pxa_set_cken(CKEN2_AC97, 0);
 	return 0;
 }
 
-static int pxa2xx_ac97_resume(struct snd_soc_pcm_interface *interface)
+static int pxa2xx_ac97_resume(struct device *dev)
 {
-	snd_card_t *card = interface->card;
-
-	if (card->power_state != SNDRV_CTL_POWER_D0) {
-		pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
-		pxa_set_cken(CKEN2_AC97, 1);
-		if (platform_ops && platform_ops->resume)
-			platform_ops->resume(platform_ops->priv);
-	}
+	struct snd_soc_pcm_interface *pcm_i = dev->driver_data;
+	struct snd_soc_pcm_codec *pcm_c = pcm_i->pcm_c;
+	struct snd_soc_codec *codec = pcm_c->codec;
+	
+	pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
+	pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
+	pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
+	pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
+#ifdef CONFIG_PXA27x
+	/* Use GPIO 113 as AC97 Reset on Bulverde */
+	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+#endif
+	pxa_set_cken(CKEN2_AC97, 1);
+	pxa2xx_ac97_reset(codec->ac97);
 	return 0;
 }
 
@@ -272,10 +269,8 @@
 #define pxa2xx_ac97_resume	NULL
 #endif
 
-static int pxa2xx_ac97_probe(struct snd_soc_pcm_interface *interface)
+static int pxa2xx_ac97_probe(struct device *dev)
 {
-	ac97_bus_t *ac97_bus;
-	ac97_template_t ac97_template;
 	int ret;
 
 	ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL);
@@ -291,13 +286,6 @@
 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
 #endif
 	pxa_set_cken(CKEN2_AC97, 1);
-
-	ret = snd_ac97_bus(interface->card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus);
-	if (ret)
-		return ret;
-	memset(&ac97_template, 0, sizeof(ac97_template));
-	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &interface->ac97);
-
 	return 0;
 
  err:
@@ -309,7 +297,7 @@
 	return ret;
 }
 
-static void pxa2xx_ac97_remove(struct snd_soc_pcm_interface *interface)
+static void pxa2xx_ac97_remove(struct device *dev)
 {
 	GCR |= GCR_ACLINK_OFF;
 	free_irq(IRQ_AC97, NULL);
@@ -320,11 +308,11 @@
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
-	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
+	struct snd_soc_codec *codec = pcm_c->codec;
 	
 	int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
 		  AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
-	return snd_ac97_set_rate(pcm_i->ac97, reg, runtime->rate);
+	return snd_ac97_set_rate(codec->ac97, reg, runtime->rate);
 }
 
 static int pxa2xx_ac97_hw_params(snd_pcm_substream_t *substream,
@@ -348,48 +336,37 @@
 	return 0;
 }
 
-static struct snd_soc_pcm_interface pxa_ac97_interface[] = {
-	{	.name = "pxa2xx-ac97",
-		.id = 0,
-		.type = SND_SOC_AC97,
-		.probe = pxa2xx_ac97_probe,
-		.remove = pxa2xx_ac97_remove,
-		.suspend = pxa2xx_ac97_suspend,
-		.resume = pxa2xx_ac97_resume,
-		.playback = {
-			.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | 
-			SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
-			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,
-			.channels_min = 2,
-			.channels_max = 2,},
-		.capture = {
-			.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | 
-			SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
-			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,
-			.channels_min = 2,
-			.channels_max = 2,},
-		.ops = {
-			.prepare = pxa2xx_ac97_prepare,
-			.hw_params = pxa2xx_ac97_hw_params,},
-	},
+struct snd_soc_pcm_interface pxa_ac97_interface = {
+	.name = "pxa2xx-ac97",
+	.id = 0,
+	.type = SND_SOC_AC97,
+	.probe = pxa2xx_ac97_probe,
+	.remove = pxa2xx_ac97_remove,
+	.suspend = pxa2xx_ac97_suspend,
+	.resume = pxa2xx_ac97_resume,
+	.playback = {
+		.sname = "AC97 Playback",
+		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | 
+		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
+		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 2,
+		.channels_max = 2,},
+	.capture = {
+		.sname = "AC97 Capture",
+		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | 
+		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
+		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 2,
+		.channels_max = 2,},
+	.ops = {
+		.prepare = pxa2xx_ac97_prepare,
+		.hw_params = pxa2xx_ac97_hw_params,},
 };
 
-static int __init pxa2xx_ac97_init(void)
-{
-	return snd_soc_register_interface(pxa_ac97_interface);
-}
-
-static void __exit pxa2xx_ac97_exit(void)
-{
-	snd_soc_unregister_interface(pxa_ac97_interface);
-}
-
 EXPORT_SYMBOL_GPL(pxa_ac97_interface);
-
-module_init(pxa2xx_ac97_init);
-module_exit(pxa2xx_ac97_exit);
+EXPORT_SYMBOL_GPL(pxa2xx_ac97_ops);
 
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
diff -urN a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
--- a/sound/soc/pxa/pxa2xx-i2s.c	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/pxa/pxa2xx-i2s.c	2005-11-30 17:31:19.000000000 +0000
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/delay.h>
-
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -41,7 +40,16 @@
 	SND_SOC_HWFMT_CBM_CFS | SND_SOC_HWFMT_NB_NF)
 
 static DECLARE_MUTEX(pxa_i2s_sem);
-static int i2s_open = 0;
+
+struct pxa_i2s_port {
+	int i2s_open;
+	u32 sadiv;
+	u32 sacr0;
+	u32 sacr1;
+	u32 saimr;
+	int master;
+};
+static struct pxa_i2s_port pxa_i2s;
 
 /*
  * priv1 is sadiv
@@ -117,11 +125,11 @@
 static int pxa2xx_i2s_startup(snd_pcm_substream_t *substream)
 {	
 	down(&pxa_i2s_sem);
-	if(!i2s_open) {
+	if(!pxa_i2s.i2s_open) {
 		SACR0 |= SACR0_RST;
 		SACR0 = 0;
 	}
-	i2s_open++;
+	pxa_i2s.i2s_open++;
 	up(&pxa_i2s_sem);
 	return 0;
 }
@@ -141,15 +149,15 @@
 {
 	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
 	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
-	int master = 0;
+	pxa_i2s.master = 0;
 	
 	if(pcm_i->hw_runtime.hformat & SND_SOC_HWFMT_CBS_CFS)
-		master = 1;
+		pxa_i2s.master = 1;
 		
-	pxa_gpio_mode(gpio_bus[master].rx);
-	pxa_gpio_mode(gpio_bus[master].tx);
-	pxa_gpio_mode(gpio_bus[master].frm);
-	pxa_gpio_mode(gpio_bus[master].clk);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].frm);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].clk);
 	pxa_set_cken(CKEN8_I2S, 1);
 	pxa_i2s_wait();
 	
@@ -175,11 +183,10 @@
 			SAIMR |= SAIMR_RFS;
 		}
 	} else {
-		
 		SACR0 = 0;
 		SACR1 = 0;
 		SAIMR = SACR1_DRPL | SACR1_DREC;
-		if (master)
+		if (pxa_i2s.master)
 			SACR0 |= SACR0_BCKD;
 		
 		SACR0 |= SACR0_RFTH(14) | SACR0_TFTH(1);
@@ -198,12 +205,15 @@
 	
 	SADIV = get_sadiv(pcm_i->hw_runtime.rate);
 	SACR0 |= SACR0_ENB;
-	
+	pcm_i->active = 1;
 	return 0;
 }
 
 static void pxa2xx_i2s_shutdown(snd_pcm_substream_t *substream)
 {
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
+	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
+	
 	down(&pxa_i2s_sem);
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		SACR1 |= SACR1_DRPL;
@@ -214,33 +224,55 @@
 	}
 
 	if (SACR1 & (SACR1_DREC | SACR1_DRPL)) {
-		pxa_i2s_wait();
 		SACR0 &= ~SACR0_ENB;
+		pxa_i2s_wait();
 		pxa_set_cken(CKEN8_I2S, 0);
+		pcm_i->active = 0;
 	}
-	i2s_open--;
+	pxa_i2s.i2s_open--;
 	up(&pxa_i2s_sem);
 }
 
 #ifdef CONFIG_PM
-static int pxa2xx_i2s_suspend(struct snd_soc_pcm_interface *interface, pm_message_t state)
+static int pxa2xx_i2s_suspend(struct device *dev, pm_message_t state)
 {
-	int ret = 0;
-
-	//if (interface->card && level == SUSPEND_DISABLE)
-		//ret = pxa2xx_ac97_do_suspend(card, SNDRV_CTL_POWER_D3cold);
-
-	return ret;
+	struct snd_soc_pcm_interface *pcm_i = dev->driver_data;
+	
+	if(!pcm_i->active)
+		return 0;
+		
+	/* disable link and store registers */
+	SACR0 &= ~SACR0_ENB;
+	pxa_i2s_wait();
+	pxa_i2s.sacr0 = SACR0;
+	pxa_i2s.sacr1 = SACR1;
+	pxa_i2s.saimr = SAIMR;
+	pxa_i2s.sadiv = SADIV;
+	pxa_set_cken(CKEN8_I2S, 0);
+	return 0;
 }
 
-static int pxa2xx_i2s_resume(struct snd_soc_pcm_interface *interface)
+static int pxa2xx_i2s_resume(struct device *dev)
 {
-	int ret = 0;
-
-	//if (interface->card && level == RESUME_ENABLE)
-		//ret = pxa2xx_ac97_do_resume(card, SNDRV_CTL_POWER_D0);
-
-	return ret;
+	struct snd_soc_pcm_interface *pcm_i = dev->driver_data;
+	
+	if(!pcm_i->active)
+		return 0;
+		
+	/* restore registers and enable link*/
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].frm);
+	pxa_gpio_mode(gpio_bus[pxa_i2s.master].clk);
+	pxa_set_cken(CKEN8_I2S, 1);
+	pxa_i2s_wait();
+	
+	SACR0 = pxa_i2s.sacr0;
+	SACR1 = pxa_i2s.sacr1;
+	SAIMR = pxa_i2s.saimr;
+	SADIV = pxa_i2s.sadiv;
+	SACR0 |= SACR0_ENB;
+	return 0;
 }
 
 #else
@@ -248,52 +280,37 @@
 #define pxa2xx_i2s_resume	NULL
 #endif
 
-static struct snd_soc_pcm_interface pxa_i2s_interface[] = {
-	{	.name = "pxa2xx-i2s",
-		.id = 0,
-		.type = SND_SOC_I2S,
-		.suspend = pxa2xx_i2s_suspend,
-		.resume = pxa2xx_i2s_resume,
-		.playback = {
-			.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | 
-			SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
-			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_96000,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,
-			.channels_min = 2,
-			.channels_max = 2,},
-		.capture = {
-			.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | 
-			SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
-			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_96000,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,
-			.channels_min = 2,
-			.channels_max = 2,},
-		.ops = {
-			.startup = pxa2xx_i2s_startup,
-			.shutdown = pxa2xx_i2s_shutdown,
-			.hw_params = pxa2xx_i2s_hw_params,},
-		.hw = {
-			.num_hmodes = ARRAY_SIZE(pxa2xx_i2s),
-			.hmodes = &pxa2xx_i2s[0],},
-	},
+struct snd_soc_pcm_interface pxa_i2s_interface = {
+	.name = "pxa2xx-i2s",
+	.id = 0,
+	.type = SND_SOC_I2S,
+	.suspend = pxa2xx_i2s_suspend,
+	.resume = pxa2xx_i2s_resume,
+	.playback = {
+		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | 
+		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
+		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 2,
+		.channels_max = 2,},
+	.capture = {
+		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | 
+		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
+		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 2,
+		.channels_max = 2,},
+	.ops = {
+		.startup = pxa2xx_i2s_startup,
+		.shutdown = pxa2xx_i2s_shutdown,
+		.hw_params = pxa2xx_i2s_hw_params,},
+	.hw = {
+		.num_hmodes = ARRAY_SIZE(pxa2xx_i2s),
+		.hmodes = &pxa2xx_i2s[0],},
 };
 
-static int __init pxa2xx_soc_i2s_init(void)
-{
-	snd_soc_register_interface(pxa_i2s_interface);
-	return 0;
-}
-
-static void __exit pxa2xx_soc_i2s_exit(void)
-{
-	snd_soc_unregister_interface(pxa_i2s_interface);
-}
-
 EXPORT_SYMBOL_GPL(pxa_i2s_interface);
 
-module_init(pxa2xx_soc_i2s_init);
-module_exit(pxa2xx_soc_i2s_exit);
-
 /* Module information */ 
 MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
 MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
diff -urN a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
--- a/sound/soc/pxa/pxa2xx-pcm.c	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/pxa/pxa2xx-pcm.c	2005-11-30 17:30:15.000000000 +0000
@@ -12,7 +12,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 
@@ -353,42 +353,63 @@
 	return ret;
 }
 
-static struct snd_soc_platform pxa2xx_soc_platform;
-
-static int pxa2xx_soc_probe(struct device *dev)
+static int pxa2xx_pcm_suspend(struct device *dev, pm_message_t state)
 {
+	struct snd_soc_pcm_interface *pcm_i = dev->driver_data;
+	snd_pcm_runtime_t *runtime = pcm_i->runtime;
+	struct pxa2xx_runtime_data *rtd;
+	
+	if(!runtime)
+		return 0;
+	
+	rtd = runtime->private_data;
+	DCSR(rtd->dma_ch) &= ~DCSR_RUN;
+	
 	return 0;
 }
 
-static int pxa2xx_soc_remove(struct device *dev)
+static int pxa2xx_pcm_resume(struct device *dev)
 {
+	struct snd_soc_pcm_interface *pcm_i = dev->driver_data;
+	snd_pcm_runtime_t *runtime = pcm_i->runtime;
+	struct pxa2xx_runtime_data *rtd;
+	
+	if(!runtime)
+		return 0;
+		
+	rtd = runtime->private_data;
+	DCMD(rtd->dma_ch) = 0;
+	*rtd->params->drcmr = rtd->dma_ch | DRCMR_MAPVLD;
+	DDADR(rtd->dma_ch) = rtd->dma_desc_array_phys;
+	DCSR(rtd->dma_ch) |= DCSR_RUN;
+	
 	return 0;
-}
-
-static int __init pxa2xx_soc_init(void)
-{
-	return snd_soc_register_platform(&pxa2xx_soc_platform);
-}
+}	
 
-static void __exit pxa2xx_soc_exit(void)
-{
-	snd_soc_unregister_platform(&pxa2xx_soc_platform);
-}
-
-static struct snd_soc_platform pxa2xx_soc_platform = {
+struct snd_soc_platform pxa2xx_soc_platform = {
 	.name		= "pxa2xx-audio",
 	.bus		= &platform_bus_type,
-	.probe		= pxa2xx_soc_probe,
-	.remove		= pxa2xx_soc_remove,
 	.pcm_ops 	= &pxa2xx_pcm_ops,
 	.pcm_new	= pxa2xx_pcm_new,
 	.pcm_free	= pxa2xx_pcm_free_dma_buffers,
+	.suspend	= pxa2xx_pcm_suspend,
+	.resume		= pxa2xx_pcm_resume,
+	.iface = {
+#ifdef CONFIG_SND_PXA2xx_SOC_AC97
+		&pxa_ac97_interface,
+#endif
+#ifdef CONFIG_SND_PXA2xx_SOC_I2S
+		&pxa_i2s_interface,
+#endif
+#ifdef CONFIG_SND_PXA2xx_SOC_SSP
+		&pxa_ssp_interface[0],
+		&pxa_ssp_interface[1],
+		&pxa_ssp_interface[2],
+#endif
+		NULL,},
 };
 
-module_init(pxa2xx_soc_init);
-module_exit(pxa2xx_soc_exit);
-
-EXPORT_SYMBOL(pxa2xx_pcm_new);
+EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
 
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
diff -urN a/sound/soc/pxa/pxa2xx-pcm.h b/sound/soc/pxa/pxa2xx-pcm.h
--- a/sound/soc/pxa/pxa2xx-pcm.h	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/pxa/pxa2xx-pcm.h	2005-11-30 13:25:45.000000000 +0000
@@ -13,7 +13,7 @@
 typedef struct {
 	char *name;			/* stream identifier */
 	u32 dcmd;			/* DMA descriptor dcmd field */
-	volatile unsigned long *drcmr;		/* the DMA request channel to use */
+	volatile u32 *drcmr;		/* the DMA request channel to use */
 	u32 dev_addr;			/* device physical address for DMA */
 } pxa2xx_pcm_dma_params_t;
 
@@ -24,3 +24,8 @@
 	u32 frm;
 } pxa2xx_gpio_t;
 
+extern struct snd_soc_pcm_interface pxa_ac97_interface;
+extern struct snd_soc_pcm_interface pxa_i2s_interface;
+extern struct snd_soc_pcm_interface pxa_ssp_interface[3];
+extern struct snd_soc_platform pxa2xx_soc_platform;
+extern ac97_bus_ops_t pxa2xx_ac97_ops;
diff -urN a/sound/soc/pxa/pxa2xx-ssp.c b/sound/soc/pxa/pxa2xx-ssp.c
--- a/sound/soc/pxa/pxa2xx-ssp.c	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/pxa/pxa2xx-ssp.c	2005-11-28 17:54:45.000000000 +0000
@@ -17,7 +17,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
 
 #include <sound/driver.h>
 #include <sound/core.h>
@@ -76,6 +76,9 @@
 };
 
 static struct ssp_dev ssp[3];
+#ifdef CONFIG_PM
+static struct ssp_state ssp_state[3];
+#endif
 
 static pxa2xx_pcm_dma_params_t pxa2xx_ssp1_pcm_mono_out = {
 	.name			= "SSP1 PCM Mono out",
@@ -241,25 +244,32 @@
 
 	ssp_disable(&ssp[pcm_i->id]);
 	ssp_exit(&ssp[pcm_i->id]);
+	pcm_i->active = 0;
 }
 
 #ifdef CONFIG_PM
-static int pxa2xx_ssp_suspend(struct snd_soc_pcm_interface *interface, pm_message_t state)
+static int pxa2xx_ssp_suspend(struct device *dev, pm_message_t state)
 {
 	int ret = 0;
-
-	//if (interface->card && level == SUSPEND_DISABLE)
-		//ret = pxa2xx_ac97_do_suspend(card, SNDRV_CTL_POWER_D3cold);
-
+	struct snd_soc_pcm_interface *pcm_i = dev->driver_data;
+	
+	if(!pcm_i->active)
+		return 0;
+		
+	ssp_save_state(&ssp[pcm_i->id], &ssp_state[pcm_i->id]);
+	
 	return ret;
 }
 
-static int pxa2xx_ssp_resume(struct snd_soc_pcm_interface *interface)
+static int pxa2xx_ssp_resume(struct device *dev)
 {
 	int ret = 0;
-
-	//if (interface->card && level == RESUME_ENABLE)
-		//ret = pxa2xx_ac97_do_resume(card, SNDRV_CTL_POWER_D0);
+	struct snd_soc_pcm_interface *pcm_i = dev->driver_data;
+	
+	if(!pcm_i->active)
+		return 0;
+		
+	ssp_restore_state(&ssp[pcm_i->id], &ssp_state[pcm_i->id]);
 
 	return ret;
 }
@@ -322,11 +332,11 @@
 	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]);
-
+	pcm_i->active = 1;
 	return 0;
 }
 
-static struct snd_soc_pcm_interface pxa_ssp_interfaces[] = {
+struct snd_soc_pcm_interface pxa_ssp_interface[] = {
 	{	.name = "pxa2xx-ssp1",
 		.id = 0,
 		.type = SND_SOC_SSP,
@@ -404,25 +414,7 @@
 	},
 };
 
-static int __init pxa2xx_soc_ssp_init(void)
-{
-	snd_soc_register_interface(&pxa_ssp_interfaces[0]);
-	snd_soc_register_interface(&pxa_ssp_interfaces[1]);
-	snd_soc_register_interface(&pxa_ssp_interfaces[2]);
-	return 0;
-}
-
-static void __exit pxa2xx_soc_ssp_exit(void)
-{
-	snd_soc_unregister_interface(&pxa_ssp_interfaces[2]);
-	snd_soc_unregister_interface(&pxa_ssp_interfaces[1]);
-	snd_soc_unregister_interface(&pxa_ssp_interfaces[0]);
-}
-
-EXPORT_SYMBOL_GPL(pxa_ssp_interfaces);
-
-module_init(pxa2xx_soc_ssp_init);
-module_exit(pxa2xx_soc_ssp_exit);
+EXPORT_SYMBOL_GPL(pxa_ssp_interface);
 
 /* Module information */ 
 MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
diff -urN a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
--- a/sound/soc/pxa/tosa.c	1970-01-01 01:00:00.000000000 +0100
+++ b/sound/soc/pxa/tosa.c	2005-11-30 18:37:28.000000000 +0000
@@ -0,0 +1,312 @@
+/*
+ * tosa.c  --  SoC audio for Tosa
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Copyright 2005 Openedhand Ltd.
+ * 
+ * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ *          Richard Purdie <richard@openedhand.com>
+ * 
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  Revision history
+ *    30th Nov 2005   Initial version.
+ * 
+ * TODO:
+ *   Fill in (or delete) the gaps.
+ * 
+ */
+ 
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dpm.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/audio.h>
+
+#include "pxa2xx-pcm.h"
+
+/*
+ * Debug
+ */
+ 
+#define PFX "tosa-soc"
+#define TOSA_DEBUG 0
+
+#ifdef TOSA_DEBUG
+#define dbg(format, arg...) printk(KERN_DEBUG PFX ": " format "\n" , ## arg)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif
+#define err(format, arg...) printk(KERN_ERR PFX ": " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg)
+
+
+static struct snd_soc_machine tosa;
+
+static int tosa_startup(snd_pcm_substream_t *substream)
+{
+	return 0;
+}
+
+static void tosa_shutdown(snd_pcm_substream_t *substream)
+{
+
+}
+
+/* tosa machine specific pcm ops */
+static struct snd_soc_ops tosa_ops = {
+	.startup = tosa_startup,
+	.shutdown = tosa_shutdown,
+};
+
+
+static int tosa_suspend(struct device* dev, pm_message_t state)
+{
+	return 0;
+}
+
+static int tosa_resume(struct device* dev)
+{
+	return 0;
+}
+
+static int tosa_probe(struct device* dev)
+{
+	return 0;
+}
+
+static int tosa_remove(struct device* dev)
+{
+	return 0;
+}
+
+#ifdef TODO
+/* 
+ * This has to be completed if necessary for tosa ?
+ */
+ 
+/* example external dpm event callback */
+int external_amp_event(struct snd_soc_codec *codec, int event)
+{
+	return 0;
+}
+
+/* example machine dpm widgets */
+static const struct snd_soc_dpm_widget wm8753_dpm_widgets[] = {
+SND_SOC_DPM_HP("Headphone Jack"),
+SND_SOC_DPM_MIC("Mic1 Jack"),
+SND_SOC_DPM_AMP("Ext Amp", external_amp_event),
+};
+
+/* example machine interconnections */
+static const char* intercon[][3] = {
+	
+	/* headphone connected to LOUT1, ROUT1 */
+	{"Headphone Jack", NULL, "LOUT1"},
+	{"Headphone Jack", NULL, "ROUT1"},
+	
+	/* ext speaker connected to LOUT2, ROUT2 via amp */
+	{"Ext Amp", NULL, "LOUT2"},
+	{"Ext Amp", NULL, "ROUT2"},
+	
+	/* mic is connected to mic1 - with bias */
+	{"MIC1", NULL, "Mic Bias"},
+	{"MIC1N", NULL, "Mic Bias"},
+	{"Mic Bias", NULL, "Mic1 Jack"},
+	{"Mic Bias", NULL, "Mic1 Jack"},
+	
+	{"ACIN", NULL, "ACOP"},
+	{NULL, NULL, NULL},
+};
+
+/* example unconnected codec pins */
+static const struct snd_soc_dpm_pin tosa_pins[] = {
+	{"RXP", 0},
+	{"RXN", 0},
+	{"MIC2", 0},
+};
+
+/* headphone detect support on my board */
+static const char * hp_pol[] = {"Headphone", "Speaker"};
+static const struct soc_enum tosa_enum =
+	SOC_ENUM_SINGLE(WM8753_OUTCTL, 1, 2, hp_pol);
+
+static const snd_kcontrol_new_t wm8753_mainstone_controls[] = {
+	SOC_SINGLE("Headphone Detect Switch", WM8753_OUTCTL, 6, 1, 0),
+	SOC_ENUM("Headphone Detect Polarity", wm8753_enum),
+};
+
+/*
+ * This is an example machine initialisation for a wm8753 connected to a 
+ * Mainstone II. It is missing logic to detect hp/mic insertions and logic
+ * to re-route the audio in such an event.
+ */
+
+static int tosa_ac97_init(struct snd_soc_codec *codec)
+{
+	int i, err;
+	
+	/* set up mainstone codec pins */
+	for (i = 0; i < ARRAY_SIZE(wm8753_mainstone_pins); i++)
+		snd_soc_dpm_set_connection(codec, &wm8753_mainstone_pins[i]);
+	
+	/* add mainstone specific controls */
+	for (i = 0; i < ARRAY_SIZE(wm8753_mainstone_controls); i++) {
+		if ((err = snd_ctl_add(codec->card, snd_soc_cnew(&wm8753_mainstone_controls[i],codec, NULL))) < 0)
+			return err;
+	}
+
+	/* add mainstone specific widgets */
+	for(i = 0; i < ARRAY_SIZE(wm8753_dpm_widgets); i++) {
+		snd_soc_dpm_new_control(codec, &wm8753_dpm_widgets[i]);
+	}
+	
+	/* set up mainstone specific audio path interconnects */
+	for(i = 0; intercon[i][0] != NULL; i++) {
+		snd_soc_dpm_connect_input(codec, intercon[i][0], intercon[i][1], intercon[i][2]);
+	}
+	
+	snd_soc_dpm_sync(codec);
+	return 0;
+}
+#endif
+
+/* I've added all my different configs here atm for easier testing on ms II */
+static struct snd_soc_machine_config codecs[] = {
+{	
+	.name = "AC97", 
+	.sname = "AC97 HiFi", 
+	.iface = &pxa_ac97_interface,
+	//.init = tosa_ac97_init, -- see above
+	},
+};
+
+static void tosa_device_release(struct device * dev)
+{
+	kfree(dev);
+}
+
+static struct snd_soc_machine tosa = {
+	.name = "Tosa",
+	.probe = tosa_probe,
+	.remove = tosa_remove,
+	.suspend = tosa_suspend,
+	.resume = tosa_resume,
+	.ops = &tosa_ops,
+	.platform = &pxa2xx_soc_platform,
+	.config = codecs,
+	.nconfigs = ARRAY_SIZE(codecs),
+};
+
+
+static unsigned int tosa_ac97_read(struct snd_soc_codec *codec, 
+	unsigned int reg)
+{
+	return pxa2xx_ac97_ops.read(codec->ac97, reg);
+}
+
+static int tosa_ac97_write(struct snd_soc_codec *codec, unsigned int reg,
+	unsigned int val)
+{
+	pxa2xx_ac97_ops.write(codec->ac97, reg, val);
+	return 0;
+}
+
+static struct device *ac97_dev;
+
+static int __init tosa_ac97_init(void)
+{
+	int ret = 0;
+	struct snd_soc_codec *codec;
+	
+	if ((codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+ 
+	codec->control_data = &pxa2xx_ac97_ops;
+	if((ac97_dev = kzalloc(sizeof(struct device), GFP_KERNEL)) == NULL) {
+		kfree(codec);
+		return -ENOMEM;
+	}
+
+	ac97_dev->bus = &soc_bus_type;
+	ac97_dev->parent = NULL;
+	ac97_dev->release = tosa_device_release;
+	snprintf(ac97_dev->bus_id, BUS_ID_SIZE, "AC97");
+	ac97_dev->platform_data = codec;
+	codec->longname = "Tosa Audio Codec";
+	codec->dev = ac97_dev;
+	codec->machine = &mainstone;
+	codec->write = tosa_ac97_write;
+	codec->read = tosa_ac97_read;
+	INIT_LIST_HEAD(&codec->dpm_widgets);
+	INIT_LIST_HEAD(&codec->dpm_paths);
+
+	if((ret = device_register(ac97_dev)) < 0) {
+		err("can't register codec");
+		kfree(ac97_dev);
+		kfree(codec);
+	}
+
+	return ret;
+}
+
+static int __init tosa_init(void) 
+{
+	int ret;
+	struct device *dev;
+	
+	pxa_ac97_interface.machine = &mainstone;
+	
+	if((dev = kzalloc(sizeof(struct device), GFP_KERNEL)) == NULL) 
+		return -ENOMEM;
+	
+	if((ret = snd_soc_register_machine(&tosa)) < 0) {
+		printk(KERN_ERR "can't register tosa soc audio\n");
+		return ret;
+	}
+
+	mainstone.dev = dev;
+	dev->bus = &soc_bus_type;
+	dev->parent = NULL;
+	dev->release = tosa_device_release;
+	dev->platform_data = &tosa;
+	snprintf(dev->bus_id, BUS_ID_SIZE, "tosa-audio");
+
+	if((ret = device_register(dev)) < 0) {
+		err("can't register tosa audio device");
+		kfree(dev);
+		snd_soc_unregister_machine(&tosa);
+	}
+	
+	tosa_ac97_init();
+	return ret;
+}
+
+static void __exit tosa_exit(void) 
+{
+	device_unregister(tosa.dev);
+	kfree(ac97_dev->platform_data);
+	device_unregister(ac97_dev);
+	snd_soc_unregister_machine(&tosa);
+}
+
+module_init(tosa_init);
+module_exit(tosa_exit);
+
+/* Module information */ 
+MODULE_AUTHOR("Richard Purdie");
+MODULE_DESCRIPTION("ALSA SoC Tosa");
+MODULE_LICENSE("GPL");
diff -urN a/sound/soc/soc-bus.c b/sound/soc/soc-bus.c
--- a/sound/soc/soc-bus.c	1970-01-01 01:00:00.000000000 +0100
+++ b/sound/soc/soc-bus.c	2005-11-30 17:34:38.000000000 +0000
@@ -0,0 +1,81 @@
+/*
+ * soc-bus.c  --  ALSA Soc Audio Layer
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/string.h>
+#include <sound/soc.h>
+
+static int soc_bus_match(struct device *dev, struct device_driver *drv)
+{
+	/* match codec */
+	if(!strcmp(dev->bus_id, drv->name))
+		return 1;
+
+	/* match machine - machine has "-audio" in name */
+	if(strstr(dev->bus_id, "-audio") && !strcmp(drv->name, "soc-audio"))
+		return 1;
+	
+	return 0;
+}
+
+static int soc_bus_suspend(struct device *dev, pm_message_t state)
+{
+	int ret = 0;
+
+	if (dev->driver && dev->driver->suspend)
+		ret = dev->driver->suspend(dev, state);
+
+	return ret;
+}
+
+static int soc_bus_resume(struct device *dev)
+{
+	int ret = 0;
+
+	if (dev->driver && dev->driver->resume)
+		ret = dev->driver->resume(dev);
+
+	return ret;
+}
+
+struct bus_type soc_bus_type = {
+	.name		= "soc-audio",
+	.match		= soc_bus_match,
+	.suspend	= soc_bus_suspend,
+	.resume		= soc_bus_resume,
+};
+
+static int __init soc_bus_init(void)
+{
+	printk(KERN_INFO "soc: version %s liam.girdwood@wolfsonmicro.com\n", 
+		SND_SOC_VERSION);
+	return bus_register(&soc_bus_type);
+}
+
+subsys_initcall(soc_bus_init);
+
+static void __exit soc_bus_exit(void)
+{
+	bus_unregister(&soc_bus_type);
+}
+
+module_exit(soc_bus_exit);
+
+EXPORT_SYMBOL(soc_bus_type);
+
+/* Module information */ 
+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_DESCRIPTION("ALSA SoC Core");
+MODULE_LICENSE("GPL");
diff -urN a/sound/soc/soc-core.c b/sound/soc/soc-core.c
--- a/sound/soc/soc-core.c	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/soc-core.c	2005-11-30 17:35:45.000000000 +0000
@@ -16,8 +16,6 @@
  *
  *  TODO:
  *   o Finish machine layer - move machine stuff out pxa2xx-pcm.c
- *   o Make codec info const and copy on registration (e.g. kcontrols)
- *   o Change away from ALSA pm callbacks and types for 2.6.15
  *   o Add hw rules to enforce rates, etc.
  *   o More testing with other codecs/machines.
  *   o Add more codecs and platforms to ensure good API coverage.
@@ -33,6 +31,7 @@
 #include <linux/i2c.h>
 #include <linux/pm.h>
 #include <linux/bitops.h>
+#include <linux/platform_device.h>
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -41,19 +40,12 @@
 #include <sound/soc-dpm.h>
 #include <sound/initval.h>
 
-#define SND_SOC_VERSION "0.7"
-
 #define iface_name(x) \
 	(((x) == SND_SOC_AC97) ? "ac97" : \
 	((x) == SND_SOC_I2S) ? "i2s" : \
 	((x) == SND_SOC_SSP) ? "ssp" : NULL)
 
 static DECLARE_MUTEX(soc_sem);
-static LIST_HEAD(codecs);
-static LIST_HEAD(interfaces);
-static struct snd_soc_platform *platform = NULL;
-static struct snd_soc_machine *machine = NULL;
-
 
 int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
 				unsigned short mask, unsigned short value)
@@ -111,13 +103,13 @@
 
 /* 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, 
+static int soc_hw_params(snd_pcm_substream_t *substream, 
 	snd_pcm_hw_params_t *params)
 {
 	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
 	struct snd_soc_pcm_interface *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++) {
@@ -131,10 +123,8 @@
 		}
 	}
 	
-	if (!match) {
-		printk(KERN_ERR "soc: can't match codec and interface capabilities\n");
+	if (!match)
 		return -EINVAL;
-	}
 	
 	pcm_i->hw_runtime.hformat =
 		1 << (generic_ffs(pcm_i->hw_runtime.hformat & pcm_c->hw_runtime.hformat & SND_SOC_FORMAT_MASK) -1) | 
@@ -163,11 +153,10 @@
 	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
 	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
 	snd_pcm_runtime_t *runtime = substream->runtime;
+	struct snd_soc_machine *machine = pcm_i->machine; 
+	struct snd_soc_platform *platform = machine->platform;
 	int ret = 0;
 
-	if(!machine || !platform)
-		return -ENODEV;
-	
 	/* Check that the codec and SoC audio interface's are compatible */
 	if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		runtime->hw.rates = pcm_c->playback.rates & pcm_i->playback.rates;
@@ -184,7 +173,7 @@
 		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) {
@@ -217,7 +206,7 @@
 			goto platform_err;
 		}
 	}
-	
+
 	if(machine->ops->startup) {
 		if((ret = machine->ops->startup(substream)) < 0) {
 			printk(KERN_ERR "soc: %s startup failed\n", machine->name);
@@ -232,6 +221,7 @@
 		}
 	}
 
+	pcm_i->runtime = runtime;
 	return ret;
 
 pcm_err:
@@ -258,6 +248,8 @@
 {
 	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
 	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
+	struct snd_soc_machine *machine = pcm_i->machine; 
+	struct snd_soc_platform *platform = machine->platform;
 
 	if(pcm_i->ops.shutdown)
 		pcm_i->ops.shutdown(substream);
@@ -270,7 +262,7 @@
 	
 	if(platform->pcm_ops->close)
 		platform->pcm_ops->close(substream);
-
+	pcm_i->runtime = NULL;
 	return 0;
 }
 
@@ -280,8 +272,10 @@
 {
 	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
 	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
+	struct snd_soc_machine *machine = pcm_i->machine; 
+	struct snd_soc_platform *platform = machine->platform;
 	int ret = 0;
-
+	
 	if(platform->pcm_ops->prepare)
 		if((ret = platform->pcm_ops->prepare(substream)) < 0)
 			return ret;
@@ -301,6 +295,8 @@
 {
 	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
 	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
+	struct snd_soc_machine *machine = pcm_i->machine; 
+	struct snd_soc_platform *platform = machine->platform;
 	int ret = 0;
 
 	if(pcm_c->ops.trigger)
@@ -327,13 +323,13 @@
 	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
 	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
 	struct snd_soc_codec *codec = (struct snd_soc_codec*)pcm_i->card->private_data;
+	struct snd_soc_machine *machine = pcm_i->machine; 
+	struct snd_soc_platform *platform = machine->platform;
 	int ret = 0;
 
 	/* prepare hw non AC97 only */
-	if(pcm_i->type != SND_SOC_AC97) {
-		if((ret = soc_check_hw_params(substream, params)) < 0)
-			return ret;
-	}
+	if(pcm_i->type != SND_SOC_AC97)
+		soc_hw_params(substream, params);
 	
 	if(pcm_c->ops.hw_params) {
 		if((ret = pcm_c->ops.hw_params(substream, params)) < 0) {
@@ -372,6 +368,7 @@
 		codec->dpm_event(codec, SNDRV_CTL_POWER_D0);
 	snd_soc_dpm_codec_mute(codec, 0);
 	codec->dpm_state = SNDRV_CTL_POWER_D0;
+
 	return ret;
 	
 platform_err:
@@ -395,6 +392,8 @@
 	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
 	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
 	struct snd_soc_codec *codec = (struct snd_soc_codec*)pcm_i->card->private_data;
+	struct snd_soc_machine *machine = pcm_i->machine; 
+	struct snd_soc_platform *platform = machine->platform;
 
 	if(pcm_c->ops.hw_free)
 		pcm_c->ops.hw_free(substream);
@@ -432,128 +431,13 @@
 	.trigger	= soc_pcm_trigger,
 };
 
-#ifdef CONFIG_PM
-/*
- * SUSPEND_NOTIFY - mute outputs
- * SUSPEND_DISABLE - power down chip
- */
-static int soc_suspend(snd_card_t *card, pm_message_t state)
-{
-	struct snd_soc_codec *c = card->pm_private_data;
-	//snd_soc_pcm_interface_t *i = c->interface;
-	
-	//snd_pcm_suspend_all(c->pcm);
-	if(c->suspend)
-		c->suspend(c, state);
-	//if(i->suspend)
-	//	i->suspend(i, state);
-	snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
-	
-	return 0;
-}
-
-static int soc_resume(snd_card_t * card)
-{
-	struct snd_soc_codec *c = card->pm_private_data;
-	//snd_soc_pcm_interface_t *i = c->interface;
-	
-	if(c->resume)
-		c->resume(c);
-	//if(i->resume)
-	//	i->resume(i);
-	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
-
-	return 0;
-}
-
-#else
-#define soc_suspend	NULL
-#define soc_resume	NULL
-#endif
-
-static int soc_register_pcm(int nconfig)
-{
-	int i, reg = 1;
-
-	/* register when all pcm are created for codec */
-	for(i = 0; i < machine->nconfigs; i++) {
-		
-		if(strcmp(machine->config[i].name, machine->config[nconfig].name))
-			continue;
-		
-		if(!machine->config[i].connect || machine->config[i].card_reg)
-			reg = 0;
-	}
-	
-	if (reg) {	
-		snd_soc_pcm_register(machine, machine->config[nconfig].name);
-		for(i = 0; i < machine->nconfigs; i++) {
-			if(!strcmp(machine->config[i].name, machine->config[nconfig].name))
-				machine->config[i].card_reg = 1;
-		}
-	}
-	
-	return reg;
-}
-
-static int soc_sync_objects(void)
-{
-	int i, ret = 0;
-	
-	/* only match codecs/interfaces when we have a machine and platform */
-	if(machine == NULL || platform == NULL)
-		return ret;
-
-	/* check machine config */
-	for(i = 0; i < machine->nconfigs; i++) {
-		if(machine->config[i].connect)
-			continue;
-	
-		if((ret = snd_soc_pcm_connect(machine, i)) == 0) {
-			machine->config[i].connect = 1;
-			soc_register_pcm(i);
-		}
-	}
-	
-	return 0;
-}
-
-static int soc_probe_codec(struct snd_soc_codec *codec)
-{
-	int ret = 0;
-	
-	/* register a sound card */
-	codec->card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, codec->owner, 0);
-	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(codec->probe && (ret = codec->probe(codec)) < 0)
-		goto err;
-	codec->probed = 1;
-	codec->dpm_state = SNDRV_CTL_POWER_D3hot;
-	soc_sync_objects();
-	return 0;
-	
-err:
-	snd_card_free(codec->card);
-	platform_device_unregister(&codec->pdev);
-	codec->card = NULL;
-	return ret;
-}
 
 static void soc_free_dpm_widgets(struct snd_soc_codec *codec)
 {
 	struct snd_soc_dpm_widget *w, *lw = NULL;
 	struct snd_soc_dpm_path *p, *lp = NULL;
 	struct list_head *l;
-	
+
 	list_for_each(l, &codec->dpm_widgets)
 	{
 		w =  list_entry(l, struct snd_soc_dpm_widget, list);
@@ -575,149 +459,147 @@
 	kfree(lp);
 }
 
-static int soc_remove_codec(struct snd_soc_codec *codec)
-{	
-	if(!codec->probed)
-		return 0;
+#ifdef CONFIG_PM
+/*
+ * SUSPEND_NOTIFY - mute outputs
+ * SUSPEND_DISABLE - power down chip
+ */
+static int soc_suspend(struct device * dev, pm_message_t state)
+{
+	struct snd_soc_machine * machine = 
+		(struct snd_soc_machine*)dev->platform_data;
+	struct snd_soc_platform *platform = machine->platform;
+	int i;
 	
-	if (codec->card) {
-		snd_soc_dpm_sys_remove(&codec->pdev.dev);
-		snd_card_free(codec->card);
-		platform_device_unregister(&codec->pdev);
-		codec->card = NULL;
+	for(i = 0; platform->iface[i] != NULL; i++) {
+		dev->driver_data = platform->iface[i];
+		if(platform->suspend)
+			platform->suspend(dev, state);
+		if(platform->iface[i]->suspend)
+			platform->iface[i]->suspend(dev, state);
 	}
-	if(codec->remove)
-		codec->remove(codec);
-
-	/* free any DPM objects */
-	soc_free_dpm_widgets(codec);
-	codec->probed = 0;
-
+	dev->driver_data = NULL;
+	if(machine->suspend)
+		machine->suspend(dev, state);
 	return 0;
 }
 
-int snd_soc_register_codec(struct snd_soc_codec *codec)
+static int soc_resume(struct device * dev)
 {
-	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);
-	
-	if((ret = soc_probe_codec(codec)) < 0) {
-		printk(KERN_ERR "soc: probe of codec %s failed\n", codec->name);
-		list_del_init(&codec->list);
-		up(&soc_sem);
-		return ret;
+	struct snd_soc_machine * machine = 
+		(struct snd_soc_machine*)dev->platform_data;
+	struct snd_soc_platform *platform = machine->platform;
+	int i;
+	
+	if(machine->resume)
+		machine->resume(dev);
+		
+	for(i = 0; platform->iface[i] != NULL; i++) {
+		dev->driver_data = platform->iface[i];
+		if(platform->iface[i]->resume)
+			platform->iface[i]->resume(dev);
+		if(platform->resume)
+			platform->resume(dev);
 	}
+	dev->driver_data = NULL;
 
-	up(&soc_sem);
-	return ret;
+	return 0;
 }
 
-void snd_soc_unregister_codec(struct snd_soc_codec *codec)
+#else
+#define soc_suspend	NULL
+#define soc_resume	NULL
+#endif
+
+static int soc_probe(struct device * dev)
 {
-	down(&soc_sem); 
-	list_del_init(&codec->list);
-	soc_remove_codec(codec);	
-	up(&soc_sem);
-}
+	int ret = 0, i;
+	struct snd_soc_machine * machine 
+		= (struct snd_soc_machine*)dev->platform_data;
+	struct snd_soc_platform* platform = machine->platform;
 
-int snd_soc_register_interface(struct snd_soc_pcm_interface *iface)
-{	
-	int ret = 0;
-	
-	down(&soc_sem);	
-	if(iface->probe && (ret = iface->probe(iface)) < 0) {
-		printk(KERN_ERR "soc: probe of interface %s failed\n", iface->name);
-		up(&soc_sem);
+	if(machine->probe && ((ret = machine->probe(dev)) < 0))
 		return ret;
-	}		
 
-	INIT_LIST_HEAD(&iface->list);
-	list_add(&iface->list, &interfaces);
-	soc_sync_objects();
-	up(&soc_sem);
-	return 0;
-}
+	if(platform->probe && ((ret = platform->probe(dev)) < 0))
+		goto platform_err;
 
-void snd_soc_unregister_interface(struct snd_soc_pcm_interface *iface)
-{
-	down(&soc_sem);
-	list_del_init(&iface->list);
-	if (iface->remove) 
-		iface->remove(iface);
-	up(&soc_sem);	
-}
-
-static struct device_driver soc_pdrv;
-
-int snd_soc_register_platform(struct snd_soc_platform *p)
-{
-	int ret = 0;
-	
-	down(&soc_sem);
-	if(platform) {
-		up(&soc_sem);
-		return -EBUSY;
+	for(i = 0; platform->iface[i] != NULL; i++){
+		dev->driver_data = platform->iface[i];
+		if(platform->iface[i]->probe && 
+			((ret = platform->iface[i]->probe(dev)) < 0))
+				goto iface_err;
 	}
+	dev->driver_data = NULL;
+	return 0;
 
-	platform = p;
-	soc_pcm_ops.mmap = p->pcm_ops->mmap;
-	soc_pcm_ops.pointer = p->pcm_ops->pointer;
-	soc_pcm_ops.ioctl = p->pcm_ops->ioctl;
-	soc_pdrv.bus = p->bus;
-	soc_pdrv.name = p->name;
-	soc_pdrv.probe = p->probe;
-	soc_pdrv.remove = p->remove;
-
-	if((ret = driver_register(&soc_pdrv)) < 0) {
-		printk(KERN_ERR "soc: failed to register platform %s\n", p->name);
-		up(&soc_sem);
-		return ret;
+iface_err:
+	for(; i > 0; --i){
+		if(platform->iface[i]->remove) 
+			platform->iface[i]->remove(dev);
 	}
 	
-	soc_sync_objects();
-	up(&soc_sem);
+	if(platform->remove)
+		platform->remove(dev);
+	
+platform_err:
+	if(machine->remove)
+			machine->remove(dev);
+	
 	return ret;
 }
 
-void snd_soc_unregister_platform(struct snd_soc_platform *p)
+static int soc_remove(struct device * dev)
 {
-	struct list_head *l;
-	struct snd_soc_codec *codec = NULL;
-	
-	down(&soc_sem);
-	list_for_each(l, &codecs) {
-		codec = list_entry(l, struct snd_soc_codec, list);
-		if (codec->card) {
-			snd_soc_dpm_sys_remove(&codec->pdev.dev);
-			snd_card_free(codec->card);
-			platform_device_unregister(&codec->pdev);
-			codec->card = NULL;
-		}
+	int i;
+	struct snd_soc_machine * machine 
+		= (struct snd_soc_machine*)dev->platform_data;
+	struct snd_soc_platform * platform = machine->platform;
+
+	for(i = 0; platform->iface[i] != NULL; i++){
+		if(platform->iface[i]->remove)
+			platform->iface[i]->remove(dev);
 	}
+
+	if(platform->remove)
+		platform->remove(dev);
+
+	if(machine->remove)
+			machine->remove(dev);
 	
-	driver_unregister(&soc_pdrv);
-	platform = NULL;
-	up(&soc_sem);	
+	return 0;
 }
 
+static struct device_driver soc_drv = {
+	.name = "soc-audio",
+	.bus = &soc_bus_type,
+	.probe = soc_probe,
+	.remove = soc_remove,
+	.suspend = soc_suspend,
+	.resume  = soc_resume,
+};
+
 int snd_soc_register_machine(struct snd_soc_machine *m)
 {
+	struct snd_soc_platform* platform = m->platform;
 	int ret = 0;
 
 	down(&soc_sem);
-	if(m->probe) {
-		if((ret = m->probe(m)) < 0) {
-			up(&soc_sem);
-			return ret;
-		}
+	if(m->platform == NULL) {
+		up(&soc_sem);
+		return -ENODEV;
 	}
-	machine = m;
-	soc_sync_objects();
+
+	soc_pcm_ops.mmap = platform->pcm_ops->mmap;
+	soc_pcm_ops.pointer = platform->pcm_ops->pointer;
+	soc_pcm_ops.ioctl = platform->pcm_ops->ioctl;
+
+	if((ret = driver_register(&soc_drv)) < 0) {
+		printk(KERN_ERR "soc: failed to register machine %s\n", platform->name);
+		up(&soc_sem);
+		return ret;
+	}
+
 	up(&soc_sem);
 	return 0;
 }
@@ -725,148 +607,116 @@
 void snd_soc_unregister_machine(struct snd_soc_machine *m)
 {
 	down(&soc_sem);
-	if(machine->remove)
-		machine->remove(m);
-	machine = NULL;
-	up(&soc_sem);
-}
-
-/* find codec from pcm name */
-static struct snd_soc_codec * soc_get_codec_from_pcm(char *pcm_name, 
-	struct snd_soc_pcm_codec **pcm_c)
-{
-	struct list_head *l;
-	struct snd_soc_codec *c = NULL;
-
-	list_for_each(l, &codecs) {
-		int i = 0;
-		c = list_entry(l, struct snd_soc_codec, list);
-
-		if(c->npcms == 0)
-			continue;
-
-		for(;i < c->npcms; i++) {
-			if(!strcmp(pcm_name, c->pcms[i].name)) {
-				if(pcm_c)
-					*pcm_c = &c->pcms[i];
-				return c;
-			}
-		}
-	}
-	
-	return NULL;
-}
-
-static struct snd_soc_codec* soc_get_codec(char *name)
-{
-	struct list_head *l;
-	struct snd_soc_codec *c = NULL;
-
-	list_for_each(l, &codecs) {
-		c = list_entry(l, struct snd_soc_codec, list);
-			
-		if(!strcmp(name, c->name))
-			return c;
-	}
-	
-	return NULL;
+	driver_unregister(&soc_drv);
+	up(&soc_sem);	
 }
 
-static struct snd_soc_pcm_interface* soc_get_interface(int iface_type, int num)
-{
-	struct list_head *l;
-	struct snd_soc_pcm_interface *i = NULL;
-	
-	list_for_each(l, &interfaces) {
-		i = list_entry(l, struct snd_soc_pcm_interface, list);
-		if (i->type == iface_type && i->id == num){
-			if (i->pcm_c)
-				return NULL;
-			else
-				return i;
-		}
-	}
-	return NULL;
-}
 
-int snd_soc_pcm_connect(struct snd_soc_machine *machine, int nconfig)
+static int soc_create_pcm(struct snd_soc_codec *codec, 
+	struct snd_soc_pcm_codec *pcm_c, struct snd_soc_pcm_interface *iface, 
+	int num)
 {
 	snd_pcm_t *pcm;
-	struct snd_soc_pcm_codec *pcm_c;
-	int ret = 0;
-	struct snd_soc_pcm_interface *iface;
-	struct snd_soc_codec *codec;
-	int iface_type = machine->config[nconfig].interface;
-	int num = machine->config[nconfig].int_num;
-	char *name = machine->config[nconfig].sname;
 	char new_name[32];
+	int ret = 0;
 
-	if((codec = soc_get_codec_from_pcm(name, &pcm_c)) == NULL)
-		return -ENODEV;
-	
-	if((iface = soc_get_interface(iface_type, num)) == NULL)
-		return -ENODEV;
-	
 	/* check client and interface hw capabilities */
-	sprintf(new_name, "%s-%s-%d", pcm_c->name, iface_name(iface_type), num);
+	sprintf(new_name, "%s-%s-%d", pcm_c->name, iface_name(iface->type), num);
+
 	if((ret = snd_pcm_new(codec->card, new_name, codec->pcm_devs++, pcm_c->nplayback, pcm_c->ncapture, &pcm)) < 0) {
 		printk(KERN_ERR "soc: can't create pcm for codec %s\n", codec->name);
-		goto err;
+		return ret;
 	}
 	pcm_c->pcm_i = iface;
 	pcm_c->codec = codec;
 	iface->card = codec->card;
 	iface->pcm_c = pcm_c;
 	pcm->private_data = pcm_c;
-		
+
 	if (pcm_c->nplayback)
 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
 
 	if (pcm_c->ncapture)
 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
 
-	if((ret = platform->pcm_new(codec->card, pcm_c, pcm)) < 0) {
+	if((ret = codec->machine->platform->pcm_new(codec->card, pcm_c, pcm)) < 0) {
 		printk(KERN_ERR "soc: platform pcm constructor failed\n");
-		goto err;
+		return ret;
 	}
-	pcm->private_free = platform->pcm_free;
-	if(machine->config[nconfig].init)
-		machine->config[nconfig].init(codec);
-	
+
+	pcm->private_free = codec->machine->platform->pcm_free;
 	printk(KERN_INFO "soc: %s <-> %s mapping ok\n", pcm_c->name, iface->name);
 	return ret;
+}
+
+static int soc_match_pcms(struct snd_soc_codec *codec)
+{
+	struct snd_soc_machine *machine = codec->machine;
+	int n = 0, i, j;
+
+	for(i = 0; i < machine->nconfigs; i++) {
+		for(j = 0; j < codec->npcms; j++) {
+			if(!strcmp(codec->pcms[j].name, machine->config[i].sname)) {
+				soc_create_pcm(codec, &codec->pcms[j], machine->config[i].iface, n);
+				n++;
+			}
+		}			
+	}
 	
-err:
-	pcm_c->pcm_i = NULL;
-	iface->card = NULL;
-	iface->pcm_c = NULL;
-	return ret;
+	return n;
 }
 
-int snd_soc_pcm_register(struct snd_soc_machine *machine, char *name)
+int snd_soc_register_pcms(struct snd_soc_codec *codec)
 {
-	struct snd_soc_codec* codec;
 	int ret = 0;
 
-	if((codec = soc_get_codec(name)) == NULL)
+	/* register a sound card */
+	codec->card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, codec->owner, 0);
+	if (!codec->card) {
+		printk(KERN_ERR "soc: can't create sound card for codec %s\n", codec->name);
 		return -ENODEV;
+	}
 
+	codec->card->dev = codec->dev;
+	codec->card->private_data = codec;
+	strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
+	
+	if(soc_match_pcms(codec) == 0){
+		printk(KERN_ERR "soc: couldn't match any pcms for %s\n", codec->name);
+		return -ENODEV;
+	}
+	
+	return ret;
+
+}
+
+int snd_soc_register_card(struct snd_soc_codec *codec)
+{
+	int ret = 0, i;
+	
+	for(i = 0; i < codec->npcms; i++) {
+		if(codec->machine->config[i].init)
+			codec->machine->config[i].init(codec);
+	}
 	snprintf(codec->card->shortname, sizeof(codec->card->shortname),
 		 "%s", codec->name);
 	snprintf(codec->card->longname, sizeof(codec->card->longname),
 		 "%s (%s)", codec->longname, "SoC");
 	
-	snd_card_set_pm_callback(codec->card, soc_suspend, soc_resume, codec);
-	
 	if((ret = snd_card_register(codec->card)) < 0) {
 		printk(KERN_ERR "soc: failed to register soundcard for codec %s\n", codec->name);
 		return ret;
 	}
 	
-	codec->pdev.dev.driver_data = codec;
-	snd_soc_dpm_sys_add(&codec->pdev.dev);
+	snd_soc_dpm_sys_add(codec->dev);
+	return ret;
+}
 
-	return ret;	
+void snd_soc_free_pcms(struct snd_soc_codec *codec)
+{
+	snd_soc_dpm_sys_remove(codec->dev);
+	soc_free_dpm_widgets(codec);
+	snd_card_free(codec->card);
 }
 
 int snd_soc_set_runtime_hw(snd_pcm_substream_t *substream, const snd_pcm_hardware_t *hw)
@@ -891,8 +741,8 @@
 	memcpy(&template, _template, sizeof(template));
 	if(long_name)
 		template.name = long_name;
-	snd_runtime_check(!template.index, return NULL);
-	//template.index = codec->num;
+	snd_assert(!template.index, return NULL);
+	//template.index = codec->pcm_devs;
 	return snd_ctl_new1(&template, data);
 }
 
@@ -1015,26 +865,6 @@
 	return err;
 }
 
-static int __init snd_soc_init(void) 
-{
-	printk(KERN_INFO "soc: version %s liam.girdwood@wolfsonmicro.com\n", SND_SOC_VERSION);
-	return 0;
-}
-
-static void __exit snd_soc_exit(void) 
-{
-}
-
-module_init(snd_soc_init); 
-module_exit(snd_soc_exit);
-
-EXPORT_SYMBOL_GPL(snd_soc_register_codec);
-EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
-EXPORT_SYMBOL_GPL(snd_soc_register_platform);
-EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
-EXPORT_SYMBOL_GPL(snd_soc_pcm_connect);
-EXPORT_SYMBOL_GPL(snd_soc_register_interface);
-EXPORT_SYMBOL_GPL(snd_soc_unregister_interface);
 EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hw);
 EXPORT_SYMBOL_GPL(snd_soc_cnew);
 EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
@@ -1047,7 +877,9 @@
 EXPORT_SYMBOL_GPL(snd_soc_test_bits);
 EXPORT_SYMBOL_GPL(snd_soc_register_machine);
 EXPORT_SYMBOL_GPL(snd_soc_unregister_machine);
-EXPORT_SYMBOL_GPL(snd_soc_pcm_register);
+EXPORT_SYMBOL_GPL(snd_soc_register_pcms);
+EXPORT_SYMBOL_GPL(snd_soc_free_pcms);
+EXPORT_SYMBOL_GPL(snd_soc_register_card);
 
 /* Module information */ 
 MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
diff -urN a/sound/soc/soc-dpm.c b/sound/soc/soc-dpm.c
--- a/sound/soc/soc-dpm.c	2005-11-30 19:38:49.000000000 +0000
+++ b/sound/soc/soc-dpm.c	2005-11-29 10:21:14.000000000 +0000
@@ -18,9 +18,10 @@
  *    o Changes power status of internal codec blocks depending on the 
  *      dynamic configuration of codec internal audio paths and active
  *      DAC's/ADC's.
+ *    o Platform power domain - can support external components i.e. amps and
+ *      mic/meadphone insertion events.
  * 
  *  Todo:
- *    o Platform power domain - could this be tied into machine layer ???
  *    o DPM power change sequencing - allow for configurable sequences
  *    o Support for analogue bias optimisation.
  *    o Support for reduced codec oversampling rates.
@@ -36,6 +37,7 @@
 #include <linux/i2c.h>
 #include <linux/pm.h>
 #include <linux/bitops.h>
+#include <linux/platform_device.h>
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -634,10 +636,11 @@
 
 static ssize_t dpm_status_show(struct device *dev, struct device_attribute *attr, char *buf)   \
 {
-	struct snd_soc_codec *codec = (struct snd_soc_codec*)dev->driver_data;
+	struct snd_soc_codec *codec = (struct snd_soc_codec*)dev->platform_data;
 	struct snd_soc_dpm_widget *w = NULL;
 	struct list_head *l = NULL;
-	int count = 0; 
+	int count = 0;
+	char * state = "not set";
 
 	list_for_each(l, &codec->dpm_widgets)
 	{
@@ -646,6 +649,24 @@
 			w->id != snd_soc_dpm_input && w->id != snd_soc_dpm_output)
 			count += sprintf(buf + count, "%s: %s\n", w->name, w->power ? "On":"Off");
 	}
+	switch(codec->dpm_state){
+	case SNDRV_CTL_POWER_D0:
+		state = "D0";
+		break;
+	case SNDRV_CTL_POWER_D1:
+		state = "D1";
+		break;
+	case SNDRV_CTL_POWER_D2:
+		state = "D2";
+		break;
+	case SNDRV_CTL_POWER_D3hot:
+		state = "D3hot";
+		break;
+	case SNDRV_CTL_POWER_D3cold:
+		state = "D3cold";
+		break;
+	}
+	count += sprintf(buf + count, "PM State: %s\n", state);
 	
 	return count;
 }
@@ -820,7 +841,7 @@
 	INIT_LIST_HEAD(&w->outputs);
 	INIT_LIST_HEAD(&w->list);
 	list_add(&w->list, &codec->dpm_widgets);
-	
+
 	/* machine layer set ups unconnected pins and insertions */
 	w->connected = 1;
 	return 0;
@@ -926,7 +947,7 @@
 	list_for_each(l, &codec->dpm_widgets)
 	{
 		w = list_entry(l, struct snd_soc_dpm_widget, list);
-			
+
 		if(!strcmp(w->name, pin->name)) {
 			w->connected = pin->connected;
 		}
--- a/include/sound/soc.h	2005-11-30 19:38:49.000000000 +0000
+++ b/include/sound/soc.h	2005-11-30 17:23:27.000000000 +0000
@@ -13,7 +13,7 @@
 #ifndef __LINUX_SND_SOC_H
 #define __LINUX_SND_SOC_H
 
-#include <linux/device.h>
+#include <linux/platform_device.h>
 #include <linux/types.h>
 #include <sound/driver.h>
 #include <sound/core.h>
@@ -21,6 +21,8 @@
 #include <sound/control.h>
 #include <sound/ac97_codec.h>
 
+#define SND_SOC_VERSION "0.8"
+
 /*
  * Convenience kcontrol builders
  */
@@ -51,6 +53,13 @@
 #define SND_SOC_AC97		0x1
 #define SND_SOC_I2S			0x2
 #define SND_SOC_SSP			0x4
+  
+/*
+ * Control interface types
+ */
+#define SND_SOC_I2C			0x1
+#define SND_SOC_3W			0x2
+
 
 /*
  * hw interface formats
@@ -104,33 +113,19 @@
 struct snd_soc_machine_config;
 struct snd_soc_machine;
 struct soc_enum;
+	
+typedef int (*hw_write_t)(void *,const char* ,int);
+typedef int (*hw_read_t)(void *,char* ,int);
 
-/*
- * 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(struct snd_soc_codec *codec);
-void snd_soc_unregister_codec(struct snd_soc_codec *codec);
-
-int snd_soc_register_platform(struct snd_soc_platform *platform);
-void snd_soc_unregister_platform(struct snd_soc_platform *platform);
-
-int snd_soc_register_interface(struct snd_soc_pcm_interface *iface);
-void snd_soc_unregister_interface(struct snd_soc_pcm_interface *iface);
+extern struct bus_type soc_bus_type;
 
 int snd_soc_register_machine(struct snd_soc_machine *machine);
 void snd_soc_unregister_machine(struct snd_soc_machine *machine);
 
 /* pcm <-> interface connect */
-int snd_soc_pcm_connect(struct snd_soc_machine *machine, int nconfig);
-int snd_soc_pcm_register(struct snd_soc_machine *machine, char *name);
+void snd_soc_free_pcms(struct snd_soc_codec *codec);
+int snd_soc_register_pcms(struct snd_soc_codec* codec);
+int snd_soc_register_card(struct snd_soc_codec *codec);
 
 /* set runtime hw params */
 int snd_soc_set_runtime_hw(snd_pcm_substream_t *substream, 
@@ -224,11 +219,10 @@
 	unsigned int id;
 	unsigned char type;
 	
-	int probed;
-	int (*probe)(struct snd_soc_pcm_interface *interface);
-	void (*remove)(struct snd_soc_pcm_interface *interface);
-	int (*suspend)(struct snd_soc_pcm_interface *interface, pm_message_t state);
-	int (*resume)(struct snd_soc_pcm_interface *interface);
+	int (*probe)(struct device *dev);
+	void (*remove)(struct device *dev);
+	int (*suspend)(struct device *dev, pm_message_t state);
+	int (*resume)(struct device *dev);
 	
 	/* interface pcm capabilities */
 	struct snd_soc_pcm_stream capture;
@@ -239,13 +233,13 @@
 	struct snd_soc_hw_mode hw_runtime;
 	struct snd_soc_pcm_codec *pcm_c;
 	struct snd_soc_ops ops;
+	snd_pcm_runtime_t *runtime;
 	snd_card_t *card;
-	ac97_t *ac97;
+	struct snd_soc_machine* machine;
+	unsigned char active:1;
 	
 	/* private data */
 	void *platform_data;
-	
-	struct list_head list;
 };
 
 /* SoC Codec interface */
@@ -255,29 +249,26 @@
 	struct module *owner;
 	
 	/* callbacks */
-	int (*probe)(struct snd_soc_codec *codec);
-	void (*remove)(struct snd_soc_codec *codec);
-	int (*suspend)(struct snd_soc_codec *codec, pm_message_t state);
-	int (*resume)(struct snd_soc_codec *codec);
 	int (*dpm_event)(struct snd_soc_codec *codec, int event);
 	
 	/* runtime */
 	snd_card_t *card;
-	struct platform_device pdev;
+	ac97_t *ac97;
+	struct device *dev;
 	void *private_data;
-	void *machine_data;
+	struct snd_soc_machine *machine;
 	int active_streams;
 	int pcm_devs;
-	int probed;
 	int dpm_state;
 	
 	/* codec IO */
 	void *control_data; /* codec control (i2c/3wire) data */
 	unsigned int (*read)(struct snd_soc_codec *, unsigned int);
 	int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
+	hw_write_t hw_write;
+	hw_read_t hw_read;
 	void *reg_cache;
 	
-	struct list_head list;
 	struct list_head dpm_widgets;
 	struct list_head dpm_paths;
 	
@@ -292,20 +283,21 @@
 	
 	int	(*probe)(struct device * dev);
 	int	(*remove)(struct device * dev);
+	int (*suspend)(struct device *dev, pm_message_t state);
+	int (*resume)(struct device *dev);
 	struct bus_type	* bus;
 	int (*pcm_new)(snd_card_t *, struct snd_soc_pcm_codec *, snd_pcm_t *);
 	void (*pcm_free)(snd_pcm_t *);
 	snd_pcm_ops_t *pcm_ops;
+	
+	struct snd_soc_pcm_interface* iface[];
 };
 
 /* SoC machine configuration */
 struct snd_soc_machine_config {
 	char *name;			/* Codec name */
 	char *sname;		/* stream name */
-	int interface;		/* interface type */
-	int int_num;		/* interface number */
-	u32 connect:1;		/* interface and codec have been connected */
-	u32 card_reg:1;		/* codec card registered */
+	struct snd_soc_pcm_interface* iface;
 	u32 flags;			/* preference flags */
 	
 	/* codec/machine specific init - e.g. add machine controls */
@@ -316,14 +308,17 @@
 struct snd_soc_machine {
 	char *name;
 	
-	int	(*probe)(struct snd_soc_machine *machine);
-	int	(*remove)(struct snd_soc_machine *machine);
-	int (*suspend)(struct snd_soc_machine *machine, pm_message_t state);
-	int (*resume)(struct snd_soc_machine *machine);
+	int	(*probe)(struct device *dev);
+	int	(*remove)(struct device *dev);
+	int (*suspend)(struct device *dev, pm_message_t state);
+	int (*resume)(struct device *dev);
 	
 	struct snd_soc_ops *ops;
 	struct snd_soc_machine_config *config;
 	int nconfigs;
+	struct device *dev;
+	
+	struct snd_soc_platform* platform;
 };
 
 /* enamerated kcontrol */

