Merge branch 'topic/snd-printk' into for-linus
[pandora-kernel.git] / sound / soc / codecs / wm8903.c
index e8d2e3e..fe1307b 100644 (file)
@@ -225,94 +225,18 @@ struct wm8903_priv {
        struct snd_pcm_substream *slave_substream;
 };
 
-
-static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec,
-                                                unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-
-       BUG_ON(reg >= ARRAY_SIZE(wm8903_reg_defaults));
-
-       return cache[reg];
-}
-
-static unsigned int wm8903_hw_read(struct snd_soc_codec *codec, u8 reg)
-{
-       struct i2c_msg xfer[2];
-       u16 data;
-       int ret;
-       struct i2c_client *client = codec->control_data;
-
-       /* Write register */
-       xfer[0].addr = client->addr;
-       xfer[0].flags = 0;
-       xfer[0].len = 1;
-       xfer[0].buf = ®
-
-       /* Read data */
-       xfer[1].addr = client->addr;
-       xfer[1].flags = I2C_M_RD;
-       xfer[1].len = 2;
-       xfer[1].buf = (u8 *)&data;
-
-       ret = i2c_transfer(client->adapter, xfer, 2);
-       if (ret != 2) {
-               pr_err("i2c_transfer returned %d\n", ret);
-               return 0;
-       }
-
-       return (data >> 8) | ((data & 0xff) << 8);
-}
-
-static unsigned int wm8903_read(struct snd_soc_codec *codec,
-                               unsigned int reg)
+static int wm8903_volatile_register(unsigned int reg)
 {
        switch (reg) {
        case WM8903_SW_RESET_AND_ID:
        case WM8903_REVISION_NUMBER:
        case WM8903_INTERRUPT_STATUS_1:
        case WM8903_WRITE_SEQUENCER_4:
-               return wm8903_hw_read(codec, reg);
+               return 1;
 
        default:
-               return wm8903_read_reg_cache(codec, reg);
-       }
-}
-
-static void wm8903_write_reg_cache(struct snd_soc_codec *codec,
-                                  u16 reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-
-       BUG_ON(reg >= ARRAY_SIZE(wm8903_reg_defaults));
-
-       switch (reg) {
-       case WM8903_SW_RESET_AND_ID:
-       case WM8903_REVISION_NUMBER:
-               break;
-
-       default:
-               cache[reg] = value;
-               break;
-       }
-}
-
-static int wm8903_write(struct snd_soc_codec *codec, unsigned int reg,
-                       unsigned int value)
-{
-       u8 data[3];
-
-       wm8903_write_reg_cache(codec, reg, value);
-
-       /* Data format is 1 byte of address followed by 2 bytes of data */
-       data[0] = reg;
-       data[1] = (value >> 8) & 0xff;
-       data[2] = value & 0xff;
-
-       if (codec->hw_write(codec->control_data, data, 3) == 2)
                return 0;
-       else
-               return -EIO;
+       }
 }
 
 static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
@@ -323,13 +247,13 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
        BUG_ON(start > 48);
 
        /* Enable the sequencer */
-       reg[0] = wm8903_read(codec, WM8903_WRITE_SEQUENCER_0);
+       reg[0] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_0);
        reg[0] |= WM8903_WSEQ_ENA;
-       wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]);
+       snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]);
 
        dev_dbg(&i2c->dev, "Starting sequence at %d\n", start);
 
-       wm8903_write(codec, WM8903_WRITE_SEQUENCER_3,
+       snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3,
                     start | WM8903_WSEQ_START);
 
        /* Wait for it to complete.  If we have the interrupt wired up then
@@ -339,13 +263,13 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
        do {
                msleep(10);
 
-               reg[4] = wm8903_read(codec, WM8903_WRITE_SEQUENCER_4);
+               reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4);
        } while (reg[4] & WM8903_WSEQ_BUSY);
 
        dev_dbg(&i2c->dev, "Sequence complete\n");
 
        /* Disable the sequencer again */
-       wm8903_write(codec, WM8903_WRITE_SEQUENCER_0,
+       snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0,
                     reg[0] & ~WM8903_WSEQ_ENA);
 
        return 0;
