]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'fix/hda' into topic/hda
authorTakashi Iwai <tiwai@suse.de>
Tue, 19 Jan 2010 14:53:43 +0000 (15:53 +0100)
committerTakashi Iwai <tiwai@suse.de>
Tue, 19 Jan 2010 14:53:43 +0000 (15:53 +0100)
Conflicts:
sound/pci/hda/patch_realtek.c

1  2 
sound/core/pcm_native.c
sound/pci/ac97/ac97_patch.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c

diff --combined sound/core/pcm_native.c
index 27284f6283619e67271a0cb7772b24917dbd7a34,25b0641e6b8c28b7afefb3e54648990f6618e80c..a870fe69657890186fb92314fe7769bf743f1e6f
@@@ -516,7 -516,6 +516,7 @@@ static int snd_pcm_sw_params(struct snd
                             struct snd_pcm_sw_params *params)
  {
        struct snd_pcm_runtime *runtime;
 +      int err;
  
        if (PCM_RUNTIME_CHECK(substream))
                return -ENXIO;
                if (params->silence_threshold > runtime->buffer_size)
                        return -EINVAL;
        }
 +      err = 0;
        snd_pcm_stream_lock_irq(substream);
        runtime->tstamp_mode = params->tstamp_mode;
        runtime->period_step = params->period_step;
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
                    runtime->silence_size > 0)
                        snd_pcm_playback_silence(substream, ULONG_MAX);
 -              wake_up(&runtime->sleep);
 +              err = snd_pcm_update_state(substream, runtime);
        }
        snd_pcm_stream_unlock_irq(substream);
 -      return 0;
 +      return err;
  }
  
  static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream,
@@@ -1249,6 -1247,8 +1249,6 @@@ static int snd_pcm_do_reset(struct snd_
        if (err < 0)
                return err;
        runtime->hw_ptr_base = 0;
 -      runtime->hw_ptr_interrupt = runtime->status->hw_ptr -
 -              runtime->status->hw_ptr % runtime->period_size;
        runtime->silence_start = runtime->status->hw_ptr;
        runtime->silence_filled = 0;
        return 0;
@@@ -1918,13 -1918,13 +1918,13 @@@ int snd_pcm_hw_constraints_complete(str
  
        err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
                                           hw->rate_min, hw->rate_max);
-        if (err < 0)
-                return err;
+       if (err < 0)
+               return err;
  
        err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
                                           hw->period_bytes_min, hw->period_bytes_max);
-        if (err < 0)
-                return err;
+       if (err < 0)
+               return err;
  
        err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS,
                                           hw->periods_min, hw->periods_max);
