Merge branch 'nfs-for-2.6.32'
[pandora-kernel.git] / sound / soc / codecs / wm8990.c
index d029818..2d702db 100644 (file)
@@ -108,53 +108,7 @@ static const u16 wm8990_reg[] = {
        0x0000,     /* R63 - Driver internal */
 };
 
-/*
- * read wm8990 register cache
- */
-static inline unsigned int wm8990_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-       BUG_ON(reg >= ARRAY_SIZE(wm8990_reg));
-       return cache[reg];
-}
-
-/*
- * write wm8990 register cache
- */
-static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-
-       /* Reset register and reserved registers are uncached */
-       if (reg == 0 || reg >= ARRAY_SIZE(wm8990_reg))
-               return;
-
-       cache[reg] = value;
-}
-
-/*
- * write to the wm8990 register space
- */
-static int wm8990_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int value)
-{
-       u8 data[3];
-
-       data[0] = reg & 0xFF;
-       data[1] = (value >> 8) & 0xFF;
-       data[2] = value & 0xFF;
-
-       wm8990_write_reg_cache(codec, reg, value);
-
-       if (codec->hw_write(codec->control_data, data, 3) == 2)
-               return 0;
-       else
-               return -EIO;
-}
-
-#define wm8990_reset(c) wm8990_write(c, WM8990_RESET, 0)
+#define wm8990_reset(c) snd_soc_write(c, WM8990_RESET, 0)
 
 static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600);
 
@@ -187,8 +141,8 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
                return ret;
 
        /* now hit the volume update bits (always bit 8) */
-       val = wm8990_read_reg_cache(codec, reg);
-       return wm8990_write(codec, reg, val | 0x0100);
+       val = snd_soc_read(codec, reg);
+       return snd_soc_write(codec, reg, val | 0x0100);
 }
 
 #define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\
@@ -427,8 +381,8 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
 {
        u16 reg, fakepower;
 
-       reg = wm8990_read_reg_cache(w->codec, WM8990_POWER_MANAGEMENT_2);
-       fakepower = wm8990_read_reg_cache(w->codec, WM8990_INTDRIVBITS);
+       reg = snd_soc_read(w->codec, WM8990_POWER_MANAGEMENT_2);
+       fakepower = snd_soc_read(w->codec, WM8990_INTDRIVBITS);
 
        if (fakepower & ((1 << WM8990_INMIXL_PWR_BIT) |
                (1 << WM8990_AINLMUX_PWR_BIT))) {
@@ -443,7 +397,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
        } else {
                reg &= ~WM8990_AINL_ENA;
        }
-       wm8990_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg);
+       snd_soc_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg);
 
        return 0;
 }
@@ -457,7 +411,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
 
        switch (reg_shift) {
        case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) :
-               reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER1);
+               reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER1);
                if (reg & WM8990_LDLO) {
                        printk(KERN_WARNING
                        "Cannot set as Output Mixer 1 LDLO Set\n");
@@ -465,7 +419,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
                }
                break;
        case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8):
-               reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER2);
+               reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER2);
                if (reg & WM8990_RDRO) {
                        printk(KERN_WARNING
                        "Cannot set as Output Mixer 2 RDRO Set\n");
@@ -473,7 +427,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
                }
                break;
        case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8):
-               reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER);
+               reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER);
                if (reg & WM8990_LDSPK) {
                        printk(KERN_WARNING
                        "Cannot set as Speaker Mixer LDSPK Set\n");
@@ -481,7 +435,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
                }
                break;
        case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8):
-               reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER);
+               reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER);
                if (reg & WM8990_RDSPK) {
                        printk(KERN_WARNING
                        "Cannot set as Speaker Mixer RDSPK Set\n");
@@ -1029,24 +983,24 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai,
                pll_factors(&pll_div, freq_out * 4, freq_in);
 
                /* Turn on PLL */
-               reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2);
+               reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
                reg |= WM8990_PLL_ENA;
-               wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
+               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
 
                /* sysclk comes from PLL */
-               reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2);
-               wm8990_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC);
+               reg = snd_soc_read(codec, WM8990_CLOCKING_2);
+               snd_soc_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC);
 
                /* set up N , fractional mode and pre-divisor if neccessary */
