OSDN Git Service

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
authorYoshinori Sato <ysato@users.sourceforge.jp>
Sun, 1 Jan 2012 14:38:17 +0000 (23:38 +0900)
committerYoshinori Sato <ysato@users.sourceforge.jp>
Sun, 1 Jan 2012 14:38:17 +0000 (23:38 +0900)
Conflicts:
sound/soc/codecs/wm8994.c

1  2 
drivers/gpu/drm/i915/i915_gem_tiling.c
sound/soc/codecs/wm8994.c

@@@ -92,7 -92,10 +92,10 @@@ i915_gem_detect_bit_6_swizzle(struct dr
        uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
        uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
  
-       if (IS_GEN5(dev) || IS_GEN6(dev)) {
+       if (INTEL_INFO(dev)->gen >= 6) {
+               swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+               swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+       } else if (IS_GEN5(dev)) {
                /* On Ironlake whatever DRAM config, GPU always do
                 * same swizzling setup.
                 */
  static bool
  i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
  {
 -      int tile_width;
 +      int tile_width, tile_height;
  
        /* Linear is always fine */
        if (tiling_mode == I915_TILING_NONE)
                }
        }
  
 +      if (IS_GEN2(dev) ||
 +          (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)))
 +              tile_height = 32;
 +      else
 +              tile_height = 8;
 +      /* i8xx is strange: It has 2 interleaved rows of tiles, so needs an even
 +       * number of tile rows. */
 +      if (IS_GEN2(dev))
 +              tile_height *= 2;
 +
 +      /* Size needs to be aligned to a full tile row */
 +      if (size & (tile_height * stride - 1))
 +              return false;
 +
        /* 965+ just needs multiples of tile width */
        if (INTEL_INFO(dev)->gen >= 4) {
                if (stride & (tile_width - 1))
@@@ -298,14 -287,10 +301,10 @@@ i915_gem_set_tiling(struct drm_device *
        struct drm_i915_gem_set_tiling *args = data;
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj;
-       int ret;
-       ret = i915_gem_check_is_wedged(dev);
-       if (ret)
-               return ret;
+       int ret = 0;
  
        obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-       if (obj == NULL)
+       if (&obj->base == NULL)
                return -ENOENT;
  
        if (!i915_tiling_ok(dev,
                /* Rebind if we need a change of alignment */
                if (!obj->map_and_fenceable) {
                        u32 unfenced_alignment =
-                               i915_gem_get_unfenced_gtt_alignment(obj);
+                               i915_gem_get_unfenced_gtt_alignment(dev,
+                                                                   obj->base.size,
+                                                                   args->tiling_mode);
                        if (obj->gtt_offset & (unfenced_alignment - 1))
                                ret = i915_gem_object_unbind(obj);
                }
@@@ -398,7 -385,7 +399,7 @@@ i915_gem_get_tiling(struct drm_device *
        struct drm_i915_gem_object *obj;
  
        obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-       if (obj == NULL)
+       if (&obj->base == NULL)
                return -ENOENT;
  
        mutex_lock(&dev->struct_mutex);
@@@ -456,14 -443,9 +457,9 @@@ i915_gem_swizzle_page(struct page *page
  void
  i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
  {
-       struct drm_device *dev = obj->base.dev;
-       drm_i915_private_t *dev_priv = dev->dev_private;
        int page_count = obj->base.size >> PAGE_SHIFT;
        int i;
  
-       if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
-               return;
        if (obj->bit_17 == NULL)
                return;
  
  void
  i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
  {
-       struct drm_device *dev = obj->base.dev;
-       drm_i915_private_t *dev_priv = dev->dev_private;
        int page_count = obj->base.size >> PAGE_SHIFT;
        int i;
  
-       if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
-               return;
        if (obj->bit_17 == NULL) {
                obj->bit_17 = kmalloc(BITS_TO_LONGS(page_count) *
                                           sizeof(long), GFP_KERNEL);
  #include "wm8994.h"
  #include "wm_hubs.h"
  
- struct fll_config {
-       int src;
-       int in;
-       int out;
- };
  #define WM8994_NUM_DRC 3
  #define WM8994_NUM_EQ  3
  
@@@ -59,64 -53,11 +53,11 @@@ static int wm8994_retune_mobile_base[] 
        WM8994_AIF2_EQ_GAINS_1,
  };
  
- struct wm8994_micdet {
-       struct snd_soc_jack *jack;
-       int det;
-       int shrt;
- };
- /* codec private data */
- struct wm8994_priv {
-       struct wm_hubs_data hubs;
-       enum snd_soc_control_type control_type;
-       void *control_data;
-       struct snd_soc_codec *codec;
-       int sysclk[2];
-       int sysclk_rate[2];
-       int mclk[2];
-       int aifclk[2];
-       struct fll_config fll[2], fll_suspend[2];
-       int dac_rates[2];
-       int lrclk_shared[2];
-       int mbc_ena[3];
-       /* Platform dependant DRC configuration */
-       const char **drc_texts;
-       int drc_cfg[WM8994_NUM_DRC];
-       struct soc_enum drc_enum;
-       /* Platform dependant ReTune mobile configuration */
-       int num_retune_mobile_texts;
-       const char **retune_mobile_texts;
-       int retune_mobile_cfg[WM8994_NUM_EQ];
-       struct soc_enum retune_mobile_enum;
-       /* Platform dependant MBC configuration */
-       int mbc_cfg;
-       const char **mbc_texts;
-       struct soc_enum mbc_enum;
-       struct wm8994_micdet micdet[2];
-       wm8958_micdet_cb jack_cb;
-       void *jack_cb_data;
-       bool jack_is_mic;
-       bool jack_is_video;
-       int revision;
-       struct wm8994_pdata *pdata;
-       unsigned int aif1clk_enable:1;
-       unsigned int aif2clk_enable:1;
-       unsigned int aif1clk_disable:1;
-       unsigned int aif2clk_disable:1;
- };
- static int wm8994_readable(unsigned int reg)
+ static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg)
  {
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       struct wm8994 *control = codec->control_data;
        switch (reg) {
        case WM8994_GPIO_1:
        case WM8994_GPIO_2:
        case WM8994_INTERRUPT_STATUS_2:
        case WM8994_INTERRUPT_RAW_STATUS_2:
                return 1;
+       case WM8958_DSP2_PROGRAM:
+       case WM8958_DSP2_CONFIG:
+       case WM8958_DSP2_EXECCONTROL:
+               if (control->type == WM8958)
+                       return 1;
+               else
+                       return 0;
        default:
                break;
        }
        return wm8994_access_masks[reg].readable != 0;
  }
  
- static int wm8994_volatile(unsigned int reg)
+ static int wm8994_volatile(struct snd_soc_codec *codec, unsigned int reg)
  {
        if (reg >= WM8994_CACHE_SIZE)
                return 1;
        case WM8994_LDO_2:
        case WM8958_DSP2_EXECCONTROL:
        case WM8958_MIC_DETECT_3:
+       case WM8994_DC_SERVO_4E:
                return 1;
        default:
                return 0;
@@@ -170,7 -121,7 +121,7 @@@ static int wm8994_write(struct snd_soc_
  
        BUG_ON(reg > WM8994_MAX_REGISTER);
  
-       if (!wm8994_volatile(reg)) {
+       if (!wm8994_volatile(codec, reg)) {
                ret = snd_soc_cache_write(codec, reg, value);
                if (ret != 0)
                        dev_err(codec->dev, "Cache write to %x failed: %d\n",
@@@ -188,7 -139,7 +139,7 @@@ static unsigned int wm8994_read(struct 
  
        BUG_ON(reg > WM8994_MAX_REGISTER);
  
-       if (!wm8994_volatile(reg) && wm8994_readable(reg) &&
+       if (!wm8994_volatile(codec, reg) && wm8994_readable(codec, reg) &&
            reg < codec->driver->reg_cache_size) {
                ret = snd_soc_cache_read(codec, reg, &val);
                if (ret >= 0)
@@@ -245,10 -196,6 +196,6 @@@ static int configure_aif_clock(struct s
                        aif + 1, rate);
        }
  
-       if (rate && rate < 3000000)
-               dev_warn(codec->dev, "AIF%dCLK is %dHz, should be >=3MHz for optimal performance\n",
-                        aif + 1, rate);
        wm8994->aifclk[aif] = rate;
  
        snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1 + offset,
  static int configure_clock(struct snd_soc_codec *codec)
  {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       int old, new;
+       int change, new;
  
        /* Bring up the AIF clocks first */
        configure_aif_clock(codec, 0);
        else
                new = 0;
  
-       old = snd_soc_read(codec, WM8994_CLOCKING_1) & WM8994_SYSCLK_SRC;
-       /* If there's no change then we're done. */
-       if (old == new)
+       change = snd_soc_update_bits(codec, WM8994_CLOCKING_1,
+                                    WM8994_SYSCLK_SRC, new);
+       if (!change)
                return 0;
  
-       snd_soc_update_bits(codec, WM8994_CLOCKING_1, WM8994_SYSCLK_SRC, new);
        snd_soc_dapm_sync(&codec->dapm);
  
        return 0;
@@@ -335,6 -279,8 +279,8 @@@ static const DECLARE_TLV_DB_SCALE(digit
  static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0);
  static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0);
  static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+ static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0);
+ static const DECLARE_TLV_DB_SCALE(mixin_boost_tlv, 0, 900, 0);
  
  #define WM8994_DRC_SWITCH(xname, reg, shift) \
  {     .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@@ -529,7 -475,7 +475,7 @@@ static int wm8994_get_retune_mobile_enu
                                         struct snd_ctl_elem_value *ucontrol)
  {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct wm8994_priv *wm8994 =snd_soc_codec_get_drvdata(codec);
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
  
        ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block];
@@@ -575,215 -521,6 +521,6 @@@ static const struct soc_enum dac_osr 
  static const struct soc_enum adc_osr =
        SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 1, 2, osr_text);
  
- static void wm8958_mbc_apply(struct snd_soc_codec *codec, int mbc, int start)
- {
-       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994_pdata *pdata = wm8994->pdata;
-       int pwr_reg = snd_soc_read(codec, WM8994_POWER_MANAGEMENT_5);
-       int ena, reg, aif, i;
-       switch (mbc) {
-       case 0:
-               pwr_reg &= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA);
-               aif = 0;
-               break;
-       case 1:
-               pwr_reg &= (WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA);
-               aif = 0;
-               break;
-       case 2:
-               pwr_reg &= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA);
-               aif = 1;
-               break;
-       default:
-               BUG();
-               return;
-       }
-       /* We can only enable the MBC if the AIF is enabled and we
-        * want it to be enabled. */
-       ena = pwr_reg && wm8994->mbc_ena[mbc];
-       reg = snd_soc_read(codec, WM8958_DSP2_PROGRAM);
-       dev_dbg(codec->dev, "MBC %d startup: %d, power: %x, DSP: %x\n",
-               mbc, start, pwr_reg, reg);
-       if (start && ena) {
-               /* If the DSP is already running then noop */
-               if (reg & WM8958_DSP2_ENA)
-                       return;
-               /* Switch the clock over to the appropriate AIF */
-               snd_soc_update_bits(codec, WM8994_CLOCKING_1,
-                                   WM8958_DSP2CLK_SRC | WM8958_DSP2CLK_ENA,
-                                   aif << WM8958_DSP2CLK_SRC_SHIFT |
-                                   WM8958_DSP2CLK_ENA);
-               snd_soc_update_bits(codec, WM8958_DSP2_PROGRAM,
-                                   WM8958_DSP2_ENA, WM8958_DSP2_ENA);
-               /* If we've got user supplied MBC settings use them */
-               if (pdata && pdata->num_mbc_cfgs) {
-                       struct wm8958_mbc_cfg *cfg
-                               = &pdata->mbc_cfgs[wm8994->mbc_cfg];
-                       for (i = 0; i < ARRAY_SIZE(cfg->coeff_regs); i++)
-                               snd_soc_write(codec, i + WM8958_MBC_BAND_1_K_1,
-                                             cfg->coeff_regs[i]);
-                       for (i = 0; i < ARRAY_SIZE(cfg->cutoff_regs); i++)
-                               snd_soc_write(codec,
-                                             i + WM8958_MBC_BAND_2_LOWER_CUTOFF_C1_1,
-                                             cfg->cutoff_regs[i]);
-               }
-               /* Run the DSP */
-               snd_soc_write(codec, WM8958_DSP2_EXECCONTROL,
-                             WM8958_DSP2_RUNR);
-               /* And we're off! */
-               snd_soc_update_bits(codec, WM8958_DSP2_CONFIG,
-                                   WM8958_MBC_ENA | WM8958_MBC_SEL_MASK,
-                                   mbc << WM8958_MBC_SEL_SHIFT |
-                                   WM8958_MBC_ENA);
-       } else {
-               /* If the DSP is already stopped then noop */
-               if (!(reg & WM8958_DSP2_ENA))
-                       return;
-               snd_soc_update_bits(codec, WM8958_DSP2_CONFIG,
-                                   WM8958_MBC_ENA, 0); 
-               snd_soc_update_bits(codec, WM8958_DSP2_PROGRAM,
-                                   WM8958_DSP2_ENA, 0);
-               snd_soc_update_bits(codec, WM8994_CLOCKING_1,
-                                   WM8958_DSP2CLK_ENA, 0);
-       }
- }
- static int wm8958_aif_ev(struct snd_soc_dapm_widget *w,
-                   struct snd_kcontrol *kcontrol, int event)
- {
-       struct snd_soc_codec *codec = w->codec;
-       int mbc;
-       switch (w->shift) {
-       case 13:
-       case 12:
-               mbc = 2;
-               break;
-       case 11:
-       case 10:
-               mbc = 1;
-               break;
-       case 9:
-       case 8:
-               mbc = 0;
-               break;
-       default:
-               BUG();
-               return -EINVAL;
-       }
-       switch (event) {
-       case SND_SOC_DAPM_POST_PMU:
-               wm8958_mbc_apply(codec, mbc, 1);
-               break;
-       case SND_SOC_DAPM_POST_PMD:
-               wm8958_mbc_apply(codec, mbc, 0);
-               break;
-       }
-       return 0;
- }
- static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *ucontrol)
- {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994_pdata *pdata = wm8994->pdata;
-       int value = ucontrol->value.integer.value[0];
-       int reg;
-       /* Don't allow on the fly reconfiguration */
-       reg = snd_soc_read(codec, WM8994_CLOCKING_1);
-       if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
-               return -EBUSY;
-       if (value >= pdata->num_mbc_cfgs)
-               return -EINVAL;
-       wm8994->mbc_cfg = value;
-       return 0;
- }
- static int wm8958_get_mbc_enum(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *ucontrol)
- {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       ucontrol->value.enumerated.item[0] = wm8994->mbc_cfg;
-       return 0;
- }
- static int wm8958_mbc_info(struct snd_kcontrol *kcontrol,
-                          struct snd_ctl_elem_info *uinfo)
- {
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-       uinfo->count = 1;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = 1;
-       return 0;
- }
- static int wm8958_mbc_get(struct snd_kcontrol *kcontrol,
-                         struct snd_ctl_elem_value *ucontrol)
- {
-       int mbc = kcontrol->private_value;
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       ucontrol->value.integer.value[0] = wm8994->mbc_ena[mbc];
-       return 0;
- }
- static int wm8958_mbc_put(struct snd_kcontrol *kcontrol,
-                         struct snd_ctl_elem_value *ucontrol)
- {
-       int mbc = kcontrol->private_value;
-       int i;
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       if (ucontrol->value.integer.value[0] > 1)
-               return -EINVAL;
-       for (i = 0; i < ARRAY_SIZE(wm8994->mbc_ena); i++) {
-               if (mbc != i && wm8994->mbc_ena[i]) {
-                       dev_dbg(codec->dev, "MBC %d active already\n", mbc);
-                       return -EBUSY;
-               }
-       }
-       wm8994->mbc_ena[mbc] = ucontrol->value.integer.value[0];
-       wm8958_mbc_apply(codec, mbc, wm8994->mbc_ena[mbc]);
-       return 0;
- }
- #define WM8958_MBC_SWITCH(xname, xval) {\
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
-       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
-       .info = wm8958_mbc_info, \
-       .get = wm8958_mbc_get, .put = wm8958_mbc_put, \
-       .private_value = xval }
  static const struct snd_kcontrol_new wm8994_snd_controls[] = {
  SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME,
                 WM8994_AIF1_ADC1_RIGHT_VOLUME,
@@@ -923,11 -660,52 +660,52 @@@ SOC_SINGLE_TLV("AIF2 EQ5 Volume", WM899
               eq_tlv),
  };
  
+ static const char *wm8958_ng_text[] = {
+       "30ms", "125ms", "250ms", "500ms",
+ };
+ static const struct soc_enum wm8958_aif1dac1_ng_hold =
+       SOC_ENUM_SINGLE(WM8958_AIF1_DAC1_NOISE_GATE,
+                       WM8958_AIF1DAC1_NG_THR_SHIFT, 4, wm8958_ng_text);
+ static const struct soc_enum wm8958_aif1dac2_ng_hold =
+       SOC_ENUM_SINGLE(WM8958_AIF1_DAC2_NOISE_GATE,
+                       WM8958_AIF1DAC2_NG_THR_SHIFT, 4, wm8958_ng_text);
+ static const struct soc_enum wm8958_aif2dac_ng_hold =
+       SOC_ENUM_SINGLE(WM8958_AIF2_DAC_NOISE_GATE,
+                       WM8958_AIF2DAC_NG_THR_SHIFT, 4, wm8958_ng_text);
  static const struct snd_kcontrol_new wm8958_snd_controls[] = {
  SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv),
- WM8958_MBC_SWITCH("AIF1DAC1 MBC Switch", 0),
- WM8958_MBC_SWITCH("AIF1DAC2 MBC Switch", 1),
- WM8958_MBC_SWITCH("AIF2DAC MBC Switch", 2),
+ SOC_SINGLE("AIF1DAC1 Noise Gate Switch", WM8958_AIF1_DAC1_NOISE_GATE,
+          WM8958_AIF1DAC1_NG_ENA_SHIFT, 1, 0),
+ SOC_ENUM("AIF1DAC1 Noise Gate Hold Time", wm8958_aif1dac1_ng_hold),
+ SOC_SINGLE_TLV("AIF1DAC1 Noise Gate Threshold Volume",
+              WM8958_AIF1_DAC1_NOISE_GATE, WM8958_AIF1DAC1_NG_THR_SHIFT,
+              7, 1, ng_tlv),
+ SOC_SINGLE("AIF1DAC2 Noise Gate Switch", WM8958_AIF1_DAC2_NOISE_GATE,
+          WM8958_AIF1DAC2_NG_ENA_SHIFT, 1, 0),
+ SOC_ENUM("AIF1DAC2 Noise Gate Hold Time", wm8958_aif1dac2_ng_hold),
+ SOC_SINGLE_TLV("AIF1DAC2 Noise Gate Threshold Volume",
+              WM8958_AIF1_DAC2_NOISE_GATE, WM8958_AIF1DAC2_NG_THR_SHIFT,
+              7, 1, ng_tlv),
+ SOC_SINGLE("AIF2DAC Noise Gate Switch", WM8958_AIF2_DAC_NOISE_GATE,
+          WM8958_AIF2DAC_NG_ENA_SHIFT, 1, 0),
+ SOC_ENUM("AIF2DAC Noise Gate Hold Time", wm8958_aif2dac_ng_hold),
+ SOC_SINGLE_TLV("AIF2DAC Noise Gate Threshold Volume",
+              WM8958_AIF2_DAC_NOISE_GATE, WM8958_AIF2DAC_NG_THR_SHIFT,
+              7, 1, ng_tlv),
+ };
+ static const struct snd_kcontrol_new wm1811_snd_controls[] = {
+ SOC_SINGLE_TLV("MIXINL IN1LP Boost Volume", WM8994_INPUT_MIXER_1, 7, 1, 0,
+              mixin_boost_tlv),
+ SOC_SINGLE_TLV("MIXINL IN1RP Boost Volume", WM8994_INPUT_MIXER_1, 8, 1, 0,
+              mixin_boost_tlv),
  };
  
  static int clk_sys_event(struct snd_soc_dapm_widget *w,
        return 0;
  }
  
+ static void vmid_reference(struct snd_soc_codec *codec)
+ {
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       wm8994->vmid_refcount++;
+       dev_dbg(codec->dev, "Referencing VMID, refcount is now %d\n",
+               wm8994->vmid_refcount);
+       if (wm8994->vmid_refcount == 1) {
+               /* Startup bias, VMID ramp & buffer */
+               snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+                                   WM8994_STARTUP_BIAS_ENA |
+                                   WM8994_VMID_BUF_ENA |
+                                   WM8994_VMID_RAMP_MASK,
+                                   WM8994_STARTUP_BIAS_ENA |
+                                   WM8994_VMID_BUF_ENA |
+                                   (0x11 << WM8994_VMID_RAMP_SHIFT));
+               /* Main bias enable, VMID=2x40k */
+               snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+                                   WM8994_BIAS_ENA |
+                                   WM8994_VMID_SEL_MASK,
+                                   WM8994_BIAS_ENA | 0x2);
+               msleep(20);
+       }
+ }
+ static void vmid_dereference(struct snd_soc_codec *codec)
+ {
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       wm8994->vmid_refcount--;
+       dev_dbg(codec->dev, "Dereferencing VMID, refcount is now %d\n",
+               wm8994->vmid_refcount);
+       if (wm8994->vmid_refcount == 0) {
+               /* Switch over to startup biases */
+               snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+                                   WM8994_BIAS_SRC |
+                                   WM8994_STARTUP_BIAS_ENA |
+                                   WM8994_VMID_BUF_ENA |
+                                   WM8994_VMID_RAMP_MASK,
+                                   WM8994_BIAS_SRC |
+                                   WM8994_STARTUP_BIAS_ENA |
+                                   WM8994_VMID_BUF_ENA |
+                                   (1 << WM8994_VMID_RAMP_SHIFT));
+               /* Disable main biases */
+               snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+                                   WM8994_BIAS_ENA |
+                                   WM8994_VMID_SEL_MASK, 0);
+               /* Discharge line */
+               snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
+                                   WM8994_LINEOUT1_DISCH |
+                                   WM8994_LINEOUT2_DISCH,
+                                   WM8994_LINEOUT1_DISCH |
+                                   WM8994_LINEOUT2_DISCH);
+               msleep(5);
+               /* Switch off startup biases */
+               snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+                                   WM8994_BIAS_SRC |
+                                   WM8994_STARTUP_BIAS_ENA |
+                                   WM8994_VMID_BUF_ENA |
+                                   WM8994_VMID_RAMP_MASK, 0);
+       }
+ }
+ static int vmid_event(struct snd_soc_dapm_widget *w,
+                     struct snd_kcontrol *kcontrol, int event)
+ {
+       struct snd_soc_codec *codec = w->codec;
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               vmid_reference(codec);
+               break;
+       case SND_SOC_DAPM_POST_PMD:
+               vmid_dereference(codec);
+               break;
+       }
+       return 0;
+ }
  static void wm8994_update_class_w(struct snd_soc_codec *codec)
  {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
@@@ -1018,16 -887,6 +887,16 @@@ static int late_enable_ev(struct snd_so
  
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
 +<<<<<<< HEAD
 +              if (wm8994->aif1clk_enable)
 +                      snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1,
 +                                          WM8994_AIF1CLK_ENA_MASK,
 +                                          WM8994_AIF1CLK_ENA);
 +              if (wm8994->aif2clk_enable)
 +                      snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1,
 +                                          WM8994_AIF2CLK_ENA_MASK,
 +                                          WM8994_AIF2CLK_ENA);
 +=======
                if (wm8994->aif1clk_enable) {
                        snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1,
                                            WM8994_AIF1CLK_ENA_MASK,
                                            WM8994_AIF2CLK_ENA);
                        wm8994->aif2clk_enable = 0;
                }
 +>>>>>>> d10902812c9cd5583130a4ebb9ad19c60b68149d
                break;
        }
  
