Merge branch 'fix/hda' into topic/hda
authorTakashi Iwai <tiwai@suse.de>
Mon, 16 Nov 2009 10:33:35 +0000 (11:33 +0100)
committerTakashi Iwai <tiwai@suse.de>
Mon, 16 Nov 2009 10:33:35 +0000 (11:33 +0100)
1  2 
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c

index 0d3e0c9ea81261ab3775d0432bf6b9eee10d399b,6517f589d01d6bd7be51aec9e3b2f557acfe2319..e73e395e76019b5d437a9ee0f4c486c096f38a3e
@@@ -60,7 -60,7 +60,7 @@@ static int bdl_pos_adj[SNDRV_CARDS] = {
  static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
  static int probe_only[SNDRV_CARDS];
  static int single_cmd;
 -static int enable_msi;
 +static int enable_msi = -1;
  #ifdef CONFIG_SND_HDA_PATCH_LOADER
  static char *patch[SNDRV_CARDS];
  #endif
@@@ -677,14 -677,6 +677,14 @@@ static unsigned int azx_rirb_get_respon
                }
        }
  
 +      if (!chip->polling_mode) {
 +              snd_printk(KERN_WARNING SFX "azx_get_response timeout, "
 +                         "switching to polling mode: last cmd=0x%08x\n",
 +                         chip->last_cmd[addr]);
 +              chip->polling_mode = 1;
 +              goto again;
 +      }
 +
        if (chip->msi) {
                snd_printk(KERN_WARNING SFX "No response from codec, "
                           "disabling MSI: last cmd=0x%08x\n",
                goto again;
        }
  
 -      if (!chip->polling_mode) {
 -              snd_printk(KERN_WARNING SFX "azx_get_response timeout, "
 -                         "switching to polling mode: last cmd=0x%08x\n",
 -                         chip->last_cmd[addr]);
 -              chip->polling_mode = 1;
 -              goto again;
 -      }
 -
        if (chip->probing) {
                /* If this critical timeout happens during the codec probing
                 * phase, this is likely an access to a non-existing codec
                   chip->last_cmd[addr]);
        chip->single_cmd = 1;
        bus->response_reset = 0;
-       /* re-initialize CORB/RIRB */
+       /* release CORB/RIRB */
        azx_free_cmd_io(chip);
-       azx_init_cmd_io(chip);
+       /* disable unsolicited responses */
+       azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_UNSOL);
        return -1;
  }
  
@@@ -865,7 -866,9 +866,9 @@@ static int azx_reset(struct azx *chip
        }
  
        /* Accept unsolicited responses */