index e288a5595f346e0ec40e604b06a62683c901fa47,d9266bae284977fb4bccbff7bc062d421d65cee0..1caf5e3c1f6ad481064ea70cced23293333de96a
@@@ -544,10 -544,25 +544,10 @@@ static int patch_wolfson04(struct snd_a
        return 0;
  }
  
 -static int patch_wolfson_wm9705_specific(struct snd_ac97 * ac97)
 -{
 -      int err, i;
 -      for (i = 0; i < ARRAY_SIZE(wm97xx_snd_ac97_controls); i++) {
 -              if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm97xx_snd_ac97_controls[i], ac97))) < 0)
 -                      return err;
 -      }
 -      snd_ac97_write_cache(ac97,  0x72, 0x0808);
 -      return 0;
 -}
 -
 -static struct snd_ac97_build_ops patch_wolfson_wm9705_ops = {
 -      .build_specific = patch_wolfson_wm9705_specific,
 -};
 -
  static int patch_wolfson05(struct snd_ac97 * ac97)
  {
        /* WM9705, WM9710 */
 -      ac97->build_ops = &patch_wolfson_wm9705_ops;
 +      ac97->build_ops = &patch_wolfson_wm9703_ops;
  #ifdef CONFIG_TOUCHSCREEN_WM9705
        /* WM9705 touchscreen uses AUX and VIDEO for touch */
        ac97->flags |= AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX;
@@@ -1855,6 -1870,7 +1855,7 @@@ static unsigned int ad1981_jacks_blackl
        0x10140554, /* Thinkpad T42p/R50p */
        0x10140567, /* Thinkpad T43p 2668-G7U */
        0x10140581, /* Thinkpad X41-2527 */
+       0x10280160, /* Dell Dimension 2400 */
        0x104380b0, /* Asus A7V8X-MX */
        0x11790241, /* Toshiba Satellite A-15 S127 */
        0x144dc01a, /* Samsung NP-X20C004/SEG */
index d02ea8926e7e7913d00a7a3b0c7b1c722d82d55f,f98b47cd6cfb38fc97335c3788a8f7f5cc3afca1..26ceace88c96febb3538e244d2efc3678aa72a7b
@@@ -824,9 -824,6 +824,9 @@@ int snd_hda_add_pincfg(struct hda_code
        struct hda_pincfg *pin;
        unsigned int oldcfg;
  
 +      if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
 +              return -EINVAL;
 +
        oldcfg = snd_hda_codec_get_pincfg(codec, nid);
        pin = look_up_pincfg(codec, list, nid);
        if (!pin) {
@@@ -902,25 -899,6 +902,25 @@@ static void restore_pincfgs(struct hda_
        }
  }
  
 +/**
 + * snd_hda_shutup_pins - Shut up all pins
 + * @codec: the HDA codec
 + *
 + * Clear all pin controls to shup up before suspend for avoiding click noise.
 + * The controls aren't cached so that they can be resumed properly.
 + */
 +void snd_hda_shutup_pins(struct hda_codec *codec)
 +{
 +      int i;
 +      for (i = 0; i < codec->init_pins.used; i++) {
 +              struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
 +              /* use read here for syncing after issuing each verb */
 +              snd_hda_codec_read(codec, pin->nid, 0,
 +                                 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
 +      }
 +}
 +EXPORT_SYMBOL_HDA(snd_hda_shutup_pins);
 +
  static void init_hda_cache(struct hda_cache_rec *cache,
                           unsigned int record_size);
  static void free_hda_cache(struct hda_cache_rec *cache);
@@@ -953,7 -931,6 +953,7 @@@ static void snd_hda_codec_free(struct h
  #endif
        list_del(&codec->list);
        snd_array_free(&codec->mixers);
 +      snd_array_free(&codec->nids);
        codec->bus->caddr_tbl[codec->addr] = NULL;
        if (codec->patch_ops.free)
                codec->patch_ops.free(codec);
@@@ -1008,8 -985,7 +1008,8 @@@ int /*__devinit*/ snd_hda_codec_new(str
        mutex_init(&codec->control_mutex);
        init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
        init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
 -      snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 60);
 +      snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32);
 +      snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32);
        snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
        snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
        if (codec->bus->modelname) {
@@@ -1351,11 -1327,13 +1351,13 @@@ EXPORT_SYMBOL_HDA(snd_hda_query_pin_cap
   */
  u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
  {
-       u32 pincap = snd_hda_query_pin_caps(codec, nid);
-       if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
-               snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
+       u32 pincap;
  
+       if (!codec->no_trigger_sense) {
+               pincap = snd_hda_query_pin_caps(codec, nid);
+               if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
+                       snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
+       }
        return snd_hda_codec_read(codec, nid, 0,
                                  AC_VERB_GET_PIN_SENSE, 0);
  }
@@@ -1730,7 -1708,7 +1732,7 @@@ struct snd_kcontrol *snd_hda_find_mixer
  EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
  
  /**
 - * snd_hda_ctl-add - Add a control element and assign to the codec
 + * snd_hda_ctl_add - Add a control element and assign to the codec
   * @codec: HD-audio codec
   * @nid: corresponding NID (optional)
   * @kctl: the control element to assign
   *
   * snd_hda_ctl_add() checks the control subdev id field whether
   * #HDA_SUBDEV_NID_FLAG bit is set.  If set (and @nid is zero), the lower
 - * bits value is taken as the NID to assign.
 + * bits value is taken as the NID to assign. The #HDA_NID_ITEM_AMP bit
 + * specifies if kctl->private_value is a HDA amplifier value.
   */
  int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
                    struct snd_kcontrol *kctl)
  {
        int err;
 +      unsigned short flags = 0;
        struct hda_nid_item *item;
  
 -      if (kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) {
 +      if (kctl->id.subdevice & HDA_SUBDEV_AMP_FLAG) {
 +              flags |= HDA_NID_ITEM_AMP;
                if (nid == 0)
 -                      nid = kctl->id.subdevice & 0xffff;
 -              kctl->id.subdevice = 0;
 +                      nid = get_amp_nid_(kctl->private_value);
        }
 +      if ((kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) != 0 && nid == 0)
 +              nid = kctl->id.subdevice & 0xffff;
 +      if (kctl->id.subdevice & (HDA_SUBDEV_NID_FLAG|HDA_SUBDEV_AMP_FLAG))
 +              kctl->id.subdevice = 0;
        err = snd_ctl_add(codec->bus->card, kctl);
        if (err < 0)
                return err;
                return -ENOMEM;
        item->kctl = kctl;
        item->nid = nid;
 +      item->flags = flags;
        return 0;
  }
  EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
  
 +/**
 + * snd_hda_add_nid - Assign a NID to a control element
 + * @codec: HD-audio codec
 + * @nid: corresponding NID (optional)
 + * @kctl: the control element to assign
 + * @index: index to kctl
 + *
 + * Add the given control element to an array inside the codec instance.
 + * This function is used when #snd_hda_ctl_add cannot be used for 1:1
 + * NID:KCTL mapping - for example "Capture Source" selector.
 + */
 +int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl,
 +                  unsigned int index, hda_nid_t nid)
 +{
 +      struct hda_nid_item *item;
 +
 +      if (nid > 0) {
 +              item = snd_array_new(&codec->nids);
 +              if (!item)
 +                      return -ENOMEM;
 +              item->kctl = kctl;
 +              item->index = index;
 +              item->nid = nid;
 +              return 0;
 +      }
 +      return -EINVAL;
 +}
 +EXPORT_SYMBOL_HDA(snd_hda_add_nid);
 +
  /**
   * snd_hda_ctls_clear - Clear all controls assigned to the given codec
   * @codec: HD-audio codec
@@@ -1817,7 -1759,6 +1819,7 @@@ void snd_hda_ctls_clear(struct hda_code
        for (i = 0; i < codec->mixers.used; i++)
                snd_ctl_remove(codec->bus->card, items[i].kctl);
        snd_array_free(&codec->mixers);
 +      snd_array_free(&codec->nids);
  }
  
  /* pseudo device locking
@@@ -3537,8 -3478,6 +3539,8 @@@ int snd_hda_add_new_ctls(struct hda_cod
  
        for (; knew->name; knew++) {
                struct snd_kcontrol *kctl;
 +              if (knew->iface == -1)  /* skip this codec private value */
 +                      continue;
                kctl = snd_ctl_new1(knew, codec);
                if (!kctl)
                        return -ENOMEM;
index 11c4aa8ee9966c32f446d473e6b86b151d55a3ba,0a770a28e71f8b66a6c225bf08133dcec5d99390..0c8f05cc56beebdfcec62f2ff0f5d0a6c19b6bdf
@@@ -789,7 -789,6 +789,7 @@@ struct hda_codec 
        u32 *wcaps;
  
        struct snd_array mixers;        /* list of assigned mixer elements */
 +      struct snd_array nids;          /* list of mapped mixer elements */
  
        struct hda_cache_rec amp_cache; /* cache for amp access */
        struct hda_cache_rec cmd_cache; /* cache for other commands */
        unsigned int pin_amp_workaround:1; /* pin out-amp takes index
                                            * (e.g. Conexant codecs)
                                            */
+       unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
  #ifdef CONFIG_SND_HDA_POWER_SAVE
        unsigned int power_on :1;       /* current (global) power-state */
        unsigned int power_transition :1; /* power-state in transition */
@@@ -898,7 -898,6 +899,7 @@@ int snd_hda_codec_set_pincfg(struct hda
                             unsigned int cfg);
  int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
                       hda_nid_t nid, unsigned int cfg); /* for hwdep */
 +void snd_hda_shutup_pins(struct hda_codec *codec);
  
  /*
   * Mixer
index cecd3c10899080f180a8ae8dd370539532e4722f,69a941c7b1588b7db4a9acd0fe79da65824c8944..21011b5199de5d4a24fdfa4d88fff015b4dc67cf
@@@ -174,7 -174,6 +174,7 @@@ static struct snd_kcontrol_new ad_beep_
  static int ad198x_build_controls(struct hda_codec *codec)
  {
        struct ad198x_spec *spec = codec->spec;
 +      struct snd_kcontrol *kctl;
        unsigned int i;
        int err;
  
                        if (!kctl)
                                return -ENOMEM;
                        kctl->private_value = spec->beep_amp;
 -                      err = snd_hda_ctl_add(codec,
 -                                              get_amp_nid_(spec->beep_amp),
 -                                              kctl);
 +                      err = snd_hda_ctl_add(codec, 0, kctl);
                        if (err < 0)
                                return err;
                }
        }
  
        ad198x_free_kctls(codec); /* no longer needed */
 +
 +      /* assign Capture Source enums to NID */
 +      kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
 +      if (!kctl)
 +              kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
 +      for (i = 0; kctl && i < kctl->count; i++) {
 +              err = snd_hda_add_nid(codec, kctl, i, spec->capsrc_nids[i]);
 +              if (err < 0)
 +                      return err;
 +      }
 +
 +      /* assign IEC958 enums to NID */
 +      kctl = snd_hda_find_mixer_ctl(codec,
 +                      SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source");
 +      if (kctl) {
 +              err = snd_hda_add_nid(codec, kctl, 0,
 +                                    spec->multiout.dig_out_nid);
 +              if (err < 0)
 +                      return err;
 +      }
 +
        return 0;
  }
  
@@@ -441,11 -421,6 +441,11 @@@ static int ad198x_build_pcms(struct hda
        return 0;
  }
  
 +static inline void ad198x_shutup(struct hda_codec *codec)
 +{
 +      snd_hda_shutup_pins(codec);
 +}
 +
  static void ad198x_free_kctls(struct hda_codec *codec)
  {
        struct ad198x_spec *spec = codec->spec;
        snd_array_free(&spec->kctls);
  }
  
 +static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
 +                              hda_nid_t hp)
 +{
 +      struct ad198x_spec *spec = codec->spec;
 +      snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
 +                          !spec->inv_eapd ? 0x00 : 0x02);
 +      snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
 +                          !spec->inv_eapd ? 0x00 : 0x02);
 +}
 +
 +static void ad198x_power_eapd(struct hda_codec *codec)
 +{
 +      /* We currently only handle front, HP */
 +      switch (codec->vendor_id) {
 +      case 0x11d41882:
 +      case 0x11d4882a:
 +      case 0x11d41884:
 +      case 0x11d41984:
 +      case 0x11d41883:
 +      case 0x11d4184a:
 +      case 0x11d4194a:
 +      case 0x11d4194b:
 +              ad198x_power_eapd_write(codec, 0x12, 0x11);
 +              break;
 +      case 0x11d41981:
 +      case 0x11d41983:
 +              ad198x_power_eapd_write(codec, 0x05, 0x06);
 +              break;
 +      case 0x11d41986:
 +              ad198x_power_eapd_write(codec, 0x1b, 0x1a);
 +              break;
 +      case 0x11d41988:
 +      case 0x11d4198b:
 +      case 0x11d4989a:
 +      case 0x11d4989b:
 +              ad198x_power_eapd_write(codec, 0x29, 0x22);
 +              break;
 +      }
 +}
 +
  static void ad198x_free(struct hda_codec *codec)
  {
        struct ad198x_spec *spec = codec->spec;
        if (!spec)
                return;
  
 +      ad198x_shutup(codec);
        ad198x_free_kctls(codec);
        kfree(spec);
        snd_hda_detach_beep_device(codec);
  }
  
 +#ifdef SND_HDA_NEEDS_RESUME
 +static int ad198x_suspend(struct hda_codec *codec, pm_message_t state)
 +{
 +      ad198x_shutup(codec);
 +      ad198x_power_eapd(codec);
 +      return 0;
 +}
 +
 +static int ad198x_resume(struct hda_codec *codec)
 +{
 +      ad198x_init(codec);
 +      snd_hda_codec_resume_amp(codec);
 +      snd_hda_codec_resume_cache(codec);
 +      return 0;
 +}
 +#endif
 +
  static struct hda_codec_ops ad198x_patch_ops = {
        .build_controls = ad198x_build_controls,
        .build_pcms = ad198x_build_pcms,
  #ifdef CONFIG_SND_HDA_POWER_SAVE
        .check_power_status = ad198x_check_power_status,
  #endif
 +#ifdef SND_HDA_NEEDS_RESUME
 +      .suspend = ad198x_suspend,
 +      .resume = ad198x_resume,
 +#endif
 +      .reboot_notify = ad198x_shutup,
  };
  
  