+       /* We may also have postponed startup of DSP, handle that. */
+       wm8958_aif_ev(w, kcontrol, event);
        return 0;
  }
  
@@@ -1055,17 -916,6 +927,17 @@@ static int late_disable_ev(struct snd_s
  
        switch (event) {
        case SND_SOC_DAPM_POST_PMD:
 +<<<<<<< HEAD
 +              if (wm8994->aif1clk_enable) {
 +                      snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1,
 +                                          WM8994_AIF1CLK_ENA_MASK, 0);
 +                      wm8994->aif1clk_enable = 0;
 +              }
 +              if (wm8994->aif2clk_enable) {
 +                      snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1,
 +                                          WM8994_AIF2CLK_ENA_MASK, 0);
 +                      wm8994->aif2clk_enable = 0;
 +=======
                if (wm8994->aif1clk_disable) {
                        snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1,
                                            WM8994_AIF1CLK_ENA_MASK, 0);
                        snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1,
                                            WM8994_AIF2CLK_ENA_MASK, 0);
                        wm8994->aif2clk_disable = 0;
 +>>>>>>> d10902812c9cd5583130a4ebb9ad19c60b68149d
                }
                break;
        }
@@@ -1093,12 -942,9 +965,12 @@@ static int aif1clk_ev(struct snd_soc_da
        case SND_SOC_DAPM_PRE_PMU:
                wm8994->aif1clk_enable = 1;
                break;
 +<<<<<<< HEAD
 +=======
        case SND_SOC_DAPM_POST_PMD:
                wm8994->aif1clk_disable = 1;
                break;
 +>>>>>>> d10902812c9cd5583130a4ebb9ad19c60b68149d
        }
  
        return 0;