-       azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UNSOL);
+       if (!chip->single_cmd)
+               azx_writel(chip, GCTL, azx_readl(chip, GCTL) |
+                          ICH6_GCTL_UNSOL);
  
        /* detect codecs */
        if (!chip->codec_mask) {
@@@ -980,7 -983,8 +983,8 @@@ static void azx_init_chip(struct azx *c
        azx_int_enable(chip);
  
        /* initialize the codec command I/O */
-       azx_init_cmd_io(chip);
+       if (!chip->single_cmd)
+               azx_init_cmd_io(chip);
  
        /* program the position buffer */
        azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
@@@ -2150,7 -2154,6 +2154,7 @@@ static int azx_resume(struct pci_dev *p
  static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf)
  {
        struct azx *chip = container_of(nb, struct azx, reboot_notifier);
 +      snd_hda_bus_reboot_notify(chip->bus);
        azx_stop_chip(chip);
        return NOTIFY_OK;
  }
@@@ -2301,9 -2304,11 +2305,9 @@@ static void __devinit check_probe_mask(
  }
  
  /*
 - * white-list for enable_msi
 + * white/black-list for enable_msi
   */
 -static struct snd_pci_quirk msi_white_list[] __devinitdata = {
 -      SND_PCI_QUIRK(0x103c, 0x30f7, "HP Pavilion dv4t-1300", 1),
 -      SND_PCI_QUIRK(0x103c, 0x3607, "HP Compa CQ40", 1),
 +static struct snd_pci_quirk msi_black_list[] __devinitdata = {
        {}
  };
  
@@@ -2311,12 -2316,10 +2315,12 @@@ static void __devinit check_msi(struct 
  {
        const struct snd_pci_quirk *q;
  
 -      chip->msi = enable_msi;
 -      if (chip->msi)
 +      if (enable_msi >= 0) {
 +              chip->msi = !!enable_msi;
                return;
 -      q = snd_pci_quirk_lookup(chip->pci, msi_white_list);
 +      }
 +      chip->msi = 1;  /* enable MSI as default */
 +      q = snd_pci_quirk_lookup(chip->pci, msi_black_list);
        if (q) {
                printk(KERN_INFO
                       "hda_intel: msi for device %04x:%04x set to %d\n",
index b592419b2083b168d94a8bff118e2929bd74d08c,84a52efdb2d678fc40c3aae5ea74192a0933421c..5d7b882bd68ce252a7f6cc079c1fe39129a2a824
@@@ -4326,20 -4326,6 +4326,20 @@@ static int add_control(struct alc_spec 
        return 0;
  }
  
 +static int add_control_with_pfx(struct alc_spec *spec, int type,
 +                              const char *pfx, const char *dir,
 +                              const char *sfx, unsigned long val)
 +{
 +      char name[32];
 +      snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
 +      return add_control(spec, type, name, val);
 +}
 +
 +#define add_pb_vol_ctrl(spec, type, pfx, val) \
 +      add_control_with_pfx(spec, type, pfx, "Playback", "Volume", val)
 +#define add_pb_sw_ctrl(spec, type, pfx, val) \
 +      add_control_with_pfx(spec, type, pfx, "Playback", "Switch", val)
 +
  #define alc880_is_fixed_pin(nid)      ((nid) >= 0x14 && (nid) <= 0x17)
  #define alc880_fixed_pin_idx(nid)     ((nid) - 0x14)
  #define alc880_is_multi_pin(nid)      ((nid) >= 0x18)
@@@ -4393,6 -4379,7 +4393,6 @@@ static int alc880_auto_fill_dac_nids(st
  static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
                                             const struct auto_pin_cfg *cfg)
  {
 -      char name[32];
        static const char *chname[4] = {
                "Front", "Surround", NULL /*CLFE*/, "Side"
        };
                nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
                if (i == 2) {
                        /* Center/LFE */
 -                      err = add_control(spec, ALC_CTL_WIDGET_VOL,
 -                                        "Center Playback Volume",
 +                      err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
 +                                            "Center",
                                          HDA_COMPOSE_AMP_VAL(nid, 1, 0,
                                                              HDA_OUTPUT));
                        if (err < 0)
                                return err;
 -                      err = add_control(spec, ALC_CTL_WIDGET_VOL,
 -                                        "LFE Playback Volume",
 +                      err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
 +                                            "LFE",
                                          HDA_COMPOSE_AMP_VAL(nid, 2, 0,
                                                              HDA_OUTPUT));
                        if (err < 0)
                                return err;
 -                      err = add_control(spec, ALC_CTL_BIND_MUTE,
 -                                        "Center Playback Switch",
 +                      err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
 +                                           "Center",
                                          HDA_COMPOSE_AMP_VAL(nid, 1, 2,
                                                              HDA_INPUT));
                        if (err < 0)
                                return err;
 -                      err = add_control(spec, ALC_CTL_BIND_MUTE,
 -                                        "LFE Playback Switch",
 +                      err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
 +                                           "LFE",
                                          HDA_COMPOSE_AMP_VAL(nid, 2, 2,
                                                              HDA_INPUT));
                        if (err < 0)
                                pfx = "Speaker";
                        else
                                pfx = chname[i];
 -                      sprintf(name, "%s Playback Volume", pfx);
 -                      err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
 +                      err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
                                          HDA_COMPOSE_AMP_VAL(nid, 3, 0,
                                                              HDA_OUTPUT));
                        if (err < 0)
                                return err;
 -                      sprintf(name, "%s Playback Switch", pfx);
 -                      err = add_control(spec, ALC_CTL_BIND_MUTE, name,
 +                      err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
                                          HDA_COMPOSE_AMP_VAL(nid, 3, 2,
                                                              HDA_INPUT));
                        if (err < 0)
@@@ -4457,6 -4446,7 +4457,6 @@@ static int alc880_auto_create_extra_out
  {
        hda_nid_t nid;
        int err;
 -      char name[32];
  
        if (!pin)
                return 0;
                        spec->multiout.extra_out_nid[0] = nid;
                /* control HP volume/switch on the output mixer amp */
                nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
 -              sprintf(name, "%s Playback Volume", pfx);
 -              err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
 +              err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
                                  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
                if (err < 0)
                        return err;
 -              sprintf(name, "%s Playback Switch", pfx);
 -              err = add_control(spec, ALC_CTL_BIND_MUTE, name,
 +              err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
                                  HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
                if (err < 0)
                        return err;
        } else if (alc880_is_multi_pin(pin)) {
                /* set manual connection */
                /* we have only a switch on HP-out PIN */
 -              sprintf(name, "%s Playback Switch", pfx);
 -              err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
 +              err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
                                  HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
                if (err < 0)
                        return err;
@@@ -4494,13 -4487,16 +4494,13 @@@ static int new_analog_input(struct alc_
                            const char *ctlname,
                            int idx, hda_nid_t mix_nid)
  {
 -      char name[32];
        int err;
  
 -      sprintf(name, "%s Playback Volume", ctlname);
 -      err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
 +      err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
                          HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
        if (err < 0)
                return err;
 -      sprintf(name, "%s Playback Switch", ctlname);
 -      err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
 +      err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
                          HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
        if (err < 0)
                return err;
@@@ -4688,9 -4684,9 +4688,9 @@@ static int alc880_parse_auto_config(str
                        spec->multiout.dig_out_nid = dig_nid;
                else {
                        spec->multiout.slave_dig_outs = spec->slave_dig_outs;
-                       spec->slave_dig_outs[i - 1] = dig_nid;
-                       if (i == ARRAY_SIZE(spec->slave_dig_outs) - 1)
+                       if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
                                break;
+                       spec->slave_dig_outs[i - 1] = dig_nid;
                }
        }
        if (spec->autocfg.dig_in_pin)
@@@ -5993,6 -5989,7 +5993,6 @@@ static int alc260_add_playback_controls
  {
        hda_nid_t nid_vol;
        unsigned long vol_val, sw_val;
 -      char name[32];
        int err;
  
        if (nid >= 0x0f && nid < 0x11) {
  
        if (!(*vol_bits & (1 << nid_vol))) {
                /* first control for the volume widget */
 -              snprintf(name, sizeof(name), "%s Playback Volume", pfx);
 -              err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val);
 +              err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, vol_val);
                if (err < 0)
                        return err;
                *vol_bits |= (1 << nid_vol);
        }
 -      snprintf(name, sizeof(name), "%s Playback Switch", pfx);
 -      err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val);
 +      err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, sw_val);
        if (err < 0)
                return err;
        return 1;
@@@ -6250,7 -6249,7 +6250,7 @@@ static struct snd_pci_quirk alc260_cfg_
        SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
        SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100),
        SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
-       SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_HP_3013),
+       SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_AUTO), /* no quirk */
        SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
        SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP_3013),
        SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_DC7600),
@@@ -8912,10 -8911,11 +8912,11 @@@ static struct snd_pci_quirk alc882_ssid
        SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3),
        SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24),
        SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5),
-       /* FIXME: HP jack sense seems not working for MBP 5,1, so apparently
-        * no perfect solution yet
+       /* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2,
+        * so apparently no perfect solution yet
         */
        SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5),
