extern struct snd_ac97_bus_ops soc_ac97_ops;
 
+enum snd_soc_control_type {
+       SND_SOC_CUSTOM,
+       SND_SOC_I2C,
+       SND_SOC_SPI,
+};
+
 int snd_soc_register_platform(struct snd_soc_platform *platform);
 void snd_soc_unregister_platform(struct snd_soc_platform *platform);
 int snd_soc_register_codec(struct snd_soc_codec *codec);
 void snd_soc_unregister_codec(struct snd_soc_codec *codec);
 int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg);
 int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
-                              int addr_bits, int data_bits);
+                              int addr_bits, int data_bits,
+                              enum snd_soc_control_type control);
 
 #ifdef CONFIG_PM
 int snd_soc_suspend_device(struct device *dev);
 
  * initialise the WM8510 driver
  * register the mixer and dsp interfaces with the kernel
  */
-static int wm8510_init(struct snd_soc_device *socdev)
+static int wm8510_init(struct snd_soc_device *socdev,
+                      enum snd_soc_control_type control)
 {
        struct snd_soc_codec *codec = socdev->card->codec;
        int ret = 0;
        if (codec->reg_cache == NULL)
                return -ENOMEM;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
        if (ret < 0) {
                printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n",
                       ret);
        i2c_set_clientdata(i2c, codec);
        codec->control_data = i2c;
 
-       ret = wm8510_init(socdev);
+       ret = wm8510_init(socdev, SND_SOC_I2C);
        if (ret < 0)
                pr_err("failed to initialise WM8510\n");
 
 
        codec->control_data = spi;
 
-       ret = wm8510_init(socdev);
+       ret = wm8510_init(socdev, SND_SOC_SPI);
        if (ret < 0)
                dev_err(&spi->dev, "failed to initialise WM8510\n");
 
        wm8510_socdev = socdev;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        if (setup->i2c_address) {
-               codec->hw_write = (hw_write_t)i2c_master_send;
                ret = wm8510_add_i2c_device(pdev, setup);
        }
 #endif
 
 };
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
 
-static int wm8580_register(struct wm8580_priv *wm8580)
+static int wm8580_register(struct wm8580_priv *wm8580,
+                          enum snd_soc_control_type control)
 {
        int ret, i;
        struct snd_soc_codec *codec = &wm8580->codec;
 
        memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg));
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                goto err;
                return -ENOMEM;
 
        codec = &wm8580->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
 
        i2c_set_clientdata(i2c, wm8580);
        codec->control_data = i2c;
 
        codec->dev = &i2c->dev;
 
-       return wm8580_register(wm8580);
+       return wm8580_register(wm8580, SND_SOC_I2C);
 }
 
 static int wm8580_i2c_remove(struct i2c_client *client)
 
  * initialise the WM8728 driver
  * register the mixer and dsp interfaces with the kernel
  */
-static int wm8728_init(struct snd_soc_device *socdev)
+static int wm8728_init(struct snd_soc_device *socdev,
+                      enum snd_soc_control_type control)
 {
        struct snd_soc_codec *codec = socdev->card->codec;
        int ret = 0;
        if (codec->reg_cache == NULL)
                return -ENOMEM;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
        if (ret < 0) {
                printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n",
                       ret);
        i2c_set_clientdata(i2c, codec);
        codec->control_data = i2c;
 
-       ret = wm8728_init(socdev);
+       ret = wm8728_init(socdev, SND_SOC_I2C);
        if (ret < 0)
                pr_err("failed to initialise WM8728\n");
 
 
        codec->control_data = spi;
 
-       ret = wm8728_init(socdev);
+       ret = wm8728_init(socdev, SND_SOC_SPI);
        if (ret < 0)
                dev_err(&spi->dev, "failed to initialise WM8728\n");
 
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        if (setup->i2c_address) {
-               codec->hw_write = (hw_write_t)i2c_master_send;
                ret = wm8728_add_i2c_device(pdev, setup);
        }
 #endif
 
 };
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
 
-static int wm8731_register(struct wm8731_priv *wm8731)
+static int wm8731_register(struct wm8731_priv *wm8731,
+                          enum snd_soc_control_type control)
 {
        int ret;
        struct snd_soc_codec *codec = &wm8731->codec;
 
        memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg));
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                goto err;
 
        dev_set_drvdata(&spi->dev, wm8731);
 
-       return wm8731_register(wm8731);
+       return wm8731_register(wm8731, SND_SOC_SPI);
 }
 
 static int __devexit wm8731_spi_remove(struct spi_device *spi)
                return -ENOMEM;
 
        codec = &wm8731->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
 
        i2c_set_clientdata(i2c, wm8731);
        codec->control_data = i2c;
 
        codec->dev = &i2c->dev;
 
-       return wm8731_register(wm8731);
+       return wm8731_register(wm8731, SND_SOC_I2C);
 }
 
 static __devexit int wm8731_i2c_remove(struct i2c_client *client)
 
  * initialise the WM8750 driver
  * register the mixer and dsp interfaces with the kernel
  */