-               wm8990_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM |
+               snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM |
                        (pll_div.div2?WM8990_PRESCALE:0));
-               wm8990_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8));
-               wm8990_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF));
+               snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8));
+               snd_soc_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF));
        } else {
                /* Turn on PLL */
-               reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2);
+               reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
                reg &= ~WM8990_PLL_ENA;
-               wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
+               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
        }
        return 0;
 }
@@ -1073,8 +1027,8 @@ static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai,
        struct snd_soc_codec *codec = codec_dai->codec;
        u16 audio1, audio3;
 
-       audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1);
-       audio3 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_3);
+       audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1);
+       audio3 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_3);
 
        /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1115,8 +1069,8 @@ static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
-       wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
-       wm8990_write(codec, WM8990_AUDIO_INTERFACE_3, audio3);
+       snd_soc_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
+       snd_soc_write(codec, WM8990_AUDIO_INTERFACE_3, audio3);
        return 0;
 }
 
@@ -1128,24 +1082,24 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
 
        switch (div_id) {
        case WM8990_MCLK_DIV:
-               reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) &
+               reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
                        ~WM8990_MCLK_DIV_MASK;
-               wm8990_write(codec, WM8990_CLOCKING_2, reg | div);
+               snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
                break;
        case WM8990_DACCLK_DIV:
-               reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) &
+               reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
                        ~WM8990_DAC_CLKDIV_MASK;
-               wm8990_write(codec, WM8990_CLOCKING_2, reg | div);
+               snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
                break;
        case WM8990_ADCCLK_DIV:
-               reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) &
+               reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
                        ~WM8990_ADC_CLKDIV_MASK;
-               wm8990_write(codec, WM8990_CLOCKING_2, reg | div);
+               snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
                break;
        case WM8990_BCLK_DIV:
-               reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_1) &
+               reg = snd_soc_read(codec, WM8990_CLOCKING_1) &
                        ~WM8990_BCLK_DIV_MASK;
-               wm8990_write(codec, WM8990_CLOCKING_1, reg | div);
+               snd_soc_write(codec, WM8990_CLOCKING_1, reg | div);
                break;
        default:
                return -EINVAL;
@@ -1164,7 +1118,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_codec *codec = socdev->card->codec;
-       u16 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1);
+       u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1);
 
        audio1 &= ~WM8990_AIF_WL_MASK;
        /* bit size */
@@ -1182,7 +1136,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream,
                break;
        }
 
-       wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
+       snd_soc_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
        return 0;
 }
 
@@ -1191,12 +1145,12 @@ static int wm8990_mute(struct snd_soc_dai *dai, int mute)
        struct snd_soc_codec *codec = dai->codec;
        u16 val;
 
-       val  = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE;
+       val  = snd_soc_read(codec, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE;
 
        if (mute)
-               wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
+               snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
        else
-               wm8990_write(codec, WM8990_DAC_CTRL, val);
+               snd_soc_write(codec, WM8990_DAC_CTRL, val);
 
        return 0;
 }
@@ -1212,21 +1166,21 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
 
        case SND_SOC_BIAS_PREPARE:
                /* VMID=2*50k */
-               val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) &
+               val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
                        ~WM8990_VMID_MODE_MASK;
-               wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2);
+               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2);
                break;
 
        case SND_SOC_BIAS_STANDBY:
                if (codec->bias_level == SND_SOC_BIAS_OFF) {
                        /* Enable all output discharge bits */
-                       wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
+                       snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
                                WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
                                WM8990_DIS_OUT4 | WM8990_DIS_LOUT |
                                WM8990_DIS_ROUT);
 
                        /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */
-                       wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
+                       snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
                                     WM8990_BUFDCOPEN | WM8990_POBCTRL |
                                     WM8990_VMIDTOG);
 
@@ -1234,83 +1188,83 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
                        msleep(msecs_to_jiffies(300));
 
                        /* Disable VMIDTOG */
-                       wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
+                       snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
                                     WM8990_BUFDCOPEN | WM8990_POBCTRL);
 
                        /* disable all output discharge bits */
-                       wm8990_write(codec, WM8990_ANTIPOP1, 0);
+                       snd_soc_write(codec, WM8990_ANTIPOP1, 0);
 
                        /* Enable outputs */
