Merge branch 'fix/hda' into topic/hda
authorTakashi Iwai <tiwai@suse.de>
Wed, 23 Dec 2009 07:38:23 +0000 (08:38 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 23 Dec 2009 07:38:23 +0000 (08:38 +0100)
1  2 
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c

index 93eaf4fc39becaf423b7d81663cb287d8d8797f1,ff8ad46cc50e09dc726775322314d9ec5bb8d15f..d258569fc921f792603b1f0e2268fe18869b3c02
@@@ -2322,6 -2322,7 +2322,7 @@@ static void __devinit check_probe_mask(
   * white/black-list for enable_msi
   */
  static struct snd_pci_quirk msi_black_list[] __devinitdata = {
+       SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
        {}
  };
  
@@@ -2694,10 -2695,32 +2695,10 @@@ static struct pci_device_id azx_ids[] 
        /* ULI M5461 */
        { PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI },
        /* NVIDIA MCP */
 -      { PCI_DEVICE(0x10de, 0x026c), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0371), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x03e4), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x03f0), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x044a), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x044b), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x055c), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x055d), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0590), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0774), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0775), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0776), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0777), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x07fc), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x07fd), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0ac0), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0be2), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0be3), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0be4), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0d94), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0d95), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0d96), .driver_data = AZX_DRIVER_NVIDIA },
 -      { PCI_DEVICE(0x10de, 0x0d97), .driver_data = AZX_DRIVER_NVIDIA },
 +      { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
 +        .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
 +        .class_mask = 0xffffff,
 +        .driver_data = AZX_DRIVER_NVIDIA },
        /* Teradici */
        { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA },
        /* Creative X-Fi (CA0110-IBG) */
index eeb91f6a06c28b5c092243dcad4aad5523fc62a6,fe0423c39598b9a98fca8f1f7af48c5bb9c7eaa9..093cfbb55e9e97ed253202db54706d9e97412578
@@@ -66,6 -66,7 +66,7 @@@ struct cs_spec 
  /* available models */
  enum {
        CS420X_MBP55,
+       CS420X_IMAC27,
        CS420X_AUTO,
        CS420X_MODELS
  };
@@@ -500,8 -501,7 +501,8 @@@ static int add_mute(struct hda_codec *c
        knew.private_value = pval;
        snprintf(tmp, sizeof(tmp), "%s %s Switch", name, dir_sfx[dir]);
        *kctlp = snd_ctl_new1(&knew, codec);
 -      return snd_hda_ctl_add(codec, get_amp_nid_(pval), *kctlp);
 +      (*kctlp)->id.subdevice = HDA_SUBDEV_AMP_FLAG;
 +      return snd_hda_ctl_add(codec, 0, *kctlp);
  }
  
  static int add_volume(struct hda_codec *codec, const char *name,
        knew.private_value = pval;
        snprintf(tmp, sizeof(tmp), "%s %s Volume", name, dir_sfx[dir]);
        *kctlp = snd_ctl_new1(&knew, codec);
 -      return snd_hda_ctl_add(codec, get_amp_nid_(pval), *kctlp);
 +      (*kctlp)->id.subdevice = HDA_SUBDEV_AMP_FLAG;
 +      return snd_hda_ctl_add(codec, 0, *kctlp);
  }
  
  static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac)
@@@ -761,10 -760,6 +762,10 @@@ static int build_input(struct hda_code
                err = snd_hda_ctl_add(codec, 0, kctl);
                if (err < 0)
                        return err;
 +              err = snd_hda_add_nids(codec, kctl, 0, spec->adc_nid,
 +                                     spec->num_inputs);
 +              if (err < 0)
 +                      return err;
        }
        
        if (spec->num_inputs > 1 && !spec->mic_detect) {
@@@ -833,7 -828,8 +834,8 @@@ static void cs_automute(struct hda_code
                                    AC_VERB_SET_PIN_WIDGET_CONTROL,
                                    hp_present ? 0 : PIN_OUT);
        }