@@@ -789,7 -701,6 +789,7 @@@ static struct snd_kcontrol_new ad1986a_
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "External Amplifier",
 +              .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
                .info = ad198x_eapd_info,
                .get = ad198x_eapd_get,
                .put = ad198x_eapd_put,
@@@ -897,7 -808,6 +897,7 @@@ static struct snd_kcontrol_new ad1986a_
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = ad1986a_hp_master_sw_put,
@@@ -1276,6 -1186,8 +1276,8 @@@ static int patch_ad1986a(struct hda_cod
         */
        spec->multiout.no_share_stream = 1;
  
+       codec->no_trigger_sense = 1;
        return 0;
  }
  
@@@ -1461,6 -1373,8 +1463,8 @@@ static int patch_ad1983(struct hda_code
  
        codec->patch_ops = ad198x_patch_ops;
  
+       codec->no_trigger_sense = 1;
        return 0;
  }
  
@@@ -1698,7 -1612,6 +1702,7 @@@ static struct snd_kcontrol_new ad1981_h
        HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 +              .subdevice = HDA_SUBDEV_NID_FLAG | 0x05,
                .name = "Master Playback Switch",
                .info = ad198x_eapd_info,
                .get = ad198x_eapd_get,
@@@ -1904,6 -1817,9 +1908,9 @@@ static int patch_ad1981(struct hda_code
                codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
                break;
        }
+       codec->no_trigger_sense = 1;
        return 0;
  }
  
@@@ -2220,7 -2136,6 +2227,7 @@@ static struct snd_kcontrol_new ad1988_l
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "External Amplifier",
 +              .subdevice = HDA_SUBDEV_NID_FLAG | 0x12,
                .info = ad198x_eapd_info,
                .get = ad198x_eapd_get,
                .put = ad198x_eapd_put,
@@@ -2342,7 -2257,6 +2349,7 @@@ static struct snd_kcontrol_new ad1988_s
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "IEC958 Playback Source",
 +              .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
                .info = ad1988_spdif_playback_source_info,
                .get = ad1988_spdif_playback_source_get,
                .put = ad1988_spdif_playback_source_put,
@@@ -2675,7 -2589,7 +2682,7 @@@ static int add_control(struct ad198x_sp
        if (! knew->name)
                return -ENOMEM;
        if (get_amp_nid_(val))
 -              knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val);
 +              knew->subdevice = HDA_SUBDEV_AMP_FLAG;
        knew->private_value = val;
        return 0;
  }
@@@ -3211,6 -3125,8 +3218,8 @@@ static int patch_ad1988(struct hda_code
  #endif
        spec->vmaster_nid = 0x04;
  
+       codec->no_trigger_sense = 1;
        return 0;
  }
  
@@@ -3423,6 -3339,8 +3432,8 @@@ static int patch_ad1884(struct hda_code
  
        codec->patch_ops = ad198x_patch_ops;
  
+       codec->no_trigger_sense = 1;
        return 0;
  }
  
@@@ -3829,7 -3747,6 +3840,7 @@@ static struct snd_kcontrol_new ad1884a_
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = ad1884a_mobile_master_sw_put,
@@@ -3858,7 -3775,6 +3869,7 @@@ static struct snd_kcontrol_new ad1884a_
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = ad1884a_mobile_master_sw_put,
@@@ -4200,7 -4116,6 +4211,7 @@@ static struct snd_kcontrol_new ad1984a_
  /*    HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .name = "Master Playback Switch",
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
@@@ -4383,6 -4298,8 +4394,8 @@@ static int patch_ad1884a(struct hda_cod
                break;
        }
  
+       codec->no_trigger_sense = 1;
        return 0;
  }
  
@@@ -4719,6 -4636,9 +4732,9 @@@ static int patch_ad1882(struct hda_code
                spec->mixers[2] = ad1882_6stack_mixers;
                break;
        }
+       codec->no_trigger_sense = 1;
        return 0;
  }
  
index 141ff446104ab30b169727681ced2368f72172a5,6ae610c0111e6e31ed28b9186228586b55f940f5..c53faa959390458c8de34c30f928fa349f0dac5f
@@@ -338,7 -338,7 +338,7 @@@ struct alc_spec 
        void (*init_hook)(struct hda_codec *codec);
        void (*unsol_event)(struct hda_codec *codec, unsigned int res);
  #ifdef CONFIG_SND_HDA_POWER_SAVE
 -      void (*power_hook)(struct hda_codec *codec, int power);
 +      void (*power_hook)(struct hda_codec *codec);
  #endif
  
        /* for pin sensing */