-                       wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00);
+                       snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00);
 
                        msleep(msecs_to_jiffies(50));
 
                        /* Enable VMID at 2x50k */
-                       wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02);
+                       snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02);
 
                        msleep(msecs_to_jiffies(100));
 
                        /* Enable VREF */
-                       wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
+                       snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
 
                        msleep(msecs_to_jiffies(600));
 
                        /* Enable BUFIOEN */
-                       wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
+                       snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
                                     WM8990_BUFDCOPEN | WM8990_POBCTRL |
                                     WM8990_BUFIOEN);
 
                        /* Disable outputs */
-                       wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x3);
+                       snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x3);
 
                        /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
-                       wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN);
+                       snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN);
 
                        /* Enable workaround for ADC clocking issue. */
-                       wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0x2);
-                       wm8990_write(codec, WM8990_EXT_CTL1, 0xa003);
-                       wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0);
+                       snd_soc_write(codec, WM8990_EXT_ACCESS_ENA, 0x2);
+                       snd_soc_write(codec, WM8990_EXT_CTL1, 0xa003);
+                       snd_soc_write(codec, WM8990_EXT_ACCESS_ENA, 0);
                }
 
                /* VMID=2*250k */
-               val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) &
+               val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
                        ~WM8990_VMID_MODE_MASK;
-               wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4);
+               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4);
                break;
 
        case SND_SOC_BIAS_OFF:
                /* Enable POBCTRL and SOFT_ST */
-               wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
+               snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
                        WM8990_POBCTRL | WM8990_BUFIOEN);
 
                /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */
-               wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
+               snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
                        WM8990_BUFDCOPEN | WM8990_POBCTRL |
                        WM8990_BUFIOEN);
 
                /* mute DAC */
-               val = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL);
-               wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
+               val = snd_soc_read(codec, WM8990_DAC_CTRL);
+               snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
 
                /* Enable any disabled outputs */
-               wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
+               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
 
                /* Disable VMID */
-               wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01);
+               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01);
 
                msleep(msecs_to_jiffies(300));
 
                /* Enable all output discharge bits */
-               wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
+               snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
                        WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
                        WM8990_DIS_OUT4 | WM8990_DIS_LOUT |
                        WM8990_DIS_ROUT);
 
                /* Disable VREF */
-               wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x0);
+               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x0);
 
                /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
-               wm8990_write(codec, WM8990_ANTIPOP2, 0x0);
+               snd_soc_write(codec, WM8990_ANTIPOP2, 0x0);
                break;
        }
 
@@ -1411,8 +1365,6 @@ static int wm8990_init(struct snd_soc_device *socdev)
 
        codec->name = "WM8990";
        codec->owner = THIS_MODULE;
-       codec->read = wm8990_read_reg_cache;
-       codec->write = wm8990_write;
        codec->set_bias_level = wm8990_set_bias_level;
        codec->dai = &wm8990_dai;
        codec->num_dai = 2;
@@ -1422,6 +1374,12 @@ static int wm8990_init(struct snd_soc_device *socdev)
        if (codec->reg_cache == NULL)
                return -ENOMEM;
 
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       if (ret < 0) {
+               printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret);
+               goto pcm_err;
+       }
+
        wm8990_reset(codec);
 
        /* register pcms */
@@ -1435,18 +1393,18 @@ static int wm8990_init(struct snd_soc_device *socdev)
        codec->bias_level = SND_SOC_BIAS_OFF;
        wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       reg = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_4);
-       wm8990_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1);
+       reg = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_4);
+       snd_soc_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1);
 
-       reg = wm8990_read_reg_cache(codec, WM8990_GPIO1_GPIO2) &
+       reg = snd_soc_read(codec, WM8990_GPIO1_GPIO2) &
                ~WM8990_GPIO1_SEL_MASK;
-       wm8990_write(codec, WM8990_GPIO1_GPIO2, reg | 1);
+       snd_soc_write(codec, WM8990_GPIO1_GPIO2, reg | 1);
 
-       reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2);
-       wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA);
+       reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
+       snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA);
 
-       wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
-       wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
+       snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
+       snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
 
        snd_soc_add_controls(codec, wm8990_snd_controls,
                                ARRAY_SIZE(wm8990_snd_controls));