-       if (spec->board_config == CS420X_MBP55) {
+       if (spec->board_config == CS420X_MBP55 ||
+           spec->board_config == CS420X_IMAC27) {
                unsigned int gpio = hp_present ? 0x02 : 0x08;
                snd_hda_codec_write(codec, 0x01, 0,
                                    AC_VERB_SET_GPIO_DATA, gpio);
@@@ -1075,12 -1071,14 +1077,14 @@@ static int cs_parse_auto_config(struct 
  
  static const char *cs420x_models[CS420X_MODELS] = {
        [CS420X_MBP55] = "mbp55",
+       [CS420X_IMAC27] = "imac27",
        [CS420X_AUTO] = "auto",
  };
  
  
  static struct snd_pci_quirk cs420x_cfg_tbl[] = {
        SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
+       SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),
        {} /* terminator */
  };
  
@@@ -1103,8 -1101,23 +1107,23 @@@ static struct cs_pincfg mbp55_pincfgs[
        {} /* terminator */
  };
  
+ static struct cs_pincfg imac27_pincfgs[] = {
+       { 0x09, 0x012b4050 },
+       { 0x0a, 0x90100140 },
+       { 0x0b, 0x90100142 },
+       { 0x0c, 0x018b3020 },
+       { 0x0d, 0x90a00110 },
+       { 0x0e, 0x400000f0 },
+       { 0x0f, 0x01cbe030 },
+       { 0x10, 0x014be060 },
+       { 0x12, 0x01ab9070 },
+       { 0x15, 0x400000f0 },
+       {} /* terminator */
+ };
  static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = {
        [CS420X_MBP55] = mbp55_pincfgs,
+       [CS420X_IMAC27] = imac27_pincfgs,
  };
  
  static void fix_pincfg(struct hda_codec *codec, int model)
@@@ -1134,6 -1147,7 +1153,7 @@@ static int patch_cs420x(struct hda_code
                fix_pincfg(codec, spec->board_config);
  
        switch (spec->board_config) {
+       case CS420X_IMAC27:
        case CS420X_MBP55:
                /* GPIO1 = headphones */
                /* GPIO3 = speakers */
index 1ab2958a290b852d9ad5420bff68a3c3bfdf34ba,c578c28f368eba10cc6baacb4ea81e549436af14..947785f43b28566f782d04dc721e0786c95a2ac0
@@@ -29,6 -29,7 +29,7 @@@
  
  #include "hda_codec.h"
  #include "hda_local.h"
+ #include "hda_beep.h"
  
  #define CXT_PIN_DIR_IN              0x00
  #define CXT_PIN_DIR_OUT             0x01
@@@ -111,6 -112,7 +112,7 @@@ struct conexant_spec 
        unsigned int dell_automute;
        unsigned int port_d_mode;
        unsigned char ext_mic_bias;
+       unsigned int dell_vostro;
  };
  
  static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
@@@ -476,6 -478,7 +478,7 @@@ static void conexant_free(struct hda_co
                snd_array_free(&spec->jacks);
        }
  #endif
+       snd_hda_detach_beep_device(codec);
        kfree(codec->spec);
  }
  
@@@ -2109,9 -2112,12 +2112,12 @@@ static int cxt5066_mic_boost_mux_enum_g
  {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        int val;
+       hda_nid_t nid = kcontrol->private_value & 0xff;
+       int inout = (kcontrol->private_value & 0x100) ?
+               AC_AMP_GET_INPUT : AC_AMP_GET_OUTPUT;
  
-       val = snd_hda_codec_read(codec, 0x17, 0,
-               AC_VERB_GET_AMP_GAIN_MUTE, AC_AMP_GET_OUTPUT);
+       val = snd_hda_codec_read(codec, nid, 0,
+               AC_VERB_GET_AMP_GAIN_MUTE, inout);
  
        ucontrol->value.enumerated.item[0] = val & AC_AMP_GAIN;
        return 0;
@@@ -2123,6 -2129,9 +2129,9 @@@ static int cxt5066_mic_boost_mux_enum_p
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        const struct hda_input_mux *imux = &cxt5066_analog_mic_boost;
        unsigned int idx;
+       hda_nid_t nid = kcontrol->private_value & 0xff;
+       int inout = (kcontrol->private_value & 0x100) ?
+               AC_AMP_SET_INPUT : AC_AMP_SET_OUTPUT;
  
        if (!imux->num_items)
                return 0;
        if (idx >= imux->num_items)
                idx = imux->num_items - 1;
  
-       snd_hda_codec_write_cache(codec, 0x17, 0,
+       snd_hda_codec_write_cache(codec, nid, 0,
                AC_VERB_SET_AMP_GAIN_MUTE,
-               AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT |
+               AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | inout |
                        imux->items[idx].index);
  
        return 1;
@@@ -2178,7 -2187,6 +2187,7 @@@ static struct snd_kcontrol_new cxt5066_
                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
                                  SNDRV_CTL_ELEM_ACCESS_TLV_READ |
                                  SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,
 +              .subdevice = HDA_SUBDEV_AMP_FLAG,
                .info = snd_hda_mixer_amp_volume_info,
                .get = snd_hda_mixer_amp_volume_get,
                .put = snd_hda_mixer_amp_volume_put,
@@@ -2202,10 -2210,11 +2211,11 @@@ static struct snd_kcontrol_new cxt5066_
  
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Analog Mic Boost Capture Enum",
+               .name = "Ext Mic Boost Capture Enum",
                .info = cxt5066_mic_boost_mux_enum_info,
                .get = cxt5066_mic_boost_mux_enum_get,
                .put = cxt5066_mic_boost_mux_enum_put,
+               .private_value = 0x17,
        },
  
        HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others),
        {}
  };
  
+ static struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Int Mic Boost Capture Enum",
+               .info = cxt5066_mic_boost_mux_enum_info,
+               .get = cxt5066_mic_boost_mux_enum_get,
+               .put = cxt5066_mic_boost_mux_enum_put,
+               .private_value = 0x23 | 0x100,
+       },
+       HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
+       {}
+ };
  static struct hda_verb cxt5066_init_verbs[] = {
        {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
        {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
@@@ -2398,11 -2420,16 +2421,16 @@@ static struct hda_verb cxt5066_init_ver
  /* initialize jack-sensing, too */
  static int cxt5066_init(struct hda_codec *codec)
  {
+       struct conexant_spec *spec = codec->spec;
        snd_printdd("CXT5066: init\n");
        conexant_init(codec);
        if (codec->patch_ops.unsol_event) {
                cxt5066_hp_automute(codec);
-               cxt5066_automic(codec);
+               if (spec->dell_vostro)
+                       cxt5066_vostro_automic(codec);
+               else
+                       cxt5066_automic(codec);
        }
        return 0;
  }
@@@ -2501,7 -2528,10 +2529,10 @@@ static int patch_cxt5066(struct hda_cod
                spec->init_verbs[0] = cxt5066_init_verbs_vostro;
                spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
                spec->mixers[spec->num_mixers++] = cxt5066_mixers;
+               spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers;
                spec->port_d_mode = 0;
+               spec->dell_vostro = 1;
+               snd_hda_attach_beep_device(codec, 0x13);
  
                /* no S/PDIF out */
                spec->multiout.dig_out_nid = 0;
index 012435212e5837d57434a4684eca98cf819d4583,0877bae5dae110066a8d6a37e64238c9d27cda5b..e7cdc6a7d61ddc6e6844cf93616aa2a7e9f1942a
@@@ -337,6 -337,9 +337,9 @@@ struct alc_spec 
        /* hooks */
        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);
+ #endif
  
        /* for pin sensing */
        unsigned int sense_updated: 1;
@@@ -388,6 -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);
  #endif
  };
  
@@@ -629,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, \
@@@ -681,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, \
@@@ -736,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, \
@@@ -790,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, \
@@@ -904,6 -904,7 +908,7 @@@ static void setup_preset(struct hda_cod
        spec->unsol_event = preset->unsol_event;
        spec->init_hook = preset->init_hook;
  #ifdef CONFIG_SND_HDA_POWER_SAVE
+       spec->power_hook = preset->power_hook;
        spec->loopback.amplist = preset->loopbacks;
  #endif
  
@@@ -1669,9 -1670,6 +1674,6 @@@ static struct hda_verb alc889_acer_aspi
  /*  some bit here disables the other DACs. Init=0x4900 */
        {0x20, AC_VERB_SET_COEF_INDEX, 0x08},
        {0x20, AC_VERB_SET_PROC_COEF, 0x0000},
- /* Enable amplifiers */
-       {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
-       {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
  /* DMIC fix
   * This laptop has a stereo digital microphone. The mics are only 1cm apart
   * which makes the stereo useless. However, either the mic or the ALC889
@@@ -1784,6 -1782,25 +1786,25 @@@ static struct snd_kcontrol_new alc888_b
        { } /* end */
  };
  
+ static struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
+       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
+               HDA_OUTPUT),
+       HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+       HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, 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, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       { } /* end */
+ };
  static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
@@@ -1814,6 -1831,16 +1835,16 @@@ 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)
+ {
+       snd_hda_codec_write(codec, 0x14, 0,
+                           AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0);
+       snd_hda_codec_write(codec, 0x15, 0,
+                           AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0);
+ }
+ #endif
  /*
   * ALC880 3-stack model
   *
@@@ -2416,15 -2443,6 +2447,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
@@@ -2439,11 -2457,8 +2470,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_nids(codec, kctl, i, nids,
 +                                     spec->input_mux->num_items);
 +              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;
  }
  
@@@ -3688,12 -3634,29 +3719,29 @@@ static void alc_free(struct hda_codec *
        snd_hda_detach_beep_device(codec);
  }
  
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+ static int alc_suspend(struct hda_codec *codec, pm_message_t state)
+ {
+       struct alc_spec *spec = codec->spec;
+       if (spec && spec->power_hook)
+               spec->power_hook(codec, 0);
+       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
@@@ -3710,6 -3673,7 +3758,7 @@@ static struct hda_codec_ops alc_patch_o
        .resume = alc_resume,
  #endif
  #ifdef CONFIG_SND_HDA_POWER_SAVE
+       .suspend = alc_suspend,
        .check_power_status = alc_check_power_status,
  #endif
  };
@@@ -3868,7 -3832,6 +3917,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,   \
@@@ -4418,7 -4380,7 +4467,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;
  }
@@@ -5169,7 -5131,6 +5218,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,
@@@ -5208,7 -5169,6 +5257,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,
@@@ -9010,7 -8970,7 +9059,7 @@@ static struct snd_pci_quirk alc882_cfg_
        SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
        SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
        SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8  */