@@@ -391,7 -391,7 +391,7 @@@ struct alc_config_preset 
        void (*init_hook)(struct hda_codec *);
  #ifdef CONFIG_SND_HDA_POWER_SAVE
        struct hda_amp_list *loopbacks;
 -      void (*power_hook)(struct hda_codec *codec, int power);
 +      void (*power_hook)(struct hda_codec *codec);
  #endif
  };
  
@@@ -633,7 -633,6 +633,7 @@@ static int alc_pin_mode_put(struct snd_
  
  #define ALC_PIN_MODE(xname, nid, dir) \
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
 +        .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
          .info = alc_pin_mode_info, \
          .get = alc_pin_mode_get, \
          .put = alc_pin_mode_put, \
@@@ -685,7 -684,6 +685,7 @@@ static int alc_gpio_data_put(struct snd
  }
  #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
 +        .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
          .info = alc_gpio_data_info, \
          .get = alc_gpio_data_get, \
          .put = alc_gpio_data_put, \
@@@ -740,7 -738,6 +740,7 @@@ static int alc_spdif_ctrl_put(struct sn
  }
  #define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
 +        .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
          .info = alc_spdif_ctrl_info, \
          .get = alc_spdif_ctrl_get, \
          .put = alc_spdif_ctrl_put, \
@@@ -794,7 -791,6 +794,7 @@@ static int alc_eapd_ctrl_put(struct snd
  
  #define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
 +        .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
          .info = alc_eapd_ctrl_info, \
          .get = alc_eapd_ctrl_get, \
          .put = alc_eapd_ctrl_put, \
@@@ -1097,6 -1093,16 +1097,16 @@@ static void alc889_coef_init(struct hda
        snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
  }
  
+ /* turn on/off EAPD control (only if available) */
+ static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
+ {
+       if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
+               return;
+       if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
+               snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
+                                   on ? 2 : 0);
+ }
  static void alc_auto_init_amp(struct hda_codec *codec, int type)
  {
        unsigned int tmp;
        case ALC_INIT_DEFAULT:
                switch (codec->vendor_id) {
                case 0x10ec0260:
-                       snd_hda_codec_write(codec, 0x0f, 0,
-                                           AC_VERB_SET_EAPD_BTLENABLE, 2);
-                       snd_hda_codec_write(codec, 0x10, 0,
-                                           AC_VERB_SET_EAPD_BTLENABLE, 2);
+                       set_eapd(codec, 0x0f, 1);
+                       set_eapd(codec, 0x10, 1);
                        break;
                case 0x10ec0262:
                case 0x10ec0267:
                case 0x10ec0268:
                case 0x10ec0269:
+               case 0x10ec0270:
                case 0x10ec0272:
                case 0x10ec0660:
                case 0x10ec0662:
                case 0x10ec0663:
                case 0x10ec0862:
                case 0x10ec0889:
-                       snd_hda_codec_write(codec, 0x14, 0,
-                                           AC_VERB_SET_EAPD_BTLENABLE, 2);
-                       snd_hda_codec_write(codec, 0x15, 0,
-                                           AC_VERB_SET_EAPD_BTLENABLE, 2);
+                       set_eapd(codec, 0x14, 1);
+                       set_eapd(codec, 0x15, 1);
                        break;
                }
                switch (codec->vendor_id) {
@@@ -1234,6 -1237,8 +1241,8 @@@ static void alc_init_auto_mic(struct hd
                        return; /* invalid entry */
                }
        }
+       if (!ext || !fixed)
+               return;
        if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
                return; /* no unsol support */
        snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x\n",
@@@ -1835,6 -1840,14 +1844,6 @@@ static void alc889_acer_aspire_8930g_se
        spec->autocfg.speaker_pins[2] = 0x1b;
  }
  
 -#ifdef CONFIG_SND_HDA_POWER_SAVE
 -static void alc889_power_eapd(struct hda_codec *codec, int power)
 -{
 -      set_eapd(codec, 0x14, power);
 -      set_eapd(codec, 0x15, power);
 -}
 -#endif
 -
  /*
   * ALC880 3-stack model
   *
@@@ -2437,15 -2450,6 +2446,15 @@@ static const char *alc_slave_sws[] = 
   * build control elements
   */
  
 +#define NID_MAPPING           (-1)
 +
 +#define SUBDEV_SPEAKER_               (0 << 6)
 +#define SUBDEV_HP_            (1 << 6)
 +#define SUBDEV_LINE_          (2 << 6)
 +#define SUBDEV_SPEAKER(x)     (SUBDEV_SPEAKER_ | ((x) & 0x3f))
 +#define SUBDEV_HP(x)          (SUBDEV_HP_ | ((x) & 0x3f))
 +#define SUBDEV_LINE(x)                (SUBDEV_LINE_ | ((x) & 0x3f))
 +
  static void alc_free_kctls(struct hda_codec *codec);
  
  #ifdef CONFIG_SND_HDA_INPUT_BEEP
@@@ -2460,11 -2464,8 +2469,11 @@@ static struct snd_kcontrol_new alc_beep
  static int alc_build_controls(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
 -      int err;
 -      int i;
 +      struct snd_kcontrol *kctl;
 +      struct snd_kcontrol_new *knew;
 +      int i, j, err;
 +      unsigned int u;
 +      hda_nid_t nid;
  
        for (i = 0; i < spec->num_mixers; i++) {
                err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
                        if (!kctl)
                                return -ENOMEM;
                        kctl->private_value = spec->beep_amp;
 -                      err = snd_hda_ctl_add(codec,
 -                                      get_amp_nid_(spec->beep_amp), kctl);
 +                      err = snd_hda_ctl_add(codec, 0, kctl);
                        if (err < 0)
                                return err;
                }
        }
  
        alc_free_kctls(codec); /* no longer needed */
 +
 +      /* assign Capture Source enums to NID */
 +      kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
 +      if (!kctl)
 +              kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
 +      for (i = 0; kctl && i < kctl->count; i++) {
 +              hda_nid_t *nids = spec->capsrc_nids;
 +              if (!nids)
 +                      nids = spec->adc_nids;
 +              err = snd_hda_add_nid(codec, kctl, i, nids[i]);
 +              if (err < 0)
 +                      return err;
 +      }
 +      if (spec->cap_mixer) {
 +              const char *kname = kctl ? kctl->id.name : NULL;
 +              for (knew = spec->cap_mixer; knew->name; knew++) {
 +                      if (kname && strcmp(knew->name, kname) == 0)
 +                              continue;
 +                      kctl = snd_hda_find_mixer_ctl(codec, knew->name);
 +                      for (i = 0; kctl && i < kctl->count; i++) {
 +                              err = snd_hda_add_nid(codec, kctl, i,
 +                                                    spec->adc_nids[i]);
 +                              if (err < 0)
 +                                      return err;
 +                      }
 +              }
 +      }
 +
 +      /* other nid->control mapping */
 +      for (i = 0; i < spec->num_mixers; i++) {
 +              for (knew = spec->mixers[i]; knew->name; knew++) {
 +                      if (knew->iface != NID_MAPPING)
 +                              continue;
 +                      kctl = snd_hda_find_mixer_ctl(codec, knew->name);
 +                      if (kctl == NULL)
 +                              continue;
 +                      u = knew->subdevice;
 +                      for (j = 0; j < 4; j++, u >>= 8) {
 +                              nid = u & 0x3f;
 +                              if (nid == 0)
 +                                      continue;
 +                              switch (u & 0xc0) {
 +                              case SUBDEV_SPEAKER_:
 +                                      nid = spec->autocfg.speaker_pins[nid];
 +                                      break;
 +                              case SUBDEV_LINE_:
 +                                      nid = spec->autocfg.line_out_pins[nid];
 +                                      break;
 +                              case SUBDEV_HP_:
 +                                      nid = spec->autocfg.hp_pins[nid];
 +                                      break;
 +                              default:
 +                                      continue;
 +                              }
 +                              err = snd_hda_add_nid(codec, kctl, 0, nid);
 +                              if (err < 0)
 +                                      return err;
 +                      }
 +                      u = knew->private_value;
 +                      for (j = 0; j < 4; j++, u >>= 8) {
 +                              nid = u & 0xff;
 +                              if (nid == 0)
 +                                      continue;
 +                              err = snd_hda_add_nid(codec, kctl, 0, nid);
 +                              if (err < 0)
 +                                      return err;
 +                      }
 +              }
 +      }
        return 0;
  }
  