+       SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5),
        {} /* terminator */
  };
  
@@@ -9814,9 -9814,9 +9815,9 @@@ static int alc882_parse_auto_config(str
                        spec->multiout.dig_out_nid = dig_nid;
                else {
                        spec->multiout.slave_dig_outs = spec->slave_dig_outs;
-                       spec->slave_dig_outs[i - 1] = dig_nid;
-                       if (i == ARRAY_SIZE(spec->slave_dig_outs) - 1)
+                       if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
                                break;
+                       spec->slave_dig_outs[i - 1] = dig_nid;
                }
        }
        if (spec->autocfg.dig_in_pin)
@@@ -10956,6 -10956,7 +10957,6 @@@ static int alc262_check_volbit(hda_nid_
  static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
                                  const char *pfx, int *vbits)
  {
 -      char name[32];
        unsigned long val;
        int vbit;
  
        if (*vbits & vbit) /* a volume control for this mixer already there */
                return 0;
        *vbits |= vbit;
 -      snprintf(name, sizeof(name), "%s Playback Volume", pfx);
        if (vbit == 2)
                val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT);
        else
                val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT);
 -      return add_control(spec, ALC_CTL_WIDGET_VOL, name, val);
 +      return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, val);
  }
  
  static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid,
                                 const char *pfx)
  {
 -      char name[32];
        unsigned long val;
  
        if (!nid)
                return 0;
 -      snprintf(name, sizeof(name), "%s Playback Switch", pfx);
        if (nid == 0x16)
                val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
        else
                val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
 -      return add_control(spec, ALC_CTL_WIDGET_MUTE, name, val);
 +      return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val);
  }
  
  /* add playback controls from the parsed DAC table */