-       SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC883_TARGA_2ch_DIG),
+       SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO),
        SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
        SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
        SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
@@@ -9373,6 -9333,7 +9422,7 @@@ static struct alc_config_preset alc882_
                .dac_nids = alc883_dac_nids,
                .adc_nids = alc883_adc_nids_alt,
                .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+               .capsrc_nids = alc883_capsrc_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .init_hook = alc_automute_amp,
        },
        [ALC888_ACER_ASPIRE_8930G] = {
-               .mixers = { alc888_base_mixer,
+               .mixers = { alc889_acer_aspire_8930g_mixer,
                                alc883_chmode_mixer },
                .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
-                               alc889_acer_aspire_8930g_verbs },
+                               alc889_acer_aspire_8930g_verbs,
+                               alc889_eapd_verbs},
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
                .unsol_event = alc_automute_amp_unsol_event,
                .setup = alc889_acer_aspire_8930g_setup,
                .init_hook = alc_automute_amp,
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+               .power_hook = alc889_power_eapd,
+ #endif
        },
        [ALC888_ACER_ASPIRE_7730G] = {
                .mixers = { alc883_3ST_6ch_mixer,
                .dac_nids = alc883_dac_nids,
                .adc_nids = alc883_adc_nids_alt,
                .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+               .capsrc_nids = alc883_capsrc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
                .channel_mode = alc883_sixstack_modes,
                .input_mux = &alc883_capture_source,
                .dac_nids = alc883_dac_nids,
                .adc_nids = alc883_adc_nids_alt,
                .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+               .capsrc_nids = alc883_capsrc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_lenovo_101e_capture_source,
                        alc880_gpio1_init_verbs },
                .adc_nids = alc883_adc_nids,
                .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+               .capsrc_nids = alc883_capsrc_nids,
                .dac_nids = alc883_dac_nids,
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .channel_mode = alc889A_mb31_6ch_modes,
@@@ -10280,14 -10248,8 +10337,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),
@@@ -10445,12 -10407,6 +10502,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[] = {
@@@ -10781,6 -10737,13 +10838,13 @@@ static struct hda_verb alc262_lenovo_30
        {}
  };
  