@@@ -3683,11 -3616,6 +3692,11 @@@ static int alc_build_pcms(struct hda_co
        return 0;
  }
  
 +static inline void alc_shutup(struct hda_codec *codec)
 +{
 +      snd_hda_shutup_pins(codec);
 +}
 +
  static void alc_free_kctls(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
@@@ -3708,47 -3636,17 +3717,44 @@@ static void alc_free(struct hda_codec *
        if (!spec)
                return;
  
 +      alc_shutup(codec);
        alc_free_kctls(codec);
        kfree(spec);
        snd_hda_detach_beep_device(codec);
  }
  
  #ifdef CONFIG_SND_HDA_POWER_SAVE
-               snd_hda_codec_write(codec, 0x0f, 0,
-                                   AC_VERB_SET_EAPD_BTLENABLE, 0x00);
-               snd_hda_codec_write(codec, 0x10, 0,
-                                   AC_VERB_SET_EAPD_BTLENABLE, 0x00);
 +static void alc_power_eapd(struct hda_codec *codec)
 +{
 +      /* We currently only handle front, HP */
 +      switch (codec->vendor_id) {
 +      case 0x10ec0260:
-               snd_hda_codec_write(codec, 0x14, 0,
-                                   AC_VERB_SET_EAPD_BTLENABLE, 0x00);
-               snd_hda_codec_write(codec, 0x15, 0,
-                                   AC_VERB_SET_EAPD_BTLENABLE, 0x00);
++              set_eapd(codec, 0x0f, 0);
++              set_eapd(codec, 0x10, 0);
 +              break;
 +      case 0x10ec0262:
 +      case 0x10ec0267:
 +      case 0x10ec0268:
 +      case 0x10ec0269:
++      case 0x10ec0270:
 +      case 0x10ec0272:
 +      case 0x10ec0660:
 +      case 0x10ec0662:
 +      case 0x10ec0663:
 +      case 0x10ec0862:
 +      case 0x10ec0889:
++              set_eapd(codec, 0x14, 0);
++              set_eapd(codec, 0x15, 0);
 +              break;
 +      }
 +}
 +
  static int alc_suspend(struct hda_codec *codec, pm_message_t state)
  {
        struct alc_spec *spec = codec->spec;
 +      alc_shutup(codec);
        if (spec && spec->power_hook)
 -              spec->power_hook(codec, 0);
 +              spec->power_hook(codec);
        return 0;
  }
  #endif
  #ifdef SND_HDA_NEEDS_RESUME
  static int alc_resume(struct hda_codec *codec)
  {
 -#ifdef CONFIG_SND_HDA_POWER_SAVE
 -      struct alc_spec *spec = codec->spec;
 -#endif
        codec->patch_ops.init(codec);
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
 -#ifdef CONFIG_SND_HDA_POWER_SAVE
 -      if (spec && spec->power_hook)
 -              spec->power_hook(codec, 1);
 -#endif
        return 0;
  }
  #endif
@@@ -3778,7 -3683,6 +3784,7 @@@ static struct hda_codec_ops alc_patch_o
        .suspend = alc_suspend,
        .check_power_status = alc_check_power_status,
  #endif
 +      .reboot_notify = alc_shutup,
  };
  
  
@@@ -3935,7 -3839,6 +3941,7 @@@ static int alc_test_pin_src_put(struct 
  #define PIN_CTL_TEST(xname,nid) {                     \
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,    \
                        .name = xname,                 \
 +                      .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
                        .info = alc_test_pin_ctl_info, \
                        .get = alc_test_pin_ctl_get,   \
                        .put = alc_test_pin_ctl_put,   \
  #define PIN_SRC_TEST(xname,nid) {                     \
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,    \
                        .name = xname,                 \
 +                      .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
                        .info = alc_test_pin_src_info, \
                        .get = alc_test_pin_src_get,   \
                        .put = alc_test_pin_src_put,   \
@@@ -4485,7 -4387,7 +4491,7 @@@ static int add_control(struct alc_spec 
        if (!knew->name)
                return -ENOMEM;
        if (get_amp_nid_(val))
 -              knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val);
 +              knew->subdevice = HDA_SUBDEV_AMP_FLAG;
        knew->private_value = val;
        return 0;
  }
@@@ -4917,6 -4819,49 +4923,49 @@@ static void fixup_automic_adc(struct hd
        spec->auto_mic = 0; /* disable auto-mic to be sure */
  }
  
+ /* choose the ADC/MUX containing the input pin and initialize the setup */
+ static void fixup_single_adc(struct hda_codec *codec)
+ {
+       struct alc_spec *spec = codec->spec;
+       hda_nid_t pin;
+       int i;
+       /* search for the input pin; there must be only one */
+       for (i = 0; i < AUTO_PIN_LAST; i++) {
+               if (spec->autocfg.input_pins[i]) {
+                       pin = spec->autocfg.input_pins[i];
+                       break;
+               }
+       }
+       if (!pin)
+               return;
+       /* set the default connection to that pin */
+       for (i = 0; i < spec->num_adc_nids; i++) {
+               hda_nid_t cap = spec->capsrc_nids ?
+                       spec->capsrc_nids[i] : spec->adc_nids[i];
+               int idx;
+               idx = get_connection_index(codec, cap, pin);
+               if (idx < 0)
+                       continue;
+               /* use only this ADC */
+               if (spec->capsrc_nids)
+                       spec->capsrc_nids += i;
+               spec->adc_nids += i;
+               spec->num_adc_nids = 1;
+               /* select or unmute this route */
+               if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
+                       snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
+                                                HDA_AMP_MUTE, 0);
+               } else {
+                       snd_hda_codec_write_cache(codec, cap, 0,
+                                         AC_VERB_SET_CONNECT_SEL, idx);
+               }
+               return;
+       }
+ }
  static void set_capture_mixer(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
                  alc_capture_mixer3 },
        };
        if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) {
-               int mux;
-               if (spec->auto_mic) {
-                       mux = 0;
+               int mux = 0;
+               if (spec->auto_mic)
                        fixup_automic_adc(codec);
-               } else if (spec->input_mux && spec->input_mux->num_items > 1)
-                       mux = 1;
-               else
-                       mux = 0;
+               else if (spec->input_mux) {
+                       if (spec->input_mux->num_items > 1)
+                               mux = 1;
+                       else if (spec->input_mux->num_items == 1)
+                               fixup_single_adc(codec);
+               }
                spec->cap_mixer = caps[mux][spec->num_adc_nids - 1];
        }
  }