-static int wm8750_init(struct snd_soc_device *socdev)
+static int wm8750_init(struct snd_soc_device *socdev,
+                      enum snd_soc_control_type control)
 {
        struct snd_soc_codec *codec = socdev->card->codec;
        int reg, ret = 0;
        if (codec->reg_cache == NULL)
                return -ENOMEM;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
        if (ret < 0) {
                printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
                goto err;
        i2c_set_clientdata(i2c, codec);
        codec->control_data = i2c;
 
-       ret = wm8750_init(socdev);
+       ret = wm8750_init(socdev, SND_SOC_I2C);
        if (ret < 0)
                pr_err("failed to initialise WM8750\n");
 
 
        codec->control_data = spi;
 
-       ret = wm8750_init(socdev);
+       ret = wm8750_init(socdev, SND_SOC_SPI);
        if (ret < 0)
                dev_err(&spi->dev, "failed to initialise WM8750\n");
 
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        if (setup->i2c_address) {
-               codec->hw_write = (hw_write_t)i2c_master_send;
                ret = wm8750_add_i2c_device(pdev, setup);
        }
 #endif
 
 };
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960);
 
-static int wm8960_register(struct wm8960_priv *wm8960)
+static int wm8960_register(struct wm8960_priv *wm8960,
+                          enum snd_soc_control_type control)
 {
        struct wm8960_data *pdata = wm8960->codec.dev->platform_data;
        struct snd_soc_codec *codec = &wm8960->codec;
 
        memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg));
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                goto err;
                return -ENOMEM;
 
        codec = &wm8960->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
 
        i2c_set_clientdata(i2c, wm8960);
        codec->control_data = i2c;
 
        codec->dev = &i2c->dev;
 
-       return wm8960_register(wm8960);
+       return wm8960_register(wm8960, SND_SOC_I2C);
 }
 
 static __devexit int wm8960_i2c_remove(struct i2c_client *client)
 
        return 0;
 }
 
-static int wm8971_init(struct snd_soc_device *socdev)
+static int wm8971_init(struct snd_soc_device *socdev,
+                      enum snd_soc_control_type control)
 {
        struct snd_soc_codec *codec = socdev->card->codec;
        int reg, ret = 0;
        if (codec->reg_cache == NULL)
                return -ENOMEM;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
        if (ret < 0) {
                printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
                goto err;
 
        codec->control_data = i2c;
 
-       ret = wm8971_init(socdev);
+       ret = wm8971_init(socdev, SND_SOC_I2C);
        if (ret < 0)
                pr_err("failed to initialise WM8971\n");
 
 
 #if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
        if (setup->i2c_address) {
-               codec->hw_write = (hw_write_t)i2c_master_send;
                ret = wm8971_add_i2c_device(pdev, setup);
        }
 #endif
 
 };
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988);
 
-static int wm8988_register(struct wm8988_priv *wm8988)
+static int wm8988_register(struct wm8988_priv *wm8988,
+                          enum snd_soc_control_type control)
 {
        struct snd_soc_codec *codec = &wm8988->codec;
        int ret;
        memcpy(codec->reg_cache, wm8988_reg,
               sizeof(wm8988_reg));
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                goto err;
                return -ENOMEM;
 
        codec = &wm8988->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
 
        i2c_set_clientdata(i2c, wm8988);
        codec->control_data = i2c;
 
        codec->dev = &i2c->dev;
 
-       return wm8988_register(wm8988);
+       return wm8988_register(wm8988, SND_SOC_I2C);
 }
 
 static int wm8988_i2c_remove(struct i2c_client *client)
 
        spi->dev.driver_data = wm8988;
 
-       return wm8988_register(wm8988);
+       return wm8988_register(wm8988, SND_SOC_SPI);
 }
 
 static int __devexit wm8988_spi_remove(struct spi_device *spi)
 
  *  option) any later version.
  */
 
+#include <linux/i2c.h>
 #include <sound/soc.h>
 
 static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
  * @type: Type of cache.
  * @addr_bits: Number of bits of register address data.
  * @data_bits: Number of bits of data per register.
+ * @control: Control bus used.
  *
  * Register formats are frequently shared between many I2C and SPI
  * devices.  In order to promote code reuse the ASoC core provides
  * volatile registers.
  */
 int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
-                              int addr_bits, int data_bits)
+                              int addr_bits, int data_bits,
+                              enum snd_soc_control_type control)
 {
        int i;
 
        codec->write = io_types[i].write;
        codec->read = io_types[i].read;
 
+       switch (control) {
+       case SND_SOC_CUSTOM:
+               break;
+
+       case SND_SOC_I2C:
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+               codec->hw_write = (hw_write_t)i2c_master_send;
+#endif
+               break;
+
+       case SND_SOC_SPI:
+               break;
+       }
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);