+ static struct hda_verb alc262_lenovo_3000_init_verbs[] = {
+       /* Front Mic pin: input vref at 50% */
+       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
+       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {}
+ };
  static struct hda_input_mux alc262_fujitsu_capture_source = {
        .num_items = 3,
        .items = {
@@@ -10924,17 -10887,11 +10988,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),
@@@ -10965,7 -10922,6 +11029,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,
@@@ -11120,11 -11076,6 +11184,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 */
  };
  
@@@ -11835,7 -11786,8 +11899,8 @@@ static struct alc_config_preset alc262_
        [ALC262_LENOVO_3000] = {
                .mixers = { alc262_lenovo_3000_mixer },
                .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
-                               alc262_lenovo_3000_unsol_verbs },
+                               alc262_lenovo_3000_unsol_verbs,
+                               alc262_lenovo_3000_init_verbs },
                .num_dacs = ARRAY_SIZE(alc262_dac_nids),
                .dac_nids = alc262_dac_nids,
                .hp_nid = 0x03,
@@@ -12142,7 -12094,6 +12207,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,
@@@ -12158,7 -12109,6 +12223,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,
@@@ -12176,7 -12126,6 +12241,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,
@@@ -13129,7 -13078,6 +13194,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,
@@@ -13150,7 -13098,6 +13215,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,
index a4526d008042794419badabbdc6596db0d71533b,417fb22ae83c8200a86c3fb2107be722b896c821..2f08b434bbd8409c2e1f793e6a0df6813150c899
@@@ -2685,7 -2685,7 +2685,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;
  }
  