@@@ -5236,7 -5182,6 +5286,7 @@@ static struct snd_kcontrol_new alc260_h
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
                .info = snd_ctl_boolean_mono_info,
                .get = alc260_hp_master_sw_get,
                .put = alc260_hp_master_sw_put,
@@@ -5275,7 -5220,6 +5325,7 @@@ static struct snd_kcontrol_new alc260_h
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
                .info = snd_ctl_boolean_mono_info,
                .get = alc260_hp_master_sw_get,
                .put = alc260_hp_master_sw_put,
@@@ -7201,8 -7145,8 +7251,8 @@@ static struct snd_kcontrol_new alc885_m
        HDA_BIND_MUTE   ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
        HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
        HDA_BIND_MUTE   ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
-       HDA_CODEC_VOLUME("HP Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
-       HDA_BIND_MUTE   ("HP Playback Switch", 0x0f, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
+       HDA_BIND_MUTE   ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
        HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
        HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
        HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
@@@ -7603,6 -7547,7 +7653,7 @@@ static struct hda_verb alc885_mb5_init_
        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
        {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
+       {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
        /* Front Mic pin: input vref at 80% */
        {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
        {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
@@@ -7787,6 -7732,27 +7838,27 @@@ static void alc885_mbp3_setup(struct hd
        spec->autocfg.speaker_pins[0] = 0x14;
  }
  
+ static void alc885_mb5_automute(struct hda_codec *codec)
+ {
+       unsigned int present;
+       present = snd_hda_codec_read(codec, 0x14, 0,
+                                    AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+       snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+       snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ }
+ static void alc885_mb5_unsol_event(struct hda_codec *codec,
+                                   unsigned int res)
+ {
+       /* Headphone insertion or removal. */
+       if ((res >> 26) == ALC880_HP_EVENT)
+               alc885_mb5_automute(codec);
+ }
  static void alc885_imac91_automute(struct hda_codec *codec)
  {
        unsigned int present;
@@@ -9233,6 -9199,8 +9305,8 @@@ static struct alc_config_preset alc882_
                .input_mux = &mb5_capture_source,
                .dig_out_nid = ALC882_DIGOUT_NID,
                .dig_in_nid = ALC882_DIGIN_NID,
+               .unsol_event = alc885_mb5_unsol_event,
+               .init_hook = alc885_mb5_automute,
        },
        [ALC885_MACPRO] = {
                .mixers = { alc882_macpro_mixer },
                .setup = alc889_acer_aspire_8930g_setup,
                .init_hook = alc_automute_amp,
  #ifdef CONFIG_SND_HDA_POWER_SAVE
 -              .power_hook = alc889_power_eapd,
 +              .power_hook = alc_power_eapd,
  #endif
        },
        [ALC888_ACER_ASPIRE_7730G] = {
@@@ -10355,14 -10323,8 +10429,14 @@@ static int alc262_hp_master_sw_put(stru
                .info = snd_ctl_boolean_mono_info,              \
                .get = alc262_hp_master_sw_get,                 \
                .put = alc262_hp_master_sw_put,                 \
 +      }, \
 +      {                                                       \
 +              .iface = NID_MAPPING,                           \
 +              .name = "Master Playback Switch",               \
 +              .private_value = 0x15 | (0x16 << 8) | (0x1b << 16),     \
        }
  
 +
  static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
        ALC262_HP_MASTER_SWITCH,
        HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
@@@ -10520,12 -10482,6 +10594,12 @@@ static int alc262_hippo_master_sw_put(s
                .info = snd_ctl_boolean_mono_info,              \
                .get = alc262_hippo_master_sw_get,              \
                .put = alc262_hippo_master_sw_put,              \
 +      },                                                      \
 +      {                                                       \
 +              .iface = NID_MAPPING,                           \
 +              .name = "Master Playback Switch",               \
 +              .subdevice = SUBDEV_HP(0) | (SUBDEV_LINE(0) << 8) | \
 +                           (SUBDEV_SPEAKER(0) << 16), \
        }
  
  static struct snd_kcontrol_new alc262_hippo_mixer[] = {
@@@ -11006,17 -10962,11 +11080,17 @@@ static struct snd_kcontrol_new alc262_f
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = alc262_fujitsu_master_sw_put,
                .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
        },
 +      {
 +              .iface = NID_MAPPING,
 +              .name = "Master Playback Switch",
 +              .private_value = 0x1b,
 +      },
        HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
        HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
        HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
@@@ -11047,7 -10997,6 +11121,7 @@@ static struct snd_kcontrol_new alc262_l
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = alc262_lenovo_3000_master_sw_put,
@@@ -11202,11 -11151,6 +11276,11 @@@ static struct snd_kcontrol_new alc262_u
                .get = alc_mux_enum_get,
                .put = alc262_ultra_mux_enum_put,
        },
 +      {
 +              .iface = NID_MAPPING,
 +              .name = "Capture Source",
 +              .private_value = 0x15,
 +      },
        { } /* end */
  };
  
@@@ -11310,7 -11254,7 +11384,7 @@@ static int alc262_auto_create_multi_out
  }
  
  #define alc262_auto_create_input_ctls \
-       alc880_auto_create_input_ctls
+       alc882_auto_create_input_ctls
  
  /*
   * generic initialization of ADC, input mixers and output mixers
@@@ -12225,7 -12169,6 +12299,7 @@@ static struct snd_kcontrol_new alc268_a
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = alc268_acer_master_sw_put,
@@@ -12241,7 -12184,6 +12315,7 @@@ static struct snd_kcontrol_new alc268_a
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = alc268_acer_master_sw_put,
@@@ -12259,7 -12201,6 +12333,7 @@@ static struct snd_kcontrol_new alc268_a
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = alc268_acer_master_sw_put,
@@@ -12605,6 -12546,7 +12679,7 @@@ static int alc268_new_analog_output(str
                dac = 0x02;
                break;
        case 0x15:
+       case 0x21:
                dac = 0x03;
                break;
        default:
@@@ -13212,7 -13154,6 +13287,7 @@@ static struct snd_kcontrol_new alc269_q
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = alc268_acer_master_sw_put,
@@@ -13233,7 -13174,6 +13308,7 @@@ static struct snd_kcontrol_new alc269_l
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_switch_info,
                .get = snd_hda_mixer_amp_switch_get,
                .put = alc268_acer_master_sw_put,
@@@ -14991,17 -14931,15 +15066,19 @@@ static int patch_alc861(struct hda_code
        spec->stream_digital_playback = &alc861_pcm_digital_playback;
        spec->stream_digital_capture = &alc861_pcm_digital_capture;
  
+       if (!spec->cap_mixer)
+               set_capture_mixer(codec);
        set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
  
        spec->vmaster_nid = 0x03;
  
        codec->patch_ops = alc_patch_ops;
 -      if (board_config == ALC861_AUTO)
 +      if (board_config == ALC861_AUTO) {
                spec->init_hook = alc861_auto_init;
 +#ifdef CONFIG_SND_HDA_POWER_SAVE
 +              spec->power_hook = alc_power_eapd;
 +#endif
 +      }
  #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
                spec->loopback.amplist = alc861_loopbacks;
@@@ -15633,7 -15571,7 +15710,7 @@@ static struct alc_config_preset alc861v
  static int alc861vd_auto_create_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
  {
-       return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x09, 0);
+       return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x22, 0);
  }
  
  
@@@ -17391,7 -17329,7 +17468,7 @@@ static struct snd_pci_quirk alc662_cfg_
        SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
        SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
                      ALC662_3ST_6ch_DIG),
-       SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB200", ALC663_ASUS_MODE4),
+       SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO),
        SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
        SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
                      ALC662_3ST_6ch_DIG),
index e28c810bc00cbf7e0f0393278aa2123b269d200e,799ba2570902a066ead90e38a1ce17e5b351f4e8..dbffb5b5c69df26877ab9e28165263c659e4575b
@@@ -2688,7 -2688,7 +2688,7 @@@ static struct snd_kcontrol_new 
  stac_control_new(struct sigmatel_spec *spec,
                 struct snd_kcontrol_new *ktemp,
                 const char *name,
 -               hda_nid_t nid)
 +               unsigned int subdev)
  {
        struct snd_kcontrol_new *knew;
  
                spec->kctls.alloced--;
                return NULL;
        }
 -      if (nid)
 -              knew->subdevice = HDA_SUBDEV_NID_FLAG | nid;
 +      knew->subdevice = subdev;
        return knew;
  }
  
@@@ -2714,7 -2715,7 +2714,7 @@@ static int stac92xx_add_control_temp(st
                                     unsigned long val)
  {
        struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name,
 -                                                       get_amp_nid_(val));
 +                                                       HDA_SUBDEV_AMP_FLAG);
        if (!knew)
                return -ENOMEM;
        knew->index = idx;
@@@ -4159,52 -4160,34 +4159,52 @@@ static void stac92xx_power_down(struct 
  static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
                                  int enable);
  
 +static inline int get_int_hint(struct hda_codec *codec, const char *key,
 +                             int *valp)
 +{
 +      const char *p;
 +      p = snd_hda_get_hint(codec, key);
 +      if (p) {
 +              unsigned long val;
 +              if (!strict_strtoul(p, 0, &val)) {
 +                      *valp = val;
 +                      return 1;
 +              }
 +      }
 +      return 0;
 +}
 +
  /* override some hints from the hwdep entry */
  static void stac_store_hints(struct hda_codec *codec)
  {
        struct sigmatel_spec *spec = codec->spec;
 -      const char *p;
        int val;
  
        val = snd_hda_get_bool_hint(codec, "hp_detect");
        if (val >= 0)
                spec->hp_detect = val;
 -      p = snd_hda_get_hint(codec, "gpio_mask");
 -      if (p) {
 -              spec->gpio_mask = simple_strtoul(p, NULL, 0);
 +      if (get_int_hint(codec, "gpio_mask", &spec->gpio_mask)) {
                spec->eapd_mask = spec->gpio_dir = spec->gpio_data =
                        spec->gpio_mask;
        }
 -      p = snd_hda_get_hint(codec, "gpio_dir");
 -      if (p)
 -              spec->gpio_dir = simple_strtoul(p, NULL, 0) & spec->gpio_mask;
 -      p = snd_hda_get_hint(codec, "gpio_data");
 -      if (p)
 -              spec->gpio_data = simple_strtoul(p, NULL, 0) & spec->gpio_mask;
 -      p = snd_hda_get_hint(codec, "eapd_mask");
 -      if (p)
 -              spec->eapd_mask = simple_strtoul(p, NULL, 0) & spec->gpio_mask;
 +      if (get_int_hint(codec, "gpio_dir", &spec->gpio_dir))
 +              spec->gpio_mask &= spec->gpio_mask;
 +      if (get_int_hint(codec, "gpio_data", &spec->gpio_data))
 +              spec->gpio_dir &= spec->gpio_mask;
 +      if (get_int_hint(codec, "eapd_mask", &spec->eapd_mask))
 +              spec->eapd_mask &= spec->gpio_mask;
 +      if (get_int_hint(codec, "gpio_mute", &spec->gpio_mute))
 +              spec->gpio_mute &= spec->gpio_mask;
        val = snd_hda_get_bool_hint(codec, "eapd_switch");
        if (val >= 0)
                spec->eapd_switch = val;
 +      get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity);
 +      if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) {
 +              spec->gpio_mask |= spec->gpio_led;
 +              spec->gpio_dir |= spec->gpio_led;
 +              if (spec->gpio_led_polarity)
 +                      spec->gpio_data |= spec->gpio_led;
 +      }
  }
  
  static int stac92xx_init(struct hda_codec *codec)
@@@ -4389,8 -4372,18 +4389,8 @@@ static void stac92xx_free_kctls(struct 
  static void stac92xx_shutup(struct hda_codec *codec)
  {
        struct sigmatel_spec *spec = codec->spec;
 -      int i;
 -      hda_nid_t nid;
  
 -      /* reset each pin before powering down DAC/ADC to avoid click noise */
 -      nid = codec->start_nid;
 -      for (i = 0; i < codec->num_nodes; i++, nid++) {
 -              unsigned int wcaps = get_wcaps(codec, nid);
 -              unsigned int wid_type = get_wcaps_type(wcaps);
 -              if (wid_type == AC_WID_PIN)
 -                      snd_hda_codec_read(codec, nid, 0,
 -                              AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
 -      }
 +      snd_hda_shutup_pins(codec);
  
        if (spec->eapd_mask)
                stac_gpio_set(codec, spec->gpio_mask,
@@@ -4460,14 -4453,7 +4460,7 @@@ static inline int get_pin_presence(stru
  {
        if (!nid)
                return 0;
-       /* NOTE: we can't use snd_hda_jack_detect() here because STAC/IDT
-        * codecs behave wrongly when SET_PIN_SENSE is triggered, although
-        * the pincap gives TRIG_REQ bit.
-        */
-       if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0) &
-           AC_PINSENSE_PRESENCE)
-               return 1;
-       return 0;
+       return snd_hda_jack_detect(codec, nid);
  }
  
  static void stac92xx_line_out_detect(struct hda_codec *codec,
@@@ -4744,6 -4730,26 +4737,26 @@@ static void stac92xx_unsol_event(struc
        }
  }
  
+ static int hp_blike_system(u32 subsystem_id);
+ static void set_hp_led_gpio(struct hda_codec *codec)
+ {
+       struct sigmatel_spec *spec = codec->spec;
+       switch (codec->vendor_id) {
+       case 0x111d7608:
+               /* GPIO 0 */
+               spec->gpio_led = 0x01;
+               break;
+       case 0x111d7600:
+       case 0x111d7601:
+       case 0x111d7602:
+       case 0x111d7603:
+               /* GPIO 3 */
+               spec->gpio_led = 0x08;
+               break;
+       }
+ }
  /*
   * This method searches for the mute LED GPIO configuration
   * provided as OEM string in SMBIOS. The format of that string
   *
   * So, HP B-series like systems may have HP_Mute_LED_0 (current models)
   * or  HP_Mute_LED_0_3 (future models) OEM SMBIOS strings
+  *
+  *
+  * The dv-series laptops don't seem to have the HP_Mute_LED* strings in
+  * SMBIOS - at least the ones I have seen do not have them - which include
+  * my own system (HP Pavilion dv6-1110ax) and my cousin's
+  * HP Pavilion dv9500t CTO.
+  * Need more information on whether it is true across the entire series.
+  * -- kunal
   */
  static int find_mute_led_gpio(struct hda_codec *codec)
  {
                while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING,
                                                                NULL, dev))) {
                        if (sscanf(dev->name, "HP_Mute_LED_%d_%d",
-                             &spec->gpio_led_polarity,
-                             &spec->gpio_led) == 2) {
+                                 &spec->gpio_led_polarity,
+                                 &spec->gpio_led) == 2) {
                                spec->gpio_led = 1 << spec->gpio_led;
                                return 1;
                        }
                        if (sscanf(dev->name, "HP_Mute_LED_%d",
-                             &spec->gpio_led_polarity) == 1) {
-                               switch (codec->vendor_id) {
-                               case 0x111d7608:
-                                       /* GPIO 0 */
-                                       spec->gpio_led = 0x01;
-                                       return 1;
-                               case 0x111d7600:
-                               case 0x111d7601:
-                               case 0x111d7602:
-                               case 0x111d7603:
-                                       /* GPIO 3 */
-                                       spec->gpio_led = 0x08;
-                                       return 1;
-                               }
+                                 &spec->gpio_led_polarity) == 1) {
+                               set_hp_led_gpio(codec);
+                               return 1;
                        }
                }
+               /*
+                * Fallback case - if we don't find the DMI strings,
+                * we statically set the GPIO - if not a B-series system.
+                */
+               if (!hp_blike_system(codec->subsystem_id)) {
+                       set_hp_led_gpio(codec);
+                       spec->gpio_led_polarity = 1;
+                       return 1;
+               }
        }
        return 0;
  }
@@@ -4969,6 -4982,7 +4989,7 @@@ static int patch_stac9200(struct hda_co
        if (spec == NULL)
                return -ENOMEM;
  
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        spec->num_pins = ARRAY_SIZE(stac9200_pin_nids);
        spec->pin_nids = stac9200_pin_nids;
@@@ -5031,6 -5045,7 +5052,7 @@@ static int patch_stac925x(struct hda_co
        if (spec == NULL)
                return -ENOMEM;
  
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        spec->num_pins = ARRAY_SIZE(stac925x_pin_nids);
        spec->pin_nids = stac925x_pin_nids;
@@@ -5115,6 -5130,7 +5137,7 @@@ static int patch_stac92hd73xx(struct hd
        if (spec == NULL)
                return -ENOMEM;
  
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        codec->slave_dig_outs = stac92hd73xx_slave_dig_outs;
        spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids);
@@@ -5262,6 -5278,7 +5285,7 @@@ static int patch_stac92hd83xxx(struct h
        if (spec == NULL)
                return -ENOMEM;
  
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs;
        spec->digbeep_nid = 0x21;
@@@ -5414,54 -5431,6 +5438,54 @@@ static int stac92hd71bxx_connected_smux
                return 0;
  }
  
 +/* HP dv7 bass switch - GPIO5 */
 +#define stac_hp_bass_gpio_info        snd_ctl_boolean_mono_info
 +static int stac_hp_bass_gpio_get(struct snd_kcontrol *kcontrol,
 +                               struct snd_ctl_elem_value *ucontrol)
 +{
 +      struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 +      struct sigmatel_spec *spec = codec->spec;
 +      ucontrol->value.integer.value[0] = !!(spec->gpio_data & 0x20);
 +      return 0;
 +}
 +
 +static int stac_hp_bass_gpio_put(struct snd_kcontrol *kcontrol,
 +                               struct snd_ctl_elem_value *ucontrol)
 +{
 +      struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 +      struct sigmatel_spec *spec = codec->spec;
 +      unsigned int gpio_data;
 +
 +      gpio_data = (spec->gpio_data & ~0x20) |
 +              (ucontrol->value.integer.value[0] ? 0x20 : 0);
 +      if (gpio_data == spec->gpio_data)
 +              return 0;
 +      spec->gpio_data = gpio_data;
 +      stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
 +      return 1;
 +}
 +
 +static struct snd_kcontrol_new stac_hp_bass_sw_ctrl = {
 +      .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 +      .info = stac_hp_bass_gpio_info,
 +      .get = stac_hp_bass_gpio_get,
 +      .put = stac_hp_bass_gpio_put,
 +};
 +
 +static int stac_add_hp_bass_switch(struct hda_codec *codec)
 +{
 +      struct sigmatel_spec *spec = codec->spec;
 +
 +      if (!stac_control_new(spec, &stac_hp_bass_sw_ctrl,
 +                            "Bass Speaker Playback Switch", 0))
 +              return -ENOMEM;
 +
 +      spec->gpio_mask |= 0x20;
 +      spec->gpio_dir |= 0x20;
 +      spec->gpio_data |= 0x20;
 +      return 0;
 +}
 +
  static int patch_stac92hd71bxx(struct hda_codec *codec)
  {
        struct sigmatel_spec *spec;
        if (spec == NULL)
                return -ENOMEM;
  
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        codec->patch_ops = stac92xx_patch_ops;
        spec->num_pins = STAC92HD71BXX_NUM_PINS;
@@@ -5605,6 -5575,8 +5630,8 @@@ again
        spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
        spec->num_smuxes = stac92hd71bxx_connected_smuxes(codec, 0x1e);
  
+       snd_printdd("Found board config: %d\n", spec->board_config);
        switch (spec->board_config) {
        case STAC_HP_M4:
                /* enable internal microphone */
                return err;
        }
  
 +      /* enable bass on HP dv7 */
 +      if (spec->board_config == STAC_HP_DV5) {
 +              unsigned int cap;
 +              cap = snd_hda_param_read(codec, 0x1, AC_PAR_GPIO_CAP);
 +              cap &= AC_GPIO_IO_COUNT;
 +              if (cap >= 6)
 +                      stac_add_hp_bass_switch(codec);
 +      }
 +
        codec->proc_widget_hook = stac92hd7x_proc_hook;
  
        return 0;
@@@ -5725,6 -5688,7 +5752,7 @@@ static int patch_stac922x(struct hda_co
        if (spec == NULL)
                return -ENOMEM;
  
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        spec->num_pins = ARRAY_SIZE(stac922x_pin_nids);
        spec->pin_nids = stac922x_pin_nids;
@@@ -5828,6 -5792,7 +5856,7 @@@ static int patch_stac927x(struct hda_co
        if (spec == NULL)
                return -ENOMEM;
  
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        codec->slave_dig_outs = stac927x_slave_dig_outs;
        spec->num_pins = ARRAY_SIZE(stac927x_pin_nids);
@@@ -5962,6 -5927,7 +5991,7 @@@ static int patch_stac9205(struct hda_co
        if (spec == NULL)
                return -ENOMEM;
  
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        spec->num_pins = ARRAY_SIZE(stac9205_pin_nids);
        spec->pin_nids = stac9205_pin_nids;
@@@ -6117,6 -6083,7 +6147,7 @@@ static int patch_stac9872(struct hda_co
        spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (spec == NULL)
                return -ENOMEM;
+       codec->no_trigger_sense = 1;
        codec->spec = spec;
        spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
        spec->pin_nids = stac9872_pin_nids;