@@ -357,12 +281,12 @@ static void wm8903_sync_reg_cache(struct snd_soc_codec *codec, u16 *cache)
 
        /* There really ought to be something better we can do here :/ */
        for (i = 0; i < ARRAY_SIZE(wm8903_reg_defaults); i++)
-               cache[i] = wm8903_hw_read(codec, i);
+               cache[i] = codec->hw_read(codec, i);
 }
 
 static void wm8903_reset(struct snd_soc_codec *codec)
 {
-       wm8903_write(codec, WM8903_SW_RESET_AND_ID, 0);
+       snd_soc_write(codec, WM8903_SW_RESET_AND_ID, 0);
        memcpy(codec->reg_cache, wm8903_reg_defaults,
               sizeof(wm8903_reg_defaults));
 }
@@ -423,52 +347,52 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
        }
 
        if (event & SND_SOC_DAPM_PRE_PMU) {
-               val = wm8903_read(codec, reg);
+               val = snd_soc_read(codec, reg);
 
                /* Short the output */
                val &= ~(WM8903_OUTPUT_SHORT << shift);
-               wm8903_write(codec, reg, val);
+               snd_soc_write(codec, reg, val);
        }
 
        if (event & SND_SOC_DAPM_POST_PMU) {
-               val = wm8903_read(codec, reg);
+               val = snd_soc_read(codec, reg);
 
                val |= (WM8903_OUTPUT_IN << shift);
-               wm8903_write(codec, reg, val);
+               snd_soc_write(codec, reg, val);
 
                val |= (WM8903_OUTPUT_INT << shift);
-               wm8903_write(codec, reg, val);
+               snd_soc_write(codec, reg, val);
 
                /* Turn on the output ENA_OUTP */
                val |= (WM8903_OUTPUT_OUT << shift);
-               wm8903_write(codec, reg, val);
+               snd_soc_write(codec, reg, val);
 
                /* Enable the DC servo */
-               dcs_reg = wm8903_read(codec, WM8903_DC_SERVO_0);
+               dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0);
                dcs_reg |= dcs_bit;
-               wm8903_write(codec, WM8903_DC_SERVO_0, dcs_reg);
+               snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg);
 
                /* Remove the short */
                val |= (WM8903_OUTPUT_SHORT << shift);
-               wm8903_write(codec, reg, val);
+               snd_soc_write(codec, reg, val);
        }
 
        if (event & SND_SOC_DAPM_PRE_PMD) {
-               val = wm8903_read(codec, reg);
+               val = snd_soc_read(codec, reg);
 
                /* Short the output */
                val &= ~(WM8903_OUTPUT_SHORT << shift);
-               wm8903_write(codec, reg, val);
+               snd_soc_write(codec, reg, val);
 
                /* Disable the DC servo */
-               dcs_reg = wm8903_read(codec, WM8903_DC_SERVO_0);
+               dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0);
                dcs_reg &= ~dcs_bit;
-               wm8903_write(codec, WM8903_DC_SERVO_0, dcs_reg);
+               snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg);
 
                /* Then disable the intermediate and output stages */
                val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT |
                          WM8903_OUTPUT_IN) << shift);
-               wm8903_write(codec, reg, val);
+               snd_soc_write(codec, reg, val);
        }
 
        return 0;
@@ -492,13 +416,13 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
        u16 reg;
        int ret;
 