@@@ -2711,7 -2712,7 +2711,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;
@@@ -3778,15 -3779,16 +3778,16 @@@ static int stac92xx_parse_auto_config(s
                err = snd_hda_attach_beep_device(codec, nid);
                if (err < 0)
                        return err;
-               /* IDT/STAC codecs have linear beep tone parameter */
-               codec->beep->linear_tone = 1;
-               /* if no beep switch is available, make its own one */
-               caps = query_amp_caps(codec, nid, HDA_OUTPUT);
-               if (codec->beep &&
-                   !((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT)) {
-                       err = stac92xx_beep_switch_ctl(codec);
-                       if (err < 0)
-                               return err;
+               if (codec->beep) {
+                       /* IDT/STAC codecs have linear beep tone parameter */
+                       codec->beep->linear_tone = 1;
+                       /* if no beep switch is available, make its own one */
+                       caps = query_amp_caps(codec, nid, HDA_OUTPUT);
+                       if (!(caps & AC_AMPCAP_MUTE)) {
+                               err = stac92xx_beep_switch_ctl(codec);
+                               if (err < 0)
+                                       return err;
+                       }
                }
        }
  #endif
@@@ -5402,54 -5404,6 +5403,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;
@@@ -5690,15 -5644,6 +5691,15 @@@ again
                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;
This page took 0.057087 seconds and 5 git commands to generate.