@@@ -1114,19 -960,14 +986,19 @@@ static int aif2clk_ev(struct snd_soc_da
        case SND_SOC_DAPM_PRE_PMU:
                wm8994->aif2clk_enable = 1;
                break;
 +<<<<<<< HEAD
 +=======
        case SND_SOC_DAPM_POST_PMD:
                wm8994->aif2clk_disable = 1;
                break;
 +>>>>>>> d10902812c9cd5583130a4ebb9ad19c60b68149d
        }
  
        return 0;
  }
  
 +<<<<<<< HEAD
 +=======
  static int adc_mux_ev(struct snd_soc_dapm_widget *w,
                      struct snd_kcontrol *kcontrol, int event)
  {
        return 0;
  }
  
++<<<<<<< HEAD
 +>>>>>>> d10902812c9cd5583130a4ebb9ad19c60b68149d
++=======
+ static int micbias_ev(struct snd_soc_dapm_widget *w,
+                     struct snd_kcontrol *kcontrol, int event)
+ {
+       late_enable_ev(w, kcontrol, event);
+       return 0;
+ }
++>>>>>>> c7f46b7aa4ae5cbef32eb5e016512a14f936affa
  static int dac_ev(struct snd_soc_dapm_widget *w,
                  struct snd_kcontrol *kcontrol, int event)
  {
@@@ -1161,7 -1008,8 +1043,8 @@@ static const char *hp_mux_text[] = 
  static int wm8994_put_hp_enum(struct snd_kcontrol *kcontrol,
                              struct snd_ctl_elem_value *ucontrol)
  {
-       struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_dapm_widget *w = wlist->widgets[0];
        struct snd_soc_codec *codec = w->codec;
        int ret;
  
@@@ -1288,7 -1136,8 +1171,8 @@@ SOC_DAPM_SINGLE("AIF1.1 Switch", WM8994
  static int wm8994_put_class_w(struct snd_kcontrol *kcontrol,
                              struct snd_ctl_elem_value *ucontrol)
  {
-       struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_dapm_widget *w = wlist->widgets[0];
        struct snd_soc_codec *codec = w->codec;
        int ret;
  
@@@ -1428,13 -1277,33 +1312,33 @@@ SND_SOC_DAPM_PGA_E("Late DAC2L Enable P
        late_enable_ev, SND_SOC_DAPM_PRE_PMU),
  SND_SOC_DAPM_PGA_E("Late DAC2R Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0,
        late_enable_ev, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_PGA_E("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0,
+       late_enable_ev, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MIXER_E("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0,
+                    left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer),
+                    late_enable_ev, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MIXER_E("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0,
+                    right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer),
+                    late_enable_ev, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MUX_E("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux,
+                  late_enable_ev, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MUX_E("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux,
+                  late_enable_ev, SND_SOC_DAPM_PRE_PMU),
  
  SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev)
  };
  
  static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = {
  SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, NULL, 0),
- SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0)
+ SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0,
+                  left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
+ SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0,
+                  right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
+ SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux),
+ SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux),
  };
  
  static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = {
@@@ -1450,35 -1319,33 +1354,40 @@@ SND_SOC_DAPM_DAC_E("DAC1R", NULL, SND_S
  
  static const struct snd_soc_dapm_widget wm8994_dac_widgets[] = {
  SND_SOC_DAPM_DAC("DAC2L", NULL, WM8994_POWER_MANAGEMENT_5, 3, 0),
 +<<<<<<< HEAD
 +SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0),
 +=======
  SND_SOC_DAPM_DAC("DAC2R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0),
 +>>>>>>> d10902812c9cd5583130a4ebb9ad19c60b68149d
  SND_SOC_DAPM_DAC("DAC1L", NULL, WM8994_POWER_MANAGEMENT_5, 1, 0),
  SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0),
  };
  
 +<<<<<<< HEAD
 +=======
  static const struct snd_soc_dapm_widget wm8994_adc_revd_widgets[] = {
- SND_SOC_DAPM_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux,
-                  adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
- SND_SOC_DAPM_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux,
-                  adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_VIRT_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux,
+                       adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_VIRT_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux,
+                       adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
  };
  
  static const struct snd_soc_dapm_widget wm8994_adc_widgets[] = {
- SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux),
- SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux),
+ SND_SOC_DAPM_VIRT_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux),
+ SND_SOC_DAPM_VIRT_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux),
  };
  
 +>>>>>>> d10902812c9cd5583130a4ebb9ad19c60b68149d
  static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = {
  SND_SOC_DAPM_INPUT("DMIC1DAT"),
  SND_SOC_DAPM_INPUT("DMIC2DAT"),
  SND_SOC_DAPM_INPUT("Clock"),
  
+ SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev,
+                     SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, vmid_event,
+                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event,
                    SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
  
@@@ -1552,7 -1419,7 +1461,7 @@@ SND_SOC_DAPM_MUX("AIF2DAC Mux", SND_SOC
  SND_SOC_DAPM_MUX("AIF2ADC Mux", SND_SOC_NOPM, 0, 0, &aif2adc_mux),
  
  SND_SOC_DAPM_AIF_IN("AIF3DACDAT", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0),
- SND_SOC_DAPM_AIF_IN("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
  
  SND_SOC_DAPM_SUPPLY("TOCLK", WM8994_CLOCKING_1, 4, 0, NULL, 0),
  
@@@ -1568,20 -1435,6 +1477,23 @@@ SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8994
  SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0),
  SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0),
  
 +<<<<<<< HEAD
++<<<<<<< HEAD
 +SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux),
 +SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux),
 +
 +=======
 +>>>>>>> d10902812c9cd5583130a4ebb9ad19c60b68149d
 +SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux),
 +SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux),
 +
 +SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0,
 +                 left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
 +SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0,
 +                 right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
 +