@@@ -11457,6 -11461,7 +11458,7 @@@ static struct snd_pci_quirk alc262_cfg_
        SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
        SND_PCI_QUIRK(0x104d, 0x9016, "Sony VAIO", ALC262_AUTO), /* dig-only */
        SND_PCI_QUIRK(0x104d, 0x9025, "Sony VAIO Z21MN", ALC262_TOSHIBA_S06),
+       SND_PCI_QUIRK(0x104d, 0x9035, "Sony VAIO VGN-FW170J", ALC262_AUTO),
        SND_PCI_QUIRK_MASK(0x104d, 0xff00, 0x9000, "Sony VAIO",
                           ALC262_SONY_ASSAMD),
        SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
@@@ -12321,9 -12326,11 +12323,9 @@@ static struct snd_kcontrol_new alc268_t
  static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
                                    const char *ctlname, int idx)
  {
 -      char name[32];
        hda_nid_t dac;
        int err;
  
 -      sprintf(name, "%s Playback Volume", ctlname);
        switch (nid) {
        case 0x14:
        case 0x16:
        }
        if (spec->multiout.dac_nids[0] != dac &&
            spec->multiout.dac_nids[1] != dac) {
 -              err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
 +              err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
                                  HDA_COMPOSE_AMP_VAL(dac, 3, idx,
                                                      HDA_OUTPUT));
                if (err < 0)
                spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
        }
  
 -      sprintf(name, "%s Playback Switch", ctlname);
        if (nid != 0x16)
 -              err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
 +              err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
                          HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
        else /* mono */
 -              err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
 +              err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
                          HDA_COMPOSE_AMP_VAL(nid, 2, idx, HDA_OUTPUT));
        if (err < 0)
                return err;