-       reg = wm8903_read(codec, WM8903_CLASS_W_0);
+       reg = snd_soc_read(codec, WM8903_CLASS_W_0);
 
        /* Turn it off if we're about to enable bypass */
        if (ucontrol->value.integer.value[0]) {
                if (wm8903->class_w_users == 0) {
                        dev_dbg(&i2c->dev, "Disabling Class W\n");
-                       wm8903_write(codec, WM8903_CLASS_W_0, reg &
+                       snd_soc_write(codec, WM8903_CLASS_W_0, reg &
                                     ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V));
                }
                wm8903->class_w_users++;
@@ -511,7 +435,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
        if (!ucontrol->value.integer.value[0]) {
                if (wm8903->class_w_users == 1) {
                        dev_dbg(&i2c->dev, "Enabling Class W\n");
-                       wm8903_write(codec, WM8903_CLASS_W_0, reg |
+                       snd_soc_write(codec, WM8903_CLASS_W_0, reg |
                                     WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
                }
                wm8903->class_w_users--;
@@ -715,8 +639,6 @@ SOC_ENUM("DAC Soft Mute Rate", soft_mute),
 SOC_ENUM("DAC Mute Mode", mute_mode),
 SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0),
 SOC_ENUM("DAC De-emphasis", dac_deemphasis),
-SOC_SINGLE("DAC Sloping Stopband Filter Switch",
-          WM8903_DAC_DIGITAL_1, 11, 1, 0),
 SOC_ENUM("DAC Companding Mode", dac_companding),
 SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0),
 
@@ -1011,55 +933,55 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,
        switch (level) {
        case SND_SOC_BIAS_ON:
        case SND_SOC_BIAS_PREPARE:
-               reg = wm8903_read(codec, WM8903_VMID_CONTROL_0);
+               reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0);
                reg &= ~(WM8903_VMID_RES_MASK);
                reg |= WM8903_VMID_RES_50K;
-               wm8903_write(codec, WM8903_VMID_CONTROL_0, reg);
+               snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg);
                break;
 
        case SND_SOC_BIAS_STANDBY:
                if (codec->bias_level == SND_SOC_BIAS_OFF) {
-                       wm8903_write(codec, WM8903_CLOCK_RATES_2,
+                       snd_soc_write(codec, WM8903_CLOCK_RATES_2,
                                     WM8903_CLK_SYS_ENA);
 
                        /* Change DC servo dither level in startup sequence */
-                       wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, 0x11);
-                       wm8903_write(codec, WM8903_WRITE_SEQUENCER_1, 0x1257);
-                       wm8903_write(codec, WM8903_WRITE_SEQUENCER_2, 0x2);
+                       snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, 0x11);
+                       snd_soc_write(codec, WM8903_WRITE_SEQUENCER_1, 0x1257);
+                       snd_soc_write(codec, WM8903_WRITE_SEQUENCER_2, 0x2);
 
                        wm8903_run_sequence(codec, 0);
                        wm8903_sync_reg_cache(codec, codec->reg_cache);
 
                        /* Enable low impedence charge pump output */
-                       reg = wm8903_read(codec,
+                       reg = snd_soc_read(codec,
                                          WM8903_CONTROL_INTERFACE_TEST_1);
-                       wm8903_write(codec, WM8903_CONTROL_INTERFACE_TEST_1,
+                       snd_soc_write(codec, WM8903_CONTROL_INTERFACE_TEST_1,
                                     reg | WM8903_TEST_KEY);
-                       reg2 = wm8903_read(codec, WM8903_CHARGE_PUMP_TEST_1);
-                       wm8903_write(codec, WM8903_CHARGE_PUMP_TEST_1,
+                       reg2 = snd_soc_read(codec, WM8903_CHARGE_PUMP_TEST_1);
+                       snd_soc_write(codec, WM8903_CHARGE_PUMP_TEST_1,
                                     reg2 | WM8903_CP_SW_KELVIN_MODE_MASK);
-                       wm8903_write(codec, WM8903_CONTROL_INTERFACE_TEST_1,
+                       snd_soc_write(codec, WM8903_CONTROL_INTERFACE_TEST_1,
                                     reg);
 
                        /* By default no bypass paths are enabled so
                         * enable Class W support.
                         */
                        dev_dbg(&i2c->dev, "Enabling Class W\n");
-                       wm8903_write(codec, WM8903_CLASS_W_0, reg |
+                       snd_soc_write(codec, WM8903_CLASS_W_0, reg |
                                     WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
                }
 
-               reg = wm8903_read(codec, WM8903_VMID_CONTROL_0);
+               reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0);
                reg &= ~(WM8903_VMID_RES_MASK);
                reg |= WM8903_VMID_RES_250K;
-               wm8903_write(codec, WM8903_VMID_CONTROL_0, reg);
+               snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg);
                break;
 
        case SND_SOC_BIAS_OFF:
                wm8903_run_sequence(codec, 32);
-               reg = wm8903_read(codec, WM8903_CLOCK_RATES_2);
+               reg = snd_soc_read(codec, WM8903_CLOCK_RATES_2);
                reg &= ~WM8903_CLK_SYS_ENA;
-               wm8903_write(codec, WM8903_CLOCK_RATES_2, reg);
+               snd_soc_write(codec, WM8903_CLOCK_RATES_2, reg);
                break;
        }
 
@@ -1083,7 +1005,7 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai,
                              unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
-       u16 aif1 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_1);
+       u16 aif1 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_1);
 
        aif1 &= ~(WM8903_LRCLK_DIR | WM8903_BCLK_DIR | WM8903_AIF_FMT_MASK |
                  WM8903_AIF_LRCLK_INV | WM8903_AIF_BCLK_INV);
@@ -1161,7 +1083,7 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
-       wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
+       snd_soc_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
 
        return 0;
 }