++=======
++>>>>>>> c7f46b7aa4ae5cbef32eb5e016512a14f936affa
  SND_SOC_DAPM_POST("Debug log", post_ev),
  };
  
@@@ -1800,11 -1653,17 +1712,17 @@@ static const struct snd_soc_dapm_route 
        { "AIF2DACDAT", NULL, "AIF1DACDAT" },
        { "AIF1ADCDAT", NULL, "AIF2ADCDAT" },
        { "AIF2ADCDAT", NULL, "AIF1ADCDAT" },
+       { "MICBIAS1", NULL, "CLK_SYS" },
+       { "MICBIAS1", NULL, "MICBIAS Supply" },
+       { "MICBIAS2", NULL, "CLK_SYS" },
+       { "MICBIAS2", NULL, "MICBIAS Supply" },
  };
  
  static const struct snd_soc_dapm_route wm8994_intercon[] = {
        { "AIF2DACL", NULL, "AIF2DAC Mux" },
        { "AIF2DACR", NULL, "AIF2DAC Mux" },
+       { "MICBIAS1", NULL, "VMID" },
+       { "MICBIAS2", NULL, "VMID" },
  };
  
  static const struct snd_soc_dapm_route wm8958_intercon[] = {
@@@ -1909,9 -1768,12 +1827,12 @@@ static int _wm8994_set_fll(struct snd_s
                          unsigned int freq_in, unsigned int freq_out)
  {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       struct wm8994 *control = codec->control_data;
        int reg_offset, ret;
        struct fll_div fll;
        u16 reg, aif1, aif2;
+       unsigned long timeout;
+       bool was_enabled;
  
        aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1)
                & WM8994_AIF1CLK_ENA;
                return -EINVAL;
        }
  