@@@ -12379,7 -12387,8 +12381,7 @@@ static int alc268_auto_create_multi_out
  
        nid = cfg->speaker_pins[0];
        if (nid == 0x1d) {
 -              err = add_control(spec, ALC_CTL_WIDGET_VOL,
 -                                "Speaker Playback Volume",
 +              err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, "Speaker",
                                  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
                if (err < 0)
                        return err;
  
        nid = cfg->line_out_pins[1] | cfg->line_out_pins[2];
        if (nid == 0x16) {
 -              err = add_control(spec, ALC_CTL_WIDGET_MUTE,
 -                                "Mono Playback Switch",
 +              err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, "Mono",
                                  HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT));
                if (err < 0)
                        return err;
@@@ -14249,7 -14259,9 +14251,7 @@@ static int alc861_auto_fill_dac_nids(st
  static int alc861_create_out_sw(struct hda_codec *codec, const char *pfx,
                                hda_nid_t nid, unsigned int chs)
  {
 -      char name[32];
 -      snprintf(name, sizeof(name), "%s Playback Switch", pfx);
 -      return add_control(codec->spec, ALC_CTL_WIDGET_MUTE, name,
 +      return add_pb_sw_ctrl(codec->spec, ALC_CTL_WIDGET_MUTE, pfx,
                           HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
  }
  
@@@ -15373,6 -15385,7 +15375,6 @@@ static void alc861vd_auto_init_analog_i
  static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
                                             const struct auto_pin_cfg *cfg)
  {
 -      char name[32];
        static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"};
        hda_nid_t nid_v, nid_s;
        int i, err;
  
                if (i == 2) {
                        /* Center/LFE */
 -                      err = add_control(spec, ALC_CTL_WIDGET_VOL,
 -                                        "Center Playback Volume",
 +                      err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
 +                                            "Center",
                                          HDA_COMPOSE_AMP_VAL(nid_v, 1, 0,
                                                              HDA_OUTPUT));
                        if (err < 0)
                                return err;
 -                      err = add_control(spec, ALC_CTL_WIDGET_VOL,
 -                                        "LFE Playback Volume",
 +                      err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
 +                                            "LFE",
                                          HDA_COMPOSE_AMP_VAL(nid_v, 2, 0,
                                                              HDA_OUTPUT));
                        if (err < 0)
                                return err;
 -                      err = add_control(spec, ALC_CTL_BIND_MUTE,
 -                                        "Center Playback Switch",
 +                      err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
 +                                           "Center",
                                          HDA_COMPOSE_AMP_VAL(nid_s, 1, 2,
                                                              HDA_INPUT));
                        if (err < 0)
                                return err;
 -                      err = add_control(spec, ALC_CTL_BIND_MUTE,
 -                                        "LFE Playback Switch",
 +                      err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
 +                                           "LFE",
                                          HDA_COMPOSE_AMP_VAL(nid_s, 2, 2,
                                                              HDA_INPUT));
                        if (err < 0)
                                        pfx = "PCM";
                        } else
                                pfx = chname[i];
 -                      sprintf(name, "%s Playback Volume", pfx);
 -                      err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
 +                      err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
                                          HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
                                                              HDA_OUTPUT));
                        if (err < 0)
                        if (cfg->line_outs == 1 &&
                            cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
                                pfx = "Speaker";
 -                      sprintf(name, "%s Playback Switch", pfx);
 -                      err = add_control(spec, ALC_CTL_BIND_MUTE, name,
 +                      err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
                                          HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
                                                              HDA_INPUT));
                        if (err < 0)
@@@ -15449,6 -15464,7 +15451,6 @@@ static int alc861vd_auto_create_extra_o
  {
        hda_nid_t nid_v, nid_s;
        int err;
 -      char name[32];
  
        if (!pin)
                return 0;
                nid_s = alc861vd_idx_to_mixer_switch(
                                alc880_fixed_pin_idx(pin));
  
 -              sprintf(name, "%s Playback Volume", pfx);
 -              err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
 +              err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
                                  HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT));
                if (err < 0)
                        return err;
 -              sprintf(name, "%s Playback Switch", pfx);
 -              err = add_control(spec, ALC_CTL_BIND_MUTE, name,
 +              err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
                                  HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT));
                if (err < 0)
                        return err;
        } else if (alc880_is_multi_pin(pin)) {
                /* set manual connection */
                /* we have only a switch on HP-out PIN */
 -              sprintf(name, "%s Playback Switch", pfx);
 -              err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
 +              err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
                                  HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
                if (err < 0)
                        return err;
@@@ -17244,17 -17263,21 +17246,17 @@@ static int alc662_auto_fill_dac_nids(st
        return 0;
  }
  
 -static int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx,
 +static inline int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx,
                              hda_nid_t nid, unsigned int chs)
  {
 -      char name[32];
 -      sprintf(name, "%s Playback Volume", pfx);
 -      return add_control(spec, ALC_CTL_WIDGET_VOL, name,
 +      return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
                           HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
  }
  
 -static int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx,
 +static inline int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx,
                             hda_nid_t nid, unsigned int chs)
  {
 -      char name[32];
 -      sprintf(name, "%s Playback Switch", pfx);
 -      return add_control(spec, ALC_CTL_WIDGET_MUTE, name,
 +      return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
                           HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT));
  }
  