@@ -1171,14 +1093,14 @@ static int wm8903_digital_mute(struct snd_soc_dai *codec_dai, int mute)
        struct snd_soc_codec *codec = codec_dai->codec;
        u16 reg;
 
-       reg = wm8903_read(codec, WM8903_DAC_DIGITAL_1);
+       reg = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
 
        if (mute)
                reg |= WM8903_DAC_MUTE;
        else
                reg &= ~WM8903_DAC_MUTE;
 
-       wm8903_write(codec, WM8903_DAC_DIGITAL_1, reg);
+       snd_soc_write(codec, WM8903_DAC_DIGITAL_1, reg);
 
        return 0;
 }
@@ -1368,17 +1290,24 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
        int cur_val;
        int clk_sys;
 
-       u16 aif1 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_1);
-       u16 aif2 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_2);
-       u16 aif3 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_3);
-       u16 clock0 = wm8903_read(codec, WM8903_CLOCK_RATES_0);
-       u16 clock1 = wm8903_read(codec, WM8903_CLOCK_RATES_1);
+       u16 aif1 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_1);
+       u16 aif2 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_2);
+       u16 aif3 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_3);
+       u16 clock0 = snd_soc_read(codec, WM8903_CLOCK_RATES_0);
+       u16 clock1 = snd_soc_read(codec, WM8903_CLOCK_RATES_1);
+       u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
 
        if (substream == wm8903->slave_substream) {
                dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n");
                return 0;
        }
 
+       /* Enable sloping stopband filter for low sample rates */
+       if (fs <= 24000)
+               dac_digital1 |= WM8903_DAC_SB_FILT;
+       else
+               dac_digital1 &= ~WM8903_DAC_SB_FILT;
+
        /* Configure sample rate logic for DSP - choose nearest rate */
        dsp_config = 0;
        best_val = abs(sample_rates[dsp_config].rate - fs);
@@ -1498,11 +1427,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
        aif2 |= bclk_divs[bclk_div].div;
        aif3 |= bclk / fs;
 
-       wm8903_write(codec, WM8903_CLOCK_RATES_0, clock0);
-       wm8903_write(codec, WM8903_CLOCK_RATES_1, clock1);
-       wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
-       wm8903_write(codec, WM8903_AUDIO_INTERFACE_2, aif2);
-       wm8903_write(codec, WM8903_AUDIO_INTERFACE_3, aif3);
+       snd_soc_write(codec, WM8903_CLOCK_RATES_0, clock0);
+       snd_soc_write(codec, WM8903_CLOCK_RATES_1, clock1);
+       snd_soc_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
+       snd_soc_write(codec, WM8903_AUDIO_INTERFACE_2, aif2);
+       snd_soc_write(codec, WM8903_AUDIO_INTERFACE_3, aif3);
+       snd_soc_write(codec, WM8903_DAC_DIGITAL_1, dac_digital1);
 
        return 0;
 }
@@ -1587,7 +1517,7 @@ static int wm8903_resume(struct platform_device *pdev)
        if (tmp_cache) {
                for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++)
                        if (tmp_cache[i] != reg_cache[i])
-                               wm8903_write(codec, i, tmp_cache[i]);
+                               snd_soc_write(codec, i, tmp_cache[i]);
        } else {
                dev_err(&i2c->dev, "Failed to allocate temporary cache\n");
        }