+       reg = snd_soc_read(codec, WM8994_FLL1_CONTROL_1 + reg_offset);
+       was_enabled = reg & WM8994_FLL1_ENA;
        switch (src) {
        case 0:
                /* Allow no source specification when stopping */
                            (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) |
                            (src - 1));
  
+       /* Clear any pending completion from a previous failure */
+       try_wait_for_completion(&wm8994->fll_locked[id]);
        /* Enable (with fractional mode if required) */
        if (freq_out) {
+               /* Enable VMID if we need it */
+               if (!was_enabled) {
+                       switch (control->type) {
+                       case WM8994:
+                               vmid_reference(codec);
+                               break;
+                       case WM8958:
+                               if (wm8994->revision < 1)
+                                       vmid_reference(codec);
+                               break;
+                       default:
+                               break;
+                       }
+               }
                if (fll.k)
                        reg = WM8994_FLL1_ENA | WM8994_FLL1_FRAC;
                else
                snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset,
                                    WM8994_FLL1_ENA | WM8994_FLL1_FRAC,
                                    reg);
+               if (wm8994->fll_locked_irq) {
+                       timeout = wait_for_completion_timeout(&wm8994->fll_locked[id],
+                                                             msecs_to_jiffies(10));
+                       if (timeout == 0)
+                               dev_warn(codec->dev,
+                                        "Timed out waiting for FLL lock\n");
+               } else {
+                       msleep(5);
+               }
+       } else {
+               if (was_enabled) {
+                       switch (control->type) {
+                       case WM8994:
+                               vmid_dereference(codec);
+                               break;
+                       case WM8958:
+                               if (wm8994->revision < 1)
+                                       vmid_dereference(codec);
+                               break;
+                       default:
+                               break;
+                       }
+               }
        }
  
        wm8994->fll[id].in = freq_in;
        return 0;
  }
  
+ static irqreturn_t wm8994_fll_locked_irq(int irq, void *data)
+ {
+       struct completion *completion = data;
+       complete(completion);
+       return IRQ_HANDLED;
+ }
  
  static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 };
  
@@@ -2110,9 -2025,6 +2084,6 @@@ static int wm8994_set_bias_level(struc
                break;
  
        case SND_SOC_BIAS_PREPARE:
-               /* VMID=2x40k */
-               snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
-                                   WM8994_VMID_SEL_MASK, 0x2);
                break;
  
        case SND_SOC_BIAS_STANDBY:
                                                            WM8958_CP_DISCH);
                                }
                                break;
+                       case WM1811:
+                               if (wm8994->revision < 2) {
+                                       snd_soc_write(codec, 0x102, 0x3);
+                                       snd_soc_write(codec, 0x5d, 0x7e);
+                                       snd_soc_write(codec, 0x5e, 0x0);
+                                       snd_soc_write(codec, 0x102, 0x0);
+                               }
+                               break;
                        }
  
                        /* Discharge LINEOUT1 & 2 */
                                            WM8994_LINEOUT2_DISCH,
                                            WM8994_LINEOUT1_DISCH |
                                            WM8994_LINEOUT2_DISCH);
-                       /* Startup bias, VMID ramp & buffer */
-                       snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
-                                           WM8994_STARTUP_BIAS_ENA |
-                                           WM8994_VMID_BUF_ENA |
-                                           WM8994_VMID_RAMP_MASK,
-                                           WM8994_STARTUP_BIAS_ENA |
-                                           WM8994_VMID_BUF_ENA |
-                                           (0x11 << WM8994_VMID_RAMP_SHIFT));
-                       /* Main bias enable, VMID=2x40k */
-                       snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
-                                           WM8994_BIAS_ENA |
-                                           WM8994_VMID_SEL_MASK,
-                                           WM8994_BIAS_ENA | 0x2);
-                       msleep(20);
                }
  
-               /* VMID=2x500k */
-               snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
-                                   WM8994_VMID_SEL_MASK, 0x4);
  
                break;
  
        case SND_SOC_BIAS_OFF:
                if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
-                       /* Switch over to startup biases */
-                       snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
-                                           WM8994_BIAS_SRC |
-                                           WM8994_STARTUP_BIAS_ENA |
-                                           WM8994_VMID_BUF_ENA |
-                                           WM8994_VMID_RAMP_MASK,
-                                           WM8994_BIAS_SRC |
-                                           WM8994_STARTUP_BIAS_ENA |
-                                           WM8994_VMID_BUF_ENA |
-                                           (1 << WM8994_VMID_RAMP_SHIFT));
-                       /* Disable main biases */
-                       snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
-                                           WM8994_BIAS_ENA |
-                                           WM8994_VMID_SEL_MASK, 0);
-                       /* Discharge line */
-                       snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
-                                           WM8994_LINEOUT1_DISCH |
-                                           WM8994_LINEOUT2_DISCH,
-                                           WM8994_LINEOUT1_DISCH |
-                                           WM8994_LINEOUT2_DISCH);
-                       msleep(5);
-                       /* Switch off startup biases */
-                       snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
-                                           WM8994_BIAS_SRC |
-                                           WM8994_STARTUP_BIAS_ENA |
-                                           WM8994_VMID_BUF_ENA |
-                                           WM8994_VMID_RAMP_MASK, 0);
+                       wm8994->cur_fw = NULL;
  
                        pm_runtime_put(codec->dev);
                }
@@@ -2311,10 -2182,18 +2241,18 @@@ static int wm8994_set_dai_fmt(struct sn
  
        /* The AIF2 format configuration needs to be mirrored to AIF3
         * on WM8958 if it's in use so just do it all the time. */
-       if (control->type == WM8958 && dai->id == 2)
-               snd_soc_update_bits(codec, WM8958_AIF3_CONTROL_1,
-                                   WM8994_AIF1_LRCLK_INV |
-                                   WM8958_AIF3_FMT_MASK, aif1);
+       switch (control->type) {
+       case WM1811:
+       case WM8958:
+               if (dai->id == 2)
+                       snd_soc_update_bits(codec, WM8958_AIF3_CONTROL_1,
+                                           WM8994_AIF1_LRCLK_INV |
+                                           WM8958_AIF3_FMT_MASK, aif1);
+               break;
+       default:
+               break;
+       }
  
        snd_soc_update_bits(codec, aif1_reg,
                            WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV |
@@@ -2356,7 -2235,6 +2294,6 @@@ static int wm8994_hw_params(struct snd_
                            struct snd_soc_dai *dai)
  {
        struct snd_soc_codec *codec = dai->codec;
-       struct wm8994 *control = codec->control_data;
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        int aif1_reg;
        int aif2_reg;
                        dev_dbg(codec->dev, "AIF2 using split LRCLK\n");
                }
                break;
-       case 3:
-               switch (control->type) {
-               case WM8958:
-                       aif1_reg = WM8958_AIF3_CONTROL_1;
-                       break;
-               default:
-                       return 0;
-               }
        default:
                return -EINVAL;
        }
        bclk |= best << WM8994_AIF1_BCLK_DIV_SHIFT;
  
        lrclk = bclk_rate / params_rate(params);
+       if (!lrclk) {
+               dev_err(dai->dev, "Unable to generate LRCLK from %dHz BCLK\n",
+                       bclk_rate);
+               return -EINVAL;
+       }
        dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n",
                lrclk, bclk_rate / lrclk);
  
