diff --git a/include/sound/soc-dpm.h b/include/sound/soc-dpm.h
index dfbff2a..5d4ebab 100644
--- a/include/sound/soc-dpm.h
+++ b/include/sound/soc-dpm.h
@@ -89,20 +89,20 @@
 #define SND_SOC_DPM_STREAM_PAUSE_PUSH	0x8
 #define SND_SOC_DPM_STREAM_PAUSE_RELEASE	0x10  
 
-typedef struct snd_soc_dpm_widget snd_soc_dpm_widget_t;
-typedef enum snd_soc_dpm_type snd_soc_dpm_type_t;
-typedef struct snd_soc_dpm_path snd_soc_dpm_path_t;
+struct snd_soc_dpm_widget;
+enum snd_soc_dpm_type;
+struct snd_soc_dpm_path;
 	
 int snd_soc_dpm_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_soc_dpm_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_soc_dpm_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_soc_dpm_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
-int snd_soc_dpm_new_control(snd_soc_codec_t *codec, const snd_soc_dpm_widget_t *widget);
-int snd_soc_dpm_connect_input(snd_soc_codec_t *codec, char *target_name, 
+int snd_soc_dpm_new_control(struct snd_soc_codec *codec, const struct snd_soc_dpm_widget *widget);
+int snd_soc_dpm_connect_input(struct snd_soc_codec *codec, char *target_name, 
 	char *control_name, char *src_name);
-int snd_soc_dpm_sync(snd_soc_codec_t *codec);
-int snd_soc_dpm_stream_event(snd_soc_codec_t *codec, char * stream, int event);
-int snd_soc_dpm_codec_event(snd_soc_codec_t *codec, int event);
+int snd_soc_dpm_sync(struct snd_soc_codec *codec);
+int snd_soc_dpm_stream_event(struct snd_soc_codec *codec, char * stream, int event);
+int snd_soc_dpm_codec_event(struct snd_soc_codec *codec, int event);
 void snd_soc_dpm_sys_remove(struct device *dev);
 int snd_soc_dpm_sys_add(struct device *dev);
 
@@ -122,8 +122,8 @@ enum snd_soc_dpm_type {
 struct snd_soc_dpm_path {
 	char *name;
 	char *long_name;
-	snd_soc_dpm_widget_t *in;
-	snd_soc_dpm_widget_t *out;
+	struct snd_soc_dpm_widget *in;
+	struct snd_soc_dpm_widget *out;
 	snd_kcontrol_t *kcontrol;
 	
 	u8 connect:1;	/* applies to widget inputs only */
@@ -135,10 +135,10 @@ struct snd_soc_dpm_path {
 };
 
 struct snd_soc_dpm_widget {
-	snd_soc_dpm_type_t id;
+	enum snd_soc_dpm_type id;
 	char *name;
 	char *sname;
-	snd_soc_codec_t *codec;
+	struct snd_soc_codec *codec;
 	struct list_head list;
 	
 	/* dpm control */
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 7f017e1..e4b274c 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -15,6 +15,7 @@
 
 #include <linux/device.h>
 #include <linux/types.h>
+#include <linux/i2c.h>
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -90,18 +91,20 @@
 /*
  * Codec IO
  */
-#define snd_soc_read(codec, reg) codec->read(reg)
-#define snd_soc_write(codec, reg, value) codec->write(reg, value)
+#define snd_soc_read(codec, reg) codec->read(codec, reg)
+#define snd_soc_write(codec, reg, value) codec->write(codec, reg, value)
 
-typedef struct snd_soc_codec snd_soc_codec_t;
-typedef struct snd_soc_pcm_codec snd_soc_pcm_codec_t;
-typedef struct snd_soc_platform snd_soc_platform_t;
-typedef struct snd_soc_pcm_interface snd_soc_pcm_interface_t;
-typedef struct snd_soc_pcm_stream snd_soc_pcm_stream_t;
-typedef struct snd_soc_ops snd_soc_ops_t;
-typedef struct snd_soc_hw_bus snd_soc_hw_bus_t;
-typedef struct snd_soc_hw_mode snd_soc_hw_mode_t;
-typedef struct snd_soc_machine snd_soc_machine_t;
+struct snd_soc_pcm_stream;
+struct snd_soc_ops;
+struct snd_soc_hw_mode;
+struct snd_soc_hw_bus;
+struct snd_soc_pcm_codec;
+struct snd_soc_pcm_interface;
+struct snd_soc_codec;
+struct snd_soc_platform;
+struct snd_soc_machine_config;
+struct snd_soc_machine;
+struct soc_enum;
 
 /*
  * SoC registration objects:-
@@ -114,31 +117,31 @@ typedef struct snd_soc_machine snd_soc_m
  * Only 1 Platform and Machine may be registered with the SoC layer. However there is
  * no limit on the number of codecs and interfaces that can be registered.
  */
-int snd_soc_register_codec(snd_soc_codec_t *codec);
-void snd_soc_unregister_codec(snd_soc_codec_t *codec);
+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(snd_soc_platform_t *platform);
-void snd_soc_unregister_platform(snd_soc_platform_t *platform);
+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(snd_soc_pcm_interface_t *iface);
-void snd_soc_unregister_interface(snd_soc_pcm_interface_t *iface);
+int snd_soc_register_interface(struct snd_soc_pcm_interface *iface);
+void snd_soc_unregister_interface(struct snd_soc_pcm_interface *iface);
 
-int snd_soc_register_machine(snd_soc_machine_t *machine);
-void snd_soc_unregister_machine(snd_soc_machine_t *machine);
+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(snd_soc_machine_t *machine, char *name, int iface_type, int num);
-int snd_soc_pcm_register(snd_soc_machine_t *machine, char *name);
+int snd_soc_pcm_connect(struct snd_soc_machine *machine, int nconfig);
+int snd_soc_pcm_register(struct snd_soc_machine *machine, char *name);
 
 /* set runtime hw params */
 int snd_soc_set_runtime_hw(snd_pcm_substream_t *substream, 
 	const snd_pcm_hardware_t *hw);
 
 /* codec register bit access */
-int snd_soc_update_bits(snd_soc_codec_t *codec, unsigned short reg,
+int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
 				unsigned short mask, unsigned short value);
 				
-int snd_soc_test_bits(snd_soc_codec_t *codec, unsigned short reg,
+int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
 				unsigned short mask, unsigned short value);
 
 /*
@@ -153,7 +156,7 @@ int snd_soc_put_enum_double(snd_kcontrol
 int snd_soc_info_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo);
 int snd_soc_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_soc_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
-
+	
 /* SoC supported stream types */
 struct snd_soc_pcm_stream {
 	char *sname;
@@ -189,7 +192,7 @@ struct snd_soc_hw_mode {
 /* SoC hardware bus and all modes */
 struct snd_soc_hw_bus {
 	int num_hmodes;				/* number of hw modes */
-	snd_soc_hw_mode_t *hmodes;	/* array of supported audio hw modes */	
+	struct snd_soc_hw_mode *hmodes;	/* array of supported audio hw modes */	
 };
 
 /* SoC Codec pcm stream */
@@ -197,17 +200,17 @@ struct snd_soc_pcm_codec {
 	char *name;
 
 	/* codec pcm capabilities */
-	snd_soc_pcm_stream_t playback;
-	snd_soc_pcm_stream_t capture;
-	snd_soc_hw_bus_t hw;
+	struct snd_soc_pcm_stream playback;
+	struct snd_soc_pcm_stream capture;
+	struct snd_soc_hw_bus hw;
 	int nplayback;
 	int ncapture;
 	
 	/* runtime info */
-	snd_soc_hw_mode_t hw_runtime;
-	snd_soc_ops_t ops;
-	snd_soc_pcm_interface_t *pcm_i;
-	snd_soc_codec_t *codec;
+	struct snd_soc_hw_mode hw_runtime;
+	struct snd_soc_ops ops;
+	struct snd_soc_pcm_interface *pcm_i;
+	struct snd_soc_codec *codec;
 	
 	/* private data */
 	void *priv;
@@ -223,20 +226,20 @@ struct snd_soc_pcm_interface {
 	unsigned char type;
 	
 	int probed;
-	int (*probe)(snd_soc_pcm_interface_t *interface);
-	void (*remove)(snd_soc_pcm_interface_t *interface);
-	int (*suspend)(snd_soc_pcm_interface_t *interface, pm_message_t state);
-	int (*resume)(snd_soc_pcm_interface_t *interface);
+	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);
 	
 	/* interface pcm capabilities */
-	snd_soc_pcm_stream_t capture;
-	snd_soc_pcm_stream_t playback;
-	snd_soc_hw_bus_t hw;
+	struct snd_soc_pcm_stream capture;
+	struct snd_soc_pcm_stream playback;
+	struct snd_soc_hw_bus hw;
 	
 	/* runtime info */
-	snd_soc_hw_mode_t hw_runtime;
-	snd_soc_pcm_codec_t *pcm_c;
-	snd_soc_ops_t ops;
+	struct snd_soc_hw_mode hw_runtime;
+	struct snd_soc_pcm_codec *pcm_c;
+	struct snd_soc_ops ops;
 	snd_card_t *card;
 	ac97_t *ac97;
 	
@@ -253,11 +256,11 @@ struct snd_soc_codec {
 	struct module *owner;
 	
 	/* callbacks */
-	int (*probe)(snd_soc_codec_t *codec);
-	void (*remove)(snd_soc_codec_t *codec);
-	int (*suspend)(snd_soc_codec_t *codec, pm_message_t state);
-	int (*resume)(snd_soc_codec_t *codec);
-	int (*dpm_event)(snd_soc_codec_t *codec, int event);
+	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;
@@ -266,20 +269,22 @@ struct snd_soc_codec {
 	int active_streams;
 	int pcm_devs;
 	int probed;
+	struct i2c_client i2c;
 	
 	/* codec IO */
-	unsigned int (*read)(u16);
-	int (*write)(u16, unsigned int);
+	unsigned int (*read)(struct snd_soc_codec *, unsigned int);
+	int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
+	void *reg_cache;
 	
 	struct list_head list;
 	struct list_head dpm_widgets;
 	struct list_head dpm_paths;
 	
 	/* codec pcms */
-	snd_soc_pcm_codec_t *pcms;
+	struct snd_soc_pcm_codec *pcms;
 	int	npcms;
 };
-
+	
 /* SoC platform interface */
 struct snd_soc_platform {
 	char *name;
@@ -287,20 +292,33 @@ struct snd_soc_platform {
 	int	(*probe)(struct device * dev);
 	int	(*remove)(struct device * dev);
 	struct bus_type	* bus;
-	int (*pcm_new)(snd_card_t *, snd_soc_pcm_codec_t *, snd_pcm_t *);
+	int (*pcm_new)(snd_card_t *, struct snd_soc_pcm_codec *, snd_pcm_t *);
 	snd_pcm_ops_t *pcm_ops;
 };
 
+/* 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 */
+	u32 flags;			/* preference flags */
+};
+
 /* SoC machine interface */
 struct snd_soc_machine {
 	char *name;
 	
-	int	(*probe)(snd_soc_machine_t *machine);
-	int	(*remove)(snd_soc_machine_t *machine);
-	int (*suspend)(snd_soc_machine_t *machine, pm_message_t state);
-	int (*resume)(snd_soc_machine_t *machine);
+	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);
 	
 	struct snd_soc_ops *ops;
+	struct snd_soc_machine_config *config;
+	int nconfigs;
 };
 
 /* enamerated kcontrol */
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index b58d51f..44db053 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -21,6 +21,12 @@ config SND_SOC_WM8750
 	depends SND_SOC
 	help
 	  Say Y or M if you want to support the WM8750 codec.
+	  
+config SND_SOC_WM8971
+	tristate "SoC driver for the WM8971 codec"
+	depends SND_SOC
+	help
+	  Say Y or M if you want to support the WM8971 codec.
 
 config SND_SOC_WM9713_VOICE
 	tristate "SoC driver for the WM9713 Voice codec"
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 1c564aa..9421304 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -2,10 +2,12 @@ snd-soc-ac97-objs := ac97.o
 snd-soc-wm8753-objs := wm8753.o
 snd-soc-wm8731-objs := wm8731.o
 snd-soc-wm8750-objs := wm8750.o
+snd-soc-wm8971-objs := wm8971.o
 snd-soc-wm9713-voice-objs := wm9713-voice.o
 
 obj-$(CONFIG_SND_SOC_AC97_CODEC)	+= snd-soc-ac97.o
 obj-$(CONFIG_SND_SOC_WM8753)	+= snd-soc-wm8753.o
 obj-$(CONFIG_SND_SOC_WM8731)	+= snd-soc-wm8731.o
 obj-$(CONFIG_SND_SOC_WM8750)	+= snd-soc-wm8750.o
+obj-$(CONFIG_SND_SOC_WM8971)	+= snd-soc-wm8971.o
 obj-$(CONFIG_SND_SOC_WM9713_VOICE)	+= snd-soc-wm9713-voice.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 44ebee1..3278938 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -26,7 +26,7 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 
-static int ac97_soc_add_widgets(snd_soc_codec_t * codec)
+static int ac97_soc_add_widgets(struct snd_soc_codec * codec)
 {
 	return 0;
 }
@@ -35,21 +35,21 @@ static void ac97_soc_device_release(stru
 {
 }
 
-static int ac97_soc_suspend(snd_soc_codec_t *codec, pm_message_t state)
+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(snd_soc_codec_t *codec)
+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;
 }
 
-static snd_soc_pcm_codec_t ac97_soc_client = {
+static struct snd_soc_pcm_codec ac97_soc_client = {
 	.name = "AC97 Audio",
 	.playback = {
 		.sname = "AC97 Playback",
@@ -67,10 +67,10 @@ static snd_soc_pcm_codec_t ac97_soc_clie
 		.channels_max = 2,},
 };
 
-static snd_soc_codec_t ac97_soc_codec;
+static struct snd_soc_codec ac97_soc_codec;
 static snd_pcm_t *pcm_ac97;
 
-static int ac97_soc_probe(snd_soc_codec_t *codec)
+static int ac97_soc_probe(struct snd_soc_codec *codec)
 {
 	int ret;
 	
@@ -86,12 +86,12 @@ static int ac97_soc_probe(snd_soc_codec_
 /* 
  * unregister interfaces and clean up
  */
-static void ac97_soc_remove(snd_soc_codec_t *codec)
+static void ac97_soc_remove(struct snd_soc_codec *codec)
 {
-	printk("%s %s %d\n",  __FILE__, __FUNCTION__, __LINE__);
+
 }
 
-static snd_soc_codec_t ac97_soc_codec = {
+static struct snd_soc_codec ac97_soc_codec = {
 	.name = "SoC AC97",
 	.longname = "ALSA SoC Generic AC97 Codec",
 	.owner = THIS_MODULE,
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 892c93e..a0ab318 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -60,7 +60,8 @@ static unsigned short normal_i2c[] = { 0
 /* Magic definition of all other variables and things */
 I2C_CLIENT_INSMOD;
 
-struct i2c_client *wm8731_i2c;
+static struct i2c_driver wm8731_i2c_driver;
+static struct i2c_client client_template;
 
 /*
  * wm8731 register cache
@@ -68,22 +69,22 @@ struct i2c_client *wm8731_i2c;
  * using 2 wire for device control, so we cache them instead. 
  * There is no point in caching the reset register
  */
-static u16 reg_cache[WM8731_CACHEREGNUM] = {
+static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
     0x0023, 0x0023, 0x0121, 0x0121, 
     0x0012, 0x0000, 0x0000, 0x0000, 
-    0x0000, 0x0000, 0x0000
+    0x0000, 0x0000
 };
 
 #define WM8731_HWFMT \
 	(SND_SOC_HWFMT_I2S | SND_SOC_HWFMT_LEFT_J | SND_SOC_HWFMT_RIGHT_J | \
-	SND_SOC_HWFMT_CBS_CFS | \
+	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)
-//	SND_SOC_HWFMT_CBS_CFM | 
+
 /*
  * priv1 is srate register setting
  */
-static snd_soc_hw_mode_t wm8731_hwfmt[] = {
+static struct snd_soc_hw_mode wm8731_hwfmt[] = {
 
 	{WM8731_HWFMT, SND_SOC_HWBITS(16), 8000 ,  64, 0x000c},
 	{WM8731_HWFMT, SND_SOC_HWBITS(16), 8000,   96, 0x000e},
@@ -120,76 +121,34 @@ static snd_soc_hw_mode_t wm8731_hwfmt[] 
 /*
  * read wm8731 register cache
  */
-static inline unsigned int wm8731_read_reg_cache(u16 reg)
+static inline unsigned int wm8731_read_reg_cache(struct snd_soc_codec * codec,
+	unsigned int reg)
 {
+	u16 *cache = codec->reg_cache;
 	if (reg == WM8731_RESET) 
 		return 0;
-	if (reg >= WM8731_CACHEREGNUM)
+	if (reg > WM8731_CACHEREGNUM)
 		return -1;
-	return reg_cache[reg];
+	return cache[reg];
 }
 
 /*
  * write wm8731 register cache
  */
-static inline void wm8731_write_reg_cache(u16 reg, unsigned int value)
+static inline void wm8731_write_reg_cache(struct snd_soc_codec * codec,
+	u16 reg, unsigned int value)
 {
-	printk("wm8731: Writing %x to %x\n", value, reg);
-	if (reg < WM8731_CACHEREGNUM)
-		reg_cache[reg] = value;
-}
-
-static struct i2c_client client_template;
-static int wm8731_reset(struct i2c_client *client);
-	
-/*
- * Attach WM8731 2 wire client 
- */
-static int wm8731_i2c_probe(struct i2c_adapter *adap, int addr, int kind)
-{		 
-	client_template.adapter = adap;
-	client_template.addr = addr;
-	
-	if ((wm8731_i2c = kmalloc(sizeof(struct i2c_client),GFP_KERNEL)) == NULL)
-		return -ENOMEM;
-
-	memcpy(wm8731_i2c, &client_template, sizeof(struct i2c_client));
-
-	return i2c_attach_client(wm8731_i2c);
-}
-
-static int wm8731_i2c_detach(struct i2c_client *client)
-{
-	i2c_detach_client(client);
-	kfree(client);
-	return 0;
-}
-
-static int wm8731_i2c_attach(struct i2c_adapter *adap)
-{
-	return i2c_probe(adap, &addr_data, wm8731_i2c_probe);
+	u16 *cache = codec->reg_cache;
+	if (reg > WM8731_CACHEREGNUM)
+		return;
+	cache[reg] = value;
 }
 
-/* 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,
-};
-
 /*
  * write to the WM8731 register space
  */
-static int wm8731_2w_write(struct i2c_client *client, u8 reg, u16 value)
+static int wm8731_write(struct snd_soc_codec * codec, unsigned int reg, 
+	unsigned int value)
 {
 	u8 data[2];
 
@@ -200,51 +159,38 @@ static int wm8731_2w_write(struct i2c_cl
 	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
 	data[1] = value & 0x00ff;
 
-	wm8731_write_reg_cache (reg, value);
+	wm8731_write_reg_cache (codec, reg, value);
 
-	if (i2c_master_send(client, data, 2) == 2)
+	if (i2c_master_send(&codec->i2c, data, 2) == 2)
 		return 0;
 	else
 		return -1;
 }
 
-static int wm8731_write (u16 reg, unsigned int value)
-{
-	return wm8731_2w_write(wm8731_i2c, reg, value);	
-}
-
-/* 
- * reset the WM8731
- */
-static int wm8731_reset(struct i2c_client *client)
-{
-	return wm8731_2w_write (client, WM8731_RESET, 0);
-}
+#define wm8731_reset(c)	wm8731_write(c, WM8731_RESET, 0)
 
-static const char* wm8731_sidetone_att[] = {"-6dB", "-9dB", "-12dB", "-15dB"};
 static const char* wm8731_input_select[] = {"Line In", "Mic"};
 
 static const struct soc_enum wm8731_enum[] = {
 	SOC_ENUM_SINGLE(WM8731_APANA, 2, 2, wm8731_input_select),
-	SOC_ENUM_SINGLE(WM8731_APANA, 6, 4, wm8731_sidetone_att),
 };
 
 static const snd_kcontrol_new_t wm8731_snd_controls[] = {
 
-SOC_SINGLE("Playback Left Volume", WM8731_LOUT1V, 0, 127, 0),
-SOC_SINGLE("Playback Left ZC Switch", WM8731_LOUT1V, 7, 1, 0),
-SOC_SINGLE("Playback Right Volume", WM8731_ROUT1V, 0, 127, 0),
-SOC_SINGLE("Playback Right ZC Switch", WM8731_ROUT1V, 7, 1, 0),
-
-SOC_SINGLE("Capture Line Left Volume", WM8731_LINVOL, 0, 31, 0),
-SOC_SINGLE("Capture Line Left Switch", WM8731_LINVOL, 7, 1, 1),
-SOC_SINGLE("Capture Line Right Volume", WM8731_RINVOL, 0, 31, 0),
-SOC_SINGLE("Capture Line Right Switch", WM8731_RINVOL, 7, 1, 1),
+SOC_SINGLE("Left Playback Volume", WM8731_LOUT1V, 0, 127, 0),
+SOC_SINGLE("Left Playback ZC Switch", WM8731_LOUT1V, 7, 1, 0),
+SOC_SINGLE("Right Playback Volume", WM8731_ROUT1V, 0, 127, 0),
+SOC_SINGLE("Right Playback ZC Switch", WM8731_ROUT1V, 7, 1, 0),
+
+SOC_SINGLE("Line Left Capture Volume", WM8731_LINVOL, 0, 31, 0),
+SOC_SINGLE("Line Left Capture Switch", WM8731_LINVOL, 7, 1, 1),
+SOC_SINGLE("Line Right Capture Volume", WM8731_RINVOL, 0, 31, 0),
+SOC_SINGLE("Line Right Capture Switch", WM8731_RINVOL, 7, 1, 1),
 
-SOC_SINGLE("Mic Boost Switch", WM8731_APANA, 0, 1, 0),
-SOC_SINGLE("Mic Switch", WM8731_APANA, 1, 1, 0),
+SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0),
+SOC_SINGLE("Mic Capture Switch", WM8731_APANA, 1, 1, 0),
 
-SOC_ENUM("Sidetone Attenuation", wm8731_enum[1]),
+SOC_SINGLE("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1),
 
 SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1),
 SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0),
@@ -252,7 +198,7 @@ SOC_SINGLE("Store DC Offset Switch", WM8
 };
 
 /* add non dpm controls */
-static int wm8731_add_controls(snd_soc_codec_t *codec)
+static int wm8731_add_controls(struct snd_soc_codec *codec)
 {
 	int err, i;
 
@@ -267,7 +213,7 @@ static int wm8731_add_controls(snd_soc_c
 
 /* Output Mixer */
 static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = {
-SOC_DPM_SINGLE("Line Switch", WM8731_APANA, 3, 1, 0),
+SOC_DPM_SINGLE("Bypass Switch", WM8731_APANA, 3, 1, 0),
 SOC_DPM_SINGLE("Sidetone Switch", WM8731_APANA, 5, 1, 0),
 SOC_DPM_SINGLE("Playback Switch", WM8731_APANA, 4, 1, 0),
 };
@@ -277,7 +223,7 @@ static const snd_kcontrol_new_t wm8753_i
 SOC_DPM_ENUM("Input Select", wm8731_enum[0]);
 
 
-static const snd_soc_dpm_widget_t wm8731_dpm_widgets[] = {
+static const struct snd_soc_dpm_widget wm8731_dpm_widgets[] = {
 SND_SOC_DPM_CLOCK("WM8731 Clock", WM8731_PWR, 6, 1),
 SND_SOC_DPM_CLOCK("WM8731 Osc", WM8731_PWR, 5, 1),
 SND_SOC_DPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, &wm8731_output_mixer_controls[0], 
@@ -296,7 +242,7 @@ SND_SOC_DPM_INPUT("RLINEIN"),
 SND_SOC_DPM_INPUT("LLINEIN"),
 };
 
-static int wm8731_add_widgets(snd_soc_codec_t *codec)
+static int wm8731_add_widgets(struct snd_soc_codec *codec)
 {
 	int i;
 	
@@ -307,7 +253,7 @@ static int wm8731_add_widgets(snd_soc_co
 	/* set up audio path interconnects */
 	
 	/* output mixer */
-	snd_soc_dpm_connect_input(codec, "Output Mixer", "Line Switch", "Line Input");
+	snd_soc_dpm_connect_input(codec, "Output Mixer", "Bypass Switch", "Line Input");
 	snd_soc_dpm_connect_input(codec, "Output Mixer", "Playback Switch", "DAC");
 	snd_soc_dpm_connect_input(codec, "Output Mixer", "Sidetone Switch", "Mic");
 	
@@ -332,14 +278,15 @@ static int wm8731_add_widgets(snd_soc_co
 
 static int wm8731_pcm_prepare(snd_pcm_substream_t *substream)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
+	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_CBS_CFM:
-		//	iface |= 0x0020;
-		//	break;
+		case SND_SOC_HWFMT_CBM_CFM:
+			iface |= 0x0040;
+			break;
 		case SND_SOC_HWFMT_CBS_CFS:
 			break;
 	
@@ -393,17 +340,17 @@ static int wm8731_pcm_prepare(snd_pcm_su
 			break;
 	}
 	
-	if (wm8731_2w_write(wm8731_i2c, WM8731_ACTIVE, 0x00) != 0)
+	if (wm8731_write(codec, WM8731_ACTIVE, 0x00) != 0)
 		return -EIO;
 
 	/* set rate */
-	wm8731_2w_write(wm8731_i2c, WM8731_SRATE, pcm_c->hw_runtime.priv1);
+	wm8731_write(codec, WM8731_SRATE, pcm_c->hw_runtime.priv1);
 
-	wm8731_2w_write(wm8731_i2c, WM8731_IFACE, iface);
+	wm8731_write(codec, WM8731_IFACE, iface);
 
-	wm8731_2w_write(wm8731_i2c, WM8731_APANA, 0x12);
+	wm8731_write(codec, WM8731_APANA, 0x12);
 
-	if (wm8731_2w_write(wm8731_i2c, WM8731_ACTIVE, 0x01) != 0)
+	if (wm8731_write(codec, WM8731_ACTIVE, 0x01) != 0)
 		return -EIO;
 
 	return 0;
@@ -413,41 +360,41 @@ static void wm8731_device_release(struct
 {
 }
 
-static int wm8731_dpm_event(snd_soc_codec_t *codec, int event)
+static int wm8731_dpm_event(struct snd_soc_codec *codec, int event)
 {
-	u16 pwr_reg = wm8731_read_reg_cache(WM8731_PWR) & 0xff1f;
-	u16 act_reg = wm8731_read_reg_cache(WM8731_ACTIVE) & 0xfffe;
-	u16 dac_reg = wm8731_read_reg_cache(WM8731_APDIGI) & 0xfff7;
+	u16 pwr_reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff1f;
+	u16 act_reg = wm8731_read_reg_cache(codec, WM8731_ACTIVE) & 0xfffe;
+	u16 dac_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7;
 
 	switch (event) {
 		case SNDRV_CTL_POWER_D0: /* full On */
 			/* vref/mid, clk and osc on, dac unmute, active */
-			wm8731_2w_write(wm8731_i2c, WM8731_ACTIVE, act_reg | 0x0001);
-			wm8731_2w_write(wm8731_i2c, WM8731_APDIGI, dac_reg & 0xfff7);
+			wm8731_write(codec, WM8731_ACTIVE, act_reg | 0x0001);
+			wm8731_write(codec, WM8731_APDIGI, dac_reg & 0xfff7);
 			break;
 		case SNDRV_CTL_POWER_D1: /* partial On */
 		case SNDRV_CTL_POWER_D2: /* partial On */
 			break;
 		case SNDRV_CTL_POWER_D3hot: /* Off, with power */
 			/* everything off except vref/vmid, dac mute, inactive */
-			wm8731_2w_write(wm8731_i2c, WM8731_APDIGI, dac_reg | 0x0008);
-			wm8731_2w_write(wm8731_i2c, WM8731_PWR, pwr_reg | 0x0010);
-			wm8731_2w_write(wm8731_i2c, WM8731_ACTIVE, act_reg);
-			wm8731_2w_write(wm8731_i2c, WM8731_PWR, 0xff7f);
+			wm8731_write(codec, WM8731_APDIGI, dac_reg | 0x0008);
+			wm8731_write(codec, WM8731_PWR, pwr_reg | 0x0010);
+			wm8731_write(codec, WM8731_ACTIVE, act_reg);
+			wm8731_write(codec, WM8731_PWR, 0xff7f);
 			break;
 		case SNDRV_CTL_POWER_D3cold: /* Off, without power */
 			/* everything off, dac mute, inactive */
-			wm8731_2w_write(wm8731_i2c, WM8731_APDIGI, dac_reg | 0x0008);
-			wm8731_2w_write(wm8731_i2c, WM8731_PWR, pwr_reg | 0x0010);
-			wm8731_2w_write(wm8731_i2c, WM8731_ACTIVE, act_reg);
-			wm8731_2w_write(wm8731_i2c, WM8731_PWR, 0xffff);
+			wm8731_write(codec, WM8731_APDIGI, dac_reg | 0x0008);
+			wm8731_write(codec, WM8731_PWR, pwr_reg | 0x0010);
+			wm8731_write(codec, WM8731_ACTIVE, act_reg);
+			wm8731_write(codec, WM8731_PWR, 0xffff);
 			break;
 	}
-	
+
 	return 0;
 }
 
-static snd_soc_pcm_codec_t wm8731_pcm_client = {
+static struct snd_soc_pcm_codec wm8731_pcm_client = {
 	.name = "WM8731",
 	.playback = {
 		.sname = "Playback",
@@ -478,73 +425,38 @@ static snd_soc_pcm_codec_t wm8731_pcm_cl
 	},
 };
 
-static snd_soc_codec_t wm8731_soc_codec;
-
-static ssize_t mute_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{        
-	int val = simple_strtoul(buf, NULL, 10);
-	
-	if (val)
-		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L | CORGI_SCP_MUTE_R);
-	else
-		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L | CORGI_SCP_MUTE_R);
-
-	return count;
-}
-
-static DEVICE_ATTR(mute, 0200, NULL, mute_store);
-
-static ssize_t spk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{        
-	int val = simple_strtoul(buf, NULL, 10);
-	
-	if (val)
-		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
-	else
-		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
-
-	return count;
-}
-
-static DEVICE_ATTR(spk, 0200, NULL, spk_store);
-
 /*
  * initialise the WM8731 driver
  * register the mixer and dsp interfaces with the kernel 
  */
-static int wm8731_probe(snd_soc_codec_t *codec)
+static int wm8731_probe(struct snd_soc_codec *codec)
 {
 	int reg;
 	
-	wm8731_reset(wm8731_i2c);
+	wm8731_reset(codec);
 	
-	reg = wm8731_read_reg_cache(WM8731_PWR);
-	wm8731_2w_write(wm8731_i2c, WM8731_PWR, reg);
+	reg = wm8731_read_reg_cache(codec, WM8731_PWR);
+	wm8731_write(codec, WM8731_PWR, reg);
 
-	reg = wm8731_read_reg_cache(WM8731_APANA);
-	wm8731_2w_write(wm8731_i2c, WM8731_APANA, reg);
-	reg = wm8731_read_reg_cache(WM8731_APDIGI);
-	wm8731_2w_write(wm8731_i2c, WM8731_APDIGI, reg);
+	reg = wm8731_read_reg_cache(codec, WM8731_APANA);
+	wm8731_write(codec, WM8731_APANA, reg);
+	reg = wm8731_read_reg_cache(codec, WM8731_APDIGI);
+	wm8731_write(codec, WM8731_APDIGI, reg);
 
 	wm8731_dpm_event(codec, SNDRV_CTL_POWER_D3hot);
 	
 	/* set the update bits */
-	reg = wm8731_read_reg_cache(WM8731_LOUT1V);
-	wm8731_2w_write(wm8731_i2c, WM8731_LOUT1V, reg | 0x0100);
-	reg = wm8731_read_reg_cache(WM8731_ROUT1V);
-	wm8731_2w_write(wm8731_i2c, WM8731_ROUT1V, reg | 0x0100);
-	reg = wm8731_read_reg_cache(WM8731_LINVOL);
-	wm8731_2w_write(wm8731_i2c, WM8731_LINVOL, reg | 0x0100);
-	reg = wm8731_read_reg_cache(WM8731_RINVOL);
-	wm8731_2w_write(wm8731_i2c, WM8731_RINVOL, reg | 0x0100);
-
-	wm8731_add_controls(&wm8731_soc_codec);
-	wm8731_add_widgets(&wm8731_soc_codec);
+	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);
 
-	set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON | CORGI_SCP_MUTE_L | CORGI_SCP_MUTE_R );
-
-	device_create_file(&wm8731_soc_codec.pdev.dev, &dev_attr_mute);
-	device_create_file(&wm8731_soc_codec.pdev.dev, &dev_attr_spk);
+	wm8731_add_controls(codec);
+	wm8731_add_widgets(codec);
 
 	return 0;
 }
@@ -552,33 +464,91 @@ static int wm8731_probe(snd_soc_codec_t 
 /* 
  * unregister interfaces and clean up
  */
-static void wm8731_remove(snd_soc_codec_t *codec)
+static void wm8731_remove(struct snd_soc_codec *codec)
 {
-	device_remove_file(&wm8731_soc_codec.pdev.dev, &dev_attr_mute);
-	device_remove_file(&wm8731_soc_codec.pdev.dev, &dev_attr_spk);
-
 	wm8731_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
 }
 
-static snd_soc_codec_t wm8731_soc_codec = {
-	.name = "WM8731",
-	.longname = "WM8731 Portable Codec",
-	.owner = THIS_MODULE,
-	.pdev = {
-		.name		= "soc-wm8731",
-		.id		= -1,
-		.dev		= {
-			.release = wm8731_device_release,
-		},
-	},
-	.probe = wm8731_probe,
-	.remove = wm8731_remove,
-	.read = wm8731_read_reg_cache,
-	.write = wm8731_write,
-	.dpm_event = wm8731_dpm_event,
-	.pcms = &wm8731_pcm_client,
-	.npcms = 1,
-};	
+/*
+ * Attach WM8731 2 wire client 
+ */
+static int wm8731_i2c_probe(struct i2c_adapter *adap, int addr, int kind)
+{		
+	int ret = 0;
+	struct snd_soc_codec *codec;
+
+	client_template.adapter = adap;
+	client_template.addr = addr;
+	
+	if ((codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+ 
+	memcpy(&codec->i2c, &client_template, sizeof(struct i2c_client));
+
+	if((ret = i2c_attach_client(&codec->i2c)) < 0) {
+		err("failed to attach codec at addr %x\n", addr);
+		kfree(codec);
+	}
+
+	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;
+	codec->pcms = &wm8731_pcm_client;
+	codec->npcms = 1;
+	if ((codec->reg_cache = 
+			kzalloc(sizeof(u16) * ARRAY_SIZE(wm8731_reg), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+	memcpy(codec->reg_cache, wm8731_reg, sizeof(u16) * ARRAY_SIZE(wm8731_reg));
+
+	if((ret = snd_soc_register_codec(codec)) < 0) {
+		err("can't register codec");
+		i2c_del_driver(&wm8731_i2c_driver);
+		kfree(codec->reg_cache);
+		kfree(codec);
+	}
+
+	return ret;
+}
+
+static int wm8731_i2c_detach(struct i2c_client *client)
+{
+	struct snd_soc_codec *codec = container_of(client, struct snd_soc_codec, i2c);
+
+	i2c_detach_client(client);
+	snd_soc_unregister_codec(codec);
+	kfree(codec->reg_cache);
+	kfree(codec);
+	return 0;
+}
+
+static int wm8731_i2c_attach(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, wm8731_i2c_probe);
+}
+
+/* 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 int __init wm8731_init(void)
 {	
@@ -586,28 +556,14 @@ static int __init wm8731_init(void)
 	
 	info("WM8731 Audio Codec %s", WM8731_VERSION);
 
-	if ((ret = i2c_add_driver(&wm8731_i2c_driver)) != 0) {
+	if ((ret = i2c_add_driver(&wm8731_i2c_driver)) != 0)
 		err("can't add i2c driver");
-		return ret;
-	}
-
-	if(!wm8731_i2c) {
-		err("can't find chip on i2c bus");
-		i2c_del_driver(&wm8731_i2c_driver);
-		return -ENODEV;
-	}
 	
-	if((ret = snd_soc_register_codec(&wm8731_soc_codec)) < 0) {
-		err("can't register driver");
-		i2c_del_driver(&wm8731_i2c_driver);
-		return ret;
-	}
 	return ret;
 }
 
 static void __exit wm8731_exit(void)
 {
-	snd_soc_unregister_codec(&wm8731_soc_codec);
 	i2c_del_driver(&wm8731_i2c_driver);
 }
 
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 735e67f..d47eb33 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -16,8 +16,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/i2c.h>
 #include <linux/pm.h>
+
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -31,7 +31,7 @@
 #include "wm8750.h"
 
 #define AUDIO_NAME "WM8750"
-#define WM8750_VERSION "0.3"
+#define WM8750_VERSION "0.4"
 
 /*
  * Debug
@@ -60,35 +60,36 @@ static unsigned short normal_i2c[] = {  
 /* Magic definition of all other variables and things */
 I2C_CLIENT_INSMOD;
 
-struct i2c_client* wm8750_i2c = NULL;
-
+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 
  * are using 2 wire for device control, so we cache them instead. 
  */
-static u16 reg_cache[] = {
-	0x0097, 0x0097, 0x0079, 0x0079,  //0-3
-	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
-	0x0050, 0x0050, 0x0050, 0x0050,  //36
-	0x0079, 0x0079, 0x0079,          //40
+static const u16 wm8750_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 */
+	0x0050, 0x0050, 0x0050, 0x0050,  /* 36 */
+	0x0079, 0x0079, 0x0079,          /* 40 */
 };
 
 #define WM8750_HWFMT \
 	(SND_SOC_HWFMT_I2S | SND_SOC_HWFMT_LEFT_J | SND_SOC_HWFMT_RIGHT_J | \
-	SND_SOC_HWFMT_CBS_CFS | \
+	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 snd_soc_hw_mode_t wm8750_hwfmt[] = {
+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},
@@ -148,80 +149,29 @@ static snd_soc_hw_mode_t wm8750_hwfmt[] 
 /*
  * read wm8750 register cache
  */
-static inline unsigned int wm8750_read_reg_cache(u16 reg)
+static inline unsigned int wm8750_read_reg_cache(struct snd_soc_codec * codec, 
+	unsigned int reg)
 {
-	if (reg >= WM8750_CACHE_REGNUM)
+	u16 *cache = codec->reg_cache;
+	if (reg > WM8750_CACHE_REGNUM)
 		return -1;
-	return reg_cache[reg];
+	return cache[reg];
 }
 
 /*
  * write wm8750 register cache
  */
-static inline void wm8750_write_reg_cache(u16 reg, unsigned int value)
+static inline void wm8750_write_reg_cache(struct snd_soc_codec * codec, 
+	unsigned int reg, unsigned int value)
 {
-	printk("wm8750: Writing %x to %x\n", value, reg);
-	if (reg < WM8750_CACHE_REGNUM)
-		reg_cache[reg] = value;
+	u16 *cache = codec->reg_cache;
+	if (reg > WM8750_CACHE_REGNUM)
+		return;
+	cache[reg] = value;
 }
 
-static struct i2c_client client_template;
-static int wm8750_reset(struct i2c_client *client);
-static int wm8750_2w_write(struct i2c_client *client, u8 reg, u16 value);
-static int wm8750_add_controls(snd_soc_codec_t *codec);
-static int wm8750_add_widgets(snd_soc_codec_t *codec);
-static snd_soc_codec_t wm8750_soc_codec;
-
-	
-/*
- * Attach WM8750 2 wire client 
- */
-static int wm8750_i2c_probe(struct i2c_adapter *adap, int addr, int kind)
-{		
-	int reg;
-
-	client_template.adapter = adap;
-	client_template.addr = addr;
-
-	printk("wm8750_i2c_probe: Probing %d\n",addr);
-	
-	if ((wm8750_i2c = kmalloc(sizeof(struct i2c_client),GFP_KERNEL)) == NULL)
-		return -ENOMEM;
- 
-	memcpy(wm8750_i2c, &client_template, sizeof(struct i2c_client));
-
-	return i2c_attach_client(wm8750_i2c);
-}
-
-static int wm8750_i2c_detach(struct i2c_client *client)
-{
-	i2c_detach_client(client);
-	kfree(client);
-	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 wm8750_2w_write(struct i2c_client *client, u8 reg, u16 value)
+static int wm8750_write(struct snd_soc_codec * codec, unsigned int reg, 
+	unsigned int value)
 {
 	u8 data[2];
 
@@ -232,28 +182,20 @@ static int wm8750_2w_write(struct i2c_cl
 	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
 	data[1] = value & 0x00ff;
 
-	wm8750_write_reg_cache (reg, value);
-	if (i2c_master_send(client, data, 2) == 2)
+	wm8750_write_reg_cache (codec, reg, value);
+	if (i2c_master_send(&codec->i2c, data, 2) == 2)
 		return 0;
 	else
 		return -1;
 }
 
-static int wm8750_write (u16 reg, unsigned int value)
-{
-	return wm8750_2w_write(wm8750_i2c, reg, value);	
-}
-
-static int wm8750_reset(struct i2c_client *client)
-{
-	return wm8750_2w_write (client, WM8750_RESET, 0);
-}
+#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", "200Hz"};
+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"};
@@ -264,7 +206,6 @@ static const char* wm8750_line_mux[] = {
 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_micboost[] = {"Off", "13dB", "20dB", "29dB"};
 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"};
@@ -284,39 +225,36 @@ SOC_ENUM_SINGLE(WM8750_LADCIN, 6, 4, wm8
 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_LADCIN, 4, 4, wm8750_micboost),
-SOC_ENUM_SINGLE(WM8750_RADCIN, 4, 4, wm8750_micboost),
 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), /* 18 */
+SOC_ENUM_SINGLE(WM8750_ADCIN, 6, 4, wm8750_mono_mux), /* 16 */
 
 };
 
 static const snd_kcontrol_new_t wm8750_snd_controls[] = {
 
-SOC_SINGLE("Line In Left Volume", WM8750_LINVOL, 0, 63, 0),
-SOC_SINGLE("Line In Left ZC Switch", WM8750_LINVOL, 6, 1, 0),
-SOC_SINGLE("Line In Left Mute Switch", WM8750_LINVOL, 7, 1, 1),
-SOC_SINGLE("Line In Right Volume", WM8750_RINVOL, 0, 63, 0),
-SOC_SINGLE("Line In Right ZC Switch", WM8750_RINVOL, 6, 1, 0),
-SOC_SINGLE("Line In Right Mute Switch", WM8750_RINVOL, 7, 1, 1),
-
-SOC_SINGLE("Left Out 1 Volume", WM8750_LOUT1V, 0, 127, 0),
-SOC_SINGLE("Left Out 1 ZC Switch", WM8750_LOUT1V, 7, 1, 0),
-SOC_SINGLE("Right Out 1 Volume", WM8750_ROUT1V, 0, 127, 0),
-SOC_SINGLE("Right Out 1 ZC Switch", WM8750_ROUT1V, 7, 1, 0),
-
-SOC_SINGLE("Left Out 2 Volume", WM8750_LOUT2V, 0, 127, 0),
-SOC_SINGLE("Left Out 2 ZC Switch", WM8750_LOUT2V, 7, 1, 0),
-SOC_SINGLE("Right Out 2 Volume", WM8750_ROUT2V, 0, 127, 0),
-SOC_SINGLE("Right Out 2 ZC Switch", WM8750_ROUT2V, 7, 1, 0),
-
-
-SOC_ENUM("De-emphasis Control", wm8750_enum[17]),
-SOC_SINGLE("DAC Mute", WM8750_ADCDAC, 3, 1, 0),
-SOC_ENUM("ADC Polarity", wm8750_enum[16]),
-SOC_SINGLE("DAC 6dB Attenuate", WM8750_ADCDAC, 7, 1, 0),
-SOC_SINGLE("ADC 6dB Attenuate", WM8750_ADCDAC, 8, 1, 0),
+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 Volume", WM8750_LOUT1V, 0, 127, 0),
+SOC_SINGLE("Left Out1 Playback ZC Switch", WM8750_LOUT1V, 7, 1, 0),
+SOC_SINGLE("Right Out1 Playback Volume", WM8750_ROUT1V, 0, 127, 0),
+SOC_SINGLE("Right Out1 Playback ZC Switch", WM8750_ROUT1V, 7, 1, 0),
+
+SOC_SINGLE("Left Out2 Playback Volume", WM8750_LOUT2V, 0, 127, 0),
+SOC_SINGLE("Left Out2 Playback ZC Switch", WM8750_LOUT2V, 7, 1, 0),
+SOC_SINGLE("Right Out2 Playback Volume", WM8750_ROUT2V, 0, 127, 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),
@@ -334,29 +272,25 @@ SOC_ENUM("3D Lower Cut-off", wm8750_enum
 SOC_ENUM("3D Upper Cut-off", wm8750_enum[4]),
 SOC_ENUM("3D Mode", wm8750_enum[5]),
 
-SOC_SINGLE("ALC Target Volume", WM8750_ALC1, 0, 7, 0),
-SOC_SINGLE("ALC Max Volume", WM8750_ALC1, 4, 7, 0),
-SOC_ENUM("ALC Function", wm8750_enum[6]),
-SOC_SINGLE("ALC ZC Switch", WM8750_ALC2, 7, 1, 0),
-SOC_SINGLE("ALC Hold Time", WM8750_ALC2, 0, 15, 0),
-SOC_SINGLE("ALC Decay Time", WM8750_ALC3, 4, 15, 0),
-SOC_SINGLE("ALC Attack Time", WM8750_ALC3, 0, 15, 0),
-SOC_SINGLE("ALC NG Threshold", WM8750_NGATE, 3, 31, 0),
-SOC_ENUM("ALC NG Type", wm8750_enum[4]),
-SOC_SINGLE("ALC NG Switch", WM8750_NGATE, 0, 1, 0),
+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 Volume", WM8750_LADC, 0, 255, 0),
-SOC_SINGLE("Right ADC Volume", WM8750_RADC, 0, 255, 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("DAC Invert Switch", WM8750_ADCTL1, 1, 1, 0),
-SOC_SINGLE("Thermal Shutdown Switch", WM8750_ADCTL1, 8, 1, 0),
+SOC_SINGLE("Playback Invert Switch", WM8750_ADCTL1, 1, 1, 0),
+
+SOC_SINGLE("Right Out2 Playback Invert Switch", WM8750_ADCTL2, 4, 1, 0),
 
-SOC_SINGLE("Low DAC Oversample", WM8750_ADCTL2, 0, 1, 0),
-SOC_SINGLE("Low ADC Oversample", WM8750_ADCTL2, 1, 1, 0),
-SOC_SINGLE("Right Out 2 Invert Switch", WM8750_ADCTL2, 4, 1, 0),
-SOC_SINGLE("Headphone Polarity Switch", WM8750_ADCTL2, 5, 1, 0),
-SOC_SINGLE("Headphone Detect Switch", WM8750_ADCTL2, 6, 1, 0),
 
 /* Unimplemented */
 /* ADCDAC Bit 0 - ADCHPD */
@@ -372,25 +306,25 @@ SOC_SINGLE("Headphone Detect Switch", WM
 /* ADCIN Bit 4 - LDCM */ 
 /* ADCIN Bit 5 - RDCM */
 
-SOC_ENUM("Left Mic Boost", wm8750_enum[14]),
-SOC_ENUM("Right Mic Boost", wm8750_enum[15]),
+SOC_SINGLE("Left Mic Boost", WM8750_LADCIN, 4, 3, 0),
+SOC_SINGLE("Right Mic Boost", WM8750_RADCIN, 4, 3, 0),
 
-SOC_SINGLE("Left Mux to Left Mixer Volume", WM8750_LOUTM1, 4, 7, 1),
-SOC_SINGLE("Right Mux to Left Mixer Volume", WM8750_LOUTM2, 4, 7, 1),
+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 Mux to Right Mixer Volume", WM8750_ROUTM1, 4, 7, 1),
-SOC_SINGLE("Right Mux to Right Mixer Volume", WM8750_ROUTM2, 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 Mux to Mono Mixer Volume", WM8750_MOUTM1, 4, 7, 1),
-SOC_SINGLE("Right Mux to Mono Mixer Volume", WM8750_MOUTM2, 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 Volume", WM8750_MOUTV, 0, 127, 0),
-SOC_SINGLE("Mono ZC Switch", WM8750_MOUTV, 7, 1, 0),
+SOC_SINGLE("Mono Playback Volume", WM8750_MOUTV, 0, 127, 0),
+SOC_SINGLE("Mono Playback ZC Switch", WM8750_MOUTV, 7, 1, 0),
 
 };
 
 /* add non dpm controls */
-static int wm8750_add_controls(snd_soc_codec_t *codec)
+static int wm8750_add_controls(struct snd_soc_codec *codec)
 {
 	int err, i;
 
@@ -407,58 +341,58 @@ static int wm8750_add_controls(snd_soc_c
 
 /* Left Mixer */
 static const snd_kcontrol_new_t wm8750_left_mixer_controls[] = {
-SOC_DPM_SINGLE("Left DAC Switch", WM8750_LOUTM1, 8, 1, 0),
-SOC_DPM_SINGLE("Left Line Mux Switch", WM8750_LOUTM1, 7, 1, 0),
-SOC_DPM_SINGLE("Right DAC Switch", WM8750_LOUTM2, 8, 1, 0),
-SOC_DPM_SINGLE("Right Line Mux Switch", WM8750_LOUTM2, 7, 1, 0),
+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 DAC Switch", WM8750_ROUTM1, 8, 1, 0),
-SOC_DPM_SINGLE("Left Line Mux Switch", WM8750_ROUTM1, 7, 1, 0),
-SOC_DPM_SINGLE("Right DAC Switch", WM8750_ROUTM2, 8, 1, 0),
-SOC_DPM_SINGLE("Right Line Mux Switch", WM8750_ROUTM2, 7, 1, 0),
+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 DAC Switch", WM8750_MOUTM1, 8, 1, 0),
-SOC_DPM_SINGLE("Left Line Mux Switch", WM8750_MOUTM1, 7, 1, 0),
-SOC_DPM_SINGLE("Right DAC Switch", WM8750_MOUTM2, 8, 1, 0),
-SOC_DPM_SINGLE("Right Line Mux Switch", WM8750_MOUTM2, 7, 1, 0),
+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("Source", wm8750_enum[8]);
+SOC_DPM_ENUM("Route", wm8750_enum[8]);
 
 /* Right Line Mux */
 static const snd_kcontrol_new_t wm8750_right_line_controls =
-SOC_DPM_ENUM("Source", wm8750_enum[9]);
+SOC_DPM_ENUM("Route", wm8750_enum[9]);
 
 /* Left PGA Mux */
 static const snd_kcontrol_new_t wm8750_left_pga_controls =
-SOC_DPM_ENUM("Source", wm8750_enum[10]);
+SOC_DPM_ENUM("Route", wm8750_enum[10]);
 
 /* Right PGA Mux */
 static const snd_kcontrol_new_t wm8750_right_pga_controls =
-SOC_DPM_ENUM("Source", wm8750_enum[11]);
+SOC_DPM_ENUM("Route", wm8750_enum[11]);
 
 /* Out 3 Mux */
 static const snd_kcontrol_new_t wm8750_out3_controls =
-SOC_DPM_ENUM("Source", wm8750_enum[12]);
+SOC_DPM_ENUM("Route", wm8750_enum[12]);
 
 /* Differential Mux */
 static const snd_kcontrol_new_t wm8750_diffmux_controls =
-SOC_DPM_ENUM("Source", wm8750_enum[13]);
+SOC_DPM_ENUM("Route", wm8750_enum[13]);
 
 /* Mono ADC Mux */
 static const snd_kcontrol_new_t wm8750_monomux_controls =
-SOC_DPM_ENUM("Source", wm8750_enum[18]);
+SOC_DPM_ENUM("Route", wm8750_enum[16]);
 
 
-static const snd_soc_dpm_widget_t wm8750_dpm_widgets[] = {
+static const struct snd_soc_dpm_widget wm8750_dpm_widgets[] = {
 	SND_SOC_DPM_CLOCK("WM8750 Clock", WM8750_PWR1, 0, 1),
 	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)),
@@ -494,12 +428,15 @@ static const snd_soc_dpm_widget_t wm8750
 	SND_SOC_DPM_OUTPUT("MONO"),
 	SND_SOC_DPM_OUTPUT("OUT3"),
 
-	SND_SOC_DPM_INPUT("LINE1"),
-	SND_SOC_DPM_INPUT("LINE2"),
-	SND_SOC_DPM_INPUT("LINE3"),
+	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(snd_soc_codec_t *codec)
+static int wm8750_add_widgets(struct snd_soc_codec *codec)
 {
 	int i;
 	
@@ -508,16 +445,16 @@ static int wm8750_add_widgets(snd_soc_co
 	}
 	
 	/* left mixer */
-	snd_soc_dpm_connect_input(codec, "Left Mixer", "Left DAC Switch", "Left DAC");
-	snd_soc_dpm_connect_input(codec, "Left Mixer", "Left Line Mux Switch", "Left Line Mux");
-	snd_soc_dpm_connect_input(codec, "Left Mixer", "Right DAC Switch", "Right DAC");
-	snd_soc_dpm_connect_input(codec, "Left Mixer", "Right Line Mux Switch", "Right Line Mux");
+	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 DAC Switch", "Left DAC");
-	snd_soc_dpm_connect_input(codec, "Right Mixer", "Left Line Mux Switch", "Left Line Mux");
-	snd_soc_dpm_connect_input(codec, "Right Mixer", "Right DAC Switch", "Right DAC");
-	snd_soc_dpm_connect_input(codec, "Right Mixer", "Right Line Mux Switch", "Right Line Mux");
+	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");
@@ -536,10 +473,10 @@ static int wm8750_add_widgets(snd_soc_co
 	snd_soc_dpm_connect_input(codec, "ROUT2", NULL, "Right Out 2");
 
 	/* mono mixer */
-	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Left DAC Switch", "Left DAC");
-	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Left Line Mux Switch", "Left Line Mux");
-	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Right DAC Switch", "Right DAC");
-	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Right Line Mux Switch", "Right Line Mux");
+	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");
@@ -555,34 +492,36 @@ static int wm8750_add_widgets(snd_soc_co
 	snd_soc_dpm_connect_input(codec, "OUT3", NULL, "Out 3");
 
 	/* Left Line Mux */
-	snd_soc_dpm_connect_input(codec, "Left Line Mux", "Line 1", "LINE1");
-	snd_soc_dpm_connect_input(codec, "Left Line Mux", "Line 2", "LINE2");
-	snd_soc_dpm_connect_input(codec, "Left Line Mux", "Line 3", "LINE3");
+	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", "LINE1");
-	snd_soc_dpm_connect_input(codec, "Right Line Mux", "Line 2", "LINE2");
-	snd_soc_dpm_connect_input(codec, "Right Line Mux", "Line 3", "LINE3");
+	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", "LINE1");
-	snd_soc_dpm_connect_input(codec, "Left PGA Mux", "Line 2", "LINE2");
-	snd_soc_dpm_connect_input(codec, "Left PGA Mux", "Line 3", "LINE3");
+	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", "LINE1");
-	snd_soc_dpm_connect_input(codec, "Right PGA Mux", "Line 2", "LINE2");
-	snd_soc_dpm_connect_input(codec, "Right PGA Mux", "Line 3", "LINE3");
+	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", "LINE1");
-	snd_soc_dpm_connect_input(codec, "Differential Mux", "Line 2", "LINE2");
+	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");
@@ -605,14 +544,15 @@ static int wm8750_add_widgets(snd_soc_co
 
 static int wm8750_pcm_prepare(snd_pcm_substream_t *substream)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
+	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_CBS_CFM:
-		//	iface |= 0x0020;
-		//	break;
+		case SND_SOC_HWFMT_CBM_CFM:
+			iface |= 0x0020;
+			break;
 		case SND_SOC_HWFMT_CBS_CFS:
 			break;
 	}
@@ -665,10 +605,9 @@ static int wm8750_pcm_prepare(snd_pcm_su
 			break;
 	}
 	
-	
 	/* set rate */
-	wm8750_2w_write(wm8750_i2c, WM8750_SRATE, pcm_c->hw_runtime.priv1);
-	wm8750_2w_write(wm8750_i2c, WM8750_IFACE, iface);
+	wm8750_write(codec, WM8750_SRATE, pcm_c->hw_runtime.priv1);
+	wm8750_write(codec, WM8750_IFACE, iface);
 	
 	return 0;
 }
@@ -677,37 +616,37 @@ static void wm8750_device_release(struct
 {
 }
 
-static int wm8750_dpm_event(snd_soc_codec_t *codec, int event)
+static int wm8750_dpm_event(struct snd_soc_codec *codec, int event)
 {
-	u16 pwr_reg = wm8750_read_reg_cache(WM8750_PWR1) & 0xfe3f;
-	u16 dac_reg = wm8750_read_reg_cache(WM8750_ADCDAC) & 0xfff7;
+	u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3f;
+	u16 dac_reg = wm8750_read_reg_cache(codec, WM8750_ADCDAC) & 0xfff7;
 
 	switch (event) {
 		case SNDRV_CTL_POWER_D0: /* full On */
 			/* set vmid to 50k and unmute dac */
-			wm8750_2w_write(wm8750_i2c, WM8750_PWR1, pwr_reg | 0x00c0);
-			wm8750_2w_write(wm8750_i2c, WM8750_ADCDAC, dac_reg);
+			wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
+			wm8750_write(codec, WM8750_ADCDAC, dac_reg);
 			break;
 		case SNDRV_CTL_POWER_D1: /* partial On */
 		case SNDRV_CTL_POWER_D2: /* partial On */
 			/* set vmid to 5k for quick power up */
-			wm8750_2w_write(wm8750_i2c, WM8750_PWR1, pwr_reg | 0x01c0);
+			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_2w_write(wm8750_i2c, WM8750_ADCDAC, dac_reg | 0x0008);
-			wm8750_2w_write(wm8750_i2c, WM8750_PWR1, pwr_reg | 0x0140);
+			wm8750_write(codec, WM8750_ADCDAC, dac_reg | 0x0008);
+			wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x0140);
 			break;
 		case SNDRV_CTL_POWER_D3cold: /* Off, without power */
-			wm8750_2w_write(wm8750_i2c, WM8750_ADCDAC, dac_reg | 0x0008);
-			wm8750_2w_write(wm8750_i2c, WM8750_PWR1, 0x0000);
+			wm8750_write(codec, WM8750_ADCDAC, dac_reg | 0x0008);
+			wm8750_write(codec, WM8750_PWR1, 0x0000);
 			break;
 	}
 	
 	return 0;
 }
 
-static snd_soc_pcm_codec_t wm8750_pcm_client = {
+static struct snd_soc_pcm_codec wm8750_pcm_client = {
 	.name = "WM8750",
 	.playback = {
 		.sname = "Playback",
@@ -738,74 +677,39 @@ static snd_soc_pcm_codec_t wm8750_pcm_cl
 	},
 };
 
-static snd_soc_codec_t wm8750_soc_codec;
-
- 
-static ssize_t cmd_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{        
-	int val,ret;        
-	sscanf(buf, "%x %x", &val, &ret);	
-	
-	wm8750_2w_write(wm8750_i2c, val, ret);
-
-	return count;
-}   
-
-static DEVICE_ATTR(cmd, 0200, NULL, cmd_store);
-
-static ssize_t mute_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{        
-	int val = simple_strtoul(buf, NULL, 10);
-	
-	if (val)
-		set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L | SPITZ_SCP_MUTE_R);
-	else
-		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L | SPITZ_SCP_MUTE_R);
-
-	return count;
-}
-
-static DEVICE_ATTR(mute, 0200, NULL, mute_store);
-
 /*
  * initialise the WM8750 driver
  * register the mixer and dsp interfaces with the kernel 
  */
-static int wm8750_probe(snd_soc_codec_t *codec)
+static int wm8750_probe(struct snd_soc_codec *codec)
 {
 	int reg;
 	
 	info("WM8750 Audio Codec %s", WM8750_VERSION);
 	
-	wm8750_reset(wm8750_i2c);
-	
+	wm8750_reset(codec);
 	wm8750_dpm_event(codec, SNDRV_CTL_POWER_D3hot);
 
 	/* set the update bits */
-	reg = wm8750_read_reg_cache(WM8750_LDAC);
-	wm8750_2w_write(wm8750_i2c, WM8750_LDAC, reg | 0x0100);
-	reg = wm8750_read_reg_cache(WM8750_RDAC);
-	wm8750_2w_write(wm8750_i2c, WM8750_RDAC, reg | 0x0100);
-	reg = wm8750_read_reg_cache(WM8750_LOUT1V);
-	wm8750_2w_write(wm8750_i2c, WM8750_LOUT1V, reg | 0x0100);
-	reg = wm8750_read_reg_cache(WM8750_ROUT1V);
-	wm8750_2w_write(wm8750_i2c, WM8750_ROUT1V, reg | 0x0100);
-	reg = wm8750_read_reg_cache(WM8750_LOUT2V);
-	wm8750_2w_write(wm8750_i2c, WM8750_LOUT2V, reg | 0x0100);
-	reg = wm8750_read_reg_cache(WM8750_ROUT2V);
-	wm8750_2w_write(wm8750_i2c, WM8750_ROUT2V, reg | 0x0100);
-	reg = wm8750_read_reg_cache(WM8750_LINVOL);
-	wm8750_2w_write(wm8750_i2c, WM8750_LINVOL, reg | 0x0100);
-	reg = wm8750_read_reg_cache(WM8750_RINVOL);
-	wm8750_2w_write(wm8750_i2c, WM8750_RINVOL, reg | 0x0100);
-
-	wm8750_add_controls(&wm8750_soc_codec);
-	wm8750_add_widgets(&wm8750_soc_codec);
+	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);
 
-	device_create_file(&wm8750_soc_codec.pdev.dev, &dev_attr_cmd);
-	device_create_file(&wm8750_soc_codec.pdev.dev, &dev_attr_mute);
-
-	set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L | SPITZ_SCP_MUTE_R );
+	wm8750_add_controls(codec);
+	wm8750_add_widgets(codec);
 
 	return 0;
 }
@@ -813,31 +717,91 @@ static int wm8750_probe(snd_soc_codec_t 
 /* 
  * unregister interfaces and clean up
  */
-static void wm8750_remove(snd_soc_codec_t *codec)
+static void wm8750_remove(struct snd_soc_codec *codec)
 {
-	device_remove_file(&wm8750_soc_codec.pdev.dev, &dev_attr_cmd);
-	device_remove_file(&wm8750_soc_codec.pdev.dev, &dev_attr_mute);
-
 	wm8750_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
 }
 
-static snd_soc_codec_t wm8750_soc_codec = {
-	.name = "WM8750",
-	.longname = "WM8750 Portable Codec",
-	.owner = THIS_MODULE,
-	.pdev = {
-		.name		= "soc-wm8750",
-		.id		= -1,
-		.dev		= {.release = wm8750_device_release},
-	},
-	.probe = wm8750_probe,
-	.remove = wm8750_remove,
-	.read = wm8750_read_reg_cache,
-	.write = wm8750_write,
-	.dpm_event = wm8750_dpm_event,
-	.pcms = &wm8750_pcm_client,
-	.npcms = 1,
-};	
+/*
+ * 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;
+
+	client_template.adapter = adap;
+	client_template.addr = addr;
+	
+	if ((codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+ 
+	memcpy(&codec->i2c, &client_template, sizeof(struct i2c_client));
+
+	if((ret = i2c_attach_client(&codec->i2c)) < 0) {
+		err("failed to attach codec at addr %x\n", addr);
+		kfree(codec);
+	}
+
+	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(codec->reg_cache);
+		kfree(codec);
+	}
+
+	return ret;
+}
+
+static int wm8750_i2c_detach(struct i2c_client *client)
+{
+	struct snd_soc_codec *codec = container_of(client, struct snd_soc_codec, i2c);
+
+	i2c_detach_client(client);
+	snd_soc_unregister_codec(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 int __init wm8750_init(void)
 {	
@@ -845,28 +809,14 @@ static int __init wm8750_init(void)
 
 	info("WM8750 Audio Codec %s", WM8750_VERSION);
 
-	if ((ret = i2c_add_driver(&wm8750_i2c_driver)) != 0) {
+	if ((ret = i2c_add_driver(&wm8750_i2c_driver)) != 0)
 		err("can't add i2c driver");
-		return ret;
-	}
-
-	if(!wm8750_i2c) {
-		err("can't find chip on i2c bus");
-		i2c_del_driver(&wm8750_i2c_driver);
-		return -ENODEV;
-	}
 	
-	if((ret = snd_soc_register_codec(&wm8750_soc_codec)) < 0) {
-		err("can't register driver");
-		i2c_del_driver(&wm8750_i2c_driver);
-		return ret;
-	}
 	return ret;
 }
 
 static void __exit wm8750_exit(void)
 {
-	snd_soc_unregister_codec(&wm8750_soc_codec);
 	i2c_del_driver(&wm8750_i2c_driver);
 }
 
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index fc6b085..507d58e 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -34,7 +34,7 @@
 #include "wm8753.h"
 
 #define AUDIO_NAME "wm8753"
-#define WM8753_VERSION "0.4"
+#define WM8753_VERSION "0.5"
 
 /*
  * Debug
@@ -69,14 +69,16 @@ static unsigned short normal_i2c[] = { W
 
 /* Magic definition of all other variables and things */
 I2C_CLIENT_INSMOD;
-struct i2c_client* wm8753_i2c = NULL;
+
+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 
  * are using 2 wire for device control, so we cache them instead. 
  */
-static u16 reg_cache[] = {
+static const u16 wm8753_reg[] = {
     0x0008, 0x0000, 0x000a, 0x000a,  
     0x0033, 0x0000, 0x0007, 0x00ff,
     0x00ff, 0x000f, 0x000f, 0x007b, 
@@ -133,7 +135,7 @@ static struct _pll_div pll_div[] = {
  * priv1 is pll/mclk freq
  * priv2 is bits[15..8] = MCLK divisor, bits[7..0] = sr
  */
-static snd_soc_hw_mode_t wm8753_hifi[] = {
+static struct snd_soc_hw_mode wm8753_hifi[] = {
 	{WM8753_HIFI_HWFMT, 	SND_SOC_HWBITS(16),		8000,	768,	12288000, 	0x020c},
 	{WM8753_HIFI_HWFMT, 	SND_SOC_HWBITS(16),		8000,	384,	12288000, 	0x040c},
 	{WM8753_HIFI_HWFMT, 	SND_SOC_HWBITS(16),		8000,	192,	12288000, 	0x080c},
@@ -200,7 +202,7 @@ static snd_soc_hw_mode_t wm8753_hifi[] =
  * priv1 is pll/mclk freq
  * priv2 is bits[15..8] = PCM divisor, bits[7..0] = psr
  */
-static snd_soc_hw_mode_t wm8753_voice[] = {
+static struct snd_soc_hw_mode wm8753_voice[] = {
 	{WM8753_VOICE_HWFMT, 	SND_SOC_HWBITS(16),		48000,	256,	12288000, 	0x0000},
 	{WM8753_VOICE_HWFMT, 	SND_SOC_HWBITS(16),		44100,	256,	11289600, 	0x0000},
 	{WM8753_VOICE_HWFMT, 	SND_SOC_HWBITS(16),		32000,	384,	12288000, 	0x0001},
@@ -215,73 +217,34 @@ static snd_soc_hw_mode_t wm8753_voice[] 
 /*
  * read wm8753 register cache
  */
-static inline unsigned int wm8753_read_reg_cache(u16 reg)
+static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec * codec, 
+	unsigned int reg)
 {
-	if(reg < 1 || reg > (ARRAY_SIZE(reg_cache) + 1))
+	u16 *cache = codec->reg_cache;
+	if(reg < 1 || reg > (ARRAY_SIZE(wm8753_reg) + 1))
 		return -1;
-	return reg_cache[reg - 1];
+	return cache[reg - 1];
 }
 
 /*
  * write wm8753 register cache
  */
-static inline void wm8753_write_reg_cache(u16 reg, unsigned int value)
+static inline void wm8753_write_reg_cache(struct snd_soc_codec * codec, 
+	unsigned int reg, unsigned int value)
 {
-	if(reg < 1 || reg > (ARRAY_SIZE(reg_cache) + 1))
+	u16 *cache = codec->reg_cache;
+	if(reg < 1 || reg > (ARRAY_SIZE(wm8753_reg) + 1))
 		return;
-	reg_cache[reg - 1] = value;
+	cache[reg - 1] = value;
 }
 
 static struct i2c_client client_template;
-static int wm8753_reset(struct i2c_client *client);
-	
-/*
- * Attach WM8753 2 wire client 
- */
-static int wm8753_i2c_probe(struct i2c_adapter *adap, int addr, int kind)
-{
-    client_template.adapter = adap;
-    client_template.addr = addr;
-	
-    if ((wm8753_i2c = kmalloc(sizeof(struct i2c_client),GFP_KERNEL)) == NULL)
-        return -ENOMEM;
-
-    memcpy(wm8753_i2c, &client_template, sizeof(struct i2c_client));
-	return i2c_attach_client(wm8753_i2c);
-}
-
-static int wm8753_i2c_detach(struct i2c_client *client)
-{
-	i2c_detach_client(client);
-	kfree(client);
-	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,
-};
 
 /*
  * write to the WM8753 register space
  */
-static int wm8753_2w_write(struct i2c_client *client, u8 reg, u16 value)
+static int wm8753_write(struct snd_soc_codec * codec, unsigned int reg,
+	unsigned int value)
 {
 	u8 data[2];
 
@@ -292,25 +255,15 @@ static int wm8753_2w_write(struct i2c_cl
 	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
 	data[1] = value & 0x00ff;
 
-	wm8753_write_reg_cache (reg, value);
-	if (i2c_master_send(client, data, 2) == 2)
+	wm8753_write_reg_cache (codec, reg, value);
+	if (i2c_master_send(&codec->i2c, data, 2) == 2)
 		return 0;
 	else
 		return -1;
 }
 
-static int wm8753_write (u16 reg, unsigned int value)
-{
-	return wm8753_2w_write(wm8753_i2c, reg, value);	
-}
+#define wm8753_reset(c) wm8753_write(c, WM8753_RESET, 0)
 
-/* 
- * reset the WM8753
- */
-static int wm8753_reset(struct i2c_client *client)
-{
-	return wm8753_2w_write (client, WM8753_RESET, 0);
-}
 
 /*
  * WM8753 Controls
@@ -379,36 +332,34 @@ static const snd_kcontrol_new_t wm8753_s
 SOC_SINGLE("Left PCM Volume", WM8753_LDAC, 0, 255, 0),
 SOC_SINGLE("Right PCM Volume", WM8753_RDAC, 0, 255, 0),
 	
-SOC_SINGLE("Left ADC Volume", WM8753_LADC, 0, 63, 0),
-SOC_SINGLE("Left ADC Switch", WM8753_LADC, 7, 1, 0),
-SOC_SINGLE("Left ADC ZC Switch", WM8753_LADC, 6, 1, 0),
-SOC_SINGLE("Right ADC Volume", WM8753_RADC, 0, 63, 0),
-SOC_SINGLE("Right ADC Switch", WM8753_RADC, 7, 1, 0),
-SOC_SINGLE("Right ADC ZC Switch", WM8753_RADC, 6, 1, 0),
+SOC_SINGLE("Left ADC Capture Volume", WM8753_LADC, 0, 63, 0),
+SOC_SINGLE("Left ADC Capture Switch", WM8753_LADC, 7, 1, 0),
+SOC_SINGLE("Left ADC Capture ZC Switch", WM8753_LADC, 6, 1, 0),
+SOC_SINGLE("Right ADC Capture Volume", WM8753_RADC, 0, 63, 0),
+SOC_SINGLE("Right ADC Capture Switch", WM8753_RADC, 7, 1, 0),
+SOC_SINGLE("Right ADC Capture ZC Switch", WM8753_RADC, 6, 1, 0),
 
 SOC_SINGLE("Left Out 1 Volume", WM8753_LOUT1V, 0, 127, 0),
 SOC_SINGLE("Left Out 1 ZC Switch", WM8753_LOUT1V, 7, 1, 0),
 SOC_SINGLE("Left Out 2 Volume", WM8753_LOUT2V, 0, 127, 0),
 SOC_SINGLE("Left Out 2 ZC Switch", WM8753_LOUT2V, 7, 1, 0),
 	
-SOC_SINGLE("Left Mux Left Mixer Volume", WM8753_LOUTM1, 4, 7, 1),
-
-SOC_SINGLE("Sidetone Left Mixer Volume", WM8753_LOUTM2, 4, 7, 1),
-SOC_SINGLE("Voice Left Mixer Volume", WM8753_LOUTM2, 0, 7, 1),
+SOC_SINGLE("Left Bypass Playback Volume", WM8753_LOUTM1, 4, 7, 1),
+SOC_SINGLE("Left Sidetone Playback Volume", WM8753_LOUTM2, 4, 7, 1),
+SOC_SINGLE("Left Voice Playback Volume", WM8753_LOUTM2, 0, 7, 1),
 
 SOC_SINGLE("Right Out 1 Volume", WM8753_ROUT1V, 0, 127, 0),
 SOC_SINGLE("Right Out 1 ZC Switch", WM8753_ROUT1V, 7, 1, 0),
 SOC_SINGLE("Right Out 2 Volume", WM8753_ROUT2V, 0, 127, 0),
 SOC_SINGLE("Right Out 2 ZC Switch", WM8753_ROUT2V, 7, 1, 0),
 
-SOC_SINGLE("Right Mux Right Mixer Volume", WM8753_ROUTM1, 4, 7, 1),
-
-SOC_SINGLE("Sidetone Right Mixer Volume", WM8753_ROUTM2, 4, 7, 1),
-SOC_SINGLE("Voice Right Mixer Volume", WM8753_ROUTM2, 0, 7, 1),
-
-SOC_SINGLE("Mono Mux Mono Mixer Volume", WM8753_MOUTM1, 4, 7, 1),
-SOC_SINGLE("Sidetone Mono Mixer Volume", WM8753_MOUTM2, 4, 7, 1),
-SOC_SINGLE("Voice Mono Mixer Volume", WM8753_MOUTM2, 4, 7, 1),
+SOC_SINGLE("Right Bypass Playback Volume", WM8753_ROUTM1, 4, 7, 1),
+SOC_SINGLE("Right Sidetone Playback Volume", WM8753_ROUTM2, 4, 7, 1),
+SOC_SINGLE("Right Voice Playback Volume", WM8753_ROUTM2, 0, 7, 1),
+
+SOC_SINGLE("Mono Bypass Playback Volume", WM8753_MOUTM1, 4, 7, 1),
+SOC_SINGLE("Mono Sidetone Playback Volume", WM8753_MOUTM2, 4, 7, 1),
+SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 4, 7, 1),
 
 SOC_SINGLE("Mono Volume", WM8753_MOUTV, 0, 127, 0),
 SOC_SINGLE("Mono ZC Switch", WM8753_MOUTV, 7, 1, 0),
@@ -420,31 +371,31 @@ SOC_SINGLE("Bass Volume", WM8753_BASS, 0
 SOC_SINGLE("Treble Volume", WM8753_TREBLE, 0, 7, 0),
 SOC_ENUM("Treble Cut-off", wm8753_enum[2]),
 
-SOC_SINGLE("Capture ST Right Mix Volume", WM8753_RECMIX1, 4, 7, 1),
-SOC_SINGLE("Capture ST Left Mix Volume", WM8753_RECMIX1, 0, 7, 1),
-SOC_SINGLE("Capture ST Voice Mix Volume", WM8753_RECMIX2, 0, 7, 1),
-
-SOC_SINGLE("Capture Left Volume", WM8753_LINVOL, 0, 63, 0),
-SOC_SINGLE("Capture Left ZC Switch", WM8753_LINVOL, 6, 1, 0),
-SOC_SINGLE("Capture Left Switch", WM8753_LINVOL, 7, 1, 1),
-SOC_SINGLE("Capture Right Volume", WM8753_RINVOL, 0, 63, 0),
-SOC_SINGLE("Capture Right ZC Switch", WM8753_RINVOL, 6, 1, 0),
-SOC_SINGLE("Capture Right Switch", WM8753_RINVOL, 7, 1, 1),
+SOC_SINGLE("Right Sidetone Capture Volume", WM8753_RECMIX1, 4, 7, 1),
+SOC_SINGLE("Left Sidetone Capture Volume", WM8753_RECMIX1, 0, 7, 1),
+SOC_SINGLE("Voice Sidetone Capture Volume", WM8753_RECMIX2, 0, 7, 1),
+
+SOC_SINGLE("Left Capture Volume", WM8753_LINVOL, 0, 63, 0),
+SOC_SINGLE("Left Capture ZC Switch", WM8753_LINVOL, 6, 1, 0),
+SOC_SINGLE("Left Capture Switch", WM8753_LINVOL, 7, 1, 1),
+SOC_SINGLE("Right Capture Volume", WM8753_RINVOL, 0, 63, 0),
+SOC_SINGLE("Right Capture ZC Switch", WM8753_RINVOL, 6, 1, 0),
+SOC_SINGLE("Right Capture Switch", WM8753_RINVOL, 7, 1, 1),
 
 SOC_ENUM("Capture Filter Select", wm8753_enum[23]),
 SOC_ENUM("Capture Filter Cut-off", wm8753_enum[24]),
 SOC_SINGLE("Capture Filter Switch", WM8753_ADC, 0, 1, 1),
 
-SOC_SINGLE("ALC Target Volume", WM8753_ALC1, 0, 7, 0),
-SOC_SINGLE("ALC Max Volume", WM8753_ALC1, 4, 7, 0),
-SOC_ENUM("ALC Function", wm8753_enum[3]),
-SOC_SINGLE("ALC ZC Switch", WM8753_ALC2, 8, 1, 0),
-SOC_SINGLE("ALC Hold Time", WM8753_ALC2, 0, 15, 1),
-SOC_SINGLE("ALC Decay Time", WM8753_ALC3, 4, 15, 1),
-SOC_SINGLE("ALC Attack Time", WM8753_ALC3, 0, 15, 0),
-SOC_SINGLE("ALC NG Threshold", WM8753_NGATE, 3, 31, 0),
-SOC_ENUM("ALC NG Type", wm8753_enum[4]),
-SOC_SINGLE("ALC NG Switch", WM8753_NGATE, 0, 1, 0),
+SOC_SINGLE("ALC Capture Target Volume", WM8753_ALC1, 0, 7, 0),
+SOC_SINGLE("ALC Capture Max Volume", WM8753_ALC1, 4, 7, 0),
+SOC_ENUM("ALC Capture Function", wm8753_enum[3]),
+SOC_SINGLE("ALC Capture ZC Switch", WM8753_ALC2, 8, 1, 0),
+SOC_SINGLE("ALC Capture Hold Time", WM8753_ALC2, 0, 15, 1),
+SOC_SINGLE("ALC Capture Decay Time", WM8753_ALC3, 4, 15, 1),
+SOC_SINGLE("ALC Capture Attack Time", WM8753_ALC3, 0, 15, 0),
+SOC_SINGLE("ALC Capture NG Threshold", WM8753_NGATE, 3, 31, 0),
+SOC_ENUM("ALC Capture NG Type", wm8753_enum[4]),
+SOC_SINGLE("ALC Capture NG Switch", WM8753_NGATE, 0, 1, 0),
 
 SOC_ENUM("3D Function", wm8753_enum[5]),
 SOC_ENUM("3D Upper Cut-off", wm8753_enum[6]),
@@ -452,19 +403,19 @@ SOC_ENUM("3D Lower Cut-off", wm8753_enum
 SOC_SINGLE("3D Volume", WM8753_3D, 1, 15, 0),
 SOC_SINGLE("3D Switch", WM8753_3D, 0, 1, 0),
 
-SOC_SINGLE("ADC 6dB Attenuate", WM8753_ADCTL1, 2, 1, 0),
-SOC_SINGLE("DAC 6dB Attenuate", WM8753_ADCTL1, 1, 1, 0),
+SOC_SINGLE("Capture 6dB Attenuate", WM8753_ADCTL1, 2, 1, 0),
+SOC_SINGLE("Playback 6dB Attenuate", WM8753_ADCTL1, 1, 1, 0),
 
 SOC_ENUM("De-emphasis", wm8753_enum[8]),
-SOC_ENUM("DAC Mono Mix", wm8753_enum[9]),
-SOC_ENUM("DAC Phase", wm8753_enum[10]),
+SOC_ENUM("Playback Mono Mix", wm8753_enum[9]),
+SOC_ENUM("Playback Phase", wm8753_enum[10]),
 
-SOC_SINGLE("Mic 2 Volume", WM8753_INCTL1, 7, 3, 0),
-SOC_SINGLE("Mic 1 Volume", WM8753_INCTL1, 5, 3, 0),
+SOC_SINGLE("Mic2 Capture Volume", WM8753_INCTL1, 7, 3, 0),
+SOC_SINGLE("Mic1 Capture Volume", WM8753_INCTL1, 5, 3, 0),
 };
 
 /* add non dpm controls */
-static int wm8753_add_controls(snd_soc_codec_t *codec)
+static int wm8753_add_controls(struct snd_soc_codec *codec)
 {
 	int err, i;
 
@@ -481,97 +432,97 @@ static int wm8753_add_controls(snd_soc_c
 
 /* Left Mixer */
 static const snd_kcontrol_new_t wm8753_left_mixer_controls[] = {
-SOC_DPM_SINGLE("Playback Voice Switch", WM8753_LOUTM2, 8, 1, 0),
-SOC_DPM_SINGLE("Sidetone Switch", WM8753_LOUTM2, 7, 1, 0),
-SOC_DPM_SINGLE("Playback Left Switch", WM8753_LOUTM1, 8, 1, 0),
-SOC_DPM_SINGLE("Capture Mux Switch", WM8753_LOUTM1, 7, 1, 0),
+SOC_DPM_SINGLE("Voice Playback Switch", WM8753_LOUTM2, 8, 1, 0),
+SOC_DPM_SINGLE("Sidetone Playback Switch", WM8753_LOUTM2, 7, 1, 0),
+SOC_DPM_SINGLE("Left Playback Switch", WM8753_LOUTM1, 8, 1, 0),
+SOC_DPM_SINGLE("Bypass Playback Switch", WM8753_LOUTM1, 7, 1, 0),
 };
 
 /* Right mixer */
 static const snd_kcontrol_new_t wm8753_right_mixer_controls[] = {
-SOC_DPM_SINGLE("Playback Voice Switch", WM8753_ROUTM2, 8, 1, 0),
-SOC_DPM_SINGLE("Sidetone Switch", WM8753_ROUTM2, 7, 1, 0),
-SOC_DPM_SINGLE("Playback Right Switch", WM8753_ROUTM1, 8, 1, 0),
-SOC_DPM_SINGLE("Capture Mux Switch", WM8753_ROUTM1, 7, 1, 0),
+SOC_DPM_SINGLE("Voice Playback Switch", WM8753_ROUTM2, 8, 1, 0),
+SOC_DPM_SINGLE("Sidetone Playback Switch", WM8753_ROUTM2, 7, 1, 0),
+SOC_DPM_SINGLE("Right Playback Switch", WM8753_ROUTM1, 8, 1, 0),
+SOC_DPM_SINGLE("Bypass Playback Switch", WM8753_ROUTM1, 7, 1, 0),
 };
 
 /* Mono mixer */
 static const snd_kcontrol_new_t wm8753_mono_mixer_controls[] = {
-SOC_DPM_SINGLE("Playback Left Switch", WM8753_MOUTM1, 8, 1, 0),
-SOC_DPM_SINGLE("Playback Right Switch", WM8753_MOUTM2, 8, 1, 0),
-SOC_DPM_SINGLE("Playback Voice Switch", WM8753_MOUTM2, 4, 1, 0),
-SOC_DPM_SINGLE("Sidetone Switch", WM8753_MOUTM2, 7, 1, 0),
-SOC_DPM_SINGLE("Capture Mux Switch", WM8753_ROUTM1, 7, 1, 0),
+SOC_DPM_SINGLE("Left Playback Switch", WM8753_MOUTM1, 8, 1, 0),
+SOC_DPM_SINGLE("Right Playback Switch", WM8753_MOUTM2, 8, 1, 0),
+SOC_DPM_SINGLE("Voice Playback Switch", WM8753_MOUTM2, 4, 1, 0),
+SOC_DPM_SINGLE("Sidetone Playback Switch", WM8753_MOUTM2, 7, 1, 0),
+SOC_DPM_SINGLE("Bypass Playback Switch", WM8753_ROUTM1, 7, 1, 0),
 };
 
 /* Mono 2 Mux */
 static const snd_kcontrol_new_t wm8753_mono2_controls =
-SOC_DPM_ENUM("Source", wm8753_enum[17]);
+SOC_DPM_ENUM("Route", wm8753_enum[17]);
 
 /* Out 3 Mux */
 static const snd_kcontrol_new_t wm8753_out3_controls =
-SOC_DPM_ENUM("Source", wm8753_enum[18]);
+SOC_DPM_ENUM("Route", wm8753_enum[18]);
 
 /* Out 4 Mux */
 static const snd_kcontrol_new_t wm8753_out4_controls =
-SOC_DPM_ENUM("Source", wm8753_enum[19]);
+SOC_DPM_ENUM("Route", wm8753_enum[19]);
 
 /* ADC Mono Mix */
 static const snd_kcontrol_new_t wm8753_adc_mono_controls =
-SOC_DPM_ENUM("Source", wm8753_enum[22]);
+SOC_DPM_ENUM("Route", wm8753_enum[22]);
 
-/* ST Record mixer */
+/* Record mixer */
 static const snd_kcontrol_new_t wm8753_record_mixer_controls[] = {
-SOC_DPM_SINGLE("Voice Switch", WM8753_RECMIX2, 3, 1, 0),
-SOC_DPM_SINGLE("Left Switch", WM8753_RECMIX1, 3, 1, 0),
-SOC_DPM_SINGLE("Right Switch", WM8753_RECMIX1, 7, 1, 0),
+SOC_DPM_SINGLE("Voice Capture Switch", WM8753_RECMIX2, 3, 1, 0),
+SOC_DPM_SINGLE("Left Capture Switch", WM8753_RECMIX1, 3, 1, 0),
+SOC_DPM_SINGLE("Right Capture Switch", WM8753_RECMIX1, 7, 1, 0),
 };
 
 /* Left ADC mux */
 static const snd_kcontrol_new_t wm8753_adc_left_controls =
-SOC_DPM_ENUM("Source", wm8753_enum[21]);
+SOC_DPM_ENUM("Route", wm8753_enum[21]);
 
 /* Right ADC mux */
 static const snd_kcontrol_new_t wm8753_adc_right_controls =
-SOC_DPM_ENUM("Source", wm8753_enum[20]);
+SOC_DPM_ENUM("Route", wm8753_enum[20]);
 
 /* MIC mux */
 static const snd_kcontrol_new_t wm8753_mic_mux_controls =
-SOC_DPM_ENUM("Source", wm8753_enum[16]);
+SOC_DPM_ENUM("Route", wm8753_enum[16]);
 
 /* ALC mixer */
 static const snd_kcontrol_new_t wm8753_alc_mixer_controls[] = {
-SOC_DPM_SINGLE("Line Switch", WM8753_INCTL2, 3, 1, 0),
-SOC_DPM_SINGLE("Mic 2 Switch", WM8753_INCTL2, 2, 1, 0),
-SOC_DPM_SINGLE("Mic 1 Switch", WM8753_INCTL2, 1, 1, 0),
-SOC_DPM_SINGLE("Rx Switch", WM8753_INCTL2, 0, 1, 0),
+SOC_DPM_SINGLE("Line Capture Switch", WM8753_INCTL2, 3, 1, 0),
+SOC_DPM_SINGLE("Mic2 Capture Switch", WM8753_INCTL2, 2, 1, 0),
+SOC_DPM_SINGLE("Mic1 Capture Switch", WM8753_INCTL2, 1, 1, 0),
+SOC_DPM_SINGLE("Rx Capture Switch", WM8753_INCTL2, 0, 1, 0),
 };
 
 /* Left Line mux */
 static const snd_kcontrol_new_t wm8753_line_left_controls =
-SOC_DPM_ENUM("Source", wm8753_enum[14]);
+SOC_DPM_ENUM("Route", wm8753_enum[14]);
 
 /* Right Line mux */
 static const snd_kcontrol_new_t wm8753_line_right_controls =
-SOC_DPM_ENUM("Source", wm8753_enum[13]);
+SOC_DPM_ENUM("Route", wm8753_enum[13]);
 
 /* Mono Line mux */
 static const snd_kcontrol_new_t wm8753_line_mono_controls =
-SOC_DPM_ENUM("Source", wm8753_enum[12]);
+SOC_DPM_ENUM("Route", wm8753_enum[12]);
 
 /* Line mux and mixer */
 static const snd_kcontrol_new_t wm8753_line_mux_mix_controls =
-SOC_DPM_ENUM("Source", wm8753_enum[11]);
+SOC_DPM_ENUM("Route", wm8753_enum[11]);
 
 /* Rx mux and mixer */
 static const snd_kcontrol_new_t wm8753_rx_mux_mix_controls =
-SOC_DPM_ENUM("Source", wm8753_enum[15]);
+SOC_DPM_ENUM("Route", wm8753_enum[15]);
 
 /* Mic Selector Mux */
 static const snd_kcontrol_new_t wm8753_mic_sel_mux_controls =
-SOC_DPM_ENUM("Source", wm8753_enum[25]);
+SOC_DPM_ENUM("Route", wm8753_enum[25]);
 
-static const snd_soc_dpm_widget_t wm8753_dpm_widgets[] = {
+static const struct snd_soc_dpm_widget wm8753_dpm_widgets[] = {
 SND_SOC_DPM_CLOCK("WM8753 Clock", WM8753_PWR1, 0, 1),
 SND_SOC_DPM_MIXER("Left Mixer", WM8753_PWR4, 0, 0, &wm8753_left_mixer_controls[0], 
 	ARRAY_SIZE(wm8753_left_mixer_controls)),
@@ -602,7 +553,7 @@ SND_SOC_DPM_OUTPUT("OUT3"),
 SND_SOC_DPM_MUX("Out4 Mux", -1, 0, 0, &wm8753_out4_controls),
 SND_SOC_DPM_VOLUME("Out 4", WM8753_PWR3, 3, 0, NULL, 0),
 SND_SOC_DPM_OUTPUT("OUT4"),
-SND_SOC_DPM_MIXER("Capture ST Mixer", WM8753_PWR4, 3, 0, &wm8753_record_mixer_controls[0], 
+SND_SOC_DPM_MIXER("Playback Mixer", WM8753_PWR4, 3, 0, &wm8753_record_mixer_controls[0], 
 	ARRAY_SIZE(wm8753_record_mixer_controls)),
 SND_SOC_DPM_ADC("Left ADC", "Left Voice Capture", WM8753_PWR2, 3, 0, NULL, 0),
 SND_SOC_DPM_ADC("Right ADC", "Right Voice Capture", WM8753_PWR2, 2, 0, NULL, 0),
@@ -635,7 +586,7 @@ SND_SOC_DPM_INPUT("MIC2N"),
 SND_SOC_DPM_INPUT("MIC2"),
 };
 
-static int wm8753_add_widgets(snd_soc_codec_t *codec)
+static int wm8753_add_widgets(struct snd_soc_codec *codec)
 {
 	int i;
 	
@@ -646,23 +597,23 @@ static int wm8753_add_widgets(snd_soc_co
 	/* set up audio path interconnects */
 	
 	/* left mixer */
-	snd_soc_dpm_connect_input(codec, "Left Mixer", "Playback Left Switch", "Left DAC");
-	snd_soc_dpm_connect_input(codec, "Left Mixer", "Playback Voice Switch", "Voice DAC");
-	snd_soc_dpm_connect_input(codec, "Left Mixer", "Sidetone Switch", "MIC ST Mux");
-	snd_soc_dpm_connect_input(codec, "Left Mixer", "Capture Mux Switch", "Line Left Mux");
+	snd_soc_dpm_connect_input(codec, "Left Mixer", "Left Playback Switch", "Left DAC");
+	snd_soc_dpm_connect_input(codec, "Left Mixer", "Voice Playback Switch", "Voice DAC");
+	snd_soc_dpm_connect_input(codec, "Left Mixer", "Sidetone Playback Switch", "MIC ST Mux");
+	snd_soc_dpm_connect_input(codec, "Left Mixer", "Bypass Playback Switch", "Line Left Mux");
 	
 	/* right mixer */
-	snd_soc_dpm_connect_input(codec, "Right Mixer", "Playback Right Switch", "Right DAC");
-	snd_soc_dpm_connect_input(codec, "Right Mixer", "Playback Voice Switch", "Voice DAC");
-	snd_soc_dpm_connect_input(codec, "Right Mixer", "Sidetone Switch", "MIC ST Mux");
-	snd_soc_dpm_connect_input(codec, "Right Mixer", "Capture Mux Switch", "Line Right Mux");
+	snd_soc_dpm_connect_input(codec, "Right Mixer", "Right Playback Switch", "Right DAC");
+	snd_soc_dpm_connect_input(codec, "Right Mixer", "Voice Playback Switch", "Voice DAC");
+	snd_soc_dpm_connect_input(codec, "Right Mixer", "Sidetone Playback Switch", "MIC ST Mux");
+	snd_soc_dpm_connect_input(codec, "Right Mixer", "Bypass Playback Switch", "Line Right Mux");
 	
 	/* mono mixer */
-	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Playback Voice Switch", "Voice DAC");
-	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Playback Left Switch", "Left DAC");
-	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Playback Right Switch", "Right DAC");
-	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Sidetone Switch", "MIC ST Mux");
-	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Capture Mux Switch", "Line Mono Mux");
+	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Voice Playback Switch", "Voice DAC");
+	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Left Playback Switch", "Left DAC");
+	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Right Playback Switch", "Right DAC");
+	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Sidetone Playback Switch", "MIC ST Mux");
+	snd_soc_dpm_connect_input(codec, "Mono Mixer", "Bypass Playback Switch", "Line Mono Mux");
 	
 	/* left out */
 	snd_soc_dpm_connect_input(codec, "Left Out 1", NULL, "Left Mixer");
@@ -704,10 +655,10 @@ static int wm8753_add_widgets(snd_soc_co
 	snd_soc_dpm_connect_input(codec, "Out 4", NULL, "Out4 Mux");
 	snd_soc_dpm_connect_input(codec, "OUT4", NULL, "Out 4");
 	
-	/* record mixer - Capture ST */
-	snd_soc_dpm_connect_input(codec, "Capture ST Mixer", "Left Switch", "Left Mixer");
-	snd_soc_dpm_connect_input(codec, "Capture ST Mixer", "Voice Switch", "Mono Mixer");
-	snd_soc_dpm_connect_input(codec, "Capture ST Mixer", "Right Switch", "Right Mixer");
+	/* record mixer  */
+	snd_soc_dpm_connect_input(codec, "Playback Mixer", "Left Capture Switch", "Left Mixer");
+	snd_soc_dpm_connect_input(codec, "Playback Mixer", "Voice Capture Switch", "Mono Mixer");
+	snd_soc_dpm_connect_input(codec, "Playback Mixer", "Right Capture Switch", "Right Mixer");
 	
 	/* Mic/SideTone Mux */
 	snd_soc_dpm_connect_input(codec, "Mic Mux", "Left PGA", "Left Capture Volume");
@@ -747,10 +698,10 @@ static int wm8753_add_widgets(snd_soc_co
 	snd_soc_dpm_connect_input(codec, "Right Capture Volume", NULL, "Mic 2 Volume");
 
 	/* ALC Mixer */
-	snd_soc_dpm_connect_input(codec, "ALC Mixer", "Line Switch", "Line Mixer");
-	snd_soc_dpm_connect_input(codec, "ALC Mixer", "Mic 2 Switch", "Mic 2 Volume");
-	snd_soc_dpm_connect_input(codec, "ALC Mixer", "Mic 1 Switch", "Mic 1 Volume");
-	snd_soc_dpm_connect_input(codec, "ALC Mixer", "Rx Switch", "Rx Mixer");
+	snd_soc_dpm_connect_input(codec, "ALC Mixer", "Line Capture Switch", "Line Mixer");
+	snd_soc_dpm_connect_input(codec, "ALC Mixer", "Mic2 Capture Switch", "Mic 2 Volume");
+	snd_soc_dpm_connect_input(codec, "ALC Mixer", "Mic1 Capture Switch", "Mic 1 Volume");
+	snd_soc_dpm_connect_input(codec, "ALC Mixer", "Rx Capture Switch", "Rx Mixer");
 	
 	/* Line Left Mux */
 	snd_soc_dpm_connect_input(codec, "Line Left Mux", "Line 1", "LINE1");
@@ -808,16 +759,16 @@ static int wm8753_add_widgets(snd_soc_co
  * set the PLL2 to generate 12.288MHz and then div by 6 to generate
  * DAC/ADC clocks from 12MHz MCLK 
  */
-static u32 wm8753_config_pll(int pll, u32 speed)
+static u32 wm8753_config_pll(struct snd_soc_codec *codec, int pll, u32 speed)
 {
 	u16 clk;
 
     if (pll == 1) {
-		clk = wm8753_read_reg_cache(WM8753_CLOCK) & 0x0010;
+		clk = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x0010;
         if (!speed) {
             /* disable PLL1  */
-            wm8753_2w_write(wm8753_i2c, WM8753_PLL1CTL1, 0x0026);
-			wm8753_2w_write(wm8753_i2c, WM8753_CLOCK, clk);
+            wm8753_write(codec, WM8753_PLL1CTL1, 0x0026);
+			wm8753_write(codec, WM8753_CLOCK, clk);
         } else {
             u16 value = 0;
             int i = 0;   
@@ -830,33 +781,33 @@ static u32 wm8753_config_pll(int pll, u3
 			
 			/* do we need to enable the PLL ? */
 			if (!pll_div[i].n) {
-				wm8753_2w_write(wm8753_i2c, WM8753_CLOCK, 0x0);
+				wm8753_write(codec, WM8753_CLOCK, 0x0);
 				return 0;
 			}
     
             /* set up N and K PLL divisor ratios */
             /* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */
             value = (pll_div[i].n << 5) + ((pll_div[i].k & 0x3c0000) >> 18);  
-            wm8753_2w_write(wm8753_i2c, WM8753_PLL1CTL2, value);
+            wm8753_write(codec, WM8753_PLL1CTL2, value);
      
             /* bits 8:0 = PLL_K[17:9] */
             value = (pll_div[i].k & 0x03fe00) >> 9;
-            wm8753_2w_write(wm8753_i2c, WM8753_PLL1CTL3, value);
+            wm8753_write(codec, WM8753_PLL1CTL3, value);
     
             /* bits 8:0 = PLL_K[8:0] */
             value = pll_div[i].k & 0x0001ff;
-            wm8753_2w_write(wm8753_i2c, WM8753_PLL1CTL4, value);
+            wm8753_write(codec, WM8753_PLL1CTL4, value);
      
             /* set PLL1 as input and enable */
-            wm8753_2w_write(wm8753_i2c, WM8753_PLL1CTL1, 0x0027);
-			wm8753_2w_write(wm8753_i2c, WM8753_CLOCK, clk | 0x0010);
+            wm8753_write(codec, WM8753_PLL1CTL1, 0x0027);
+			wm8753_write(codec, WM8753_CLOCK, clk | 0x0010);
         }
     } else {
-		clk = wm8753_read_reg_cache(WM8753_CLOCK) & 0x0008;
+		clk = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x0008;
         if (!speed) {
             /* disable PLL2  */
-            wm8753_2w_write(wm8753_i2c, WM8753_PLL2CTL1, 0x0026);
-			wm8753_2w_write(wm8753_i2c, WM8753_CLOCK, clk);
+            wm8753_write(codec, WM8753_PLL2CTL1, 0x0026);
+			wm8753_write(codec, WM8753_CLOCK, clk);
         } else {
             u16 value = 0;
             int i = 0;   
@@ -869,26 +820,26 @@ static u32 wm8753_config_pll(int pll, u3
 			
     		/* do we need to enable the PLL ? */
 			if (!pll_div[i].n) {
-				wm8753_2w_write(wm8753_i2c, WM8753_CLOCK, 0x0);
+				wm8753_write(codec, WM8753_CLOCK, 0x0);
 				return 0;
 			}
 			
             /* set up N and K PLL divisor ratios */
             /* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */
             value = (pll_div[i].n << 5) + ((pll_div[i].k & 0x3c0000) >> 18);  
-            wm8753_2w_write(wm8753_i2c, WM8753_PLL2CTL2, value);
+            wm8753_write(codec, WM8753_PLL2CTL2, value);
      
             /* bits 8:0 = PLL_K[17:9] */
             value = (pll_div[i].k & 0x03fe00) >> 9;
-            wm8753_2w_write(wm8753_i2c, WM8753_PLL2CTL3, value);
+            wm8753_write(codec, WM8753_PLL2CTL3, value);
     
             /* bits 8:0 = PLL_K[8:0] */
             value = pll_div[i].k & 0x0001ff;
-            wm8753_2w_write(wm8753_i2c, WM8753_PLL2CTL4, value);
+            wm8753_write(codec, WM8753_PLL2CTL4, value);
      
             /* set PLL1 as input and enable */
-            wm8753_2w_write(wm8753_i2c, WM8753_PLL2CTL1, 0x0027);
-			wm8753_2w_write(wm8753_i2c, WM8753_CLOCK, clk | 0x0008);
+            wm8753_write(codec, WM8753_PLL2CTL1, 0x0027);
+			wm8753_write(codec, WM8753_CLOCK, clk | 0x0008);
         }
     }
 	return speed;
@@ -896,14 +847,15 @@ static u32 wm8753_config_pll(int pll, u3
 
 static int wm8753_pcm_voice_prepare(snd_pcm_substream_t *substream)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
+	struct snd_soc_codec *codec = pcm_c->codec;
 	u16 voice = 0, ioctl, clock, srate;
 	
 	/* enable PLL */
-	wm8753_config_pll(2, pcm_c->hw_runtime.priv1);
+	wm8753_config_pll(codec, 2, pcm_c->hw_runtime.priv1);
 	
 	/* set master/slave audio interface */
-	ioctl = wm8753_read_reg_cache(WM8753_IOCTL) & 0x01f1;
+	ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x01f1;
 	switch(pcm_c->hw_runtime.hformat & SND_SOC_CLOCK_MASK) {
 		case SND_SOC_HWFMT_CBM_CFM:
 			voice |= 0x0040;
@@ -948,13 +900,13 @@ static int wm8753_pcm_voice_prepare(snd_
 	}
 	
 	/* set rate */
-	clock = wm8753_read_reg_cache(WM8753_CLOCK) & 0x003f;
+	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x003f;
 	clock |= (pcm_c->hw_runtime.priv2 & 0xff00) >> 2;
-	wm8753_2w_write(wm8753_i2c, WM8753_CLOCK, clock);
+	wm8753_write(codec, WM8753_CLOCK, clock);
 
-	srate = wm8753_read_reg_cache(WM8753_SRATE1) & 0x017f;
+	srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f;
 	srate |= (pcm_c->hw_runtime. priv2 & 0xff) << 7;
-	wm8753_2w_write(wm8753_i2c, WM8753_SRATE1, srate);
+	wm8753_write(codec, WM8753_SRATE1, srate);
 	
 	/* clock inversion */
 	switch(pcm_c->hw_runtime.hformat & SND_SOC_INV_MASK) {
@@ -968,21 +920,22 @@ static int wm8753_pcm_voice_prepare(snd_
 			voice |= 0x0010;
 			break;
 	}
-	wm8753_2w_write(wm8753_i2c, WM8753_IOCTL, ioctl);
-	wm8753_2w_write(wm8753_i2c, WM8753_PCM, voice);
+	wm8753_write(codec, WM8753_IOCTL, ioctl);
+	wm8753_write(codec, WM8753_PCM, voice);
 	return 0;
 }
 
 static int wm8753_pcm_hifi_prepare(snd_pcm_substream_t *substream)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
+	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(1, pcm_c->hw_runtime.priv1);
+	wm8753_config_pll(codec, 1, pcm_c->hw_runtime.priv1);
 	
 	/* set master/slave audio interface */
-	ioctl = wm8753_read_reg_cache(WM8753_IOCTL) & 0x00f2;
+	ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x00f2;
 	switch(pcm_c->hw_runtime.hformat & SND_SOC_CLOCK_MASK) {
 		case SND_SOC_HWFMT_CBM_CFM:
 			hifi |= 0x0040;
@@ -1027,7 +980,7 @@ static int wm8753_pcm_hifi_prepare(snd_p
 	}
 	
 	/* set rate */
-	srate = wm8753_read_reg_cache(WM8753_SRATE2) & 0x01c7;
+	srate = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x01c7;
 	switch ((pcm_c->hw_runtime.priv2 & 0xff00) >> 8){
 		case 1:
 			break;
@@ -1044,9 +997,9 @@ static int wm8753_pcm_hifi_prepare(snd_p
 			srate |= (0x4 << 3);
 			break;
 	}		
-	wm8753_2w_write(wm8753_i2c, WM8753_SRATE2, srate);
+	wm8753_write(codec, WM8753_SRATE2, srate);
 	srate = (pcm_c->hw_runtime. priv2 & 0xff) << 1;
-	wm8753_2w_write(wm8753_i2c, WM8753_SRATE1, srate);
+	wm8753_write(codec, WM8753_SRATE1, srate);
 	
 	/* clock inversion */
 	switch(pcm_c->hw_runtime.hformat & SND_SOC_INV_MASK) {
@@ -1060,8 +1013,8 @@ static int wm8753_pcm_hifi_prepare(snd_p
 			hifi |= 0x0010;
 			break;
 	}
-	wm8753_2w_write(wm8753_i2c, WM8753_IOCTL, ioctl | 0x0008);
-	wm8753_2w_write(wm8753_i2c, WM8753_HIFI, hifi);
+	wm8753_write(codec, WM8753_IOCTL, ioctl | 0x0008);
+	wm8753_write(codec, WM8753_HIFI, hifi);
 	return 0;
 }
 
@@ -1069,37 +1022,37 @@ static void wm8753_device_release(struct
 {
 }
 
-static int wm8753_dpm_event(snd_soc_codec_t *codec, int event)
+static int wm8753_dpm_event(struct snd_soc_codec *codec, int event)
 {
-	u16 pwr_reg = wm8753_read_reg_cache(WM8753_PWR1) & 0xfe3f;
-	u16 dac_reg = wm8753_read_reg_cache(WM8753_DAC) & 0xfff7;
+	u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3f;
+	u16 dac_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7;
 
 	switch (event) {
 		case SNDRV_CTL_POWER_D0: /* full On */
 			/* set vmid to 50k and unmute dac */
-			wm8753_2w_write(wm8753_i2c, WM8753_PWR1, pwr_reg | 0x00c0);
-			wm8753_2w_write(wm8753_i2c, WM8753_DAC, dac_reg);
+			wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
+			wm8753_write(codec, WM8753_DAC, dac_reg);
 			break;
 		case SNDRV_CTL_POWER_D1: /* partial On */
 		case SNDRV_CTL_POWER_D2: /* partial On */
 			/* set vmid to 5k for quick power up */
-			wm8753_2w_write(wm8753_i2c, WM8753_PWR1, pwr_reg | 0x01c0);
+			wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c0);
 			break;
 		case SNDRV_CTL_POWER_D3hot: /* Off, with power */
 			/* mute dac and set vmid to 500k, enable VREF */
-			wm8753_2w_write(wm8753_i2c, WM8753_DAC, dac_reg | 0x0008);
-			wm8753_2w_write(wm8753_i2c, WM8753_PWR1, pwr_reg | 0x0140);
+			wm8753_write(codec, WM8753_DAC, dac_reg | 0x0008);
+			wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0140);
 			break;
 		case SNDRV_CTL_POWER_D3cold: /* Off, without power */
-			wm8753_2w_write(wm8753_i2c, WM8753_DAC, dac_reg | 0x0008);
-			wm8753_2w_write(wm8753_i2c, WM8753_PWR1, 0x0001);
+			wm8753_write(codec, WM8753_DAC, dac_reg | 0x0008);
+			wm8753_write(codec, WM8753_PWR1, 0x0001);
 			break;
 	}
 	
 	return 0;
 }
 
-static snd_soc_pcm_codec_t wm8753_pcm_clients[] = {
+static struct snd_soc_pcm_codec wm8753_pcm_clients[] = {
 {	.name = "WM8753 Voice",
 	.playback = {
 		.sname = "Voice Playback",
@@ -1142,41 +1095,39 @@ static snd_soc_pcm_codec_t wm8753_pcm_cl
 		.hmodes = &wm8753_hifi[0],},},
 };
 
-static snd_soc_codec_t wm8753_soc_codec;
-
 /*
  * initialise the WM8753 driver
  * register the mixer and dsp interfaces with the kernel 
  */
-static int wm8753_probe(snd_soc_codec_t *codec)
+static int wm8753_probe(struct snd_soc_codec *codec)
 {
 	int reg;
 
-	wm8753_reset(wm8753_i2c);
+	wm8753_reset(codec);
 	
 	/* set vmid to 500k - low power standy */
 	wm8753_dpm_event(codec, SNDRV_CTL_POWER_D3hot);
 
 	/* set the update bits */
-	reg = wm8753_read_reg_cache(WM8753_LDAC);
-	wm8753_2w_write(wm8753_i2c, WM8753_LDAC, reg | 0x0100);
-	reg = wm8753_read_reg_cache(WM8753_RDAC);
-	wm8753_2w_write(wm8753_i2c, WM8753_RDAC, reg | 0x0100);
-	reg = wm8753_read_reg_cache(WM8753_LOUT1V);
-	wm8753_2w_write(wm8753_i2c, WM8753_LOUT1V, reg | 0x0100);
-	reg = wm8753_read_reg_cache(WM8753_ROUT1V);
-	wm8753_2w_write(wm8753_i2c, WM8753_ROUT1V, reg | 0x0100);
-	reg = wm8753_read_reg_cache(WM8753_LOUT2V);
-	wm8753_2w_write(wm8753_i2c, WM8753_LOUT2V, reg | 0x0100);
-	reg = wm8753_read_reg_cache(WM8753_ROUT2V);
-	wm8753_2w_write(wm8753_i2c, WM8753_ROUT2V, reg | 0x0100);
-	reg = wm8753_read_reg_cache(WM8753_LINVOL);
-	wm8753_2w_write(wm8753_i2c, WM8753_LINVOL, reg | 0x0100);
-	reg = wm8753_read_reg_cache(WM8753_RINVOL);
-	wm8753_2w_write(wm8753_i2c, WM8753_RINVOL, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_LDAC);
+	wm8753_write(codec, WM8753_LDAC, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_RDAC);
+	wm8753_write(codec, WM8753_RDAC, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V);
+	wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V);
+	wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V);
+	wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V);
+	wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_LINVOL);
+	wm8753_write(codec, WM8753_LINVOL, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
+	wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
 
-	wm8753_add_controls(&wm8753_soc_codec);
-	wm8753_add_widgets(&wm8753_soc_codec);
+	wm8753_add_controls(codec);
+	wm8753_add_widgets(codec);
 
 	return 0;
 }
@@ -1184,29 +1135,92 @@ static int wm8753_probe(snd_soc_codec_t 
 /* 
  * unregister interfaces and clean up
  */
-static void wm8753_remove(snd_soc_codec_t *codec)
+static void wm8753_remove(struct snd_soc_codec *codec)
 {
 	/* power down chip */
 	wm8753_dpm_event(codec, SNDRV_CTL_POWER_D3cold);
 }
 
-static snd_soc_codec_t wm8753_soc_codec = {
-	.name = "WM8753",
-	.longname = "WM8753 Portable Codec",
-	.owner = THIS_MODULE,
-	.pdev = {
-		.name		= "soc-wm8753",
-		.id		= -1,
-		.dev		= {.release = wm8753_device_release},
-	},
-	.probe = wm8753_probe,
-	.remove = wm8753_remove,
-	.read = wm8753_read_reg_cache,
-	.write = wm8753_write,
-	.dpm_event = wm8753_dpm_event,
-	.pcms = wm8753_pcm_clients,
-	.npcms = ARRAY_SIZE(wm8753_pcm_clients),
-};	
+/*
+ * 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;
+
+	client_template.adapter = adap;
+	client_template.addr = addr;
+	
+	if ((codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+ 
+	memcpy(&codec->i2c, &client_template, sizeof(struct i2c_client));
+
+	if((ret = i2c_attach_client(&codec->i2c)) < 0) {
+		err("failed to attach codec at addr %x\n", addr);
+		kfree(codec);
+	}
+
+	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(codec->reg_cache);
+		kfree(codec);
+	}
+
+	return ret;
+}
+
+static int wm8753_i2c_detach(struct i2c_client *client)
+{
+	struct snd_soc_codec *codec = container_of(client, struct snd_soc_codec, i2c);
+
+	i2c_detach_client(client);
+	snd_soc_unregister_codec(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 int __init wm8753_init(void)
 {	
@@ -1214,28 +1228,14 @@ static int __init wm8753_init(void)
 	
 	info("WM8753 Audio Codec %s", WM8753_VERSION);
 
-	if ((ret = i2c_add_driver(&wm8753_i2c_driver)) != 0) {
+	if ((ret = i2c_add_driver(&wm8753_i2c_driver)) != 0)
 		err("can't add i2c driver");
-		return ret;
-	}
 	
-	if(!wm8753_i2c) {
-		err("can't find chip on i2c bus");
-		i2c_del_driver(&wm8753_i2c_driver);
-		return -ENODEV;
-	}
-	
-	if((ret = snd_soc_register_codec(&wm8753_soc_codec)) < 0) {
-		err("can't register driver");
-		i2c_del_driver(&wm8753_i2c_driver);
-		return ret;
-	}
 	return ret;
 }
 
 static void __exit wm8753_exit(void)
 {
-	snd_soc_unregister_codec(&wm8753_soc_codec);
 	i2c_del_driver(&wm8753_i2c_driver);
 }
 
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
new file mode 100644
index 0000000..f5c6fcb
--- /dev/null
+++ b/sound/soc/codecs/wm8971.c
@@ -0,0 +1,766 @@
+/*
+ * wm8971.c  --  WM8971 SoC Audio driver
+ *
+ * Copyright 2005 Lab126, Inc.
+ * 
+ * Author: Kenneth Kiraly <kiraly@lab126.com>
+ *
+ * Based on wm8753.c by Liam Girdwood
+ *
+ *  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/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/pm.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 "wm8971.h"
+
+#define AUDIO_NAME "wm8971"
+#define WM8971_VERSION "0.2"
+
+
+#define PFX AUDIO_NAME
+#undef	WM8971_DEBUG
+
+#ifdef WM8971_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)
+
+
+#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
+
+/*
+ * wm8971 register cache
+ * We can't read the WM8971 register space when we 
+ * are using 2 wire for device control, so we cache them instead. 
+ */
+static const u16 wm8971_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 */
+	0x0050, 0x0050, 0x0050, 0x0050,  /* 36 */
+	0x0079, 0x0079, 0x0079,          /* 40 */
+};
+
+#define WM8971_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 wm8971_audio[] = {
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 8000,   64, 0x000c},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 8000,   96, 0x000e},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 8000,  128, 0x004c},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 8000,  192, 0x004e},
+
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 11025, 64,  0x0030},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 11025, 96,  0x0032},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 11025, 128, 0x0070},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 11025, 192, 0x0072},
+
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 12000, 64,  0x0010},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 12000, 96,  0x0012},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 12000, 128, 0x0050},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 12000, 192, 0x0052},
+
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 16000, 64,  0x0014},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 16000, 96,  0x0016},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 16000, 128, 0x0054},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 16000, 192, 0x0056},
+
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 22050, 64,  0x0034},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 22050, 96,  0x0036},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 22050, 128, 0x0074},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 22050, 192, 0x0076},
+
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 24000, 64,  0x0038},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 24000, 96,  0x003a},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 24000, 128, 0x0078},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 24000, 192, 0x007a},
+
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 32000,  64, 0x0018},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 32000,  96, 0x001a},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 32000, 128, 0x0058},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 32000, 192, 0x005a},
+
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 44100,  64, 0x0020},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 44100,  96, 0x0022},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 44100, 128, 0x0060},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 44100, 192, 0x0062},
+
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 48000,  64, 0x0000},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 48000,  96, 0x0002},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 48000, 128, 0x0040},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 48000, 192, 0x0042},
+
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 88200,  32, 0x003c},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 88200,  48, 0x003e},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 88200,  64, 0x007c},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 88200,  96, 0x007e},
+
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 96000,  32, 0x001c},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 96000,  48, 0x001e},
+	{WM8971_HWFMT, SND_SOC_HWBITS(16), 96000,  64, 0x005c},
+	{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)
+{
+	u16 *cache = codec->reg_cache;
+	if (reg < WM8971_REG_COUNT)
+		return cache[reg];
+
+	return -1;
+}
+
+static inline void wm8971_write_reg_cache(struct snd_soc_codec * codec, 
+	unsigned int reg, unsigned int value)
+{
+	u16 *cache = codec->reg_cache;
+	if (reg < WM8971_REG_COUNT)
+		cache[reg] = value;
+}
+
+static int wm8971_write(struct snd_soc_codec * codec, unsigned int reg,
+	unsigned int value)
+{
+	u8 data[2];
+
+	/* D15..D9 is WM8971 register offset, D8..D0 is register data */
+	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+	data[1] = value & 0x00ff;
+
+	wm8971_write_reg_cache (codec, reg, value);
+
+	return (i2c_master_send(&codec->i2c, data, 2) == 2) ? 0 : -1;
+}
+
+#define wm8971_reset(c)	wm8971_write(c, WM8971_RESET, 0)
+
+/* WM8971 Controls */
+static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" };
+static const char *wm8971_bass_filter[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" };
+static const char *wm8971_treble[] = { "8kHz", "4kHz" };
+static const char *wm8971_alc_func[] = { "Off", "Right", "Left", "Stereo" };
+static const char *wm8971_ng_type[] = { "Constant PGA Gain", "Mute ADC Output" };
+static const char *wm8971_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
+static const char* wm8971_mono_mux[] = {"Stereo", "Mono (Left)", "Mono (Right)", "Digital Mono"};
+static const char *wm8971_dac_phase[] = { "Non Inverted", "Inverted" };
+static const char* wm8971_lline_mux[] = {"Line", "NC", "NC", "PGA", "Differential"};
+static const char* wm8971_rline_mux[] = {"Line", "Mic", "NC", "PGA", "Differential"};
+static const char* wm8971_lpga_sel[] = {"Line", "NC", "NC", "Differential"};
+static const char* wm8971_rpga_sel[] = {"Line", "Mic", "NC", "Differential"};
+static const char* wm8971_adcpol[] = {"Normal", "L Invert", "R Invert", "L + R Invert"};
+
+static const struct soc_enum wm8971_enum[] = {
+	SOC_ENUM_SINGLE(WM8971_BASS, 7, 2, wm8971_bass),			/* 0 */
+	SOC_ENUM_SINGLE(WM8971_BASS, 6, 2, wm8971_bass_filter),
+	SOC_ENUM_SINGLE(WM8971_TREBLE, 6, 2, wm8971_treble),
+	SOC_ENUM_SINGLE(WM8971_ALC1, 7, 4, wm8971_alc_func),
+	SOC_ENUM_SINGLE(WM8971_NGATE, 1, 2, wm8971_ng_type),        /* 4 */
+	SOC_ENUM_SINGLE(WM8971_ADCDAC, 1, 4, wm8971_deemp),
+	SOC_ENUM_SINGLE(WM8971_ADCTL1, 4, 4, wm8971_mono_mux),
+	SOC_ENUM_SINGLE(WM8971_ADCTL1, 1, 1, wm8971_dac_phase),
+	SOC_ENUM_SINGLE(WM8971_LOUTM1, 0, 5, wm8971_lline_mux),     /* 8 */
+	SOC_ENUM_SINGLE(WM8971_ROUTM1, 0, 5, wm8971_rline_mux),
+	SOC_ENUM_SINGLE(WM8971_LADCIN, 6, 4, wm8971_lpga_sel),
+	SOC_ENUM_SINGLE(WM8971_RADCIN, 6, 4, wm8971_rpga_sel),
+	SOC_ENUM_SINGLE(WM8971_ADCDAC, 5, 4, wm8971_adcpol),        /* 12 */
+	SOC_ENUM_SINGLE(WM8971_ADCIN, 6, 4, wm8971_mono_mux),
+};
+
+
+static const snd_kcontrol_new_t wm8971_snd_controls[] = {
+	SOC_SINGLE("Left PCM Volume", WM8971_LDAC, 0, 255, 0),
+	SOC_SINGLE("Right PCM Volume", WM8971_RDAC, 0, 255, 0),
+
+	SOC_SINGLE("Left ADC Capture Volume", WM8971_LADC, 0, 255, 0),
+	SOC_SINGLE("Right ADC Capture Volume", WM8971_RADC, 0, 255, 0),
+
+	SOC_SINGLE("Left Out1 Playback Volume", WM8971_LOUT1V, 0, 127, 0),
+	SOC_SINGLE("Left Out1 Playback ZC Switch", WM8971_LOUT1V, 7, 1, 0),
+	SOC_SINGLE("Left Out2 Playback Volume", WM8971_LOUT2V, 0, 127, 0),
+	SOC_SINGLE("Left Out2 Playback ZC Switch", WM8971_LOUT2V, 7, 1, 0),
+
+	SOC_SINGLE("Right Out 1 Volume", WM8971_ROUT1V, 0, 127, 0),
+	SOC_SINGLE("Right Out 1 ZC Switch", WM8971_ROUT1V, 7, 1, 0),
+	SOC_SINGLE("Right Out 2 Volume", WM8971_ROUT2V, 0, 127, 0),
+	SOC_SINGLE("Right Out 2 ZC Switch", WM8971_ROUT2V, 7, 1, 0),
+
+	SOC_SINGLE("Left Bypass Left Playback Volume", WM8971_LOUTM1, 4, 7, 1),
+	SOC_SINGLE("Right Bypass Left Playback Volume", WM8971_LOUTM2, 4, 7, 1),
+
+	SOC_SINGLE("Left Bypass Right Playback Volume", WM8971_ROUTM1, 4, 7, 1),
+	SOC_SINGLE("Right Bypass Right Playback Volume", WM8971_ROUTM2, 4, 7, 1),
+
+	SOC_SINGLE("Left Bypass Mono Playback Volume", WM8971_MOUTM1, 4, 7, 1),
+	SOC_SINGLE("Right Bypass Mono Playback Volume", WM8971_MOUTM2, 4, 7, 1), 
+
+	SOC_SINGLE("Mono Playback Volume", WM8971_MOUTV, 0, 127, 0),
+	SOC_SINGLE("Mono Playback ZC Switch", WM8971_MOUTV, 7, 1, 0),
+
+	SOC_ENUM("Bass Boost", wm8971_enum[0]),
+	SOC_ENUM("Bass Filter", wm8971_enum[1]),
+	SOC_SINGLE("Bass Volume", WM8971_BASS, 0, 7, 1),
+
+	SOC_SINGLE("Treble Volume", WM8971_TREBLE, 0, 7, 0),
+	SOC_ENUM("Treble Cut-off", wm8971_enum[2]),
+
+	SOC_SINGLE("Left Capture Volume", WM8971_LINVOL, 0, 63, 0),
+	SOC_SINGLE("Left Capture ZC Switch", WM8971_LINVOL, 6, 1, 0),
+	SOC_SINGLE("Left Capture Switch", WM8971_LINVOL, 7, 1, 1),
+	SOC_SINGLE("Right Capture Volume", WM8971_RINVOL, 0, 63, 0),
+	SOC_SINGLE("Right Capture ZC Switch", WM8971_RINVOL, 6, 1, 0),
+	SOC_SINGLE("Right Capture Switch", WM8971_RINVOL, 7, 1, 1),
+
+	SOC_SINGLE("Capture Filter Switch", WM8971_ADCDAC, 0, 1, 1),
+
+	SOC_SINGLE("ALC Target Volume", WM8971_ALC1, 0, 7, 0),
+	SOC_SINGLE("ALC Max Volume", WM8971_ALC1, 4, 7, 0),
+
+	SOC_SINGLE("ALC Capture Target Volume", WM8971_ALC1, 0, 7, 0),
+	SOC_SINGLE("ALC Capture Max Volume", WM8971_ALC1, 4, 7, 0),
+	SOC_ENUM("ALC Capture Function", wm8971_enum[3]),
+	SOC_SINGLE("ALC Capture ZC Switch", WM8971_ALC2, 7, 1, 0),
+	SOC_SINGLE("ALC Capture Hold Time", WM8971_ALC2, 0, 15, 0),
+	SOC_SINGLE("ALC Capture Decay Time", WM8971_ALC3, 4, 15, 0),
+	SOC_SINGLE("ALC Capture Attack Time", WM8971_ALC3, 0, 15, 0),
+	SOC_SINGLE("ALC Capture NG Threshold", WM8971_NGATE, 3, 31, 0),
+	SOC_ENUM("ALC Capture NG Type", wm8971_enum[4]),
+	SOC_SINGLE("ALC Capture NG Switch", WM8971_NGATE, 0, 1, 0),
+
+	SOC_SINGLE("Capture 6dB Attenuate", WM8971_ADCDAC, 8, 1, 0),
+	SOC_SINGLE("Playback 6dB Attenuate", WM8971_ADCDAC, 7, 1, 0),
+
+    SOC_ENUM("Playback De-emphasis", wm8971_enum[5]),
+	SOC_ENUM("Playback Function", wm8971_enum[6]),
+	SOC_ENUM("Playback Phase", wm8971_enum[7]),
+	
+	SOC_SINGLE("Left Mic Boost", WM8971_LADCIN, 4, 3, 0),
+	SOC_SINGLE("Right Mic Boost", WM8971_RADCIN, 4, 3, 0),
+};
+
+
+/* add non-DPM controls */
+static int wm8971_add_controls(struct snd_soc_codec *codec)
+{
+	int err, i;
+
+	for (i = 0; i < ARRAY_SIZE(wm8971_snd_controls); i++) {
+		if ((err = snd_ctl_add(codec->card, snd_soc_cnew(&wm8971_snd_controls[i],codec, NULL))) < 0) {
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * DPM Controls
+ */
+
+/* Left Mixer */
+static const snd_kcontrol_new_t wm8971_left_mixer_controls[] = {
+SOC_DPM_SINGLE("Playback Switch", WM8971_LOUTM1, 8, 1, 0),
+SOC_DPM_SINGLE("Left Bypass Switch", WM8971_LOUTM1, 7, 1, 0),
+SOC_DPM_SINGLE("Right Playback Switch", WM8971_LOUTM2, 8, 1, 0),
+SOC_DPM_SINGLE("Right Bypass Switch", WM8971_LOUTM2, 7, 1, 0),
+};
+
+/* Right Mixer */
+static const snd_kcontrol_new_t wm8971_right_mixer_controls[] = {
+SOC_DPM_SINGLE("Left Playback Switch", WM8971_ROUTM1, 8, 1, 0),
+SOC_DPM_SINGLE("Left Bypass Switch", WM8971_ROUTM1, 7, 1, 0),
+SOC_DPM_SINGLE("Playback Switch", WM8971_ROUTM2, 8, 1, 0),
+SOC_DPM_SINGLE("Right Bypass Switch", WM8971_ROUTM2, 7, 1, 0),
+};
+
+/* Mono Mixer */
+static const snd_kcontrol_new_t wm8971_mono_mixer_controls[] = {
+SOC_DPM_SINGLE("Left Playback Switch", WM8971_MOUTM1, 8, 1, 0),
+SOC_DPM_SINGLE("Left Bypass Switch", WM8971_MOUTM1, 7, 1, 0),
+SOC_DPM_SINGLE("Right Playback Switch", WM8971_MOUTM2, 8, 1, 0),
+SOC_DPM_SINGLE("Right Bypass Switch", WM8971_MOUTM2, 7, 1, 0),
+};
+
+/* Left Line Mux */
+static const snd_kcontrol_new_t wm8971_left_line_controls =
+SOC_DPM_ENUM("Route", wm8971_enum[8]);
+
+/* Right Line Mux */
+static const snd_kcontrol_new_t wm8971_right_line_controls =
+SOC_DPM_ENUM("Route", wm8971_enum[9]);
+
+/* Left PGA Mux */
+static const snd_kcontrol_new_t wm8971_left_pga_controls =
+SOC_DPM_ENUM("Route", wm8971_enum[10]);
+
+/* Right PGA Mux */
+static const snd_kcontrol_new_t wm8971_right_pga_controls =
+SOC_DPM_ENUM("Route", wm8971_enum[11]);
+
+/* Mono ADC Mux */
+static const snd_kcontrol_new_t wm8971_monomux_controls =
+SOC_DPM_ENUM("Route", wm8971_enum[13]);
+
+
+static const struct snd_soc_dpm_widget wm8971_dpm_widgets[] = {
+	SND_SOC_DPM_CLOCK("WM8971 Clock", WM8971_PWR1, 0, 1),
+	SND_SOC_DPM_MIXER("Left Mixer", -1, 0, 0, &wm8971_left_mixer_controls[0], ARRAY_SIZE(wm8971_left_mixer_controls)),
+	SND_SOC_DPM_MIXER("Right Mixer", -1, 0, 0, &wm8971_right_mixer_controls[0], ARRAY_SIZE(wm8971_right_mixer_controls)),
+	SND_SOC_DPM_MIXER("Mono Mixer", WM8971_PWR2, 2, 0, &wm8971_mono_mixer_controls[0], ARRAY_SIZE(wm8971_mono_mixer_controls)),
+
+	SND_SOC_DPM_VOLUME("Right Out 2", WM8971_PWR2, 3, 0, NULL, 0),
+	SND_SOC_DPM_VOLUME("Left Out 2", WM8971_PWR2, 4, 0, NULL, 0),
+	SND_SOC_DPM_VOLUME("Right Out 1", WM8971_PWR2, 5, 0, NULL, 0),
+	SND_SOC_DPM_VOLUME("Left Out 1", WM8971_PWR2, 6, 0, NULL, 0),
+	SND_SOC_DPM_DAC("Right DAC", "Right Playback", WM8971_PWR2, 7, 0, NULL, 0),
+	SND_SOC_DPM_DAC("Left DAC", "Left Playback", WM8971_PWR2, 8, 0, NULL, 0),
+
+	//"Mic Bias", WM8971_PWR1, 1, 0
+	SND_SOC_DPM_ADC("Right ADC", "Right Capture", WM8971_PWR1, 2, 0, NULL, 0),
+	SND_SOC_DPM_ADC("Left ADC", "Left Capture", WM8971_PWR1, 3, 0, NULL, 0),
+
+	SND_SOC_DPM_MUX("Left PGA Mux", WM8971_PWR1, 5, 0, &wm8971_left_pga_controls),
+	SND_SOC_DPM_MUX("Right PGA Mux", WM8971_PWR1, 4, 0, &wm8971_right_pga_controls),
+	SND_SOC_DPM_MUX("Left Line Mux", -1, 0, 0, &wm8971_left_line_controls),
+	SND_SOC_DPM_MUX("Right Line Mux", -1, 0, 0, &wm8971_right_line_controls),
+
+	SND_SOC_DPM_MUX("Left ADC Mux", -1, 0, 0, &wm8971_monomux_controls),
+	SND_SOC_DPM_MUX("Right ADC Mux", -1, 0, 0, &wm8971_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_INPUT("LINPUT1"),
+	SND_SOC_DPM_INPUT("RINPUT1"),
+	SND_SOC_DPM_INPUT("MIC"),
+};
+
+static int wm8971_add_widgets(struct snd_soc_codec *codec)
+{
+	int i;
+	
+	for(i = 0; i < ARRAY_SIZE(wm8971_dpm_widgets); i++) {
+		snd_soc_dpm_new_control(codec, &wm8971_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", NULL, "Mono Mixer");
+	snd_soc_dpm_connect_input(codec, "MONO1", NULL, "Mono Out");
+
+	/* Left Line Mux */
+	snd_soc_dpm_connect_input(codec, "Left Line Mux", "Line", "LINPUT1");
+	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", "RINPUT1");
+	snd_soc_dpm_connect_input(codec, "Right Line Mux", "Mic", "MIC");
+	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", "LINPUT1");
+	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", "RINPUT1");
+	snd_soc_dpm_connect_input(codec, "Right PGA Mux", "Differential", "Differential Mux");
+
+	/* Differential Mux */
+	snd_soc_dpm_connect_input(codec, "Differential Mux", "Line", "LINPUT1");
+	snd_soc_dpm_connect_input(codec, "Differential Mux", "Line", "RINPUT1");
+
+	/* 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 wm8971_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 |= 0x0020;
+			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 */
+	wm8971_write(codec, WM8971_SRATE, pcm_c->hw_runtime.priv1);
+	wm8971_write(codec, WM8971_AUDIO, iface);
+	
+	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;
+	u16 dac_reg = wm8971_read_reg_cache(codec, WM8971_ADCDAC) & 0xfff7;
+
+	switch (event) {
+		case SNDRV_CTL_POWER_D0: /* full On */
+			/* set vmid to 50k and unmute dac */
+			wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x00c0);
+			wm8971_write(codec, WM8971_ADCDAC, dac_reg);
+			break;
+		case SNDRV_CTL_POWER_D1: /* partial On */
+		case SNDRV_CTL_POWER_D2: /* partial On */
+			/* set vmid to 5k for quick power up */
+			wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x01c0);
+			break;
+		case SNDRV_CTL_POWER_D3hot: /* Off, with power */
+			/* mute dac and set vmid to 500k, enable VREF */
+			wm8971_write(codec, WM8971_ADCDAC, dac_reg | 0x0008);
+			wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x0140);
+			break;
+		case SNDRV_CTL_POWER_D3cold: /* Off, without power */
+			wm8971_write(codec, WM8971_ADCDAC, dac_reg | 0x0008);
+			wm8971_write(codec, WM8971_PWR1, 0x0000);
+			break;
+	}
+	
+	return 0;
+}
+
+static struct snd_soc_pcm_codec wm8971_pcm_client[] = {
+	{
+	.name = "WM8971",
+	.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 = wm8971_pcm_prepare,
+		},
+		.hw = {
+			.num_hmodes = ARRAY_SIZE(wm8971_audio),
+			.hmodes = &wm8971_audio[0],
+		},
+	},
+};
+
+static int wm8971_probe(struct snd_soc_codec *codec)
+{
+	int reg;
+
+	/* reset the WM8971 */
+	wm8971_reset(codec);
+
+	/* power up */
+	wm8971_dpm_event(codec, SNDRV_CTL_POWER_D3hot);
+
+	/* set the update bits */
+	reg = wm8971_read_reg_cache(codec, WM8971_LDAC);
+	wm8971_write(codec, WM8971_LDAC, reg | 0x0100);
+	reg = wm8971_read_reg_cache(codec, WM8971_RDAC);
+	wm8971_write(codec, WM8971_RDAC, reg | 0x0100);
+
+	reg = wm8971_read_reg_cache(codec, WM8971_LOUT1V);
+	wm8971_write(codec, WM8971_LOUT1V, reg | 0x0100);
+	reg = wm8971_read_reg_cache(codec, WM8971_ROUT1V);
+	wm8971_write(codec, WM8971_ROUT1V, reg | 0x0100);
+
+	reg = wm8971_read_reg_cache(codec, WM8971_LOUT2V);
+	wm8971_write(codec, WM8971_LOUT2V, reg | 0x0100);
+	reg = wm8971_read_reg_cache(codec, WM8971_ROUT2V);
+	wm8971_write(codec, WM8971_ROUT2V, reg | 0x0100);
+
+	reg = wm8971_read_reg_cache(codec, WM8971_LINVOL);
+	wm8971_write(codec, WM8971_LINVOL, reg | 0x0100);
+	reg = wm8971_read_reg_cache(codec, WM8971_RINVOL);
+	wm8971_write(codec, WM8971_RINVOL, reg | 0x0100);
+
+	wm8971_add_controls(codec);
+	wm8971_add_widgets(codec);
+
+	return 0;
+}
+
+
+static void wm8971_remove(struct snd_soc_codec *codec)
+{
+	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;
+
+	client_template.adapter = adap;
+	client_template.addr = addr;
+	
+	if ((codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+ 
+	memcpy(&codec->i2c, &client_template, sizeof(struct i2c_client));
+
+	if((ret = i2c_attach_client(&codec->i2c)) < 0) {
+		err("failed to attach codec at addr %x\n", addr);
+		kfree(codec);
+	}
+
+	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(codec->reg_cache);
+		kfree(codec);
+	}
+
+	return ret;
+}
+
+static int wm8971_i2c_detach(struct i2c_client *client)
+{
+	struct snd_soc_codec *codec = container_of(client, struct snd_soc_codec, i2c);
+
+	i2c_detach_client(client);
+	snd_soc_unregister_codec(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 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;
+}
+
+
+static void __exit wm8971_exit(void)
+{
+	i2c_del_driver(&wm8971_i2c_driver);
+}
+
+
+module_init(wm8971_init);
+module_exit(wm8971_exit);
+
+MODULE_DESCRIPTION("SoC WM8971 driver");
+MODULE_AUTHOR("Lab126");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8971.h b/sound/soc/codecs/wm8971.h
new file mode 100644
index 0000000..c6fbe76
--- /dev/null
+++ b/sound/soc/codecs/wm8971.h
@@ -0,0 +1,55 @@
+/*
+ * wm8971.h  --  audio driver for WM8971
+ *
+ * Copyright 2005 Lab126, Inc.
+ *
+ * Author: Kenneth Kiraly <kiraly@lab126.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 _WM8971_H
+#define _WM8971_H
+
+#define WM8971_LINVOL	0x00
+#define WM8971_RINVOL	0x01
+#define WM8971_LOUT1V	0x02
+#define WM8971_ROUT1V	0x03
+#define WM8971_ADCDAC	0x05
+#define WM8971_AUDIO	0x07
+#define WM8971_SRATE	0x08
+#define WM8971_LDAC		0x0a
+#define WM8971_RDAC		0x0b
+#define WM8971_BASS		0x0c
+#define WM8971_TREBLE	0x0d
+#define WM8971_RESET	0x0f
+#define WM8971_ALC1		0x11
+#define	WM8971_ALC2		0x12
+#define	WM8971_ALC3		0x13
+#define WM8971_NGATE	0x14
+#define WM8971_LADC		0x15
+#define WM8971_RADC		0x16
+#define	WM8971_ADCTL1	0x17
+#define	WM8971_ADCTL2	0x18
+#define WM8971_PWR1		0x19
+#define WM8971_PWR2		0x1a
+#define	WM8971_ADCTL3	0x1b
+#define WM8971_ADCIN	0x1f
+#define	WM8971_LADCIN	0x20
+#define	WM8971_RADCIN	0x21
+#define WM8971_LOUTM1	0x22
+#define WM8971_LOUTM2	0x23
+#define WM8971_ROUTM1	0x24
+#define WM8971_ROUTM2	0x25
+#define WM8971_MOUTM1	0x26
+#define WM8971_MOUTM2	0x27
+#define WM8971_LOUT2V	0x28
+#define WM8971_ROUT2V	0x29
+#define WM8971_MOUTV	0x2A
+
+#endif
+
diff --git a/sound/soc/codecs/wm9713-voice.c b/sound/soc/codecs/wm9713-voice.c
index 0792288..2775e98 100644
--- a/sound/soc/codecs/wm9713-voice.c
+++ b/sound/soc/codecs/wm9713-voice.c
@@ -78,7 +78,7 @@
 /*
  * priv1 is pcm clock divider
  */
-static snd_soc_hw_mode_t wm9713_voice[] = {
+static struct snd_soc_hw_mode wm9713_voice[] = {
 	{WM9713_VOICE_HWFMT, 	SND_SOC_HWBITS(16),		48000,	256,	WM9713_PCM_48K, },
 	{WM9713_VOICE_HWFMT, 	SND_SOC_HWBITS(16),		32000,	384,	WM9713_PCM_32K,},
 	{WM9713_VOICE_HWFMT, 	SND_SOC_HWBITS(16),		24000,	256,	WM9713_PCM_24K,},
@@ -113,7 +113,7 @@ static void wm9713_voice_shutdown(snd_pc
 
 static int wm9713_voice_prepare(snd_pcm_substream_t *substream)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
 	u16 reg = 0x8000;
 
 	switch(pcm_c->hw_runtime.hformat & SND_SOC_CLOCK_MASK){
@@ -178,7 +178,7 @@ static int wm9713_voice_prepare(snd_pcm_
 	return 0;
 }
 
-static snd_soc_pcm_codec_t wm9713_voice_client = {
+static struct snd_soc_pcm_codec wm9713_voice_client = {
 	.name = "WM9713 Voice",
 	.playback = {
 		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
@@ -207,9 +207,9 @@ static void wm9713_device_release(struct
 {
 }
 
-static snd_soc_codec_t wm9713_soc_codec;
+static struct snd_soc_codec wm9713_soc_codec;
 
-static int wm9713_soc_probe(snd_soc_codec_t *codec)
+static int wm9713_soc_probe(struct snd_soc_codec *codec)
 {
 	int ret;
 
@@ -218,16 +218,16 @@ static int wm9713_soc_probe(snd_soc_code
 	return ret;
 }
 
-static void wm9713_soc_remove(snd_soc_codec_t *codec)
+static void wm9713_soc_remove(struct snd_soc_codec *codec)
 {
 }
 
-static snd_soc_codec_t wm9713_soc_codec = {
+static struct snd_soc_codec wm9713_soc_codec = {
 	.name = "WM9713 Voice",
-	.longname = "wm9713 voice long",
+	.longname = "WM9713 Portable Voice Codec",
 	.owner = THIS_MODULE,
 	.pdev = {
-		.name		= "wm9713 pl",
+		.name		= "alsa-wm9713",
 		.id		= -1,
 		.dev		= {.release = wm9713_device_release},
 	},
diff --git a/sound/soc/pxa/mainstone.c b/sound/soc/pxa/mainstone.c
index 2fe67a2..67f9a20 100644
--- a/sound/soc/pxa/mainstone.c
+++ b/sound/soc/pxa/mainstone.c
@@ -33,23 +33,10 @@
 #include <asm/arch/mainstone.h>
 #include <asm/arch/audio.h>
 
-struct audio_codecs_ {
-	char *name;
-	int interface;
-	int int_num;
-};
-
-/* I've added all my different configs here atm */
-static struct audio_codecs_ codecs[] = {
-	{.name = "WM8753 HiFi", SND_SOC_I2S, 0},
-	{.name = "WM8753 Voice", SND_SOC_SSP, 1},
-	{.name = "AC97 Audio", SND_SOC_AC97, 0},
-};
-
 static int mainstone_startup(snd_pcm_substream_t *substream)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
+	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
 	
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		MST_MSCWR2 &= ~MST_MSCWR2_AC97_SPKROFF;
@@ -64,8 +51,8 @@ static int mainstone_startup(snd_pcm_sub
 
 static void mainstone_shutdown(snd_pcm_substream_t *substream)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
+	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
 	
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
@@ -84,38 +71,38 @@ static struct snd_soc_ops mainstone_ops 
 
 static long mst_audio_suspend_mask;
 
-static int mainstone_suspend(snd_soc_machine_t *machine, pm_message_t state)
+static int mainstone_suspend(struct snd_soc_machine *machine, pm_message_t state)
 {
 	mst_audio_suspend_mask = MST_MSCWR2;
 	MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
 	return 0;
 }
 
-static int mainstone_resume(snd_soc_machine_t *machine)
+static int mainstone_resume(struct snd_soc_machine *machine)
 {
 	MST_MSCWR2 &= mst_audio_suspend_mask | ~MST_MSCWR2_AC97_SPKROFF;
 	return 0;
 }
 
-static int mainstone_probe(snd_soc_machine_t *machine)
+static int mainstone_probe(struct snd_soc_machine *machine)
 {
-	int i, ret = 0;
-
-	for(i = 0; i < ARRAY_SIZE(codecs); i++) {
-		if((ret = snd_soc_pcm_connect(machine, codecs[i].name, 
-			codecs[i].interface, codecs[i].int_num)) < 0) {
-			printk(KERN_ERR "soc: failed to create new pcm for %s\n", codecs[i].name);
-		}
-	}
-	
-	return snd_soc_pcm_register(machine, "WM8753");
+	return 0;
 }
 
-static int mainstone_remove(snd_soc_machine_t *machine)
+static int mainstone_remove(struct snd_soc_machine *machine)
 {
 	return 0;
 }
 
+/* I've added all my different configs here atm */
+static struct snd_soc_machine_config codecs[] = {
+	{.name = "WM8753", .sname = "WM8753 HiFi", SND_SOC_I2S, 0},
+	{.name = "WM8971", .sname = "WM8971", SND_SOC_I2S, 0},
+	{.name = "WM8750", .sname = "WM8750", SND_SOC_I2S, 0},
+	{.name = "WM8753", .sname = "WM8753 Voice", SND_SOC_SSP, 1},
+	{.name = "AC97", .sname = "AC97 Audio", SND_SOC_AC97, 0},
+};
+
 static struct snd_soc_machine mainstone = {
 	.name = "Mainstone",
 	.probe = mainstone_probe,
@@ -123,6 +110,8 @@ static struct snd_soc_machine mainstone 
 	.suspend = mainstone_suspend,
 	.resume = mainstone_resume,
 	.ops = &mainstone_ops,
+	.config = codecs,
+	.nconfigs = ARRAY_SIZE(codecs),
 };
 
 static int __init snd_soc_init(void) 
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index d729da8..235e866 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -238,7 +238,7 @@ static pxa2xx_pcm_dma_params_t pxa2xx_ac
 
 #ifdef CONFIG_PM
 
-static int pxa2xx_ac97_suspend(snd_soc_pcm_interface_t *interface, pm_message_t state)
+static int pxa2xx_ac97_suspend(struct snd_soc_pcm_interface *interface, pm_message_t state)
 {
 	snd_card_t *card = interface->card;
 	
@@ -254,7 +254,7 @@ static int pxa2xx_ac97_suspend(snd_soc_p
 	return 0;
 }
 
-static int pxa2xx_ac97_resume(snd_soc_pcm_interface_t *interface)
+static int pxa2xx_ac97_resume(struct snd_soc_pcm_interface *interface)
 {
 	snd_card_t *card = interface->card;
 
@@ -272,7 +272,7 @@ static int pxa2xx_ac97_resume(snd_soc_pc
 #define pxa2xx_ac97_resume	NULL
 #endif
 
-static int pxa2xx_ac97_probe(snd_soc_pcm_interface_t *interface)
+static int pxa2xx_ac97_probe(struct snd_soc_pcm_interface *interface)
 {
 	ac97_bus_t *ac97_bus;
 	ac97_template_t ac97_template;
@@ -309,7 +309,7 @@ static int pxa2xx_ac97_probe(snd_soc_pcm
 	return ret;
 }
 
-static void pxa2xx_ac97_remove(snd_soc_pcm_interface_t *interface)
+static void pxa2xx_ac97_remove(struct snd_soc_pcm_interface *interface)
 {
 	GCR |= GCR_ACLINK_OFF;
 	free_irq(IRQ_AC97, NULL);
@@ -319,8 +319,8 @@ static void pxa2xx_ac97_remove(snd_soc_p
 static int pxa2xx_ac97_prepare(snd_pcm_substream_t *substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
+	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
 	
 	int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
 		  AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
@@ -330,8 +330,8 @@ static int pxa2xx_ac97_prepare(snd_pcm_s
 static int pxa2xx_ac97_hw_params(snd_pcm_substream_t *substream,
 				snd_pcm_hw_params_t *params)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
+	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
 	
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		if (params_channels(params) == 2)
@@ -348,7 +348,7 @@ static int pxa2xx_ac97_hw_params(snd_pcm
 	return 0;
 }
 
-static snd_soc_pcm_interface_t pxa_ac97_interface[] = {
+static struct snd_soc_pcm_interface pxa_ac97_interface[] = {
 	{	.name = "pxa2xx-ac97",
 		.id = 0,
 		.type = SND_SOC_AC97,
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 24a64a0..d6e097b 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -35,18 +35,27 @@
 #define PXA_I2S_HWFMT \
 	(SND_SOC_HWFMT_I2S | SND_SOC_HWFMT_LEFT_J  | SND_SOC_HWFMT_CBS_CFS | \
 	SND_SOC_HWFMT_CBM_CFS | SND_SOC_HWFMT_NB_NF)
+	
+#define PXA_I2S_HWFMT_96K \
+	(SND_SOC_HWFMT_I2S | SND_SOC_HWFMT_LEFT_J  | \
+	SND_SOC_HWFMT_CBM_CFS | SND_SOC_HWFMT_NB_NF)
+
+static DECLARE_MUTEX(pxa_i2s_sem);
+static int i2s_open = 0;
 
 /*
  * priv1 is sadiv
  * priv2 is bits[15..8] = MCLK divisor, bits[7..0] = sr
  */
-static snd_soc_hw_mode_t pxa2xx_i2s[] = {
+static struct snd_soc_hw_mode pxa2xx_i2s[] = {
 	{PXA_I2S_HWFMT, 	SND_SOC_HWBITS(16),		8000,	64,		0x00000048},
 	{PXA_I2S_HWFMT, 	SND_SOC_HWBITS(16),		11025,	64,		0x00000034},
 	{PXA_I2S_HWFMT, 	SND_SOC_HWBITS(16),		16000,	64,		0x00000024},
 	{PXA_I2S_HWFMT, 	SND_SOC_HWBITS(16),		22050,	64,		0x0000001a},
 	{PXA_I2S_HWFMT, 	SND_SOC_HWBITS(16),		44100,	64,		0x0000000d},
 	{PXA_I2S_HWFMT, 	SND_SOC_HWBITS(16),		48000,	64,		0x0000000c},
+	/* 96k is not in yellow book - ymmv */
+	{PXA_I2S_HWFMT_96K, 	SND_SOC_HWBITS(16),	96000,	64,		0x00000006},
 };
 
 static pxa2xx_pcm_dma_params_t pxa2xx_i2s_pcm_stereo_out = {
@@ -108,8 +117,13 @@ static u32 get_sadiv(int rate)
 
 static int pxa2xx_i2s_startup(snd_pcm_substream_t *substream)
 {	
-	SACR0 |= SACR0_RST;
-	SACR0 = 0;
+	down(&pxa_i2s_sem);
+	if(!i2s_open) {
+		SACR0 |= SACR0_RST;
+		SACR0 = 0;
+	}
+	i2s_open++;
+	up(&pxa_i2s_sem);
 	return 0;
 }
 
@@ -126,8 +140,8 @@ static int pxa_i2s_wait(void)
 static int pxa2xx_i2s_hw_params(snd_pcm_substream_t *substream,
 				snd_pcm_hw_params_t *params)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
+	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
 	int master = 0;
 	
 	if(pcm_i->hw_runtime.hformat & SND_SOC_HWFMT_CBS_CFS)
@@ -191,7 +205,7 @@ static int pxa2xx_i2s_hw_params(snd_pcm_
 
 static void pxa2xx_i2s_shutdown(snd_pcm_substream_t *substream)
 {
-
+	down(&pxa_i2s_sem);
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		SACR1 |= SACR1_DRPL;
 		SAIMR &= ~SAIMR_TFS;
@@ -205,10 +219,12 @@ static void pxa2xx_i2s_shutdown(snd_pcm_
 		SACR0 &= ~SACR0_ENB;
 		pxa_set_cken(CKEN8_I2S, 0);
 	}
+	i2s_open--;
+	up(&pxa_i2s_sem);
 }
 
 #ifdef CONFIG_PM
-static int pxa2xx_i2s_suspend(snd_soc_pcm_interface_t *interface, pm_message_t state)
+static int pxa2xx_i2s_suspend(struct snd_soc_pcm_interface *interface, pm_message_t state)
 {
 	int ret = 0;
 
@@ -218,7 +234,7 @@ static int pxa2xx_i2s_suspend(snd_soc_pc
 	return ret;
 }
 
-static int pxa2xx_i2s_resume(snd_soc_pcm_interface_t *interface)
+static int pxa2xx_i2s_resume(struct snd_soc_pcm_interface *interface)
 {
 	int ret = 0;
 
@@ -233,7 +249,7 @@ static int pxa2xx_i2s_resume(snd_soc_pcm
 #define pxa2xx_i2s_resume	NULL
 #endif
 
-static snd_soc_pcm_interface_t pxa_i2s_interface[] = {
+static struct snd_soc_pcm_interface pxa_i2s_interface[] = {
 	{	.name = "pxa2xx-i2s",
 		.id = 0,
 		.type = SND_SOC_I2S,
@@ -242,14 +258,14 @@ static snd_soc_pcm_interface_t pxa_i2s_i
 		.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_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_48000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_96000,
 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
 			.channels_min = 2,
 			.channels_max = 2,},
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index 143bc12..c61d0e9 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -15,6 +15,7 @@
 #include <linux/device.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
+#include <linux/delay.h> //
 
 #include <sound/driver.h>
 #include <sound/core.h>
@@ -55,7 +56,7 @@ static void pxa2xx_pcm_dma_irq(int dma_c
 	snd_pcm_substream_t *substream = dev_id;
 	struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
 	int dcsr;
-
+	
 	dcsr = DCSR(dma_ch);
 	DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN;
 
@@ -71,7 +72,7 @@ static int pxa2xx_pcm_hw_params(snd_pcm_
 				snd_pcm_hw_params_t *params)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
 	struct pxa2xx_runtime_data *rtd = runtime->private_data;
 	size_t totsize = params_buffer_bytes(params);
 	size_t period = params_period_bytes(params);
@@ -81,16 +82,21 @@ static int pxa2xx_pcm_hw_params(snd_pcm_
 	dma_addr_t dma_buff_phys, next_desc_phys;
 	int ret;
 
-	if(rtd->params == dma) // liam - see if we can move dma req into open
-		return 0;
-	
-	rtd->params = dma;
-	ret = pxa_request_dma(rtd->params->name, DMA_PRIO_LOW,
-			      pxa2xx_pcm_dma_irq, substream);
-	if (ret < 0)
-		return ret;
-	rtd->dma_ch = ret;
-	
+	if(rtd->params == NULL) {
+		rtd->params = dma;
+		if((ret = pxa_request_dma(rtd->params->name, DMA_PRIO_LOW,
+			      pxa2xx_pcm_dma_irq, substream)) < 0)
+			return ret;
+		rtd->dma_ch = ret;
+	} else if(rtd->params != dma) {
+		pxa_free_dma(rtd->dma_ch);
+		rtd->params = dma;
+		if((ret = pxa_request_dma(rtd->params->name, DMA_PRIO_LOW,
+			      pxa2xx_pcm_dma_irq, substream)) < 0)
+			return ret;
+		rtd->dma_ch = ret;
+	}
+
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 	runtime->dma_bytes = totsize;
 
@@ -179,10 +185,10 @@ static snd_pcm_uframes_t pxa2xx_pcm_poin
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	struct pxa2xx_runtime_data *rtd = runtime->private_data;
-
 	dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
 			 DSADR(rtd->dma_ch) : DTADR(rtd->dma_ch);
 	snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr);
+
 	if (x == runtime->buffer_size)
 		x = 0;
 	return x;
@@ -324,7 +330,7 @@ static void pxa2xx_pcm_free_dma_buffers(
 
 static u64 pxa2xx_pcm_dmamask = 0xffffffff;
 
-int pxa2xx_pcm_new(snd_card_t *card, snd_soc_pcm_codec_t *pcm_c, snd_pcm_t *pcm)
+int pxa2xx_pcm_new(snd_card_t *card, struct snd_soc_pcm_codec *pcm_c, snd_pcm_t *pcm)
 {
 	int ret = 0;
 
@@ -350,7 +356,7 @@ int pxa2xx_pcm_new(snd_card_t *card, snd
 	return ret;
 }
 
-snd_soc_platform_t pxa2xx_soc_platform;
+static struct snd_soc_platform pxa2xx_soc_platform;
 
 static int pxa2xx_soc_probe(struct device *dev)
 {
@@ -372,7 +378,7 @@ static void __exit pxa2xx_soc_exit(void)
 	snd_soc_unregister_platform(&pxa2xx_soc_platform);
 }
 
-snd_soc_platform_t pxa2xx_soc_platform = {
+static struct snd_soc_platform pxa2xx_soc_platform = {
 	.name		= "pxa2xx-audio",
 	.bus		= &platform_bus_type,
 	.probe		= pxa2xx_soc_probe,
diff --git a/sound/soc/pxa/pxa2xx-ssp.c b/sound/soc/pxa/pxa2xx-ssp.c
index fd1102c..17efb2c 100644
--- a/sound/soc/pxa/pxa2xx-ssp.c
+++ b/sound/soc/pxa/pxa2xx-ssp.c
@@ -65,7 +65,7 @@
  * priv1 is scr divider when in master mode
  * -- liam, need some method of "doesn't matter" for fs, maybe 0  
  */
-static snd_soc_hw_mode_t pxa2xx_ssp[] = {
+static struct snd_soc_hw_mode pxa2xx_ssp[] = {
 	{PXA_SSP_HWFMT, 	SND_SOC_HWBITS(16),		8000,	256,	1626},
 	{PXA_SSP_HWFMT, 	SND_SOC_HWBITS(16),		8000,	384,	1626}, 
 	{PXA_SSP_HWFMT, 	SND_SOC_HWBITS(16),		11025,	256,	1180},
@@ -223,8 +223,8 @@ static pxa2xx_gpio_t ssp_gpios[3][2] = {
 
 static int pxa2xx_ssp_startup(snd_pcm_substream_t *substream)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
+	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
 	int ret = 0;
 	
 	if((ret = ssp_init (&ssp[pcm_i->id], pcm_i->id + 1, SSP_NO_IRQ)) < 0)
@@ -236,15 +236,15 @@ static int pxa2xx_ssp_startup(snd_pcm_su
 
 static void pxa2xx_ssp_shutdown(snd_pcm_substream_t *substream)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
+	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
 
 	ssp_disable(&ssp[pcm_i->id]);
 	ssp_exit(&ssp[pcm_i->id]);
 }
 
 #ifdef CONFIG_PM
-static int pxa2xx_ssp_suspend(snd_soc_pcm_interface_t *interface, pm_message_t state)
+static int pxa2xx_ssp_suspend(struct snd_soc_pcm_interface *interface, pm_message_t state)
 {
 	int ret = 0;
 
@@ -254,7 +254,7 @@ static int pxa2xx_ssp_suspend(snd_soc_pc
 	return ret;
 }
 
-static int pxa2xx_ssp_resume(snd_soc_pcm_interface_t *interface)
+static int pxa2xx_ssp_resume(struct snd_soc_pcm_interface *interface)
 {
 	int ret = 0;
 
@@ -272,8 +272,8 @@ static int pxa2xx_ssp_resume(snd_soc_pcm
 static int pxa2xx_ssp_hw_params(snd_pcm_substream_t *substream,
 				snd_pcm_hw_params_t *params)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
+	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
 	int master = 0, dma = 0;
 	u32 ssp_mode = 0, ssp_setup = 0, psp_mode = 0;
 	int bits = generic_ffs(pcm_i->hw_runtime.hbits);
@@ -326,7 +326,7 @@ static int pxa2xx_ssp_hw_params(snd_pcm_
 	return 0;
 }
 
-static snd_soc_pcm_interface_t pxa_ssp_interfaces[] = {
+static struct snd_soc_pcm_interface pxa_ssp_interfaces[] = {
 	{	.name = "pxa2xx-ssp1",
 		.id = 0,
 		.type = SND_SOC_SSP,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index dc7925d..c885891 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -41,7 +41,7 @@
 #include <sound/soc-dpm.h>
 #include <sound/initval.h>
 
-#define SND_SOC_VERSION "0.5"
+#define SND_SOC_VERSION "0.6"
 
 #define iface_name(x) \
 	(((x) == SND_SOC_AC97) ? "ac97" : \
@@ -55,7 +55,7 @@ static struct snd_soc_platform *platform
 static struct snd_soc_machine *machine = NULL;
 
 
-int snd_soc_update_bits(snd_soc_codec_t *codec, unsigned short reg,
+int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
 				unsigned short mask, unsigned short value)
 {
 	int change;
@@ -70,7 +70,7 @@ int snd_soc_update_bits(snd_soc_codec_t 
 	return change;
 }
 
-int snd_soc_test_bits(snd_soc_codec_t *codec, unsigned short reg,
+int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
 				unsigned short mask, unsigned short value)
 {
 	int change;
@@ -83,7 +83,8 @@ int snd_soc_test_bits(snd_soc_codec_t *c
 	return change;
 }
 
-static int soc_match_hw(snd_soc_hw_mode_t *c, snd_soc_hw_mode_t *i, int rate, int fs)
+static int soc_match_hw(struct snd_soc_hw_mode *c, struct snd_soc_hw_mode *i, 
+	int rate, int fs)
 {
 	if (c->rate != i->rate)
 		return 0;
@@ -112,8 +113,8 @@ static int soc_match_hw(snd_soc_hw_mode_
  * the given hw params */
 static int soc_check_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
+	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 */
@@ -158,8 +159,8 @@ static int soc_check_hw_params(snd_pcm_s
  */
 static int soc_pcm_open(snd_pcm_substream_t *substream)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
+	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;
 	int ret = 0;
 
@@ -254,8 +255,8 @@ ops_err:
 /* private data can be freed here */
 static int soc_pcm_close(snd_pcm_substream_t *substream)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
+	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
 
 	if(pcm_i->ops.shutdown)
 		pcm_i->ops.shutdown(substream);
@@ -276,10 +277,10 @@ static int soc_pcm_close(snd_pcm_substre
  * atomic, can be called multiple times, can refer to runtime info*/
 static int soc_pcm_prepare(snd_pcm_substream_t *substream)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
+	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
 	int ret = 0;
-	
+
 	if(platform->pcm_ops->prepare)
 		if((ret = platform->pcm_ops->prepare(substream)) < 0)
 			return ret;
@@ -297,8 +298,8 @@ static int soc_pcm_prepare(snd_pcm_subst
 
 static int soc_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
+	struct snd_soc_pcm_codec *pcm_c = substream->private_data;
+	struct snd_soc_pcm_interface *pcm_i = pcm_c->pcm_i;
 	int ret = 0;
 
 	if(pcm_c->ops.trigger)
@@ -322,9 +323,9 @@ static int soc_pcm_trigger(snd_pcm_subst
 static int soc_pcm_hw_params(snd_pcm_substream_t *substream,
 				snd_pcm_hw_params_t *params)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
-	snd_soc_codec_t *codec = (snd_soc_codec_t*)pcm_i->card->private_data;
+	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;
 	int ret = 0;
 
 	/* prepare hw non AC97 only */
@@ -386,9 +387,9 @@ codec_err:
 /* free buffers, can be called multiple times */
 static int soc_pcm_hw_free(snd_pcm_substream_t *substream)
 {
-	snd_soc_pcm_codec_t *pcm_c = substream->private_data;
-	snd_soc_pcm_interface_t *pcm_i = pcm_c->pcm_i;
-	snd_soc_codec_t *codec = (snd_soc_codec_t*)pcm_i->card->private_data;
+	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;
 
 	if(pcm_c->ops.hw_free)
 		pcm_c->ops.hw_free(substream);
@@ -427,7 +428,7 @@ static snd_pcm_ops_t soc_pcm_ops = {
  */
 static int soc_suspend(snd_card_t *card, pm_message_t state)
 {
-	snd_soc_codec_t *c = card->pm_private_data;
+	struct snd_soc_codec *c = card->pm_private_data;
 	//snd_soc_pcm_interface_t *i = c->interface;
 	
 	//snd_pcm_suspend_all(c->pcm);
@@ -442,7 +443,7 @@ static int soc_suspend(snd_card_t *card,
 
 static int soc_resume(snd_card_t * card)
 {
-	snd_soc_codec_t *c = card->pm_private_data;
+	struct snd_soc_codec *c = card->pm_private_data;
 	//snd_soc_pcm_interface_t *i = c->interface;
 	
 	if(c->resume)
@@ -459,7 +460,54 @@ static int soc_resume(snd_card_t * card)
 #define soc_resume	NULL
 #endif
 
-static int soc_probe_codec(snd_soc_codec_t *codec)
+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;
 	
@@ -478,6 +526,7 @@ static int soc_probe_codec(snd_soc_codec
 	if(codec->probe && (ret = codec->probe(codec)) < 0)
 		goto err;
 	codec->probed = 1;
+	soc_sync_objects();
 	return 0;
 	
 err:
@@ -487,15 +536,15 @@ err:
 	return ret;
 }
 
-static void soc_free_dpm_widgets(snd_soc_codec_t *codec)
+static void soc_free_dpm_widgets(struct snd_soc_codec *codec)
 {
-	snd_soc_dpm_widget_t *w, *lw = NULL;
-	snd_soc_dpm_path_t *p, *lp = NULL;
+	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, snd_soc_dpm_widget_t, list);
+		w =  list_entry(l, struct snd_soc_dpm_widget, list);
 		if (lw)
 			kfree(lw);
 		lw = w;
@@ -504,7 +553,7 @@ static void soc_free_dpm_widgets(snd_soc
 	
 	list_for_each(l, &codec->dpm_paths)
 	{
-		p =  list_entry(l, snd_soc_dpm_path_t, list);
+		p =  list_entry(l, struct snd_soc_dpm_path, list);
 		if(p->long_name)
 			kfree(p->long_name);
 		if (lp)
@@ -514,7 +563,7 @@ static void soc_free_dpm_widgets(snd_soc
 	kfree(lp);
 }
 
-static int soc_remove_codec(snd_soc_codec_t *codec)
+static int soc_remove_codec(struct snd_soc_codec *codec)
 {	
 	if(!codec->probed)
 		return 0;
@@ -535,7 +584,7 @@ static int soc_remove_codec(snd_soc_code
 	return 0;
 }
 
-int snd_soc_register_codec(snd_soc_codec_t *codec)
+int snd_soc_register_codec(struct snd_soc_codec *codec)
 {
 	int ret = 0;
 
@@ -543,19 +592,21 @@ int snd_soc_register_codec(snd_soc_codec
 	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;
 	}
 
-	list_add(&codec->list, &codecs);	
+		
 	up(&soc_sem);
 	return ret;
 }
 
-void snd_soc_unregister_codec(snd_soc_codec_t *codec)
+void snd_soc_unregister_codec(struct snd_soc_codec *codec)
 {
 	down(&soc_sem); 
 	list_del_init(&codec->list);
@@ -563,12 +614,11 @@ void snd_soc_unregister_codec(snd_soc_co
 	up(&soc_sem);
 }
 
-int snd_soc_register_interface(snd_soc_pcm_interface_t *iface)
+int snd_soc_register_interface(struct snd_soc_pcm_interface *iface)
 {	
 	int ret = 0;
 	
-	down(&soc_sem);
-	
+	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);
@@ -577,11 +627,12 @@ int snd_soc_register_interface(snd_soc_p
 
 	INIT_LIST_HEAD(&iface->list);
 	list_add(&iface->list, &interfaces);
+	soc_sync_objects();
 	up(&soc_sem);
 	return 0;
 }
 
-void snd_soc_unregister_interface(snd_soc_pcm_interface_t *iface)
+void snd_soc_unregister_interface(struct snd_soc_pcm_interface *iface)
 {
 	down(&soc_sem);
 	list_del_init(&iface->list);
@@ -592,7 +643,7 @@ void snd_soc_unregister_interface(snd_so
 
 static struct device_driver soc_pdrv;
 
-int snd_soc_register_platform(snd_soc_platform_t *p)
+int snd_soc_register_platform(struct snd_soc_platform *p)
 {
 	int ret = 0;
 	
@@ -616,29 +667,34 @@ int snd_soc_register_platform(snd_soc_pl
 		up(&soc_sem);
 		return ret;
 	}
-
+	
+	soc_sync_objects();
 	up(&soc_sem);
 	return ret;
 }
 
-void snd_soc_unregister_platform(snd_soc_platform_t *p)
+void snd_soc_unregister_platform(struct snd_soc_platform *p)
 {
 	struct list_head *l;
-	snd_soc_codec_t *c = NULL;
-		
-	down(&soc_sem);
-	driver_unregister(&soc_pdrv);
+	struct snd_soc_codec *codec = NULL;
 	
+	down(&soc_sem);
 	list_for_each(l, &codecs) {
-		c = list_entry(l, snd_soc_codec_t, list);
-		soc_remove_codec(c);
+		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;
+		}
 	}
 	
+	driver_unregister(&soc_pdrv);
 	platform = NULL;
 	up(&soc_sem);	
 }
 
-int snd_soc_register_machine(snd_soc_machine_t *m)
+int snd_soc_register_machine(struct snd_soc_machine *m)
 {
 	int ret = 0;
 
@@ -650,11 +706,12 @@ int snd_soc_register_machine(snd_soc_mac
 		}
 	}
 	machine = m;
+	soc_sync_objects();
 	up(&soc_sem);
 	return 0;
 }
 
-void snd_soc_unregister_machine(snd_soc_machine_t *m)
+void snd_soc_unregister_machine(struct snd_soc_machine *m)
 {
 	down(&soc_sem);
 	if(machine->remove)
@@ -664,18 +721,19 @@ void snd_soc_unregister_machine(snd_soc_
 }
 
 /* find codec from pcm name */
-static snd_soc_codec_t * soc_get_codec_from_pcm(char *pcm_name, snd_soc_pcm_codec_t **pcm_c)
+static struct snd_soc_codec * soc_get_codec_from_pcm(char *pcm_name, 
+	struct snd_soc_pcm_codec **pcm_c)
 {
 	struct list_head *l;
-	snd_soc_codec_t *c = NULL;
+	struct snd_soc_codec *c = NULL;
 
 	list_for_each(l, &codecs) {
 		int i = 0;
-		c = list_entry(l, snd_soc_codec_t, list);
+		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)
@@ -688,13 +746,13 @@ static snd_soc_codec_t * soc_get_codec_f
 	return NULL;
 }
 
-static snd_soc_codec_t * soc_get_codec(char *name)
+static struct snd_soc_codec* soc_get_codec(char *name)
 {
 	struct list_head *l;
-	snd_soc_codec_t *c = NULL;
+	struct snd_soc_codec *c = NULL;
 
 	list_for_each(l, &codecs) {
-		c = list_entry(l, snd_soc_codec_t, list);
+		c = list_entry(l, struct snd_soc_codec, list);
 			
 		if(!strcmp(name, c->name))
 			return c;
@@ -703,13 +761,13 @@ static snd_soc_codec_t * soc_get_codec(c
 	return NULL;
 }
 
-static snd_soc_pcm_interface_t* soc_get_interface(int iface_type, int num)
+static struct snd_soc_pcm_interface* soc_get_interface(int iface_type, int num)
 {
 	struct list_head *l;
-	snd_soc_pcm_interface_t *i = NULL;
+	struct snd_soc_pcm_interface *i = NULL;
 	
 	list_for_each(l, &interfaces) {
-		i = list_entry(l, snd_soc_pcm_interface_t, list);
+		i = list_entry(l, struct snd_soc_pcm_interface, list);
 		if (i->type == iface_type && i->id == num){
 			if (i->pcm_c)
 				return NULL;
@@ -720,24 +778,23 @@ static snd_soc_pcm_interface_t* soc_get_
 	return NULL;
 }
 
-int snd_soc_pcm_connect(snd_soc_machine_t *machine, char *name, int iface_type, int num)
+int snd_soc_pcm_connect(struct snd_soc_machine *machine, int nconfig)
 {
 	snd_pcm_t *pcm;
-	snd_soc_pcm_codec_t *pcm_c;
+	struct snd_soc_pcm_codec *pcm_c;
 	int ret = 0;
-	snd_soc_pcm_interface_t *iface;
-	snd_soc_codec_t *codec;
+	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];
-	
-	if((codec = soc_get_codec_from_pcm(name, &pcm_c)) == NULL) {
-		printk(KERN_ERR "soc: can't find codec pcm %s\n", name);
+
+	if((codec = soc_get_codec_from_pcm(name, &pcm_c)) == NULL)
 		return -ENODEV;
-	}
 	
-	if((iface = soc_get_interface(iface_type, num)) == NULL) {
-		printk(KERN_ERR "soc: can't find %s interface %d\n", iface_name(iface_type), num);
+	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);
@@ -746,6 +803,7 @@ int snd_soc_pcm_connect(snd_soc_machine_
 		goto err;
 	}
 	pcm_c->pcm_i = iface;
+	pcm_c->codec = codec;
 	iface->card = codec->card;
 	iface->pcm_c = pcm_c;
 	pcm->private_data = pcm_c;
@@ -771,14 +829,14 @@ err:
 	return ret;
 }
 
-int snd_soc_pcm_register(snd_soc_machine_t *machine, char *name)
+int snd_soc_pcm_register(struct snd_soc_machine *machine, char *name)
 {
-	snd_soc_codec_t * codec;
+	struct snd_soc_codec* codec;
 	int ret = 0;
 
 	if((codec = soc_get_codec(name)) == NULL)
 		return -ENODEV;
-	
+
 	snprintf(codec->card->shortname, sizeof(codec->card->shortname),
 		 "%s", codec->name);
 	snprintf(codec->card->longname, sizeof(codec->card->longname),
@@ -842,15 +900,15 @@ int snd_soc_info_enum_double(snd_kcontro
 	return 0;
 }
 
-int snd_soc_dpm_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_soc_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_soc_dpm_widget_t *widget = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	unsigned short val, bitmask;
 	
 	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
 		;
-	val = snd_soc_read(widget->codec, e->reg);
+	val = snd_soc_read(codec, e->reg);
 	ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
 	if (e->shift_l != e->shift_r)
 		ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (bitmask - 1);
@@ -860,7 +918,7 @@ int snd_soc_dpm_get_enum_double(snd_kcon
 
 int snd_soc_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_soc_codec_t *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	unsigned short val;
 	unsigned short mask, bitmask;
@@ -897,7 +955,7 @@ int snd_soc_info_volsw(snd_kcontrol_t *k
 
 int snd_soc_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_soc_codec_t *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	int reg = kcontrol->private_value & 0xff;
 	int shift = (kcontrol->private_value >> 8) & 0x0f;
 	int rshift = (kcontrol->private_value >> 12) & 0x0f;
@@ -918,7 +976,7 @@ int snd_soc_get_volsw(snd_kcontrol_t * k
 
 int snd_soc_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_soc_codec_t *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	int reg = kcontrol->private_value & 0xff;
 	int shift = (kcontrol->private_value >> 8) & 0x0f;
 	int rshift = (kcontrol->private_value >> 12) & 0x0f;
diff --git a/sound/soc/soc-dpm.c b/sound/soc/soc-dpm.c
index 9c304f7..d4bb378 100644
--- a/sound/soc/soc-dpm.c
+++ b/sound/soc/soc-dpm.c
@@ -50,19 +50,19 @@ static int dpm_status = 1;
 module_param(dpm_status, int, 0);
 MODULE_PARM_DESC(dpm_status, "enable DPM sysfs entries");
 
-static snd_soc_dpm_widget_t *dpm_cnew_widget(const snd_soc_dpm_widget_t *_widget)
+static struct snd_soc_dpm_widget *dpm_cnew_widget(const struct snd_soc_dpm_widget *_widget)
 {
-	snd_soc_dpm_widget_t* widget;
-	widget = kmalloc(sizeof(snd_soc_dpm_widget_t), GFP_KERNEL);
+	struct snd_soc_dpm_widget* widget;
+	widget = kmalloc(sizeof(struct snd_soc_dpm_widget), GFP_KERNEL);
 	if (!widget)
 		return NULL;
 	
-	memcpy(widget, _widget, sizeof(snd_soc_dpm_widget_t));
+	memcpy(widget, _widget, sizeof(struct snd_soc_dpm_widget));
 	return widget;
 }
 
-static void dpm_set_path_status(snd_soc_dpm_widget_t *w, 
-	snd_soc_dpm_path_t *p, int i)
+static void dpm_set_path_status(struct snd_soc_dpm_widget *w, 
+	struct snd_soc_dpm_path *p, int i)
 {	
 	switch (w->id)
 	{
@@ -115,8 +115,9 @@ static void dpm_set_path_status(snd_soc_
 	//printk("* %s --> %s %s\n", w->name, p->name, p->connect ? "connect" : "disconnect");
 }	
 
-static int dpm_connect_mux(snd_soc_codec_t *codec, snd_soc_dpm_widget_t *src, snd_soc_dpm_widget_t *dest,
-	snd_soc_dpm_path_t *path, char *control_name, const snd_kcontrol_new_t *kcontrol)
+static int dpm_connect_mux(struct snd_soc_codec *codec, struct snd_soc_dpm_widget *src, 
+	struct snd_soc_dpm_widget *dest, struct snd_soc_dpm_path *path, 
+	char *control_name, const snd_kcontrol_new_t *kcontrol)
 {
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	int i;
@@ -135,8 +136,8 @@ static int dpm_connect_mux(snd_soc_codec
 	return -ENODEV;
 }
 
-static int dpm_connect_mixer(snd_soc_codec_t *codec, snd_soc_dpm_widget_t *src, snd_soc_dpm_widget_t *dest,
-	snd_soc_dpm_path_t *path, char *control_name)
+static int dpm_connect_mixer(struct snd_soc_codec *codec, struct snd_soc_dpm_widget *src, 
+	struct snd_soc_dpm_widget *dest, struct snd_soc_dpm_path *path, char *control_name)
 {
 	int i;
 	
@@ -154,18 +155,18 @@ static int dpm_connect_mixer(snd_soc_cod
 	return -ENODEV;
 }
 
-int snd_soc_dpm_connect_input(snd_soc_codec_t *codec, char *dest_name, 
+int snd_soc_dpm_connect_input(struct snd_soc_codec *codec, char *dest_name, 
 	char * control_name, char *src_name)
 {
-	snd_soc_dpm_path_t *path;
-	snd_soc_dpm_widget_t *src = NULL, *dest = NULL, *w;
+	struct snd_soc_dpm_path *path;
+	struct snd_soc_dpm_widget *src = NULL, *dest = NULL, *w;
 	struct list_head *l;
 	int ret = 0;
 
 	/* find src and dest widgets */
 	list_for_each(l, &codec->dpm_widgets)
 	{
-		w = list_entry(l, snd_soc_dpm_widget_t, list);
+		w = list_entry(l, struct snd_soc_dpm_widget, list);
 		
 		if(!(strcmp(w->name, dest_name))) {
 			dest = w;
@@ -179,10 +180,10 @@ int snd_soc_dpm_connect_input(snd_soc_co
 	if(src == NULL || dest == NULL)
 		return -ENODEV;
 	
-	path = kmalloc(sizeof(snd_soc_dpm_path_t), GFP_KERNEL);
+	path = kzalloc(sizeof(struct snd_soc_dpm_path), GFP_KERNEL);
 	if (!path)
 		return -ENOMEM;
-	memset(path, 0, sizeof(snd_soc_dpm_path_t));
+	
 	path->in = src;
 	path->out = dest;
 	INIT_LIST_HEAD(&path->list);
@@ -229,11 +230,11 @@ err:
 	return ret;
 }
 
-static int dpm_update_bits(snd_soc_dpm_widget_t *widget, int power)
+static int dpm_update_bits(struct snd_soc_dpm_widget *widget, int power)
 {
 	int change;
 	unsigned short old, new;
-	snd_soc_codec_t *codec = widget->codec;
+	struct snd_soc_codec *codec = widget->codec;
 	
 	if(widget->reg < 0 || widget->id == snd_soc_dpm_input ||
 		widget->id == snd_soc_dpm_output)
@@ -257,12 +258,12 @@ static int dpm_update_bits(snd_soc_dpm_w
 	return change;
 }
 
-static int dpm_sync_mixer(snd_soc_codec_t *codec, snd_soc_dpm_widget_t *w)
+static int dpm_sync_mixer(struct snd_soc_codec *codec, struct snd_soc_dpm_widget *w)
 {
 	int i, ret = 0;
 	char name[32];
 	struct list_head *lp;
-	snd_soc_dpm_path_t *path;
+	struct snd_soc_dpm_path *path;
 	
 	/* add kcontrol */
 	for (i = 0; i < w->num_kcontrols; i++) {
@@ -270,7 +271,7 @@ static int dpm_sync_mixer(snd_soc_codec_
 		/* match name */
 		list_for_each(lp, &w->inputs)
 		{
-			path = list_entry(lp, snd_soc_dpm_path_t, list_out);
+			path = list_entry(lp, struct snd_soc_dpm_path, list_out);
 			
 			if (path->name != (char*)w->kcontrols[i].name) 
 				continue;
@@ -293,10 +294,10 @@ static int dpm_sync_mixer(snd_soc_codec_
 	return ret;
 }
 
-static int dpm_sync_mux(snd_soc_codec_t *codec, snd_soc_dpm_widget_t *w)
+static int dpm_sync_mux(struct snd_soc_codec *codec, struct snd_soc_dpm_widget *w)
 {
 	struct list_head *lp;
-	snd_soc_dpm_path_t *path = NULL;
+	struct snd_soc_dpm_path *path = NULL;
 	snd_kcontrol_t *kcontrol;
 	int ret = 0;
 	
@@ -313,7 +314,7 @@ static int dpm_sync_mux(snd_soc_codec_t 
 
 	list_for_each(lp, &w->inputs)
 	{
-		path = list_entry(lp, snd_soc_dpm_path_t, list_out);
+		path = list_entry(lp, struct snd_soc_dpm_path, list_out);
 		path->kcontrol = kcontrol;
 	}
 	
@@ -323,14 +324,14 @@ static int dpm_sync_mux(snd_soc_codec_t 
 /*
  * Reset 'walked' bit for each path
  */
-static void dpm_clear_walk(snd_soc_codec_t *codec)
+static void dpm_clear_walk(struct snd_soc_codec *codec)
 {
-	snd_soc_dpm_path_t *p = NULL;
+	struct snd_soc_dpm_path *p = NULL;
 	struct list_head *l = NULL;
 		
 	list_for_each(l, &codec->dpm_paths)
 	{
-		p = list_entry(l, snd_soc_dpm_path_t, list);
+		p = list_entry(l, struct snd_soc_dpm_path, list);
 		p->walked = 0;		
 	}
 }
@@ -338,10 +339,10 @@ static void dpm_clear_walk(snd_soc_codec
 /*
  * Check for a completed path to an active or physically connected output widget
  */
-static int is_connected_output_ep(snd_soc_dpm_widget_t *widget)
+static int is_connected_output_ep(struct snd_soc_dpm_widget *widget)
 {
 	struct list_head *lp;
-	snd_soc_dpm_path_t *path = NULL;
+	struct snd_soc_dpm_path *path = NULL;
 	int con = 0;
 
 	if(widget->id == snd_soc_dpm_adc && widget->active)
@@ -351,7 +352,7 @@ static int is_connected_output_ep(snd_so
 	
 	list_for_each(lp, &widget->outputs)
 	{
-		path = list_entry(lp, snd_soc_dpm_path_t, list_in);
+		path = list_entry(lp, struct snd_soc_dpm_path, list_in);
 		if(path->walked)
 			continue;
 	
@@ -367,10 +368,10 @@ static int is_connected_output_ep(snd_so
 /*
  * Check for a completed path to an active or physically connected input widget
  */
-static int is_connected_input_ep(snd_soc_dpm_widget_t *widget)
+static int is_connected_input_ep(struct snd_soc_dpm_widget *widget)
 {
 	struct list_head *lp;
-	snd_soc_dpm_path_t *path = NULL;
+	struct snd_soc_dpm_path *path = NULL;
 	int con = 0;
 	
 	if(widget->id == snd_soc_dpm_dac && widget->active)
@@ -380,7 +381,7 @@ static int is_connected_input_ep(snd_soc
 	
 	list_for_each(lp, &widget->inputs)
 	{
-		path = list_entry(lp, snd_soc_dpm_path_t, list_out);
+		path = list_entry(lp, struct snd_soc_dpm_path, list_out);
 		if(path->walked)
 			continue;
 	
@@ -393,15 +394,15 @@ static int is_connected_input_ep(snd_soc
 	return con;
 }
 
-static int dpm_power_widgets(snd_soc_codec_t *codec)
+static int dpm_power_widgets(struct snd_soc_codec *codec)
 {
-	snd_soc_dpm_widget_t *w;
+	struct snd_soc_dpm_widget *w;
 	struct list_head *l;
 	int in, out, pm;
 	
 	list_for_each(l, &codec->dpm_widgets)
 	{
-		w = list_entry(l, snd_soc_dpm_widget_t, list);
+		w = list_entry(l, struct snd_soc_dpm_widget, list);
 		
 		if(w->id == snd_soc_dpm_vref || w->id == snd_soc_dpm_clock)
 			continue;
@@ -433,41 +434,44 @@ static int dpm_power_widgets(snd_soc_cod
 	return 0;
 }
 
-static int dpm_mux_update_power(snd_soc_dpm_widget_t *widget, 
+static int dpm_mux_update_power(struct snd_soc_dpm_widget *widget, 
 	snd_kcontrol_t *kcontrol, int mask, int val, struct soc_enum* e)
 {
 	struct list_head *l;
-	snd_soc_dpm_path_t *path;
+	struct snd_soc_dpm_path *path;
 	
 	if(widget->id != snd_soc_dpm_mux)
 		return -ENODEV; 
-		
+
 	if (!snd_soc_test_bits(widget->codec, e->reg, mask, val))
 		return 0;
 	
 	/* find dpm widget path assoc with kcontrol */
 	list_for_each(l, &widget->codec->dpm_paths)
 	{
-		path = list_entry(l, snd_soc_dpm_path_t, list);
+		path = list_entry(l, struct snd_soc_dpm_path, list);
 		if (path->kcontrol != kcontrol)
 			continue;
-		
+
+		if(!path->name || ! e->texts[val])
+			continue;
+
 		/* we now need to match the string in the enum to the path */
 		if (!(strcmp(path->name, e->texts[val])))
 			path->connect = 1; /* new connection */
 		else
-			path->connect = 0; /* old connection must be powered down */
+			path->connect = 0; /* old connection must be powered down */	
 	}
 	
 	dpm_power_widgets(widget->codec);			
 	return 0;
 }
 
-static int dpm_mixer_update_power(snd_soc_dpm_widget_t *widget, 
+static int dpm_mixer_update_power(struct snd_soc_dpm_widget *widget, 
 	snd_kcontrol_t *kcontrol, int reg, int val_mask, int val, int invert)
 {
 	struct list_head *l;
-	snd_soc_dpm_path_t *path;
+	struct snd_soc_dpm_path *path;
 
 	if(widget->id != snd_soc_dpm_mixer)
 		return -ENODEV; 
@@ -478,7 +482,7 @@ static int dpm_mixer_update_power(snd_so
 	/* find dpm widget path assoc with kcontrol */
 	list_for_each(l, &widget->codec->dpm_paths)
 	{
-		path = list_entry(l, snd_soc_dpm_path_t, list);
+		path = list_entry(l, struct snd_soc_dpm_path, list);
 		if (path->kcontrol != kcontrol)
 			continue;
 			
@@ -496,14 +500,14 @@ static int dpm_mixer_update_power(snd_so
 
 static ssize_t dpm_status_show(struct device *dev, struct device_attribute *attr, char *buf)   \
 {
-	snd_soc_codec_t *codec = (snd_soc_codec_t*)dev->driver_data;
-	snd_soc_dpm_widget_t *w = NULL;
+	struct snd_soc_codec *codec = (struct snd_soc_codec*)dev->driver_data;
+	struct snd_soc_dpm_widget *w = NULL;
 	struct list_head *l = NULL;
 	int count = 0; 
 
 	list_for_each(l, &codec->dpm_widgets)
 	{
-		w = list_entry(l, snd_soc_dpm_widget_t, list);
+		w = list_entry(l, struct snd_soc_dpm_widget, list);
 		if (w->name && w->reg > 0 && 
 			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");
@@ -529,14 +533,14 @@ void snd_soc_dpm_sys_remove(struct devic
 		device_remove_file(dev, &dev_attr_dpm);
 } 
 
-int snd_soc_dpm_sync(snd_soc_codec_t *codec)
+int snd_soc_dpm_sync(struct snd_soc_codec *codec)
 {
-	snd_soc_dpm_widget_t *w = NULL;
+	struct snd_soc_dpm_widget *w = NULL;
 	struct list_head *lw;
 	
 	list_for_each(lw, &codec->dpm_widgets)
 	{
-		w = list_entry(lw, snd_soc_dpm_widget_t, list);
+		w = list_entry(lw, struct snd_soc_dpm_widget, list);
 
 		switch(w->id) {
 			case snd_soc_dpm_mixer:
@@ -563,7 +567,7 @@ int snd_soc_dpm_sync(snd_soc_codec_t *co
 
 int snd_soc_dpm_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_soc_dpm_widget_t *widget = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dpm_widget *widget = snd_kcontrol_chip(kcontrol);
 	int reg = kcontrol->private_value & 0xff;
 	int shift = (kcontrol->private_value >> 8) & 0x0f;
 	int rshift = (kcontrol->private_value >> 12) & 0x0f;
@@ -584,7 +588,7 @@ int snd_soc_dpm_get_volsw(snd_kcontrol_t
 
 int snd_soc_dpm_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_soc_dpm_widget_t *widget = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dpm_widget *widget = snd_kcontrol_chip(kcontrol);
 	int reg = kcontrol->private_value & 0xff;
 	int shift = (kcontrol->private_value >> 8) & 0x0f;
 	int rshift = (kcontrol->private_value >> 12) & 0x0f;
@@ -609,15 +613,15 @@ int snd_soc_dpm_put_volsw(snd_kcontrol_t
 	return snd_soc_update_bits(widget->codec, reg, val_mask, val);
 }
 
-int snd_soc_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_soc_dpm_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_soc_codec_t *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dpm_widget *widget = snd_kcontrol_chip(kcontrol);
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	unsigned short val, bitmask;
 	
 	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
 		;
-	val = snd_soc_read(codec, e->reg);
+	val = snd_soc_read(widget->codec, e->reg);
 	ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
 	if (e->shift_l != e->shift_r)
 		ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (bitmask - 1);
@@ -627,16 +631,17 @@ int snd_soc_get_enum_double(snd_kcontrol
 
 int snd_soc_dpm_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_soc_dpm_widget_t *widget = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dpm_widget *widget = snd_kcontrol_chip(kcontrol);
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
-	unsigned short val;
+	unsigned short val, mux;
 	unsigned short mask, bitmask;
 	
 	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
 		;
 	if (ucontrol->value.enumerated.item[0] > e->mask - 1)
 		return -EINVAL;
-	val = ucontrol->value.enumerated.item[0] << e->shift_l;
+	mux = ucontrol->value.enumerated.item[0];
+	val = mux << e->shift_l;
 	mask = (bitmask - 1) << e->shift_l;
 	if (e->shift_l != e->shift_r) {
 		if (ucontrol->value.enumerated.item[1] > e->mask - 1)
@@ -644,14 +649,14 @@ int snd_soc_dpm_put_enum_double(snd_kcon
 		val |= ucontrol->value.enumerated.item[1] << e->shift_r;
 		mask |= (bitmask - 1) << e->shift_r;
 	}
-	
-	dpm_mux_update_power(widget, kcontrol, mask, val, e);
+
+	dpm_mux_update_power(widget, kcontrol, mask, mux, e);
 	return snd_soc_update_bits(widget->codec, e->reg, mask, val);
 }
 
-int snd_soc_dpm_new_control(snd_soc_codec_t *codec, const snd_soc_dpm_widget_t *widget)
+int snd_soc_dpm_new_control(struct snd_soc_codec *codec, const struct snd_soc_dpm_widget *widget)
 {
-	snd_soc_dpm_widget_t *w;
+	struct snd_soc_dpm_widget *w;
 
 	if ((w = dpm_cnew_widget(widget)) == NULL)
 		return -ENOMEM;
@@ -667,14 +672,14 @@ int snd_soc_dpm_new_control(snd_soc_code
 	return 0;
 }
 
-int snd_soc_dpm_stream_event(snd_soc_codec_t *codec, char * stream, int event)
+int snd_soc_dpm_stream_event(struct snd_soc_codec *codec, char * stream, int event)
 {
-	snd_soc_dpm_widget_t *w;
+	struct snd_soc_dpm_widget *w;
 	struct list_head *l = NULL;	
 	
 	list_for_each(l, &codec->dpm_widgets)
 	{
-		w = list_entry(l, snd_soc_dpm_widget_t, list);
+		w = list_entry(l, struct snd_soc_dpm_widget, list);
 
 		if (!w->sname)
 			continue;
@@ -700,9 +705,9 @@ int snd_soc_dpm_stream_event(snd_soc_cod
 	return 0;
 }
 
-int snd_soc_dpm_codec_event(snd_soc_codec_t *codec, int event)
+int snd_soc_dpm_codec_event(struct snd_soc_codec *codec, int event)
 {
-	snd_soc_dpm_widget_t *w;
+	struct snd_soc_dpm_widget *w;
 	struct list_head *l = NULL;	
 	int pm = 0, active = 0;
 
@@ -722,7 +727,7 @@ int snd_soc_dpm_codec_event(snd_soc_code
 	list_for_each(l, &codec->dpm_widgets)
 	{
 		int tpm = pm;
-		w = list_entry(l, snd_soc_dpm_widget_t, list);
+		w = list_entry(l, struct snd_soc_dpm_widget, list);
 		if(w->id == snd_soc_dpm_vref || w->id == snd_soc_dpm_clock) {
 			codec->active_streams += active;
 			