@@ -1618,9 +1548,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
        codec->dev = &i2c->dev;
        codec->name = "WM8903";
        codec->owner = THIS_MODULE;
-       codec->read = wm8903_read;
-       codec->write = wm8903_write;
-       codec->hw_write = (hw_write_t)i2c_master_send;
        codec->bias_level = SND_SOC_BIAS_OFF;
        codec->set_bias_level = wm8903_set_bias_level;
        codec->dai = &wm8903_dai;
@@ -1628,18 +1555,25 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
        codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache);
        codec->reg_cache = &wm8903->reg_cache[0];
        codec->private_data = wm8903;
+       codec->volatile_register = wm8903_volatile_register;
 
        i2c_set_clientdata(i2c, codec);
        codec->control_data = i2c;
 
-       val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret);
+               goto err;
+       }
+
+       val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID);
        if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
                dev_err(&i2c->dev,
                        "Device with ID register %x is not a WM8903\n", val);
                return -ENODEV;
        }
 
-       val = wm8903_read(codec, WM8903_REVISION_NUMBER);
+       val = snd_soc_read(codec, WM8903_REVISION_NUMBER);
        dev_info(&i2c->dev, "WM8903 revision %d\n",
                 val & WM8903_CHIP_REV_MASK);
 
@@ -1649,35 +1583,35 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
        wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* Latch volume update bits */
-       val = wm8903_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT);
+       val = snd_soc_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT);
        val |= WM8903_ADCVU;
-       wm8903_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val);
-       wm8903_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val);
+       snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val);
+       snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val);
 
-       val = wm8903_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT);
+       val = snd_soc_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT);
        val |= WM8903_DACVU;
-       wm8903_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val);
-       wm8903_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val);
+       snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val);
+       snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val);
 
-       val = wm8903_read(codec, WM8903_ANALOGUE_OUT1_LEFT);
+       val = snd_soc_read(codec, WM8903_ANALOGUE_OUT1_LEFT);
        val |= WM8903_HPOUTVU;
-       wm8903_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val);
-       wm8903_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val);
+       snd_soc_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val);
+       snd_soc_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val);
 
-       val = wm8903_read(codec, WM8903_ANALOGUE_OUT2_LEFT);
+       val = snd_soc_read(codec, WM8903_ANALOGUE_OUT2_LEFT);
        val |= WM8903_LINEOUTVU;
-       wm8903_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val);
-       wm8903_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val);
+       snd_soc_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val);
+       snd_soc_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val);
 
-       val = wm8903_read(codec, WM8903_ANALOGUE_OUT3_LEFT);
+       val = snd_soc_read(codec, WM8903_ANALOGUE_OUT3_LEFT);
        val |= WM8903_SPKVU;
-       wm8903_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val);
-       wm8903_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val);
+       snd_soc_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val);
+       snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val);
 
        /* Enable DAC soft mute by default */
-       val = wm8903_read(codec, WM8903_DAC_DIGITAL_1);
+       val = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
        val |= WM8903_DAC_MUTEMODE;
-       wm8903_write(codec, WM8903_DAC_DIGITAL_1, val);
+       snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val);
 
        wm8903_dai.dev = &i2c->dev;
        wm8903_codec = codec;
@@ -1721,6 +1655,21 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm8903_i2c_suspend(struct i2c_client *client, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&client->dev);
+}
+
+static int wm8903_i2c_resume(struct i2c_client *client)
+{
+       return snd_soc_resume_device(&client->dev);
+}
+#else
+#define wm8903_i2c_suspend NULL
+#define wm8903_i2c_resume NULL
+#endif
+
 /* i2c codec control layer */
 static const struct i2c_device_id wm8903_i2c_id[] = {
        { "wm8903", 0 },
@@ -1735,6 +1684,8 @@ static struct i2c_driver wm8903_i2c_driver = {
        },
        .probe    = wm8903_i2c_probe,
        .remove   = __devexit_p(wm8903_i2c_remove),
+       .suspend  = wm8903_i2c_suspend,
+       .resume   = wm8903_i2c_resume,
        .id_table = wm8903_i2c_id,
 };