@@@ -2527,6 -2402,7 +2461,7 @@@ static int wm8994_aif3_hw_params(struc
        switch (dai->id) {
        case 3:
                switch (control->type) {
+               case WM1811:
                case WM8958:
                        aif1_reg = WM8958_AIF3_CONTROL_1;
                        break;
        return snd_soc_update_bits(codec, aif1_reg, WM8994_AIF1_WL_MASK, aif1);
  }
  
+ static void wm8994_aif_shutdown(struct snd_pcm_substream *substream,
+                               struct snd_soc_dai *dai)
+ {
+       struct snd_soc_codec *codec = dai->codec;
+       int rate_reg = 0;
+       switch (dai->id) {
+       case 1:
+               rate_reg = WM8994_AIF1_RATE;
+               break;
+       case 2:
+               rate_reg = WM8994_AIF2_RATE;
+               break;
+       default:
+               break;
+       }
+       /* If the DAI is idle then configure the divider tree for the
+        * lowest output rate to save a little power if the clock is
+        * still active (eg, because it is system clock).
+        */
+       if (rate_reg && !dai->playback_active && !dai->capture_active)
+               snd_soc_update_bits(codec, rate_reg,
+                                   WM8994_AIF1_SR_MASK |
+                                   WM8994_AIF1CLK_RATE_MASK, 0x9);
+ }
  static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute)
  {
        struct snd_soc_codec *codec = codec_dai->codec;
@@@ -2613,6 -2516,21 +2575,21 @@@ static int wm8994_set_tristate(struct s
        return snd_soc_update_bits(codec, reg, mask, val);
  }
  
+ static int wm8994_aif2_probe(struct snd_soc_dai *dai)
+ {
+       struct snd_soc_codec *codec = dai->codec;
+       /* Disable the pulls on the AIF if we're using it to save power. */
+       snd_soc_update_bits(codec, WM8994_GPIO_3,
+                           WM8994_GPN_PU | WM8994_GPN_PD, 0);
+       snd_soc_update_bits(codec, WM8994_GPIO_4,
+                           WM8994_GPN_PU | WM8994_GPN_PD, 0);
+       snd_soc_update_bits(codec, WM8994_GPIO_5,
+                           WM8994_GPN_PU | WM8994_GPN_PD, 0);
+       return 0;
+ }
  #define WM8994_RATES SNDRV_PCM_RATE_8000_96000
  
  #define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
@@@ -2622,6 -2540,7 +2599,7 @@@ static struct snd_soc_dai_ops wm8994_ai
        .set_sysclk     = wm8994_set_dai_sysclk,
        .set_fmt        = wm8994_set_dai_fmt,
        .hw_params      = wm8994_hw_params,
+       .shutdown       = wm8994_aif_shutdown,
        .digital_mute   = wm8994_aif_mute,
        .set_pll        = wm8994_set_fll,
        .set_tristate   = wm8994_set_tristate,
@@@ -2631,6 -2550,7 +2609,7 @@@ static struct snd_soc_dai_ops wm8994_ai
        .set_sysclk     = wm8994_set_dai_sysclk,
        .set_fmt        = wm8994_set_dai_fmt,
        .hw_params      = wm8994_hw_params,
+       .shutdown       = wm8994_aif_shutdown,
        .digital_mute   = wm8994_aif_mute,
        .set_pll        = wm8994_set_fll,
        .set_tristate   = wm8994_set_tristate,
@@@ -2678,6 -2598,7 +2657,7 @@@ static struct snd_soc_dai_driver wm8994
                        .rates = WM8994_RATES,
                        .formats = WM8994_FORMATS,
                },
+               .probe = wm8994_aif2_probe,
                .ops = &wm8994_aif2_dai_ops,
        },
        {
  static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
  {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       struct wm8994 *control = codec->control_data;
        int i, ret;
  
+       switch (control->type) {
+       case WM8994:
+               snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0);
+               break;
+       case WM1811:
+       case WM8958:
+               snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+                                   WM8958_MICD_ENA, 0);
+               break;
+       }
        for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
                memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i],
-                      sizeof(struct fll_config));
+                      sizeof(struct wm8994_fll_config));
                ret = _wm8994_set_fll(codec, i + 1, 0, 0, 0);
                if (ret < 0)
                        dev_warn(codec->dev, "Failed to stop FLL%d: %d\n",
  static int wm8994_resume(struct snd_soc_codec *codec)
  {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       struct wm8994 *control = codec->control_data;
        int i, ret;
        unsigned int val, mask;
  
                                 i + 1, ret);
        }
  
+       switch (control->type) {
+       case WM8994:
+               if (wm8994->micdet[0].jack || wm8994->micdet[1].jack)
+                       snd_soc_update_bits(codec, WM8994_MICBIAS,
+                                           WM8994_MICD_ENA, WM8994_MICD_ENA);
+               break;
+       case WM1811:
+       case WM8958:
+               if (wm8994->jack_cb)
+                       snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+                                           WM8958_MICD_ENA, WM8958_MICD_ENA);
+               break;
+       }
        return 0;
  }
  #else
@@@ -2895,39 -2843,18 +2902,18 @@@ static void wm8994_handle_pdata(struct 
        dev_dbg(codec->dev, "%d ReTune Mobile configurations\n",
                pdata->num_retune_mobile_cfgs);
  
-       if (pdata->num_mbc_cfgs) {
-               struct snd_kcontrol_new control[] = {
-                       SOC_ENUM_EXT("MBC Mode", wm8994->mbc_enum,
-                                    wm8958_get_mbc_enum, wm8958_put_mbc_enum),
-               };
-               /* We need an array of texts for the enum API */
-               wm8994->mbc_texts = kmalloc(sizeof(char *)
-                                           * pdata->num_mbc_cfgs, GFP_KERNEL);
-               if (!wm8994->mbc_texts) {
-                       dev_err(wm8994->codec->dev,
-                               "Failed to allocate %d MBC config texts\n",
-                               pdata->num_mbc_cfgs);
-                       return;
-               }
-               for (i = 0; i < pdata->num_mbc_cfgs; i++)
-                       wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name;
-               wm8994->mbc_enum.max = pdata->num_mbc_cfgs;
-               wm8994->mbc_enum.texts = wm8994->mbc_texts;
-               ret = snd_soc_add_controls(wm8994->codec, control, 1);
-               if (ret != 0)
-                       dev_err(wm8994->codec->dev,
-                               "Failed to add MBC mode controls: %d\n", ret);
-       }
        if (pdata->num_retune_mobile_cfgs)
                wm8994_handle_retune_mobile_pdata(wm8994);
        else
                snd_soc_add_controls(wm8994->codec, wm8994_eq_controls,
                                     ARRAY_SIZE(wm8994_eq_controls));
+       for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) {
+               if (pdata->micbias[i]) {
+                       snd_soc_write(codec, WM8958_MICBIAS1 + i,
+                               pdata->micbias[i] & 0xffff);
+               }
+       }
  }
  
  /**
@@@ -3038,46 -2965,18 +3024,18 @@@ static void wm8958_default_micdet(u16 s
        int report = 0;
  
        /* If nothing present then clear our statuses */
-       if (!(status & WM8958_MICD_STS)) {
-               wm8994->jack_is_video = false;
-               wm8994->jack_is_mic = false;
+       if (!(status & WM8958_MICD_STS))
                goto done;
-       }
-       /* Assume anything over 475 ohms is a microphone and remember
-        * that we've seen one (since buttons override it) */
-       if (status & 0x600)
-               wm8994->jack_is_mic = true;
-       if (wm8994->jack_is_mic)
-               report |= SND_JACK_MICROPHONE;
  
-       /* Video has an impedence of approximately 75 ohms; assume
-        * this isn't used as a button and remember it since buttons
-        * override it. */
-       if (status & 0x40)
-               wm8994->jack_is_video = true;
-       if (wm8994->jack_is_video)
-               report |= SND_JACK_VIDEOOUT;
+       report = SND_JACK_MICROPHONE;
  
        /* Everything else is buttons; just assign slots */
-       if (status & 0x4)
+       if (status & 0x1c)
                report |= SND_JACK_BTN_0;