@@@ -17332,11 -17355,13 +17334,11 @@@ static int alc662_auto_create_extra_out
                return 0;
        nid = alc662_look_for_dac(codec, pin);
        if (!nid) {
 -              char name[32];
                /* the corresponding DAC is already occupied */
                if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
                        return 0; /* no way */
                /* create a switch only */
 -              sprintf(name, "%s Playback Switch", pfx);
 -              return add_control(spec, ALC_CTL_WIDGET_MUTE, name,
 +              return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
                                   HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
        }
  
index 9c33700b21a89748df89618808340d7936d3d7e6,86de305fc9f225ef382f6a7bdfbd438a2f97840f..2d3e2e415eb0278f74bf35e31ab22297d4a432eb
@@@ -1590,6 -1590,8 +1590,8 @@@ static struct snd_pci_quirk stac92hd73x
                                "Dell Studio 17", STAC_DELL_M6_DMIC),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02be,
                                "Dell Studio 1555", STAC_DELL_M6_DMIC),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02bd,
+                               "Dell Studio 1557", STAC_DELL_M6_DMIC),
        {} /* terminator */
  };
  
@@@ -4327,28 -4329,6 +4329,28 @@@ static void stac92xx_free_kctls(struct 
        snd_array_free(&spec->kctls);
  }
  
 +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);
 +      }
 +
 +      if (spec->eapd_mask)
 +              stac_gpio_set(codec, spec->gpio_mask,
 +                              spec->gpio_dir, spec->gpio_data &
 +                              ~spec->eapd_mask);
 +}
 +
  static void stac92xx_free(struct hda_codec *codec)
  {
        struct sigmatel_spec *spec = codec->spec;
        if (! spec)
                return;
  
 +      stac92xx_shutup(codec);
        stac92xx_free_jacks(codec);
        snd_array_free(&spec->events);
  
@@@ -4816,7 -4795,24 +4818,7 @@@ static int stac92xx_hp_check_power_stat
  
  static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
  {
 -      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);
 -      }
 -
 -      if (spec->eapd_mask)
 -              stac_gpio_set(codec, spec->gpio_mask,
 -                              spec->gpio_dir, spec->gpio_data &
 -                              ~spec->eapd_mask);
 +      stac92xx_shutup(codec);
        return 0;
  }
  #endif
@@@ -4831,7 -4827,6 +4833,7 @@@ static struct hda_codec_ops stac92xx_pa
        .suspend = stac92xx_suspend,
        .resume = stac92xx_resume,
  #endif
 +      .reboot_notify = stac92xx_shutup,
  };
  
  static int patch_stac9200(struct hda_codec *codec)