-       if (status & 0x8)
-               report |= SND_JACK_BTN_1;
-       if (status & 0x10)
-               report |= SND_JACK_BTN_2;
-       if (status & 0x20)
-               report |= SND_JACK_BTN_3;
-       if (status & 0x80)
-               report |= SND_JACK_BTN_4;
-       if (status & 0x100)
-               report |= SND_JACK_BTN_5;
  
  done:
        snd_soc_jack_report(wm8994->micdet[0].jack, report,
-                           SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 |
-                           SND_JACK_BTN_3 | SND_JACK_BTN_4 | SND_JACK_BTN_5 |
-                           SND_JACK_MICROPHONE | SND_JACK_VIDEOOUT);
+                           SND_JACK_BTN_0 | SND_JACK_MICROPHONE);
  }
  
  /**
@@@ -3102,8 -3001,13 +3060,13 @@@ int wm8958_mic_detect(struct snd_soc_co
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = codec->control_data;
  
-       if (control->type != WM8958)
+       switch (control->type) {
+       case WM1811:
+       case WM8958:
+               break;
+       default:
                return -EINVAL;
+       }
  
        if (jack) {
                if (!cb) {
@@@ -3131,19 -3035,34 +3094,34 @@@ static irqreturn_t wm8958_mic_irq(int i
  {
        struct wm8994_priv *wm8994 = data;
        struct snd_soc_codec *codec = wm8994->codec;
-       int reg;
+       int reg, count;
  
-       reg = snd_soc_read(codec, WM8958_MIC_DETECT_3);
-       if (reg < 0) {
-               dev_err(codec->dev, "Failed to read mic detect status: %d\n",
-                       reg);
-               return IRQ_NONE;
-       }
+       /* We may occasionally read a detection without an impedence
+        * range being provided - if that happens loop again.
+        */
+       count = 10;
+       do {
+               reg = snd_soc_read(codec, WM8958_MIC_DETECT_3);
+               if (reg < 0) {
+                       dev_err(codec->dev,
+                               "Failed to read mic detect status: %d\n",
+                               reg);
+                       return IRQ_NONE;
+               }
  
-       if (!(reg & WM8958_MICD_VALID)) {
-               dev_dbg(codec->dev, "Mic detect data not valid\n");
-               goto out;
-       }
+               if (!(reg & WM8958_MICD_VALID)) {
+                       dev_dbg(codec->dev, "Mic detect data not valid\n");
+                       goto out;
+               }
+               if (!(reg & WM8958_MICD_STS) || (reg & WM8958_MICD_LVL_MASK))
+                       break;
+               msleep(1);
+       } while (count--);
+       if (count == 0)
+               dev_warn(codec->dev, "No impedence range reported for jack\n");
  
  #ifndef CONFIG_SND_SOC_WM8994_MODULE
        trace_snd_soc_jack_irq(dev_name(codec->dev));
        return IRQ_HANDLED;
  }
  
+ static irqreturn_t wm8994_fifo_error(int irq, void *data)
+ {
+       struct snd_soc_codec *codec = data;
+       dev_err(codec->dev, "FIFO error\n");
+       return IRQ_HANDLED;
+ }
+ static irqreturn_t wm8994_temp_warn(int irq, void *data)
+ {
+       struct snd_soc_codec *codec = data;
+       dev_err(codec->dev, "Thermal warning\n");
+       return IRQ_HANDLED;
+ }
+ static irqreturn_t wm8994_temp_shut(int irq, void *data)
+ {
+       struct snd_soc_codec *codec = data;
+       dev_crit(codec->dev, "Thermal shutdown\n");
+       return IRQ_HANDLED;
+ }
  static int wm8994_codec_probe(struct snd_soc_codec *codec)
  {
        struct wm8994 *control;
        wm8994->pdata = dev_get_platdata(codec->dev->parent);
        wm8994->codec = codec;
  
+       for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
+               init_completion(&wm8994->fll_locked[i]);
+       if (wm8994->pdata && wm8994->pdata->micdet_irq)
+               wm8994->micdet_irq = wm8994->pdata->micdet_irq;
+       else if (wm8994->pdata && wm8994->pdata->irq_base)
+               wm8994->micdet_irq = wm8994->pdata->irq_base +
+                                    WM8994_IRQ_MIC1_DET;
        pm_runtime_enable(codec->dev);
        pm_runtime_resume(codec->dev);
  
        /* Read our current status back from the chip - we don't want to
         * reset as this may interfere with the GPIO or LDO operation. */
        for (i = 0; i < WM8994_CACHE_SIZE; i++) {
-               if (!wm8994_readable(i) || wm8994_volatile(i))
+               if (!wm8994_readable(codec, i) || wm8994_volatile(codec, i))
                        continue;
  
                ret = wm8994_reg_read(codec->control_data, i);
                switch (wm8994->revision) {
                case 2:
                case 3:
-                       wm8994->hubs.dcs_codes = -5;
+                       wm8994->hubs.dcs_codes_l = -5;
+                       wm8994->hubs.dcs_codes_r = -5;
                        wm8994->hubs.hp_startup_mode = 1;
                        wm8994->hubs.dcs_readback_mode = 1;
+                       wm8994->hubs.series_startup = 1;
                        break;
                default:
-                       wm8994->hubs.dcs_readback_mode = 1;
+                       wm8994->hubs.dcs_readback_mode = 2;
                        break;
                }
+               break;
  
        case WM8958:
                wm8994->hubs.dcs_readback_mode = 1;
                break;
  
+       case WM1811:
+               wm8994->hubs.dcs_readback_mode = 2;
+               wm8994->hubs.no_series_update = 1;
+               switch (wm8994->revision) {
+               case 0:
+               case 1:
+               case 2:
+               case 3:
+                       wm8994->hubs.dcs_codes_l = -9;
+                       wm8994->hubs.dcs_codes_r = -5;
+                       break;
+               default:
+                       break;
+               }
+               snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1,
+                                   WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN);
+               break;
        default:
                break;
        }
  
+       wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR,
+                          wm8994_fifo_error, "FIFO error", codec);
+       wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_WARN,
+                          wm8994_temp_warn, "Thermal warning", codec);
+       wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT,
+                          wm8994_temp_shut, "Thermal shutdown", codec);
+       ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
+                                wm_hubs_dcs_done, "DC servo done",
+                                &wm8994->hubs);
+       if (ret == 0)
+               wm8994->hubs.dcs_done_irq = true;
        switch (control->type) {
        case WM8994:
-               ret = wm8994_request_irq(codec->control_data,
-                                        WM8994_IRQ_MIC1_DET,
-                                        wm8994_mic_irq, "Mic 1 detect",
-                                        wm8994);
-               if (ret != 0)
-                       dev_warn(codec->dev,
-                                "Failed to request Mic1 detect IRQ: %d\n",
-                                ret);
+               if (wm8994->micdet_irq) {
+                       ret = request_threaded_irq(wm8994->micdet_irq, NULL,
+                                                  wm8994_mic_irq,
+                                                  IRQF_TRIGGER_RISING,
+                                                  "Mic1 detect",
+                                                  wm8994);
+                       if (ret != 0)
+                               dev_warn(codec->dev,
+                                        "Failed to request Mic1 detect IRQ: %d\n",
+                                        ret);
+               }
  
                ret = wm8994_request_irq(codec->control_data,
                                         WM8994_IRQ_MIC1_SHRT,
                break;
  
        case WM8958:
+       case WM1811:
+               if (wm8994->micdet_irq) {
+                       ret = request_threaded_irq(wm8994->micdet_irq, NULL,
+                                                  wm8958_mic_irq,
+                                                  IRQF_TRIGGER_RISING,
+                                                  "Mic detect",
+                                                  wm8994);
+                       if (ret != 0)
+                               dev_warn(codec->dev,
+                                        "Failed to request Mic detect IRQ: %d\n",
+                                        ret);
+               }
+       }
+       wm8994->fll_locked_irq = true;
+       for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) {
                ret = wm8994_request_irq(codec->control_data,
-                                        WM8994_IRQ_MIC1_DET,
-                                        wm8958_mic_irq, "Mic detect",
-                                        wm8994);
+                                        WM8994_IRQ_FLL1_LOCK + i,
+                                        wm8994_fll_locked_irq, "FLL lock",
+                                        &wm8994->fll_locked[i]);
                if (ret != 0)
-                       dev_warn(codec->dev,
-                                "Failed to request Mic detect IRQ: %d\n",
-                                ret);
-               break;
+                       wm8994->fll_locked_irq = false;
        }
  
        /* Remember if AIFnLRCLK is configured as a GPIO.  This should be
        wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
  
        /* Latch volume updates (right only; we always do left then right). */
+       snd_soc_update_bits(codec, WM8994_AIF1_DAC1_LEFT_VOLUME,
+                           WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU);
        snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME,
                            WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU);
+       snd_soc_update_bits(codec, WM8994_AIF1_DAC2_LEFT_VOLUME,
+                           WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU);
        snd_soc_update_bits(codec, WM8994_AIF1_DAC2_RIGHT_VOLUME,
                            WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU);
+       snd_soc_update_bits(codec, WM8994_AIF2_DAC_LEFT_VOLUME,
+                           WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU);
        snd_soc_update_bits(codec, WM8994_AIF2_DAC_RIGHT_VOLUME,
                            WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU);
+       snd_soc_update_bits(codec, WM8994_AIF1_ADC1_LEFT_VOLUME,
+                           WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU);
        snd_soc_update_bits(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME,
                            WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU);
+       snd_soc_update_bits(codec, WM8994_AIF1_ADC2_LEFT_VOLUME,
+                           WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU);
        snd_soc_update_bits(codec, WM8994_AIF1_ADC2_RIGHT_VOLUME,
                            WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU);
+       snd_soc_update_bits(codec, WM8994_AIF2_ADC_LEFT_VOLUME,
+                           WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU);
        snd_soc_update_bits(codec, WM8994_AIF2_ADC_RIGHT_VOLUME,
                            WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU);
+       snd_soc_update_bits(codec, WM8994_DAC1_LEFT_VOLUME,
+                           WM8994_DAC1_VU, WM8994_DAC1_VU);
        snd_soc_update_bits(codec, WM8994_DAC1_RIGHT_VOLUME,
                            WM8994_DAC1_VU, WM8994_DAC1_VU);
+       snd_soc_update_bits(codec, WM8994_DAC2_LEFT_VOLUME,
+                           WM8994_DAC2_VU, WM8994_DAC2_VU);
        snd_soc_update_bits(codec, WM8994_DAC2_RIGHT_VOLUME,
                            WM8994_DAC2_VU, WM8994_DAC2_VU);
  
                            1 << WM8994_AIF2DAC_3D_GAIN_SHIFT,
                            1 << WM8994_AIF2DAC_3D_GAIN_SHIFT);
  
-       /* Unconditionally enable AIF1 ADC TDM mode; it only affects
-        * behaviour on idle TDM clock cycles. */
-       snd_soc_update_bits(codec, WM8994_AIF1_CONTROL_1,
-                           WM8994_AIF1ADC_TDM, WM8994_AIF1ADC_TDM);
+       /* Unconditionally enable AIF1 ADC TDM mode on chips which can
+        * use this; it only affects behaviour on idle TDM clock
+        * cycles. */
+       switch (control->type) {
+       case WM8994:
+       case WM8958:
+               snd_soc_update_bits(codec, WM8994_AIF1_CONTROL_1,
+                                   WM8994_AIF1ADC_TDM, WM8994_AIF1ADC_TDM);
+               break;
+       default:
+               break;
+       }
  
        wm8994_update_class_w(codec);
  
                if (wm8994->revision < 4) {
                        snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets,
                                                  ARRAY_SIZE(wm8994_lateclk_revd_widgets));
 +<<<<<<< HEAD
 +=======
                        snd_soc_dapm_new_controls(dapm, wm8994_adc_revd_widgets,
                                                  ARRAY_SIZE(wm8994_adc_revd_widgets));
 +>>>>>>> d10902812c9cd5583130a4ebb9ad19c60b68149d
                        snd_soc_dapm_new_controls(dapm, wm8994_dac_revd_widgets,
                                                  ARRAY_SIZE(wm8994_dac_revd_widgets));
                } else {
                        snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets,
                                                  ARRAY_SIZE(wm8994_lateclk_widgets));
 +<<<<<<< HEAD
 +=======
                        snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets,
                                                  ARRAY_SIZE(wm8994_adc_widgets));
 +>>>>>>> d10902812c9cd5583130a4ebb9ad19c60b68149d
                        snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets,
                                                  ARRAY_SIZE(wm8994_dac_widgets));
                }
        case WM8958:
                snd_soc_add_controls(codec, wm8958_snd_controls,
                                     ARRAY_SIZE(wm8958_snd_controls));
+               snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
+                                         ARRAY_SIZE(wm8958_dapm_widgets));
+               if (wm8994->revision < 1) {
+                       snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets,
+                                                 ARRAY_SIZE(wm8994_lateclk_revd_widgets));
+                       snd_soc_dapm_new_controls(dapm, wm8994_adc_revd_widgets,
+                                                 ARRAY_SIZE(wm8994_adc_revd_widgets));
+                       snd_soc_dapm_new_controls(dapm, wm8994_dac_revd_widgets,
+                                                 ARRAY_SIZE(wm8994_dac_revd_widgets));
+               } else {
+                       snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets,
+                                                 ARRAY_SIZE(wm8994_lateclk_widgets));
+                       snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets,
+                                                 ARRAY_SIZE(wm8994_adc_widgets));
+                       snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets,
+                                                 ARRAY_SIZE(wm8994_dac_widgets));
+               }
+               break;
+       case WM1811:
+               snd_soc_add_controls(codec, wm8958_snd_controls,
+                                    ARRAY_SIZE(wm8958_snd_controls));
+               snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
+                                         ARRAY_SIZE(wm8958_dapm_widgets));
                snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets,
                                          ARRAY_SIZE(wm8994_lateclk_widgets));
                snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets,
                                          ARRAY_SIZE(wm8994_adc_widgets));
                snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets,
                                          ARRAY_SIZE(wm8994_dac_widgets));
-               snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
-                                         ARRAY_SIZE(wm8958_dapm_widgets));
                break;
        }
                
                }
                break;
        case WM8958:
+               if (wm8994->revision < 1) {
+                       snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon,
+                                               ARRAY_SIZE(wm8994_revd_intercon));
+                       snd_soc_dapm_add_routes(dapm, wm8994_lateclk_revd_intercon,
+                                               ARRAY_SIZE(wm8994_lateclk_revd_intercon));
+               } else {
+                       snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon,
+                                               ARRAY_SIZE(wm8994_lateclk_intercon));
+                       snd_soc_dapm_add_routes(dapm, wm8958_intercon,
+                                               ARRAY_SIZE(wm8958_intercon));
+               }
+               wm8958_dsp2_init(codec);
+               break;
+       case WM1811:
                snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon,
                                        ARRAY_SIZE(wm8994_lateclk_intercon));
                snd_soc_dapm_add_routes(dapm, wm8958_intercon,
@@@ -3420,7 -3482,16 +3547,16 @@@ err_irq
        wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
        wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
        wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
-       wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994);
+       if (wm8994->micdet_irq)
+               free_irq(wm8994->micdet_irq, wm8994);
+       for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
+               wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i,
+                               &wm8994->fll_locked[i]);
+       wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
+                       &wm8994->hubs);
+       wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec);
+       wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, codec);
+       wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, codec);
  err:
        kfree(wm8994);
        return ret;
@@@ -3430,15 -3501,26 +3566,26 @@@ static int  wm8994_codec_remove(struct 
  {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = codec->control_data;
+       int i;
  
        wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
  
        pm_runtime_disable(codec->dev);
  
+       for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
+               wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i,
+                               &wm8994->fll_locked[i]);
+       wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
+                       &wm8994->hubs);
+       wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec);
+       wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, codec);
+       wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, codec);
        switch (control->type) {
        case WM8994:
-               wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT,
-                               wm8994);
+               if (wm8994->micdet_irq)
+                       free_irq(wm8994->micdet_irq, wm8994);
                wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET,
                                wm8994);
                wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT,
                                wm8994);
                break;
  
+       case WM1811:
        case WM8958:
-               wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET,
-                               wm8994);
+               if (wm8994->micdet_irq)
+                       free_irq(wm8994->micdet_irq, wm8994);
                break;
        }
+       if (wm8994->mbc)
+               release_firmware(wm8994->mbc);
+       if (wm8994->mbc_vss)
+               release_firmware(wm8994->mbc_vss);
+       if (wm8994->enh_eq)
+               release_firmware(wm8994->enh_eq);
        kfree(wm8994->retune_mobile_texts);
        kfree(wm8994->drc_texts);
        kfree(wm8994);