Merge branch 'fix/hda' into topic/hda
authorTakashi Iwai <tiwai@suse.de>
Mon, 3 Aug 2009 06:37:17 +0000 (08:37 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 3 Aug 2009 06:37:17 +0000 (08:37 +0200)
1  2 
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c

@@@ -44,7 -44,6 +44,7 @@@ struct hda_vendor_id 
  /* codec vendor labels */
  static struct hda_vendor_id hda_vendor_ids[] = {
        { 0x1002, "ATI" },
 +      { 0x1013, "Cirrus Logic" },
        { 0x1057, "Motorola" },
        { 0x1095, "Silicon Image" },
        { 0x10de, "Nvidia" },
@@@ -151,14 -150,7 +151,14 @@@ make_codec_cmd(struct hda_codec *codec
  {
        u32 val;
  
 -      val = (u32)(codec->addr & 0x0f) << 28;
 +      if ((codec->addr & ~0xf) || (direct & ~1) || (nid & ~0x7f) ||
 +          (verb & ~0xfff) || (parm & ~0xffff)) {
 +              printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x:%x\n",
 +                     codec->addr, direct, nid, verb, parm);
 +              return ~0;
 +      }
 +
 +      val = (u32)codec->addr << 28;
        val |= (u32)direct << 27;
        val |= (u32)nid << 20;
        val |= verb << 8;
@@@ -175,9 -167,6 +175,9 @@@ static int codec_exec_verb(struct hda_c
        struct hda_bus *bus = codec->bus;
        int err;
  
 +      if (cmd == ~0)
 +              return -1;
 +
        if (res)
                *res = -1;
   again:
        mutex_lock(&bus->cmd_mutex);
        err = bus->ops.command(bus, cmd);
        if (!err && res)
-               *res = bus->ops.get_response(bus);
+               *res = bus->ops.get_response(bus, codec->addr);
        mutex_unlock(&bus->cmd_mutex);
        snd_hda_power_down(codec);
        if (res && *res == -1 && bus->rirb_error) {
@@@ -302,20 -291,11 +302,20 @@@ int snd_hda_get_connections(struct hda_
        unsigned int parm;
        int i, conn_len, conns;
        unsigned int shift, num_elems, mask;
 +      unsigned int wcaps;
        hda_nid_t prev_nid;
  
        if (snd_BUG_ON(!conn_list || max_conns <= 0))
                return -EINVAL;
  
 +      wcaps = get_wcaps(codec, nid);
 +      if (!(wcaps & AC_WCAP_CONN_LIST) &&
 +          get_wcaps_type(wcaps) != AC_WID_VOL_KNB) {
 +              snd_printk(KERN_WARNING "hda_codec: "
 +                         "connection list not available for 0x%x\n", nid);
 +              return -EINVAL;
 +      }
 +
        parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
        if (parm & AC_CLIST_LONG) {
                /* long form */
                /* single connection */
                parm = snd_hda_codec_read(codec, nid, 0,
                                          AC_VERB_GET_CONNECT_LIST, 0);
 +              if (parm == -1 && codec->bus->rirb_error)
 +                      return -EIO;
                conn_list[0] = parm & mask;
                return 1;
        }
                int range_val;
                hda_nid_t val, n;
  
 -              if (i % num_elems == 0)
 +              if (i % num_elems == 0) {
                        parm = snd_hda_codec_read(codec, nid, 0,
                                                  AC_VERB_GET_CONNECT_LIST, i);
 +                      if (parm == -1 && codec->bus->rirb_error)
 +                              return -EIO;
 +              }
                range_val = !!(parm & (1 << (shift-1))); /* ranges */
                val = parm & mask;
                if (val == 0) {
@@@ -752,7 -727,8 +752,7 @@@ static int read_pin_defaults(struct hda
        for (i = 0; i < codec->num_nodes; i++, nid++) {
                struct hda_pincfg *pin;
                unsigned int wcaps = get_wcaps(codec, nid);
 -              unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
 -                              AC_WCAP_TYPE_SHIFT;
 +              unsigned int wid_type = get_wcaps_type(wcaps);
                if (wid_type != AC_WID_PIN)
                        continue;
                pin = snd_array_new(&codec->init_pins);
@@@ -915,7 -891,7 +915,7 @@@ static void hda_set_power_state(struct 
   * Returns 0 if successful, or a negative error code.
   */
  int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
 -                                  int do_init, struct hda_codec **codecp)
 +                                  struct hda_codec **codecp)
  {
        struct hda_codec *codec;
        char component[31];
                            codec->afg ? codec->afg : codec->mfg,
                            AC_PWRST_D0);
  
 -      if (do_init) {
 -              err = snd_hda_codec_configure(codec);
 -              if (err < 0)
 -                      goto error;
 -      }
        snd_hda_codec_proc_new(codec);
  
        snd_hda_create_hwdep(codec);
@@@ -1061,7 -1042,6 +1061,7 @@@ int snd_hda_codec_configure(struct hda_
                err = init_unsol_queue(codec->bus);
        return err;
  }
 +EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
  
  /**
   * snd_hda_codec_setup_stream - set up the codec for streaming
@@@ -2376,20 -2356,16 +2376,20 @@@ static void hda_set_power_state(struct 
        hda_nid_t nid;
        int i;
  
 -      snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE,
 +      /* this delay seems necessary to avoid click noise at power-down */
 +      if (power_state == AC_PWRST_D3)
 +              msleep(100);
 +      snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
                            power_state);
 -      msleep(10); /* partial workaround for "azx_get_response timeout" */
 +      /* partial workaround for "azx_get_response timeout" */
 +      if (power_state == AC_PWRST_D0)
 +              msleep(10);
  
        nid = codec->start_nid;
        for (i = 0; i < codec->num_nodes; i++, nid++) {
                unsigned int wcaps = get_wcaps(codec, nid);
                if (wcaps & AC_WCAP_POWER) {
 -                      unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
 -                              AC_WCAP_TYPE_SHIFT;
 +                      unsigned int wid_type = get_wcaps_type(wcaps);
                        if (power_state == AC_PWRST_D3 &&
                            wid_type == AC_WID_PIN) {
                                unsigned int pincap;
@@@ -2597,7 -2573,7 +2597,7 @@@ unsigned int snd_hda_calc_stream_format
        case 20:
        case 24:
        case 32:
 -              if (maxbps >= 32)
 +              if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
                        val |= 0x40;
                else if (maxbps >= 24)
                        val |= 0x30;
@@@ -2724,12 -2700,11 +2724,12 @@@ static int snd_hda_query_supported_pcm(
                                        bps = 20;
                        }
                }
 -              else if (streams == AC_SUPFMT_FLOAT32) {
 -                      /* should be exclusive */
 +              if (streams & AC_SUPFMT_FLOAT32) {
                        formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
 -                      bps = 32;
 -              } else if (streams == AC_SUPFMT_AC3) {
 +                      if (!bps)
 +                              bps = 32;
 +              }
 +              if (streams == AC_SUPFMT_AC3) {
                        /* should be exclusive */
                        /* temporary hack: we have still no proper support
                         * for the direct AC3 stream...
@@@ -3680,7 -3655,8 +3680,7 @@@ int snd_hda_parse_pin_def_config(struc
        end_nid = codec->start_nid + codec->num_nodes;
        for (nid = codec->start_nid; nid < end_nid; nid++) {
                unsigned int wid_caps = get_wcaps(codec, nid);
 -              unsigned int wid_type =
 -                      (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 +              unsigned int wid_type = get_wcaps_type(wid_caps);
                unsigned int def_conf;
                short assoc, loc;
  
@@@ -568,7 -568,7 +568,7 @@@ struct hda_bus_ops 
        /* send a single command */
        int (*command)(struct hda_bus *bus, unsigned int cmd);
        /* get a response from the last command */
-       unsigned int (*get_response)(struct hda_bus *bus);
+       unsigned int (*get_response)(struct hda_bus *bus, unsigned int addr);
        /* free the private data */
        void (*private_free)(struct hda_bus *);
        /* attach a PCM stream */
@@@ -830,8 -830,7 +830,8 @@@ enum 
  int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp,
                    struct hda_bus **busp);
  int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
 -                    int do_init, struct hda_codec **codecp);
 +                    struct hda_codec **codecp);
 +int snd_hda_codec_configure(struct hda_codec *codec);
  
  /*
   * low level functions
@@@ -939,13 -938,6 +939,13 @@@ static inline void snd_hda_power_down(s
  #define snd_hda_codec_needs_resume(codec) 1
  #endif
  
 +#ifdef CONFIG_SND_HDA_PATCH_LOADER
 +/*
 + * patch firmware
 + */
 +int snd_hda_load_patch(struct hda_bus *bus, const char *patch);
 +#endif
 +
  /*
   * Codec modularization
   */
@@@ -61,9 -61,6 +61,9 @@@ static int probe_mask[SNDRV_CARDS] = {[
  static int probe_only[SNDRV_CARDS];
  static int single_cmd;
  static int enable_msi;
 +#ifdef CONFIG_SND_HDA_PATCH_LOADER
 +static char *patch[SNDRV_CARDS];
 +#endif
  
  module_param_array(index, int, NULL, 0444);
  MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@@ -87,10 -84,6 +87,10 @@@ MODULE_PARM_DESC(single_cmd, "Use singl
                 "(for debugging only).");
  module_param(enable_msi, int, 0444);
  MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)");
 +#ifdef CONFIG_SND_HDA_PATCH_LOADER
 +module_param_array(patch, charp, NULL, 0444);
 +MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface.");
 +#endif
  
  #ifdef CONFIG_SND_HDA_POWER_SAVE
  static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
@@@ -260,7 -253,7 +260,7 @@@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SD
  
  /* STATESTS int mask: S3,SD2,SD1,SD0 */
  #define AZX_MAX_CODECS                4
- #define STATESTS_INT_MASK     0x0f
+ #define STATESTS_INT_MASK     ((1 << AZX_MAX_CODECS) - 1)
  
  /* SD_CTL bits */
  #define SD_CTL_STREAM_RESET   0x01    /* stream reset bit */
@@@ -368,8 -361,8 +368,8 @@@ struct azx_rb 
        dma_addr_t addr;        /* physical address of CORB/RIRB buffer */
        /* for RIRB */
        unsigned short rp, wp;  /* read/write pointers */
-       int cmds;               /* number of pending requests */
-       u32 res;                /* last read value */
+       int cmds[AZX_MAX_CODECS];       /* number of pending requests */
+       u32 res[AZX_MAX_CODECS];        /* last read value */
  };
  
  struct azx {
        unsigned int probing :1; /* codec probing phase */
  
        /* for debugging */
-       unsigned int last_cmd;  /* last issued command (to sync) */
+       unsigned int last_cmd[AZX_MAX_CODECS];
  
        /* for pending irqs */
        struct work_struct irq_pending_work;
@@@ -520,6 -513,7 +520,7 @@@ static int azx_alloc_cmd_io(struct azx 
  
  static void azx_init_cmd_io(struct azx *chip)
  {
+       spin_lock_irq(&chip->reg_lock);
        /* CORB set up */
        chip->corb.addr = chip->rb.addr;
        chip->corb.buf = (u32 *)chip->rb.area;
        /* RIRB set up */
        chip->rirb.addr = chip->rb.addr + 2048;
        chip->rirb.buf = (u32 *)(chip->rb.area + 2048);
-       chip->rirb.wp = chip->rirb.rp = chip->rirb.cmds = 0;
+       chip->rirb.wp = chip->rirb.rp = 0;
+       memset(chip->rirb.cmds, 0, sizeof(chip->rirb.cmds));
        azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr);
        azx_writel(chip, RIRBUBASE, upper_32_bits(chip->rirb.addr));
  
        azx_writew(chip, RINTCNT, 1);
        /* enable rirb dma and response irq */
        azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN);
+       spin_unlock_irq(&chip->reg_lock);
  }
  
  static void azx_free_cmd_io(struct azx *chip)
  {
+       spin_lock_irq(&chip->reg_lock);
        /* disable ringbuffer DMAs */
        azx_writeb(chip, RIRBCTL, 0);
        azx_writeb(chip, CORBCTL, 0);
+       spin_unlock_irq(&chip->reg_lock);
+ }
+ static unsigned int azx_command_addr(u32 cmd)
+ {
+       unsigned int addr = cmd >> 28;
+       if (addr >= AZX_MAX_CODECS) {
+               snd_BUG();
+               addr = 0;
+       }
+       return addr;
+ }
+ static unsigned int azx_response_addr(u32 res)
+ {
+       unsigned int addr = res & 0xf;
+       if (addr >= AZX_MAX_CODECS) {
+               snd_BUG();
+               addr = 0;
+       }
+       return addr;
  }
  
  /* send a command */
  static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
  {
        struct azx *chip = bus->private_data;
+       unsigned int addr = azx_command_addr(val);
        unsigned int wp;
  
+       spin_lock_irq(&chip->reg_lock);
        /* add command to corb */
        wp = azx_readb(chip, CORBWP);
        wp++;
        wp %= ICH6_MAX_CORB_ENTRIES;
  
-       spin_lock_irq(&chip->reg_lock);
-       chip->rirb.cmds++;
+       chip->rirb.cmds[addr]++;
        chip->corb.buf[wp] = cpu_to_le32(val);
        azx_writel(chip, CORBWP, wp);
        spin_unlock_irq(&chip->reg_lock);
  
        return 0;
  static void azx_update_rirb(struct azx *chip)
  {
        unsigned int rp, wp;
+       unsigned int addr;
        u32 res, res_ex;
  
        wp = azx_readb(chip, RIRBWP);
        if (wp == chip->rirb.wp)
                return;
        chip->rirb.wp = wp;
-               
        while (chip->rirb.rp != wp) {
                chip->rirb.rp++;
                chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES;
                rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
                res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
                res = le32_to_cpu(chip->rirb.buf[rp]);
+               addr = azx_response_addr(res_ex);
                if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
                        snd_hda_queue_unsol_event(chip->bus, res, res_ex);
-               else if (chip->rirb.cmds) {
-                       chip->rirb.res = res;
+               else if (chip->rirb.cmds[addr]) {
+                       chip->rirb.res[addr] = res;
                        smp_wmb();
-                       chip->rirb.cmds--;
-               }
+                       chip->rirb.cmds[addr]--;
+               } else
+                       snd_printk(KERN_ERR SFX "spurious response %#x:%#x, "
+                                  "last cmd=%#08x\n",
+                                  res, res_ex,
+                                  chip->last_cmd[addr]);
        }
  }
  
  /* receive a response */
- static unsigned int azx_rirb_get_response(struct hda_bus *bus)
+ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
+                                         unsigned int addr)
  {
        struct azx *chip = bus->private_data;
        unsigned long timeout;
                        azx_update_rirb(chip);
                        spin_unlock_irq(&chip->reg_lock);
                }
-               if (!chip->rirb.cmds) {
+               if (!chip->rirb.cmds[addr]) {
                        smp_rmb();
                        bus->rirb_error = 0;
-                       return chip->rirb.res; /* the last value */
+                       return chip->rirb.res[addr]; /* the last value */
                }
                if (time_after(jiffies, timeout))
                        break;
  
        if (chip->msi) {
                snd_printk(KERN_WARNING SFX "No response from codec, "
-                          "disabling MSI: last cmd=0x%08x\n", chip->last_cmd);
+                          "disabling MSI: last cmd=0x%08x\n",
+                          chip->last_cmd[addr]);
                free_irq(chip->irq, chip);
                chip->irq = -1;
                pci_disable_msi(chip->pci);
        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);
+                          chip->last_cmd[addr]);
                chip->polling_mode = 1;
                goto again;
        }
  
        snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
                   "switching to single_cmd mode: last cmd=0x%08x\n",
-                  chip->last_cmd);
+                  chip->last_cmd[addr]);
        chip->single_cmd = 1;
        bus->response_reset = 0;
        /* re-initialize CORB/RIRB */
   */
  
  /* receive a response */
- static int azx_single_wait_for_response(struct azx *chip)
+ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)
  {
        int timeout = 50;
  
                /* check IRV busy bit */
                if (azx_readw(chip, IRS) & ICH6_IRS_VALID) {
                        /* reuse rirb.res as the response return value */
-                       chip->rirb.res = azx_readl(chip, IR);
+                       chip->rirb.res[addr] = azx_readl(chip, IR);
                        return 0;
                }
                udelay(1);
        if (printk_ratelimit())
                snd_printd(SFX "get_response timeout: IRS=0x%x\n",
                           azx_readw(chip, IRS));
-       chip->rirb.res = -1;
+       chip->rirb.res[addr] = -1;
        return -EIO;
  }
  
  static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
  {
        struct azx *chip = bus->private_data;
+       unsigned int addr = azx_command_addr(val);
        int timeout = 50;
  
        bus->rirb_error = 0;
                        azx_writel(chip, IC, val);
                        azx_writew(chip, IRS, azx_readw(chip, IRS) |
                                   ICH6_IRS_BUSY);
-                       return azx_single_wait_for_response(chip);
+                       return azx_single_wait_for_response(chip, addr);
                }
                udelay(1);
        }
  }
  
  /* receive a response */
- static unsigned int azx_single_get_response(struct hda_bus *bus)
+ static unsigned int azx_single_get_response(struct hda_bus *bus,
+                                           unsigned int addr)
  {
        struct azx *chip = bus->private_data;
-       return chip->rirb.res;
+       return chip->rirb.res[addr];
  }
  
  /*
@@@ -764,7 -799,7 +806,7 @@@ static int azx_send_cmd(struct hda_bus 
  {
        struct azx *chip = bus->private_data;
  
-       chip->last_cmd = val;
+       chip->last_cmd[azx_command_addr(val)] = val;
        if (chip->single_cmd)
                return azx_single_send_cmd(bus, val);
        else
  }
  
  /* get a response */
- static unsigned int azx_get_response(struct hda_bus *bus)
+ static unsigned int azx_get_response(struct hda_bus *bus,
+                                    unsigned int addr)
  {
        struct azx *chip = bus->private_data;
        if (chip->single_cmd)
-               return azx_single_get_response(bus);
+               return azx_single_get_response(bus, addr);
        else
-               return azx_rirb_get_response(bus);
+               return azx_rirb_get_response(bus, addr);
  }
  
  #ifdef CONFIG_SND_HDA_POWER_SAVE
@@@ -1250,10 -1286,12 +1293,12 @@@ static int probe_codec(struct azx *chip
                (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
        unsigned int res;
  
+       mutex_lock(&chip->bus->cmd_mutex);
        chip->probing = 1;
        azx_send_cmd(chip->bus, cmd);
-       res = azx_get_response(chip->bus);
+       res = azx_get_response(chip->bus, addr);
        chip->probing = 0;
+       mutex_unlock(&chip->bus->cmd_mutex);
        if (res == -1)
                return -EIO;
        snd_printdd(SFX "codec #%d probed OK\n", addr);
@@@ -1293,7 -1331,8 +1338,7 @@@ static unsigned int azx_max_codecs[AZX_
        [AZX_DRIVER_TERA] = 1,
  };
  
 -static int __devinit azx_codec_create(struct azx *chip, const char *model,
 -                                    int no_init)
 +static int __devinit azx_codec_create(struct azx *chip, const char *model)
  {
        struct hda_bus_template bus_temp;
        int c, codecs, err;
        for (c = 0; c < max_slots; c++) {
                if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) {
                        struct hda_codec *codec;
 -                      err = snd_hda_codec_new(chip->bus, c, !no_init, &codec);
 +                      err = snd_hda_codec_new(chip->bus, c, &codec);
                        if (err < 0)
                                continue;
                        codecs++;
                snd_printk(KERN_ERR SFX "no codecs initialized\n");
                return -ENXIO;
        }
 +      return 0;
 +}
  
 +/* configure each codec instance */
 +static int __devinit azx_codec_configure(struct azx *chip)
 +{
 +      struct hda_codec *codec;
 +      list_for_each_entry(codec, &chip->bus->codec_list, list) {
 +              snd_hda_codec_configure(codec);
 +      }
        return 0;
  }
  
@@@ -2496,32 -2526,15 +2541,32 @@@ static int __devinit azx_probe(struct p
                return err;
        }
  
 +      /* set this here since it's referred in snd_hda_load_patch() */
 +      snd_card_set_dev(card, &pci->dev);
 +
        err = azx_create(card, pci, dev, pci_id->driver_data, &chip);
        if (err < 0)
                goto out_free;
        card->private_data = chip;
  
        /* create codec instances */
 -      err = azx_codec_create(chip, model[dev], probe_only[dev]);
 +      err = azx_codec_create(chip, model[dev]);
        if (err < 0)
                goto out_free;
 +#ifdef CONFIG_SND_HDA_PATCH_LOADER
 +      if (patch[dev]) {
 +              snd_printk(KERN_ERR SFX "Applying patch firmware '%s'\n",
 +                         patch[dev]);
 +              err = snd_hda_load_patch(chip->bus, patch[dev]);
 +              if (err < 0)
 +                      goto out_free;
 +      }
 +#endif
 +      if (!probe_only[dev]) {
 +              err = azx_codec_configure(chip);
 +              if (err < 0)
 +                      goto out_free;
 +      }
  
        /* create PCM streams */
        err = snd_hda_build_pcms(chip->bus);
        if (err < 0)
                goto out_free;
  
 -      snd_card_set_dev(card, &pci->dev);
 -
        err = snd_card_register(card);
        if (err < 0)
                goto out_free;
@@@ -2634,15 -2649,11 +2679,15 @@@ static struct pci_device_id azx_ids[] 
        /* this entry seems still valid -- i.e. without emu20kx chip */
        { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_GENERIC },
  #endif
 -      /* AMD Generic, PCI class code and Vendor ID for HD Audio */
 +      /* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */
        { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID),
          .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
          .class_mask = 0xffffff,
          .driver_data = AZX_DRIVER_GENERIC },
 +      { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_ANY_ID),
 +        .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
 +        .class_mask = 0xffffff,
 +        .driver_data = AZX_DRIVER_GENERIC },
        { 0, }
  };
  MODULE_DEVICE_TABLE(pci, azx_ids);
@@@ -208,6 -208,12 +208,6 @@@ enum 
        ALC885_MBP3,
        ALC885_MB5,
        ALC885_IMAC24,
 -      ALC882_AUTO,
 -      ALC882_MODEL_LAST,
 -};
 -
 -/* ALC883 models */
 -enum {
        ALC883_3ST_2ch_DIG,
        ALC883_3ST_6ch_DIG,
        ALC883_3ST_6ch,
        ALC883_FUJITSU_PI2515,
        ALC888_FUJITSU_XA3530,
        ALC883_3ST_6ch_INTEL,
 +      ALC889A_INTEL,
 +      ALC889_INTEL,
        ALC888_ASUS_M90V,
        ALC888_ASUS_EEE1601,
        ALC889A_MB31,
        ALC1200_ASUS_P5Q,
        ALC883_SONY_VAIO_TT,
 -      ALC883_AUTO,
 -      ALC883_MODEL_LAST,
 +      ALC882_AUTO,
 +      ALC882_MODEL_LAST,
  };
  
  /* for GPIO Poll */
@@@ -271,13 -275,13 +271,13 @@@ struct alc_spec 
                                                 */
        unsigned int num_init_verbs;
  
-       char stream_name_analog[16];    /* analog PCM stream */
+       char stream_name_analog[32];    /* analog PCM stream */
        struct hda_pcm_stream *stream_analog_playback;
        struct hda_pcm_stream *stream_analog_capture;
        struct hda_pcm_stream *stream_analog_alt_playback;
        struct hda_pcm_stream *stream_analog_alt_capture;
  
-       char stream_name_digital[16];   /* digital PCM stream */
+       char stream_name_digital[32];   /* digital PCM stream */
        struct hda_pcm_stream *stream_digital_playback;
        struct hda_pcm_stream *stream_digital_capture;
  
        struct snd_array kctls;
        struct hda_input_mux private_imux[3];
        hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
 +      hda_nid_t private_adc_nids[AUTO_CFG_MAX_OUTS];
 +      hda_nid_t private_capsrc_nids[AUTO_CFG_MAX_OUTS];
  
        /* hooks */
        void (*init_hook)(struct hda_codec *codec);
@@@ -415,7 -417,7 +415,7 @@@ static int alc_mux_enum_put(struct snd_
        mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
        imux = &spec->input_mux[mux_idx];
  
 -      type = (get_wcaps(codec, nid) & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 +      type = get_wcaps_type(get_wcaps(codec, nid));
        if (type == AC_WID_AUD_MIX) {
                /* Matrix-mixer style (e.g. ALC882) */
                unsigned int *cur_val = &spec->cur_mux[adc_idx];
@@@ -557,7 -559,7 +557,7 @@@ static int alc_pin_mode_get(struct snd_
  
        /* Find enumerated value for current pinctl setting */
        i = alc_pin_mode_min(dir);
-       while (alc_pin_mode_values[i] != pinctl && i <= alc_pin_mode_max(dir))
+       while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl)
                i++;
        *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
        return 0;
@@@ -1029,16 -1031,6 +1029,16 @@@ static void alc888_coef_init(struct hda
                                    AC_VERB_SET_PROC_COEF, 0x3030);
  }
  
 +static void alc889_coef_init(struct hda_codec *codec)
 +{
 +      unsigned int tmp;
 +
 +      snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
 +      tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
 +      snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
 +      snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
 +}
 +
  static void alc_auto_init_amp(struct hda_codec *codec, int type)
  {
        unsigned int tmp;
                case 0x10ec0885:
                case 0x10ec0887:
                case 0x10ec0889:
 -                      snd_hda_codec_write(codec, 0x20, 0,
 -                                          AC_VERB_SET_COEF_INDEX, 7);
 -                      tmp = snd_hda_codec_read(codec, 0x20, 0,
 -                                               AC_VERB_GET_PROC_COEF, 0);
 -                      snd_hda_codec_write(codec, 0x20, 0,
 -                                          AC_VERB_SET_COEF_INDEX, 7);
 -                      snd_hda_codec_write(codec, 0x20, 0,
 -                                          AC_VERB_SET_PROC_COEF,
 -                                          tmp | 0x2010);
 +                      alc889_coef_init(codec);
                        break;
                case 0x10ec0888:
                        alc888_coef_init(codec);
@@@ -1436,25 -1436,6 +1436,25 @@@ static void alc_automute_amp_unsol_even
                alc_automute_amp(codec);
  }
  
 +static void alc889_automute_init(struct hda_codec *codec)
 +{
 +      struct alc_spec *spec = codec->spec;
 +
 +      spec->autocfg.hp_pins[0] = 0x15;
 +      spec->autocfg.speaker_pins[0] = 0x14;
 +      spec->autocfg.speaker_pins[1] = 0x16;
 +      spec->autocfg.speaker_pins[2] = 0x17;
 +      spec->autocfg.speaker_pins[3] = 0x19;
 +      spec->autocfg.speaker_pins[4] = 0x1a;
 +      alc_automute_amp(codec);
 +}
 +
 +static void alc889_intel_init_hook(struct hda_codec *codec)
 +{
 +      alc889_coef_init(codec);
 +      alc889_automute_init(codec);
 +}
 +
  static void alc888_fujitsu_xa3530_init_hook(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
@@@ -4524,6 -4505,12 +4524,6 @@@ static int alc880_parse_auto_config(str
                                              &dig_nid, 1);
                if (err < 0)
                        continue;
 -              if (dig_nid > 0x7f) {
 -                      printk(KERN_ERR "alc880_auto: invalid dig_nid "
 -                              "connection 0x%x for NID 0x%x\n", dig_nid,
 -                              spec->autocfg.dig_out_pins[i]);
 -                      continue;
 -              }
                if (!i)
                        spec->multiout.dig_out_nid = dig_nid;
                else {
@@@ -4603,8 -4590,8 +4603,8 @@@ static int patch_alc880(struct hda_code
                                                  alc880_models,
                                                  alc880_cfg_tbl);
        if (board_config < 0) {
 -              printk(KERN_INFO "hda_codec: Unknown model for %s, "
 -                     "trying auto-probe from BIOS...\n", codec->chip_name);
 +              printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                     codec->chip_name);
                board_config = ALC880_AUTO;
        }
  
                /* check whether NID 0x07 is valid */
                unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
                /* get type */
 -              wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 +              wcap = get_wcaps_type(wcap);
                if (wcap != AC_WID_AUD_IN) {
                        spec->adc_nids = alc880_adc_nids_alt;
                        spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
@@@ -6247,7 -6234,8 +6247,7 @@@ static int patch_alc260(struct hda_code
                                                  alc260_models,
                                                  alc260_cfg_tbl);
        if (board_config < 0) {
 -              snd_printd(KERN_INFO "hda_codec: Unknown model for %s, "
 -                         "trying auto-probe from BIOS...\n",
 +              snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
                           codec->chip_name);
                board_config = ALC260_AUTO;
        }
        if (!spec->adc_nids && spec->input_mux) {
                /* check whether NID 0x04 is valid */
                unsigned int wcap = get_wcaps(codec, 0x04);
 -              wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 +              wcap = get_wcaps_type(wcap);
                /* get type */
                if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
                        spec->adc_nids = alc260_adc_nids_alt;
  
  
  /*
 - * ALC882 support
 + * ALC882/883/885/888/889 support
   *
   * ALC882 is almost identical with ALC880 but has cleaner and more flexible
   * configuration.  Each pin widget can choose any input DACs and a mixer.
   */
  #define ALC882_DIGOUT_NID     0x06
  #define ALC882_DIGIN_NID      0x0a
 +#define ALC883_DIGOUT_NID     ALC882_DIGOUT_NID
 +#define ALC883_DIGIN_NID      ALC882_DIGIN_NID
 +#define ALC1200_DIGOUT_NID    0x10
 +
  
  static struct hda_channel_mode alc882_ch_modes[1] = {
        { 8, NULL }
  };
  
 +/* DACs */
  static hda_nid_t alc882_dac_nids[4] = {
        /* front, rear, clfe, rear_surr */
        0x02, 0x03, 0x04, 0x05
  };
 +#define alc883_dac_nids               alc882_dac_nids
  
 -/* identical with ALC880 */
 +/* ADCs */
  #define alc882_adc_nids               alc880_adc_nids
  #define alc882_adc_nids_alt   alc880_adc_nids_alt
 +#define alc883_adc_nids               alc882_adc_nids_alt
 +static hda_nid_t alc883_adc_nids_alt[1] = { 0x08 };
 +static hda_nid_t alc883_adc_nids_rev[2] = { 0x09, 0x08 };
 +#define alc889_adc_nids               alc880_adc_nids
  
  static hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
  static hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
 +#define alc883_capsrc_nids    alc882_capsrc_nids_alt
 +static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 };
 +#define alc889_capsrc_nids    alc882_capsrc_nids
  
  /* input MUX */
  /* FIXME: should be a matrix-type input source selection */
@@@ -6368,17 -6343,6 +6368,17 @@@ static struct hda_input_mux alc882_capt
        },
  };
  
 +#define alc883_capture_source alc882_capture_source
 +
 +static struct hda_input_mux alc889_capture_source = {
 +      .num_items = 3,
 +      .items = {
 +              { "Front Mic", 0x0 },
 +              { "Mic", 0x3 },
 +              { "Line", 0x2 },
 +      },
 +};
 +
  static struct hda_input_mux mb5_capture_source = {
        .num_items = 3,
        .items = {
        },
  };
  
 +static struct hda_input_mux alc883_3stack_6ch_intel = {
 +      .num_items = 4,
 +      .items = {
 +              { "Mic", 0x1 },
 +              { "Front Mic", 0x0 },
 +              { "Line", 0x2 },
 +              { "CD", 0x4 },
 +      },
 +};
 +
 +static struct hda_input_mux alc883_lenovo_101e_capture_source = {
 +      .num_items = 2,
 +      .items = {
 +              { "Mic", 0x1 },
 +              { "Line", 0x2 },
 +      },
 +};
 +
 +static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
 +      .num_items = 4,
 +      .items = {
 +              { "Mic", 0x0 },
 +              { "iMic", 0x1 },
 +              { "Line", 0x2 },
 +              { "CD", 0x4 },
 +      },
 +};
 +
 +static struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
 +      .num_items = 2,
 +      .items = {
 +              { "Mic", 0x0 },
 +              { "Int Mic", 0x1 },
 +      },
 +};
 +
 +static struct hda_input_mux alc883_lenovo_sky_capture_source = {
 +      .num_items = 3,
 +      .items = {
 +              { "Mic", 0x0 },
 +              { "Front Mic", 0x1 },
 +              { "Line", 0x4 },
 +      },
 +};
 +
 +static struct hda_input_mux alc883_asus_eee1601_capture_source = {
 +      .num_items = 2,
 +      .items = {
 +              { "Mic", 0x0 },
 +              { "Line", 0x2 },
 +      },
 +};
 +
 +static struct hda_input_mux alc889A_mb31_capture_source = {
 +      .num_items = 2,
 +      .items = {
 +              { "Mic", 0x0 },
 +              /* Front Mic (0x01) unused */
 +              { "Line", 0x2 },
 +              /* Line 2 (0x03) unused */
 +              /* CD (0x04) unsused? */
 +      },
 +};
 +
 +/*
 + * 2ch mode
 + */
 +static struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
 +      { 2, NULL }
 +};
 +
  /*
   * 2ch mode
   */
@@@ -6470,18 -6363,6 +6470,18 @@@ static struct hda_verb alc882_3ST_ch2_i
        { } /* end */
  };
  
 +/*
 + * 4ch mode
 + */
 +static struct hda_verb alc882_3ST_ch4_init[] = {
 +      { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 +      { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 +      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 +      { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
 +      { } /* end */
 +};
 +
  /*
   * 6ch mode
   */
@@@ -6495,14 -6376,11 +6495,14 @@@ static struct hda_verb alc882_3ST_ch6_i
        { } /* end */
  };
  
 -static struct hda_channel_mode alc882_3ST_6ch_modes[2] = {
 +static struct hda_channel_mode alc882_3ST_6ch_modes[3] = {
        { 2, alc882_3ST_ch2_init },
 +      { 4, alc882_3ST_ch4_init },
        { 6, alc882_3ST_ch6_init },
  };
  
 +#define alc883_3ST_6ch_modes  alc882_3ST_6ch_modes
 +
  /*
   * 6ch mode
   */
@@@ -6590,276 -6468,93 +6590,276 @@@ static struct hda_channel_mode alc885_m
        { 6, alc885_mb5_ch6_init },
  };
  
 -/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
 - *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
 +
 +/*
 + * 2ch mode
   */
 -static struct snd_kcontrol_new alc882_base_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("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
 -      HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
 -      HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 -      HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, 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),
 -      HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
 -      HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
 -      HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
 +static struct hda_verb alc883_4ST_ch2_init[] = {
 +      { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 +      { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 +      { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 +      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
 +      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
        { } /* end */
  };
  
 -static struct snd_kcontrol_new alc885_mbp3_mixer[] = {
 -      HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
 -      HDA_BIND_MUTE   ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
 -      HDA_CODEC_MUTE  ("Speaker Playback Switch", 0x14, 0x00, HDA_OUTPUT),
 -      HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
 -      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, 0x00, HDA_INPUT),
 -      HDA_CODEC_MUTE  ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
 -      HDA_CODEC_VOLUME("Line Boost", 0x1a, 0x00, HDA_INPUT),
 -      HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT),
 +/*
 + * 4ch mode
 + */
 +static struct hda_verb alc883_4ST_ch4_init[] = {
 +      { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 +      { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 +      { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 +      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 +      { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
        { } /* end */
  };
  
 -static struct snd_kcontrol_new alc885_mb5_mixer[] = {
 -      HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
 -      HDA_BIND_MUTE   ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
 -      HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
 -      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("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),
 -      HDA_CODEC_MUTE  ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
 -      HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT),
 -      HDA_CODEC_VOLUME("Mic Boost", 0x19, 0x00, HDA_INPUT),
 +/*
 + * 6ch mode
 + */
 +static struct hda_verb alc883_4ST_ch6_init[] = {
 +      { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 +      { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 +      { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
 +      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 +      { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
        { } /* end */
  };
  
 -static struct snd_kcontrol_new alc882_w2jc_mixer[] = {
 -      HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 -      HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
 -      HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 -      HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, 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),
 +/*
 + * 8ch mode
 + */
 +static struct hda_verb alc883_4ST_ch8_init[] = {
 +      { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 +      { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
 +      { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 +      { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
 +      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 +      { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
        { } /* end */
  };
  
 -static struct snd_kcontrol_new alc882_targa_mixer[] = {
 -      HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 -      HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
 -      HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 -      HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, 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_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
 -      HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
 -      HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
 -      HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
 -      HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
 +static struct hda_channel_mode alc883_4ST_8ch_modes[4] = {
 +      { 2, alc883_4ST_ch2_init },
 +      { 4, alc883_4ST_ch4_init },
 +      { 6, alc883_4ST_ch6_init },
 +      { 8, alc883_4ST_ch8_init },
 +};
 +
 +
 +/*
 + * 2ch mode
 + */
 +static struct hda_verb alc883_3ST_ch2_intel_init[] = {
 +      { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 +      { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 +      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
 +      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 +      { } /* end */
 +};
 +
 +/*
 + * 4ch mode
 + */
 +static struct hda_verb alc883_3ST_ch4_intel_init[] = {
 +      { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 +      { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 +      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 +      { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
 +      { } /* end */
 +};
 +
 +/*
 + * 6ch mode
 + */
 +static struct hda_verb alc883_3ST_ch6_intel_init[] = {
 +      { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 +      { 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 },
 +      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 +      { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
 +      { } /* end */
 +};
 +
 +static struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
 +      { 2, alc883_3ST_ch2_intel_init },
 +      { 4, alc883_3ST_ch4_intel_init },
 +      { 6, alc883_3ST_ch6_intel_init },
 +};
 +
 +/*
 + * 2ch mode
 + */
 +static struct hda_verb alc889_ch2_intel_init[] = {
 +      { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
 +      { 0x19, AC_VERB_SET_CONNECT_SEL, 0x00 },
 +      { 0x16, AC_VERB_SET_CONNECT_SEL, 0x00 },
 +      { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00 },
 +      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
 +      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 +      { } /* end */
 +};
 +
 +/*
 + * 6ch mode
 + */
 +static struct hda_verb alc889_ch6_intel_init[] = {
 +      { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
 +      { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
 +      { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
 +      { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
 +      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
 +      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 +      { } /* end */
 +};
 +
 +/*
 + * 8ch mode
 + */
 +static struct hda_verb alc889_ch8_intel_init[] = {
 +      { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
 +      { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
 +      { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
 +      { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
 +      { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x03 },
 +      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 +      { } /* end */
 +};
 +
 +static struct hda_channel_mode alc889_8ch_intel_modes[3] = {
 +      { 2, alc889_ch2_intel_init },
 +      { 6, alc889_ch6_intel_init },
 +      { 8, alc889_ch8_intel_init },
 +};
 +
 +/*
 + * 6ch mode
 + */
 +static struct hda_verb alc883_sixstack_ch6_init[] = {
 +      { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
 +      { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { } /* end */
 +};
 +
 +/*
 + * 8ch mode
 + */
 +static struct hda_verb alc883_sixstack_ch8_init[] = {
 +      { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 +      { } /* end */
 +};
 +
 +static struct hda_channel_mode alc883_sixstack_modes[2] = {
 +      { 6, alc883_sixstack_ch6_init },
 +      { 8, alc883_sixstack_ch8_init },
 +};
 +
 +
 +/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
 + *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
 + */
 +static struct snd_kcontrol_new alc882_base_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("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
 +      HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
 +      HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
 +      HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 +      HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, 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),
 +      HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
 +      HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
 +      HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
 +      { } /* end */
 +};
 +
 +static struct snd_kcontrol_new alc885_mbp3_mixer[] = {
 +      HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
 +      HDA_BIND_MUTE   ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
 +      HDA_CODEC_MUTE  ("Speaker Playback Switch", 0x14, 0x00, HDA_OUTPUT),
 +      HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
 +      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, 0x00, HDA_INPUT),
 +      HDA_CODEC_MUTE  ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
 +      HDA_CODEC_VOLUME("Line Boost", 0x1a, 0x00, HDA_INPUT),
 +      HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT),
 +      { } /* end */
 +};
 +
 +static struct snd_kcontrol_new alc885_mb5_mixer[] = {
 +      HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
 +      HDA_BIND_MUTE   ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
 +      HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
 +      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("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),
 +      HDA_CODEC_MUTE  ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
 +      HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT),
 +      HDA_CODEC_VOLUME("Mic Boost", 0x19, 0x00, HDA_INPUT),
 +      { } /* end */
 +};
 +
 +static struct snd_kcontrol_new alc882_w2jc_mixer[] = {
 +      HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 +      HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
 +      HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 +      HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, 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 struct snd_kcontrol_new alc882_targa_mixer[] = {
 +      HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 +      HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
 +      HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
 +      HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 +      HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, 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_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
 +      HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
 +      HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
 +      HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
 +      HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
        { } /* end */
  };
  
@@@ -6908,7 -6603,7 +6908,7 @@@ static struct snd_kcontrol_new alc882_c
        { } /* end */
  };
  
 -static struct hda_verb alc882_init_verbs[] = {
 +static struct hda_verb alc882_base_init_verbs[] = {
        /* Front mixer: unmute input/output amp left and right (volume = 0) */
        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
        {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
        {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
  
 +      /* mute analog input loopbacks */
 +      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 +      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
 +      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
 +      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
 +
        /* Front Pin: output 0 (0x0c) */
        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
  
        /* FIXME: use matrix-type input source selection */
        /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
 -      /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
 -      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
 -      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
 -      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
        /* Input mixer2 */
        {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
 -      /* ADC1: mute amp left and right */
 -      {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 -      {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
        /* ADC2: mute amp left and right */
        {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
        {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
        { }
  };
  
 +static struct hda_verb alc882_adc1_init_verbs[] = {
 +      /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
 +      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 +      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
 +      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
 +      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
 +      /* ADC1: mute amp left and right */
 +      {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +      {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
 +      { }
 +};
 +
  static struct hda_verb alc882_eapd_verbs[] = {
        /* change to EAPD mode */
        {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
        { }
  };
  
 -/* Mac Pro test */
 -static struct snd_kcontrol_new alc882_macpro_mixer[] = {
 -      HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 -      HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
 -      HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
 -      HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
 -      /* FIXME: this looks suspicious...
 -      HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT),
 -      HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT),
 -      */
 -      { } /* end */
 +static struct hda_verb alc889_eapd_verbs[] = {
 +      {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
 +      {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
 +      { }
  };
  
 -static struct hda_verb alc882_macpro_init_verbs[] = {
 +static struct hda_verb alc_hp15_unsol_verbs[] = {
 +      {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
 +      {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
 +      {}
 +};
 +
 +static struct hda_verb alc885_init_verbs[] = {
        /* Front mixer: unmute input/output amp left and right (volume = 0) */
        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 -      /* Front Pin: output 0 (0x0c) */
 -      {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 -      {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 -      {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
 -      /* 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},
 -      /* Speaker:  output */
 -      {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 -      {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 -      {0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
 -      /* Headphone output (output 0 - 0x0c) */
 -      {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
 -      {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 -      {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
 -
 +      /* Rear mixer */
 +      {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 +      {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +      {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 +      /* CLFE mixer */
 +      {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 +      {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +      {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 +      /* Side mixer */
 +      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 +      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 +
 +      /* mute analog input loopbacks */
 +      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
 +      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
 +
 +      /* Front HP Pin: output 0 (0x0c) */
 +      {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
 +      {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 +      {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
 +      /* Front Pin: output 0 (0x0c) */
 +      {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, 0x00},
 +      /* Rear Pin: output 1 (0x0d) */
 +      {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 +      {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 +      {0x19, AC_VERB_SET_CONNECT_SEL, 0x01},
 +      /* CLFE Pin: output 2 (0x0e) */
 +      {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 +      {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 +      {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
 +      /* Side Pin: output 3 (0x0f) */
 +      {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 +      {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 +      {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
 +      /* Mic (rear) pin: input vref at 80% */
 +      {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
 +      {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 +      /* Front Mic pin: input vref at 80% */
 +      {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
 +      {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 +      /* Line In pin: input */
 +      {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 +      {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 +
 +      /* Mixer elements: 0x18, , 0x1a, 0x1b */
 +      /* Input mixer1 */
 +      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
 +      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
 +      /* Input mixer2 */
 +      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 +      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
 +      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
 +      /* Input mixer3 */
 +      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
 +      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
 +      /* ADC2: mute amp left and right */
 +      {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +      /* ADC3: mute amp left and right */
 +      {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +
 +      { }
 +};
 +
 +static struct hda_verb alc885_init_input_verbs[] = {
 +      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 +      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
 +      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
 +      { }
 +};
 +
 +
 +/* Unmute Selector 24h and set the default input to front mic */
 +static struct hda_verb alc889_init_input_verbs[] = {
 +      {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
 +      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 +      { }
 +};
 +
 +
 +#define alc883_init_verbs     alc882_base_init_verbs
 +
 +/* Mac Pro test */
 +static struct snd_kcontrol_new alc882_macpro_mixer[] = {
 +      HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 +      HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
 +      HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
 +      HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
 +      HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
 +      /* FIXME: this looks suspicious...
 +      HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT),
 +      HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT),
 +      */
 +      { } /* end */
 +};
 +
 +static struct hda_verb alc882_macpro_init_verbs[] = {
 +      /* Front mixer: unmute input/output amp left and right (volume = 0) */
 +      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 +      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 +      /* Front Pin: output 0 (0x0c) */
 +      {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 +      {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 +      {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
 +      /* 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},
 +      /* Speaker:  output */
 +      {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 +      {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 +      {0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
 +      /* Headphone output (output 0 - 0x0c) */
 +      {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
 +      {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 +      {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
 +
        /* FIXME: use matrix-type input source selection */
        /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
        /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
@@@ -7449,70 -7029,891 +7449,70 @@@ static void alc885_macpro_init_hook(str
  
  /* set up GPIO and update auto-muting at initialization */
  static void alc885_imac24_init_hook(struct hda_codec *codec)
 -{
 -      alc885_macpro_init_hook(codec);
 -      alc885_imac24_automute_init_hook(codec);
 -}
 -
 -/*
 - * generic initialization of ADC, input mixers and output mixers
 - */
 -static struct hda_verb alc882_auto_init_verbs[] = {
 -      /*
 -       * Unmute ADC0-2 and set the default input to mic-in
 -       */
 -      {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
 -      {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
 -      {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
 -      {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -
 -      /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
 -       * mixer widget
 -       * Note: PASD motherboards uses the Line In 2 as the input for
 -       * front panel mic (mic 2)
 -       */
 -      /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
 -      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 -      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 -      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
 -      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
 -      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
 -
 -      /*
 -       * Set up output mixers (0x0c - 0x0f)
 -       */
 -      /* set vol=0 to output mixers */
 -      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 -      {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 -      {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 -      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 -      /* set up input amps for analog loopback */
 -      /* Amp Indices: DAC = 0, mixer = 1 */
 -      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -      {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -      {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -      {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -
 -      /* FIXME: use matrix-type input source selection */
 -      /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
 -      /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
 -      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
 -      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
 -      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
 -      {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
 -      /* Input mixer2 */
 -      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
 -      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
 -      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
 -      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
 -      /* Input mixer3 */
 -      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
 -      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
 -      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
 -      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
 -
 -      { }
 -};
 -
 -#ifdef CONFIG_SND_HDA_POWER_SAVE
 -#define alc882_loopbacks      alc880_loopbacks
 -#endif
 -
 -/* pcm configuration: identical with ALC880 */
 -#define alc882_pcm_analog_playback    alc880_pcm_analog_playback
 -#define alc882_pcm_analog_capture     alc880_pcm_analog_capture
 -#define alc882_pcm_digital_playback   alc880_pcm_digital_playback
 -#define alc882_pcm_digital_capture    alc880_pcm_digital_capture
 -
 -/*
 - * configuration and preset
 - */
 -static const char *alc882_models[ALC882_MODEL_LAST] = {
 -      [ALC882_3ST_DIG]        = "3stack-dig",
 -      [ALC882_6ST_DIG]        = "6stack-dig",
 -      [ALC882_ARIMA]          = "arima",
 -      [ALC882_W2JC]           = "w2jc",
 -      [ALC882_TARGA]          = "targa",
 -      [ALC882_ASUS_A7J]       = "asus-a7j",
 -      [ALC882_ASUS_A7M]       = "asus-a7m",
 -      [ALC885_MACPRO]         = "macpro",
 -      [ALC885_MB5]            = "mb5",
 -      [ALC885_MBP3]           = "mbp3",
 -      [ALC885_IMAC24]         = "imac24",
 -      [ALC882_AUTO]           = "auto",
 -};
 -
 -static struct snd_pci_quirk alc882_cfg_tbl[] = {
 -      SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
 -      SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J),
 -      SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J),
 -      SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M),
 -      SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),
 -      SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
 -      SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
 -      SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
 -      SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
 -      SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8  */
 -      SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
 -      SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA),
 -      {}
 -};
 -
 -static struct alc_config_preset alc882_presets[] = {
 -      [ALC882_3ST_DIG] = {
 -              .mixers = { alc882_base_mixer },
 -              .init_verbs = { alc882_init_verbs },
 -              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 -              .dac_nids = alc882_dac_nids,
 -              .dig_out_nid = ALC882_DIGOUT_NID,
 -              .dig_in_nid = ALC882_DIGIN_NID,
 -              .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
 -              .channel_mode = alc882_ch_modes,
 -              .need_dac_fix = 1,
 -              .input_mux = &alc882_capture_source,
 -      },
 -      [ALC882_6ST_DIG] = {
 -              .mixers = { alc882_base_mixer, alc882_chmode_mixer },
 -              .init_verbs = { alc882_init_verbs },
 -              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 -              .dac_nids = alc882_dac_nids,
 -              .dig_out_nid = ALC882_DIGOUT_NID,
 -              .dig_in_nid = ALC882_DIGIN_NID,
 -              .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
 -              .channel_mode = alc882_sixstack_modes,
 -              .input_mux = &alc882_capture_source,
 -      },
 -      [ALC882_ARIMA] = {
 -              .mixers = { alc882_base_mixer, alc882_chmode_mixer },
 -              .init_verbs = { alc882_init_verbs, alc882_eapd_verbs },
 -              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 -              .dac_nids = alc882_dac_nids,
 -              .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
 -              .channel_mode = alc882_sixstack_modes,
 -              .input_mux = &alc882_capture_source,
 -      },
 -      [ALC882_W2JC] = {
 -              .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer },
 -              .init_verbs = { alc882_init_verbs, alc882_eapd_verbs,
 -                              alc880_gpio1_init_verbs },
 -              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 -              .dac_nids = alc882_dac_nids,
 -              .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
 -              .channel_mode = alc880_threestack_modes,
 -              .need_dac_fix = 1,
 -              .input_mux = &alc882_capture_source,
 -              .dig_out_nid = ALC882_DIGOUT_NID,
 -      },
 -      [ALC885_MBP3] = {
 -              .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
 -              .init_verbs = { alc885_mbp3_init_verbs,
 -                              alc880_gpio1_init_verbs },
 -              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 -              .dac_nids = alc882_dac_nids,
 -              .channel_mode = alc885_mbp_6ch_modes,
 -              .num_channel_mode = ARRAY_SIZE(alc885_mbp_6ch_modes),
 -              .input_mux = &alc882_capture_source,
 -              .dig_out_nid = ALC882_DIGOUT_NID,
 -              .dig_in_nid = ALC882_DIGIN_NID,
 -              .unsol_event = alc_automute_amp_unsol_event,
 -              .init_hook = alc885_mbp3_init_hook,
 -      },
 -      [ALC885_MB5] = {
 -              .mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
 -              .init_verbs = { alc885_mb5_init_verbs,
 -                              alc880_gpio1_init_verbs },
 -              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 -              .dac_nids = alc882_dac_nids,
 -              .channel_mode = alc885_mb5_6ch_modes,
 -              .num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes),
 -              .input_mux = &mb5_capture_source,
 -              .dig_out_nid = ALC882_DIGOUT_NID,
 -              .dig_in_nid = ALC882_DIGIN_NID,
 -      },
 -      [ALC885_MACPRO] = {
 -              .mixers = { alc882_macpro_mixer },
 -              .init_verbs = { alc882_macpro_init_verbs },
 -              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 -              .dac_nids = alc882_dac_nids,
 -              .dig_out_nid = ALC882_DIGOUT_NID,
 -              .dig_in_nid = ALC882_DIGIN_NID,
 -              .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
 -              .channel_mode = alc882_ch_modes,
 -              .input_mux = &alc882_capture_source,
 -              .init_hook = alc885_macpro_init_hook,
 -      },
 -      [ALC885_IMAC24] = {
 -              .mixers = { alc885_imac24_mixer },
 -              .init_verbs = { alc885_imac24_init_verbs },
 -              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 -              .dac_nids = alc882_dac_nids,
 -              .dig_out_nid = ALC882_DIGOUT_NID,
 -              .dig_in_nid = ALC882_DIGIN_NID,
 -              .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
 -              .channel_mode = alc882_ch_modes,
 -              .input_mux = &alc882_capture_source,
 -              .unsol_event = alc_automute_amp_unsol_event,
 -              .init_hook = alc885_imac24_init_hook,
 -      },
 -      [ALC882_TARGA] = {
 -              .mixers = { alc882_targa_mixer, alc882_chmode_mixer },
 -              .init_verbs = { alc882_init_verbs, alc880_gpio3_init_verbs,
 -                              alc882_targa_verbs},
 -              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 -              .dac_nids = alc882_dac_nids,
 -              .dig_out_nid = ALC882_DIGOUT_NID,
 -              .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
 -              .adc_nids = alc882_adc_nids,
 -              .capsrc_nids = alc882_capsrc_nids,
 -              .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
 -              .channel_mode = alc882_3ST_6ch_modes,
 -              .need_dac_fix = 1,
 -              .input_mux = &alc882_capture_source,
 -              .unsol_event = alc882_targa_unsol_event,
 -              .init_hook = alc882_targa_init_hook,
 -      },
 -      [ALC882_ASUS_A7J] = {
 -              .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer },
 -              .init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs},
 -              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 -              .dac_nids = alc882_dac_nids,
 -              .dig_out_nid = ALC882_DIGOUT_NID,
 -              .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
 -              .adc_nids = alc882_adc_nids,
 -              .capsrc_nids = alc882_capsrc_nids,
 -              .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
 -              .channel_mode = alc882_3ST_6ch_modes,
 -              .need_dac_fix = 1,
 -              .input_mux = &alc882_capture_source,
 -      },
 -      [ALC882_ASUS_A7M] = {
 -              .mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer },
 -              .init_verbs = { alc882_init_verbs, alc882_eapd_verbs,
 -                              alc880_gpio1_init_verbs,
 -                              alc882_asus_a7m_verbs },
 -              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 -              .dac_nids = alc882_dac_nids,
 -              .dig_out_nid = ALC882_DIGOUT_NID,
 -              .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
 -              .channel_mode = alc880_threestack_modes,
 -              .need_dac_fix = 1,
 -              .input_mux = &alc882_capture_source,
 -      },
 -};
 -
 -
 -/*
 - * Pin config fixes
 - */
 -enum {
 -      PINFIX_ABIT_AW9D_MAX
 -};
 -
 -static struct alc_pincfg alc882_abit_aw9d_pinfix[] = {
 -      { 0x15, 0x01080104 }, /* side */
 -      { 0x16, 0x01011012 }, /* rear */
 -      { 0x17, 0x01016011 }, /* clfe */
 -      { }
 -};
 -
 -static const struct alc_pincfg *alc882_pin_fixes[] = {
 -      [PINFIX_ABIT_AW9D_MAX] = alc882_abit_aw9d_pinfix,
 -};
 -
 -static struct snd_pci_quirk alc882_pinfix_tbl[] = {
 -      SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
 -      {}
 -};
 -
 -/*
 - * BIOS auto configuration
 - */
 -static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
 -                                            hda_nid_t nid, int pin_type,
 -                                            int dac_idx)
 -{
 -      /* set as output */
 -      struct alc_spec *spec = codec->spec;
 -      int idx;
 -
 -      alc_set_pin_output(codec, nid, pin_type);
 -      if (spec->multiout.dac_nids[dac_idx] == 0x25)
 -              idx = 4;
 -      else
 -              idx = spec->multiout.dac_nids[dac_idx] - 2;
 -      snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
 -
 -}
 -
 -static void alc882_auto_init_multi_out(struct hda_codec *codec)
 -{
 -      struct alc_spec *spec = codec->spec;
 -      int i;
 -
 -      for (i = 0; i <= HDA_SIDE; i++) {
 -              hda_nid_t nid = spec->autocfg.line_out_pins[i];
 -              int pin_type = get_pin_type(spec->autocfg.line_out_type);
 -              if (nid)
 -                      alc882_auto_set_output_and_unmute(codec, nid, pin_type,
 -                                                        i);
 -      }
 -}
 -
 -static void alc882_auto_init_hp_out(struct hda_codec *codec)
 -{
 -      struct alc_spec *spec = codec->spec;
 -      hda_nid_t pin;
 -
 -      pin = spec->autocfg.hp_pins[0];
 -      if (pin) /* connect to front */
 -              /* use dac 0 */
 -              alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
 -      pin = spec->autocfg.speaker_pins[0];
 -      if (pin)
 -              alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 -}
 -
 -#define alc882_is_input_pin(nid)      alc880_is_input_pin(nid)
 -#define ALC882_PIN_CD_NID             ALC880_PIN_CD_NID
 -
 -static void alc882_auto_init_analog_input(struct hda_codec *codec)
 -{
 -      struct alc_spec *spec = codec->spec;
 -      int i;
 -
 -      for (i = 0; i < AUTO_PIN_LAST; i++) {
 -              hda_nid_t nid = spec->autocfg.input_pins[i];
 -              if (!nid)
 -                      continue;
 -              alc_set_input_pin(codec, nid, AUTO_PIN_FRONT_MIC /*i*/);
 -              if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
 -                      snd_hda_codec_write(codec, nid, 0,
 -                                          AC_VERB_SET_AMP_GAIN_MUTE,
 -                                          AMP_OUT_MUTE);
 -      }
 -}
 -
 -static void alc882_auto_init_input_src(struct hda_codec *codec)
 -{
 -      struct alc_spec *spec = codec->spec;
 -      int c;
 -
 -      for (c = 0; c < spec->num_adc_nids; c++) {
 -              hda_nid_t conn_list[HDA_MAX_NUM_INPUTS];
 -              hda_nid_t nid = spec->capsrc_nids[c];
 -              unsigned int mux_idx;
 -              const struct hda_input_mux *imux;
 -              int conns, mute, idx, item;
 -
 -              conns = snd_hda_get_connections(codec, nid, conn_list,
 -                                              ARRAY_SIZE(conn_list));
 -              if (conns < 0)
 -                      continue;
 -              mux_idx = c >= spec->num_mux_defs ? 0 : c;
 -              imux = &spec->input_mux[mux_idx];
 -              for (idx = 0; idx < conns; idx++) {
 -                      /* if the current connection is the selected one,
 -                       * unmute it as default - otherwise mute it
 -                       */
 -                      mute = AMP_IN_MUTE(idx);
 -                      for (item = 0; item < imux->num_items; item++) {
 -                              if (imux->items[item].index == idx) {
 -                                      if (spec->cur_mux[c] == item)
 -                                              mute = AMP_IN_UNMUTE(idx);
 -                                      break;
 -                              }
 -                      }
 -                      /* check if we have a selector or mixer
 -                       * we could check for the widget type instead, but
 -                       * just check for Amp-In presence (in case of mixer
 -                       * without amp-in there is something wrong, this
 -                       * function shouldn't be used or capsrc nid is wrong)
 -                       */
 -                      if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)
 -                              snd_hda_codec_write(codec, nid, 0,
 -                                                  AC_VERB_SET_AMP_GAIN_MUTE,
 -                                                  mute);
 -                      else if (mute != AMP_IN_MUTE(idx))
 -                              snd_hda_codec_write(codec, nid, 0,
 -                                                  AC_VERB_SET_CONNECT_SEL,
 -                                                  idx);
 -              }
 -      }
 -}
 -
 -/* add mic boosts if needed */
 -static int alc_auto_add_mic_boost(struct hda_codec *codec)
 -{
 -      struct alc_spec *spec = codec->spec;
 -      int err;
 -      hda_nid_t nid;
 -
 -      nid = spec->autocfg.input_pins[AUTO_PIN_MIC];
 -      if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) {
 -              err = add_control(spec, ALC_CTL_WIDGET_VOL,
 -                                "Mic Boost",
 -                                HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
 -              if (err < 0)
 -                      return err;
 -      }
 -      nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC];
 -      if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) {
 -              err = add_control(spec, ALC_CTL_WIDGET_VOL,
 -                                "Front Mic Boost",
 -                                HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
 -              if (err < 0)
 -                      return err;
 -      }
 -      return 0;
 -}
 -
 -/* almost identical with ALC880 parser... */
 -static int alc882_parse_auto_config(struct hda_codec *codec)
 -{
 -      struct alc_spec *spec = codec->spec;
 -      int err = alc880_parse_auto_config(codec);
 -
 -      if (err < 0)
 -              return err;
 -      else if (!err)
 -              return 0; /* no config found */
 -
 -      err = alc_auto_add_mic_boost(codec);
 -      if (err < 0)
 -              return err;
 -
 -      /* hack - override the init verbs */
 -      spec->init_verbs[0] = alc882_auto_init_verbs;
 -
 -      return 1; /* config found */
 -}
 -
 -/* additional initialization for auto-configuration model */
 -static void alc882_auto_init(struct hda_codec *codec)
 -{
 -      struct alc_spec *spec = codec->spec;
 -      alc882_auto_init_multi_out(codec);
 -      alc882_auto_init_hp_out(codec);
 -      alc882_auto_init_analog_input(codec);
 -      alc882_auto_init_input_src(codec);
 -      if (spec->unsol_event)
 -              alc_inithook(codec);
 -}
 -
 -static int patch_alc883(struct hda_codec *codec); /* called in patch_alc882() */
 -
 -static int patch_alc882(struct hda_codec *codec)
 -{
 -      struct alc_spec *spec;
 -      int err, board_config;
 -
 -      spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 -      if (spec == NULL)
 -              return -ENOMEM;
 -
 -      codec->spec = spec;
 -
 -      board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST,
 -                                                alc882_models,
 -                                                alc882_cfg_tbl);
 -
 -      if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
 -              /* Pick up systems that don't supply PCI SSID */
 -              switch (codec->subsystem_id) {
 -              case 0x106b0c00: /* Mac Pro */
 -                      board_config = ALC885_MACPRO;
 -                      break;
 -              case 0x106b1000: /* iMac 24 */
 -              case 0x106b2800: /* AppleTV */
 -              case 0x106b3e00: /* iMac 24 Aluminium */
 -                      board_config = ALC885_IMAC24;
 -                      break;
 -              case 0x106b00a0: /* MacBookPro3,1 - Another revision */
 -              case 0x106b00a1: /* Macbook (might be wrong - PCI SSID?) */
 -              case 0x106b00a4: /* MacbookPro4,1 */
 -              case 0x106b2c00: /* Macbook Pro rev3 */
 -              /* Macbook 3.1 (0x106b3600) is handled by patch_alc883() */
 -              case 0x106b3800: /* MacbookPro4,1 - latter revision */
 -                      board_config = ALC885_MBP3;
 -                      break;
 -              case 0x106b3f00: /* Macbook 5,1 */
 -              case 0x106b4000: /* Macbook Pro 5,1 - FIXME: HP jack sense
 -                                *   seems not working, so apparently
 -                                *   no perfect solution yet
 -                                */
 -                      board_config = ALC885_MB5;
 -                      break;
 -              default:
 -                      /* ALC889A is handled better as ALC888-compatible */
 -                      if (codec->revision_id == 0x100101 ||
 -                          codec->revision_id == 0x100103) {
 -                              alc_free(codec);
 -                              return patch_alc883(codec);
 -                      }
 -                      printk(KERN_INFO "hda_codec: Unknown model for %s, "
 -                             "trying auto-probe from BIOS...\n",
 -                             codec->chip_name);
 -                      board_config = ALC882_AUTO;
 -              }
 -      }
 -
 -      alc_fix_pincfg(codec, alc882_pinfix_tbl, alc882_pin_fixes);
 -
 -      if (board_config == ALC882_AUTO) {
 -              /* automatic parse from the BIOS config */
 -              err = alc882_parse_auto_config(codec);
 -              if (err < 0) {
 -                      alc_free(codec);
 -                      return err;
 -              } else if (!err) {
 -                      printk(KERN_INFO
 -                             "hda_codec: Cannot set up configuration "
 -                             "from BIOS.  Using base mode...\n");
 -                      board_config = ALC882_3ST_DIG;
 -              }
 -      }
 -
 -      err = snd_hda_attach_beep_device(codec, 0x1);
 -      if (err < 0) {
 -              alc_free(codec);
 -              return err;
 -      }
 -
 -      if (board_config != ALC882_AUTO)
 -              setup_preset(spec, &alc882_presets[board_config]);
 -
 -      spec->stream_analog_playback = &alc882_pcm_analog_playback;
 -      spec->stream_analog_capture = &alc882_pcm_analog_capture;
 -      /* FIXME: setup DAC5 */
 -      /*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/
 -      spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
 -
 -      spec->stream_digital_playback = &alc882_pcm_digital_playback;
 -      spec->stream_digital_capture = &alc882_pcm_digital_capture;
 -
 -      if (!spec->adc_nids && spec->input_mux) {
 -              /* check whether NID 0x07 is valid */
 -              unsigned int wcap = get_wcaps(codec, 0x07);
 -              /* get type */
 -              wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 -              if (wcap != AC_WID_AUD_IN) {
 -                      spec->adc_nids = alc882_adc_nids_alt;
 -                      spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
 -                      spec->capsrc_nids = alc882_capsrc_nids_alt;
 -              } else {
 -                      spec->adc_nids = alc882_adc_nids;
 -                      spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
 -                      spec->capsrc_nids = alc882_capsrc_nids;
 -              }
 -      }
 -      set_capture_mixer(spec);
 -      set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 -
 -      spec->vmaster_nid = 0x0c;
 -
 -      codec->patch_ops = alc_patch_ops;
 -      if (board_config == ALC882_AUTO)
 -              spec->init_hook = alc882_auto_init;
 -#ifdef CONFIG_SND_HDA_POWER_SAVE
 -      if (!spec->loopback.amplist)
 -              spec->loopback.amplist = alc882_loopbacks;
 -#endif
 -      codec->proc_widget_hook = print_realtek_coef;
 -
 -      return 0;
 -}
 -
 -/*
 - * ALC883 support
 - *
 - * ALC883 is almost identical with ALC880 but has cleaner and more flexible
 - * configuration.  Each pin widget can choose any input DACs and a mixer.
 - * Each ADC is connected from a mixer of all inputs.  This makes possible
 - * 6-channel independent captures.
 - *
 - * In addition, an independent DAC for the multi-playback (not used in this
 - * driver yet).
 - */
 -#define ALC883_DIGOUT_NID     0x06
 -#define ALC883_DIGIN_NID      0x0a
 -
 -#define ALC1200_DIGOUT_NID    0x10
 -
 -static hda_nid_t alc883_dac_nids[4] = {
 -      /* front, rear, clfe, rear_surr */
 -      0x02, 0x03, 0x04, 0x05
 -};
 -
 -static hda_nid_t alc883_adc_nids[2] = {
 -      /* ADC1-2 */
 -      0x08, 0x09,
 -};
 -
 -static hda_nid_t alc883_adc_nids_alt[1] = {
 -      /* ADC1 */
 -      0x08,
 -};
 -
 -static hda_nid_t alc883_adc_nids_rev[2] = {
 -      /* ADC2-1 */
 -      0x09, 0x08
 -};
 -
 -#define alc889_adc_nids               alc880_adc_nids
 -
 -static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 };
 -
 -static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 };
 -
 -#define alc889_capsrc_nids    alc882_capsrc_nids
 -
 -/* input MUX */
 -/* FIXME: should be a matrix-type input source selection */
 -
 -static struct hda_input_mux alc883_capture_source = {
 -      .num_items = 4,
 -      .items = {
 -              { "Mic", 0x0 },
 -              { "Front Mic", 0x1 },
 -              { "Line", 0x2 },
 -              { "CD", 0x4 },
 -      },
 -};
 -
 -static struct hda_input_mux alc883_3stack_6ch_intel = {
 -      .num_items = 4,
 -      .items = {
 -              { "Mic", 0x1 },
 -              { "Front Mic", 0x0 },
 -              { "Line", 0x2 },
 -              { "CD", 0x4 },
 -      },
 -};
 -
 -static struct hda_input_mux alc883_lenovo_101e_capture_source = {
 -      .num_items = 2,
 -      .items = {
 -              { "Mic", 0x1 },
 -              { "Line", 0x2 },
 -      },
 -};
 -
 -static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
 -      .num_items = 4,
 -      .items = {
 -              { "Mic", 0x0 },
 -              { "iMic", 0x1 },
 -              { "Line", 0x2 },
 -              { "CD", 0x4 },
 -      },
 -};
 -
 -static struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
 -      .num_items = 2,
 -      .items = {
 -              { "Mic", 0x0 },
 -              { "Int Mic", 0x1 },
 -      },
 -};
 -
 -static struct hda_input_mux alc883_lenovo_sky_capture_source = {
 -      .num_items = 3,
 -      .items = {
 -              { "Mic", 0x0 },
 -              { "Front Mic", 0x1 },
 -              { "Line", 0x4 },
 -      },
 -};
 -
 -static struct hda_input_mux alc883_asus_eee1601_capture_source = {
 -      .num_items = 2,
 -      .items = {
 -              { "Mic", 0x0 },
 -              { "Line", 0x2 },
 -      },
 -};
 -
 -static struct hda_input_mux alc889A_mb31_capture_source = {
 -      .num_items = 2,
 -      .items = {
 -              { "Mic", 0x0 },
 -              /* Front Mic (0x01) unused */
 -              { "Line", 0x2 },
 -              /* Line 2 (0x03) unused */
 -              /* CD (0x04) unsused? */
 -      },
 -};
 -
 -/*
 - * 2ch mode
 - */
 -static struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
 -      { 2, NULL }
 -};
 -
 -/*
 - * 2ch mode
 - */
 -static struct hda_verb alc883_3ST_ch2_init[] = {
 -      { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 -      { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 -      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
 -      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 -      { } /* end */
 -};
 -
 -/*
 - * 4ch mode
 - */
 -static struct hda_verb alc883_3ST_ch4_init[] = {
 -      { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 -      { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 -      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 -      { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
 -      { } /* end */
 -};
 -
 -/*
 - * 6ch mode
 - */
 -static struct hda_verb alc883_3ST_ch6_init[] = {
 -      { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 -      { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
 -      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 -      { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
 -      { } /* end */
 -};
 -
 -static struct hda_channel_mode alc883_3ST_6ch_modes[3] = {
 -      { 2, alc883_3ST_ch2_init },
 -      { 4, alc883_3ST_ch4_init },
 -      { 6, alc883_3ST_ch6_init },
 -};
 -
 -
 -/*
 - * 2ch mode
 - */
 -static struct hda_verb alc883_4ST_ch2_init[] = {
 -      { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 -      { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 -      { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 -      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
 -      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 -      { } /* end */
 -};
 -
 -/*
 - * 4ch mode
 - */
 -static struct hda_verb alc883_4ST_ch4_init[] = {
 -      { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 -      { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 -      { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 -      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 -      { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
 -      { } /* end */
 -};
 -
 -/*
 - * 6ch mode
 - */
 -static struct hda_verb alc883_4ST_ch6_init[] = {
 -      { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 -      { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 -      { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
 -      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 -      { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
 -      { } /* end */
 -};
 -
 -/*
 - * 8ch mode
 - */
 -static struct hda_verb alc883_4ST_ch8_init[] = {
 -      { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 -      { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
 -      { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 -      { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
 -      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 -      { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
 -      { } /* end */
 -};
 -
 -static struct hda_channel_mode alc883_4ST_8ch_modes[4] = {
 -      { 2, alc883_4ST_ch2_init },
 -      { 4, alc883_4ST_ch4_init },
 -      { 6, alc883_4ST_ch6_init },
 -      { 8, alc883_4ST_ch8_init },
 -};
 -
 -
 -/*
 - * 2ch mode
 - */
 -static struct hda_verb alc883_3ST_ch2_intel_init[] = {
 -      { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 -      { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 -      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
 -      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 -      { } /* end */
 -};
 -
 -/*
 - * 4ch mode
 - */
 -static struct hda_verb alc883_3ST_ch4_intel_init[] = {
 -      { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 -      { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
 -      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 -      { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
 -      { } /* end */
 -};
 -
 -/*
 - * 6ch mode
 - */
 -static struct hda_verb alc883_3ST_ch6_intel_init[] = {
 -      { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 -      { 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 },
 -      { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
 -      { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
 -      { } /* end */
 -};
 -
 -static struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
 -      { 2, alc883_3ST_ch2_intel_init },
 -      { 4, alc883_3ST_ch4_intel_init },
 -      { 6, alc883_3ST_ch6_intel_init },
 -};
 -
 -/*
 - * 6ch mode
 - */
 -static struct hda_verb alc883_sixstack_ch6_init[] = {
 -      { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
 -      { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { } /* end */
 -};
 +{
 +      alc885_macpro_init_hook(codec);
 +      alc885_imac24_automute_init_hook(codec);
 +}
  
  /*
 - * 8ch mode
 + * generic initialization of ADC, input mixers and output mixers
   */
 -static struct hda_verb alc883_sixstack_ch8_init[] = {
 -      { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 -      { } /* end */
 -};
 +static struct hda_verb alc883_auto_init_verbs[] = {
 +      /*
 +       * Unmute ADC0-2 and set the default input to mic-in
 +       */
 +      {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
 +      {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 +      {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
 +      {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  
 -static struct hda_channel_mode alc883_sixstack_modes[2] = {
 -      { 6, alc883_sixstack_ch6_init },
 -      { 8, alc883_sixstack_ch8_init },
 +      /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
 +       * mixer widget
 +       * Note: PASD motherboards uses the Line In 2 as the input for
 +       * front panel mic (mic 2)
 +       */
 +      /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
 +      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 +      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
 +      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
 +      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
 +
 +      /*
 +       * Set up output mixers (0x0c - 0x0f)
 +       */
 +      /* set vol=0 to output mixers */
 +      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 +      {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 +      {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 +      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 +      /* set up input amps for analog loopback */
 +      /* Amp Indices: DAC = 0, mixer = 1 */
 +      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 +      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 +      {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 +      {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 +      {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 +      {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 +      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 +      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 +      {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 +      {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 +
 +      /* FIXME: use matrix-type input source selection */
 +      /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
 +      /* Input mixer2 */
 +      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
 +      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
 +      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
 +      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
 +      /* Input mixer3 */
 +      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
 +      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
 +      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
 +      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
 +
 +      { }
  };
  
  /* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */
@@@ -7565,7 -7966,34 +7565,7 @@@ static struct hda_verb alc883_medion_ea
        { }
  };
  
 -/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
 - *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
 - */
 -
 -static struct snd_kcontrol_new alc883_base_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("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
 -      HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
 -      HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 -      HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, 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),
 -      HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
 -      HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
 -      HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
 -      { } /* end */
 -};
 +#define alc883_base_mixer     alc882_base_mixer
  
  static struct snd_kcontrol_new alc883_mitac_mixer[] = {
        HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
@@@ -7676,30 -8104,6 +7676,30 @@@ static struct snd_kcontrol_new alc883_3
        { } /* end */
  };
  
 +static struct snd_kcontrol_new alc885_8ch_intel_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("Speaker Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
 +      HDA_BIND_MUTE("Speaker Playback Switch", 0x0f, 2, HDA_INPUT),
 +      HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
 +      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, 0x3, HDA_INPUT),
 +      HDA_CODEC_VOLUME("Mic Boost", 0x1b, 0, HDA_INPUT),
 +      HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
 +      HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
 +      HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT),
 +      HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
 +      { } /* end */
 +};
 +
  static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
        HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
        HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@@ -7940,6 -8344,84 +7940,6 @@@ static struct snd_kcontrol_new alc883_c
        { } /* end */
  };
  
 -static struct hda_verb alc883_init_verbs[] = {
 -      /* ADC1: mute amp left and right */
 -      {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
 -      /* ADC2: mute amp left and right */
 -      {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 -      {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
 -      /* Front mixer: unmute input/output amp left and right (volume = 0) */
 -      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 -      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 -      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 -      /* Rear mixer */
 -      {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 -      {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 -      {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 -      /* CLFE mixer */
 -      {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 -      {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 -      {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 -      /* Side mixer */
 -      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 -      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 -      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 -
 -      /* mute analog input loopbacks */
 -      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 -      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 -      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
 -      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
 -      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
 -
 -      /* Front Pin: output 0 (0x0c) */
 -      {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, 0x00},
 -      /* Rear Pin: output 1 (0x0d) */
 -      {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 -      {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 -      {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
 -      /* CLFE Pin: output 2 (0x0e) */
 -      {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 -      {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 -      {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
 -      /* Side Pin: output 3 (0x0f) */
 -      {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 -      {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 -      {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
 -      /* Mic (rear) pin: input vref at 80% */
 -      {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
 -      {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 -      /* 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},
 -      /* Line In pin: input */
 -      {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 -      {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 -      /* Line-2 In: Headphone output (output 0 - 0x0c) */
 -      {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
 -      {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 -      {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
 -      /* CD pin widget for input */
 -      {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 -
 -      /* FIXME: use matrix-type input source selection */
 -      /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
 -      /* Input mixer2 */
 -      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 -      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
 -      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
 -      /* Input mixer3 */
 -      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 -      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
 -      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
 -      { }
 -};
 -
  /* toggle speaker-output according to the hp-jack state */
  static void alc883_mitac_init_hook(struct hda_codec *codec)
  {
@@@ -8366,11 -8848,74 +8366,11 @@@ static void alc883_vaiott_init_hook(str
  {
        struct alc_spec *spec = codec->spec;
  
 -      spec->autocfg.hp_pins[0] = 0x15;
 -      spec->autocfg.speaker_pins[0] = 0x14;
 -      spec->autocfg.speaker_pins[1] = 0x17;
 -      alc_automute_amp(codec);
 -}
 -
 -/*
 - * generic initialization of ADC, input mixers and output mixers
 - */
 -static struct hda_verb alc883_auto_init_verbs[] = {
 -      /*
 -       * Unmute ADC0-2 and set the default input to mic-in
 -       */
 -      {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
 -      {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
 -      {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -
 -      /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
 -       * mixer widget
 -       * Note: PASD motherboards uses the Line In 2 as the input for
 -       * front panel mic (mic 2)
 -       */
 -      /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
 -      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 -      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 -      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
 -      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
 -      {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
 -
 -      /*
 -       * Set up output mixers (0x0c - 0x0f)
 -       */
 -      /* set vol=0 to output mixers */
 -      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 -      {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 -      {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 -      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 -      /* set up input amps for analog loopback */
 -      /* Amp Indices: DAC = 0, mixer = 1 */
 -      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -      {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -      {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -      {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -
 -      /* FIXME: use matrix-type input source selection */
 -      /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
 -      /* Input mixer1 */
 -      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
 -      /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */
 -      {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
 -      /* Input mixer2 */
 -      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
 -      /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */
 -      {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
 -
 -      { }
 -};
 +      spec->autocfg.hp_pins[0] = 0x15;
 +      spec->autocfg.speaker_pins[0] = 0x14;
 +      spec->autocfg.speaker_pins[1] = 0x17;
 +      alc_automute_amp(codec);
 +}
  
  static struct hda_verb alc888_asus_m90v_verbs[] = {
        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
@@@ -8482,44 -9027,25 +8482,44 @@@ static void alc889A_mb31_unsol_event(st
                alc889A_mb31_automute(codec);
  }
  
 +
  #ifdef CONFIG_SND_HDA_POWER_SAVE
 -#define alc883_loopbacks      alc880_loopbacks
 +#define alc882_loopbacks      alc880_loopbacks
  #endif
  
  /* pcm configuration: identical with ALC880 */
 -#define alc883_pcm_analog_playback    alc880_pcm_analog_playback
 -#define alc883_pcm_analog_capture     alc880_pcm_analog_capture
 -#define alc883_pcm_analog_alt_capture alc880_pcm_analog_alt_capture
 -#define alc883_pcm_digital_playback   alc880_pcm_digital_playback
 -#define alc883_pcm_digital_capture    alc880_pcm_digital_capture
 +#define alc882_pcm_analog_playback    alc880_pcm_analog_playback
 +#define alc882_pcm_analog_capture     alc880_pcm_analog_capture
 +#define alc882_pcm_digital_playback   alc880_pcm_digital_playback
 +#define alc882_pcm_digital_capture    alc880_pcm_digital_capture
 +
 +static hda_nid_t alc883_slave_dig_outs[] = {
 +      ALC1200_DIGOUT_NID, 0,
 +};
 +
 +static hda_nid_t alc1200_slave_dig_outs[] = {
 +      ALC883_DIGOUT_NID, 0,
 +};
  
  /*
   * configuration and preset
   */
 -static const char *alc883_models[ALC883_MODEL_LAST] = {
 -      [ALC883_3ST_2ch_DIG]    = "3stack-dig",
 +static const char *alc882_models[ALC882_MODEL_LAST] = {
 +      [ALC882_3ST_DIG]        = "3stack-dig",
 +      [ALC882_6ST_DIG]        = "6stack-dig",
 +      [ALC882_ARIMA]          = "arima",
 +      [ALC882_W2JC]           = "w2jc",
 +      [ALC882_TARGA]          = "targa",
 +      [ALC882_ASUS_A7J]       = "asus-a7j",
 +      [ALC882_ASUS_A7M]       = "asus-a7m",
 +      [ALC885_MACPRO]         = "macpro",
 +      [ALC885_MB5]            = "mb5",
 +      [ALC885_MBP3]           = "mbp3",
 +      [ALC885_IMAC24]         = "imac24",
 +      [ALC883_3ST_2ch_DIG]    = "3stack-2ch-dig",
        [ALC883_3ST_6ch_DIG]    = "3stack-6ch-dig",
        [ALC883_3ST_6ch]        = "3stack-6ch",
 -      [ALC883_6ST_DIG]        = "6stack-dig",
 +      [ALC883_6ST_DIG]        = "alc883-6stack-dig",
        [ALC883_TARGA_DIG]      = "targa-dig",
        [ALC883_TARGA_2ch_DIG]  = "targa-2ch-dig",
        [ALC883_TARGA_8ch_DIG]  = "targa-8ch-dig",
        [ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
        [ALC888_FUJITSU_XA3530] = "fujitsu-xa3530",
        [ALC883_3ST_6ch_INTEL]  = "3stack-6ch-intel",
 +      [ALC889A_INTEL]         = "intel-alc889a",
 +      [ALC889_INTEL]          = "intel-x58",
        [ALC1200_ASUS_P5Q]      = "asus-p5q",
        [ALC889A_MB31]          = "mb31",
        [ALC883_SONY_VAIO_TT]   = "sony-vaio-tt",
 -      [ALC883_AUTO]           = "auto",
 +      [ALC882_AUTO]           = "auto",
  };
  
 -static struct snd_pci_quirk alc883_cfg_tbl[] = {
 -      SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG),
 +static struct snd_pci_quirk alc882_cfg_tbl[] = {
 +      SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
 +
        SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_ACER_ASPIRE),
                ALC888_ACER_ASPIRE_8930G),
        SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
                ALC888_ACER_ASPIRE_8930G),
 -      SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC883_AUTO),
 -      SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC883_AUTO),
 +      SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC882_AUTO),
 +      SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC882_AUTO),
        SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
                ALC888_ACER_ASPIRE_6530G),
        SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
         *    model=auto should work fine now
         */
        /* SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER), */
 +
        SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
 +
        SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
        SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
        SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
        SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
        SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP),
        SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", ALC888_3ST_HP),
 +
 +      SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J),
 +      SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J),
 +      SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M),
        SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
 +      SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),
 +      SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
 +      SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
        SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG),
        SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q),
        SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601),
 +
 +      SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC883_SONY_VAIO_TT),
        SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG),
 -      SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
 +      SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
        SND_PCI_QUIRK(0x1071, 0x8227, "Mitac 82801H", ALC883_MITAC),
        SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
        SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
        SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
        SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
 -      SND_PCI_QUIRK(0x1458, 0xa002, "MSI", ALC883_6ST_DIG),
 +      SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
 +
        SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
        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, 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),
        SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
        SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
        SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
        SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG),
 +      SND_PCI_QUIRK(0x1462, 0x42cd, "MSI", ALC883_TARGA_DIG),
        SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
        SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
        SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
        SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
        SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG),
        SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
 +      SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG),
 +
        SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
        SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
        SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
        SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD),
        SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
 +      /* SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), */
        SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
        SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1100, "FSC AMILO Xi/Pi25xx",
                      ALC883_FUJITSU_PI2515),
        SND_PCI_QUIRK(0x17c0, 0x4085, "MEDION MD96630", ALC888_LENOVO_MS7195_DIG),
        SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG),
        SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
 +
        SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
        SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL),
        SND_PCI_QUIRK(0x8086, 0x2503, "82801H", ALC883_MITAC),
 -      SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC883_3ST_6ch_INTEL),
 +      SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL),
 +      SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL),
 +      SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL),
        SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
 -      SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC883_SONY_VAIO_TT),
 -      {}
 -};
  
 -static hda_nid_t alc883_slave_dig_outs[] = {
 -      ALC1200_DIGOUT_NID, 0,
 +      {}
  };
  
 -static hda_nid_t alc1200_slave_dig_outs[] = {
 -      ALC883_DIGOUT_NID, 0,
 +/* codec SSID table for Intel Mac */
 +static struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
 +      SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3),
 +      SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3),
 +      SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3),
 +      SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_MACPRO),
 +      SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_IMAC24),
 +      SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24),
 +      SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3),
 +      SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31),
 +      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
 +       */
 +      SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5),
 +      {} /* terminator */
  };
  
 -static struct alc_config_preset alc883_presets[] = {
 +static struct alc_config_preset alc882_presets[] = {
 +      [ALC882_3ST_DIG] = {
 +              .mixers = { alc882_base_mixer },
 +              .init_verbs = { alc882_base_init_verbs,
 +                              alc882_adc1_init_verbs },
 +              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 +              .dac_nids = alc882_dac_nids,
 +              .dig_out_nid = ALC882_DIGOUT_NID,
 +              .dig_in_nid = ALC882_DIGIN_NID,
 +              .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
 +              .channel_mode = alc882_ch_modes,
 +              .need_dac_fix = 1,
 +              .input_mux = &alc882_capture_source,
 +      },
 +      [ALC882_6ST_DIG] = {
 +              .mixers = { alc882_base_mixer, alc882_chmode_mixer },
 +              .init_verbs = { alc882_base_init_verbs,
 +                              alc882_adc1_init_verbs },
 +              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 +              .dac_nids = alc882_dac_nids,
 +              .dig_out_nid = ALC882_DIGOUT_NID,
 +              .dig_in_nid = ALC882_DIGIN_NID,
 +              .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
 +              .channel_mode = alc882_sixstack_modes,
 +              .input_mux = &alc882_capture_source,
 +      },
 +      [ALC882_ARIMA] = {
 +              .mixers = { alc882_base_mixer, alc882_chmode_mixer },
 +              .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
 +                              alc882_eapd_verbs },
 +              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 +              .dac_nids = alc882_dac_nids,
 +              .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
 +              .channel_mode = alc882_sixstack_modes,
 +              .input_mux = &alc882_capture_source,
 +      },
 +      [ALC882_W2JC] = {
 +              .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer },
 +              .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
 +                              alc882_eapd_verbs, alc880_gpio1_init_verbs },
 +              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 +              .dac_nids = alc882_dac_nids,
 +              .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
 +              .channel_mode = alc880_threestack_modes,
 +              .need_dac_fix = 1,
 +              .input_mux = &alc882_capture_source,
 +              .dig_out_nid = ALC882_DIGOUT_NID,
 +      },
 +      [ALC885_MBP3] = {
 +              .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
 +              .init_verbs = { alc885_mbp3_init_verbs,
 +                              alc880_gpio1_init_verbs },
 +              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 +              .dac_nids = alc882_dac_nids,
 +              .channel_mode = alc885_mbp_6ch_modes,
 +              .num_channel_mode = ARRAY_SIZE(alc885_mbp_6ch_modes),
 +              .input_mux = &alc882_capture_source,
 +              .dig_out_nid = ALC882_DIGOUT_NID,
 +              .dig_in_nid = ALC882_DIGIN_NID,
 +              .unsol_event = alc_automute_amp_unsol_event,
 +              .init_hook = alc885_mbp3_init_hook,
 +      },
 +      [ALC885_MB5] = {
 +              .mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
 +              .init_verbs = { alc885_mb5_init_verbs,
 +                              alc880_gpio1_init_verbs },
 +              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 +              .dac_nids = alc882_dac_nids,
 +              .channel_mode = alc885_mb5_6ch_modes,
 +              .num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes),
 +              .input_mux = &mb5_capture_source,
 +              .dig_out_nid = ALC882_DIGOUT_NID,
 +              .dig_in_nid = ALC882_DIGIN_NID,
 +      },
 +      [ALC885_MACPRO] = {
 +              .mixers = { alc882_macpro_mixer },
 +              .init_verbs = { alc882_macpro_init_verbs },
 +              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 +              .dac_nids = alc882_dac_nids,
 +              .dig_out_nid = ALC882_DIGOUT_NID,
 +              .dig_in_nid = ALC882_DIGIN_NID,
 +              .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
 +              .channel_mode = alc882_ch_modes,
 +              .input_mux = &alc882_capture_source,
 +              .init_hook = alc885_macpro_init_hook,
 +      },
 +      [ALC885_IMAC24] = {
 +              .mixers = { alc885_imac24_mixer },
 +              .init_verbs = { alc885_imac24_init_verbs },
 +              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 +              .dac_nids = alc882_dac_nids,
 +              .dig_out_nid = ALC882_DIGOUT_NID,
 +              .dig_in_nid = ALC882_DIGIN_NID,
 +              .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
 +              .channel_mode = alc882_ch_modes,
 +              .input_mux = &alc882_capture_source,
 +              .unsol_event = alc_automute_amp_unsol_event,
 +              .init_hook = alc885_imac24_init_hook,
 +      },
 +      [ALC882_TARGA] = {
 +              .mixers = { alc882_targa_mixer, alc882_chmode_mixer },
 +              .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
 +                              alc880_gpio3_init_verbs, alc882_targa_verbs},
 +              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 +              .dac_nids = alc882_dac_nids,
 +              .dig_out_nid = ALC882_DIGOUT_NID,
 +              .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
 +              .adc_nids = alc882_adc_nids,
 +              .capsrc_nids = alc882_capsrc_nids,
 +              .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
 +              .channel_mode = alc882_3ST_6ch_modes,
 +              .need_dac_fix = 1,
 +              .input_mux = &alc882_capture_source,
 +              .unsol_event = alc882_targa_unsol_event,
 +              .init_hook = alc882_targa_init_hook,
 +      },
 +      [ALC882_ASUS_A7J] = {
 +              .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer },
 +              .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
 +                              alc882_asus_a7j_verbs},
 +              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 +              .dac_nids = alc882_dac_nids,
 +              .dig_out_nid = ALC882_DIGOUT_NID,
 +              .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
 +              .adc_nids = alc882_adc_nids,
 +              .capsrc_nids = alc882_capsrc_nids,
 +              .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
 +              .channel_mode = alc882_3ST_6ch_modes,
 +              .need_dac_fix = 1,
 +              .input_mux = &alc882_capture_source,
 +      },
 +      [ALC882_ASUS_A7M] = {
 +              .mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer },
 +              .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
 +                              alc882_eapd_verbs, alc880_gpio1_init_verbs,
 +                              alc882_asus_a7m_verbs },
 +              .num_dacs = ARRAY_SIZE(alc882_dac_nids),
 +              .dac_nids = alc882_dac_nids,
 +              .dig_out_nid = ALC882_DIGOUT_NID,
 +              .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
 +              .channel_mode = alc880_threestack_modes,
 +              .need_dac_fix = 1,
 +              .input_mux = &alc882_capture_source,
 +      },
        [ALC883_3ST_2ch_DIG] = {
                .mixers = { alc883_3ST_2ch_mixer },
                .init_verbs = { alc883_init_verbs },
                .need_dac_fix = 1,
                .input_mux = &alc883_3stack_6ch_intel,
        },
 +      [ALC889A_INTEL] = {
 +              .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
 +              .init_verbs = { alc885_init_verbs, alc885_init_input_verbs,
 +                              alc_hp15_unsol_verbs },
 +              .num_dacs = ARRAY_SIZE(alc883_dac_nids),
 +              .dac_nids = alc883_dac_nids,
 +              .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
 +              .adc_nids = alc889_adc_nids,
 +              .dig_out_nid = ALC883_DIGOUT_NID,
 +              .dig_in_nid = ALC883_DIGIN_NID,
 +              .slave_dig_outs = alc883_slave_dig_outs,
 +              .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
 +              .channel_mode = alc889_8ch_intel_modes,
 +              .capsrc_nids = alc889_capsrc_nids,
 +              .input_mux = &alc889_capture_source,
 +              .init_hook = alc889_automute_init,
 +              .unsol_event = alc_automute_amp_unsol_event,
 +              .need_dac_fix = 1,
 +      },
 +      [ALC889_INTEL] = {
 +              .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
 +              .init_verbs = { alc885_init_verbs, alc889_init_input_verbs,
 +                              alc889_eapd_verbs, alc_hp15_unsol_verbs},
 +              .num_dacs = ARRAY_SIZE(alc883_dac_nids),
 +              .dac_nids = alc883_dac_nids,
 +              .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
 +              .adc_nids = alc889_adc_nids,
 +              .dig_out_nid = ALC883_DIGOUT_NID,
 +              .dig_in_nid = ALC883_DIGIN_NID,
 +              .slave_dig_outs = alc883_slave_dig_outs,
 +              .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
 +              .channel_mode = alc889_8ch_intel_modes,
 +              .capsrc_nids = alc889_capsrc_nids,
 +              .input_mux = &alc889_capture_source,
 +              .init_hook = alc889_intel_init_hook,
 +              .unsol_event = alc_automute_amp_unsol_event,
 +              .need_dac_fix = 1,
 +      },
        [ALC883_6ST_DIG] = {
                .mixers = { alc883_base_mixer, alc883_chmode_mixer },
                .init_verbs = { alc883_init_verbs },
  };
  
  
 +/*
 + * Pin config fixes
 + */
 +enum {
 +      PINFIX_ABIT_AW9D_MAX
 +};
 +
 +static struct alc_pincfg alc882_abit_aw9d_pinfix[] = {
 +      { 0x15, 0x01080104 }, /* side */
 +      { 0x16, 0x01011012 }, /* rear */
 +      { 0x17, 0x01016011 }, /* clfe */
 +      { }
 +};
 +
 +static const struct alc_pincfg *alc882_pin_fixes[] = {
 +      [PINFIX_ABIT_AW9D_MAX] = alc882_abit_aw9d_pinfix,
 +};
 +
 +static struct snd_pci_quirk alc882_pinfix_tbl[] = {
 +      SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
 +      {}
 +};
 +
  /*
   * BIOS auto configuration
   */
 -static void alc883_auto_set_output_and_unmute(struct hda_codec *codec,
 +static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
                                              hda_nid_t nid, int pin_type,
                                              int dac_idx)
  {
  
  }
  
 -static void alc883_auto_init_multi_out(struct hda_codec *codec)
 +static void alc882_auto_init_multi_out(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
        int i;
                hda_nid_t nid = spec->autocfg.line_out_pins[i];
                int pin_type = get_pin_type(spec->autocfg.line_out_type);
                if (nid)
 -                      alc883_auto_set_output_and_unmute(codec, nid, pin_type,
 +                      alc882_auto_set_output_and_unmute(codec, nid, pin_type,
                                                          i);
        }
  }
  
 -static void alc883_auto_init_hp_out(struct hda_codec *codec)
 +static void alc882_auto_init_hp_out(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
        hda_nid_t pin;
        pin = spec->autocfg.hp_pins[0];
        if (pin) /* connect to front */
                /* use dac 0 */
 -              alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
 +              alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
        pin = spec->autocfg.speaker_pins[0];
        if (pin)
 -              alc883_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 +              alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 +}
 +
 +static void alc882_auto_init_analog_input(struct hda_codec *codec)
 +{
 +      struct alc_spec *spec = codec->spec;
 +      int i;
 +
 +      for (i = 0; i < AUTO_PIN_LAST; i++) {
 +              hda_nid_t nid = spec->autocfg.input_pins[i];
 +              if (!nid)
 +                      continue;
 +              alc_set_input_pin(codec, nid, i);
 +              if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
 +                      snd_hda_codec_write(codec, nid, 0,
 +                                          AC_VERB_SET_AMP_GAIN_MUTE,
 +                                          AMP_OUT_MUTE);
 +      }
  }
  
 -#define alc883_is_input_pin(nid)      alc880_is_input_pin(nid)
 -#define ALC883_PIN_CD_NID             ALC880_PIN_CD_NID
 -
 -static void alc883_auto_init_analog_input(struct hda_codec *codec)
 +static void alc882_auto_init_input_src(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
 -      int i;
 +      int c;
  
 -      for (i = 0; i < AUTO_PIN_LAST; i++) {
 -              hda_nid_t nid = spec->autocfg.input_pins[i];
 -              if (alc883_is_input_pin(nid)) {
 -                      alc_set_input_pin(codec, nid, i);
 -                      if (nid != ALC883_PIN_CD_NID &&
 -                          (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
 +      for (c = 0; c < spec->num_adc_nids; c++) {
 +              hda_nid_t conn_list[HDA_MAX_NUM_INPUTS];
 +              hda_nid_t nid = spec->capsrc_nids[c];
 +              unsigned int mux_idx;
 +              const struct hda_input_mux *imux;
 +              int conns, mute, idx, item;
 +
 +              conns = snd_hda_get_connections(codec, nid, conn_list,
 +                                              ARRAY_SIZE(conn_list));
 +              if (conns < 0)
 +                      continue;
 +              mux_idx = c >= spec->num_mux_defs ? 0 : c;
 +              imux = &spec->input_mux[mux_idx];
 +              for (idx = 0; idx < conns; idx++) {
 +                      /* if the current connection is the selected one,
 +                       * unmute it as default - otherwise mute it
 +                       */
 +                      mute = AMP_IN_MUTE(idx);
 +                      for (item = 0; item < imux->num_items; item++) {
 +                              if (imux->items[item].index == idx) {
 +                                      if (spec->cur_mux[c] == item)
 +                                              mute = AMP_IN_UNMUTE(idx);
 +                                      break;
 +                              }
 +                      }
 +                      /* check if we have a selector or mixer
 +                       * we could check for the widget type instead, but
 +                       * just check for Amp-In presence (in case of mixer
 +                       * without amp-in there is something wrong, this
 +                       * function shouldn't be used or capsrc nid is wrong)
 +                       */
 +                      if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)
                                snd_hda_codec_write(codec, nid, 0,
                                                    AC_VERB_SET_AMP_GAIN_MUTE,
 -                                                  AMP_OUT_MUTE);
 +                                                  mute);
 +                      else if (mute != AMP_IN_MUTE(idx))
 +                              snd_hda_codec_write(codec, nid, 0,
 +                                                  AC_VERB_SET_CONNECT_SEL,
 +                                                  idx);
                }
        }
  }
  
 -#define alc883_auto_init_input_src    alc882_auto_init_input_src
 +/* add mic boosts if needed */
 +static int alc_auto_add_mic_boost(struct hda_codec *codec)
 +{
 +      struct alc_spec *spec = codec->spec;
 +      int err;
 +      hda_nid_t nid;
 +
 +      nid = spec->autocfg.input_pins[AUTO_PIN_MIC];
 +      if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) {
 +              err = add_control(spec, ALC_CTL_WIDGET_VOL,
 +                                "Mic Boost",
 +                                HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
 +              if (err < 0)
 +                      return err;
 +      }
 +      nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC];
 +      if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) {
 +              err = add_control(spec, ALC_CTL_WIDGET_VOL,
 +                                "Front Mic Boost",
 +                                HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
 +              if (err < 0)
 +                      return err;
 +      }
 +      return 0;
 +}
  
  /* almost identical with ALC880 parser... */
 -static int alc883_parse_auto_config(struct hda_codec *codec)
 +static int alc882_parse_auto_config(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
 -      int err = alc880_parse_auto_config(codec);
 -      struct auto_pin_cfg *cfg = &spec->autocfg;
 +      struct auto_pin_cfg *autocfg = &spec->autocfg;
 +      unsigned int wcap;
        int i;
 +      int err = alc880_parse_auto_config(codec);
  
        if (err < 0)
                return err;
  
        /* hack - override the init verbs */
        spec->init_verbs[0] = alc883_auto_init_verbs;
 +      /* if ADC 0x07 is available, initialize it, too */
 +      wcap = get_wcaps(codec, 0x07);
 +      wcap = get_wcaps_type(wcap);
 +      if (wcap == AC_WID_AUD_IN)
 +              add_verb(spec, alc882_adc1_init_verbs);
  
 -      /* setup input_mux for ALC889 */
 -      if (codec->vendor_id == 0x10ec0889) {
 -              /* digital-mic input pin is excluded in alc880_auto_create..()
 -               * because it's under 0x18
 -               */
 -              if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 ||
 -                  cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) {
 -                      struct hda_input_mux *imux = &spec->private_imux[0];
 -                      for (i = 1; i < 3; i++)
 -                              memcpy(&spec->private_imux[i],
 -                                     &spec->private_imux[0],
 -                                     sizeof(spec->private_imux[0]));
 -                      imux->items[imux->num_items].label = "Int DMic";
 -                      imux->items[imux->num_items].index = 0x0b;
 -                      imux->num_items++;
 -                      spec->num_mux_defs = 3;
 -                      spec->input_mux = spec->private_imux;
 -              }
 +      /* digital-mic input pin is excluded in alc880_auto_create..()
 +       * because it's under 0x18
 +       */
 +      if (autocfg->input_pins[AUTO_PIN_MIC] == 0x12 ||
 +          autocfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) {
 +              struct hda_input_mux *imux = &spec->private_imux[0];
 +              for (i = 1; i < 3; i++)
 +                      memcpy(&spec->private_imux[i],
 +                             &spec->private_imux[0],
 +                             sizeof(spec->private_imux[0]));
 +              imux->items[imux->num_items].label = "Int DMic";
 +              imux->items[imux->num_items].index = 0x0b;
 +              imux->num_items++;
 +              spec->num_mux_defs = 3;
 +              spec->input_mux = spec->private_imux;
        }
  
        return 1; /* config found */
  }
  
  /* additional initialization for auto-configuration model */
 -static void alc883_auto_init(struct hda_codec *codec)
 +static void alc882_auto_init(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
 -      alc883_auto_init_multi_out(codec);
 -      alc883_auto_init_hp_out(codec);
 -      alc883_auto_init_analog_input(codec);
 -      alc883_auto_init_input_src(codec);
 +      alc882_auto_init_multi_out(codec);
 +      alc882_auto_init_hp_out(codec);
 +      alc882_auto_init_analog_input(codec);
 +      alc882_auto_init_input_src(codec);
        if (spec->unsol_event)
                alc_inithook(codec);
  }
  
 -static int patch_alc883(struct hda_codec *codec)
 +static int patch_alc882(struct hda_codec *codec)
  {
        struct alc_spec *spec;
        int err, board_config;
  
        codec->spec = spec;
  
 -      alc_fix_pll_init(codec, 0x20, 0x0a, 10);
 +      switch (codec->vendor_id) {
 +      case 0x10ec0882:
 +      case 0x10ec0885:
 +              break;
 +      default:
 +              /* ALC883 and variants */
 +              alc_fix_pll_init(codec, 0x20, 0x0a, 10);
 +              break;
 +      }
  
 -      board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST,
 -                                                alc883_models,
 -                                                alc883_cfg_tbl);
 -      if (board_config < 0 || board_config >= ALC883_MODEL_LAST) {
 -              /* Pick up systems that don't supply PCI SSID */
 -              switch (codec->subsystem_id) {
 -              case 0x106b3600: /* Macbook 3.1 */
 -                      board_config = ALC889A_MB31;
 -                      break;
 -              default:
 -                      printk(KERN_INFO
 -                              "hda_codec: Unknown model for %s, trying "
 -                              "auto-probe from BIOS...\n", codec->chip_name);
 -                      board_config = ALC883_AUTO;
 -              }
 +      board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST,
 +                                                alc882_models,
 +                                                alc882_cfg_tbl);
 +
 +      if (board_config < 0 || board_config >= ALC882_MODEL_LAST)
 +              board_config = snd_hda_check_board_codec_sid_config(codec,
 +                      ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
 +
 +      if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
 +              printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                     codec->chip_name);
 +              board_config = ALC882_AUTO;
        }
  
 -      if (board_config == ALC883_AUTO) {
 +      alc_fix_pincfg(codec, alc882_pinfix_tbl, alc882_pin_fixes);
 +
 +      if (board_config == ALC882_AUTO) {
                /* automatic parse from the BIOS config */
 -              err = alc883_parse_auto_config(codec);
 +              err = alc882_parse_auto_config(codec);
                if (err < 0) {
                        alc_free(codec);
                        return err;
                        printk(KERN_INFO
                               "hda_codec: Cannot set up configuration "
                               "from BIOS.  Using base mode...\n");
 -                      board_config = ALC883_3ST_2ch_DIG;
 +                      board_config = ALC882_3ST_DIG;
                }
        }
  
                return err;
        }
  
 -      if (board_config != ALC883_AUTO)
 -              setup_preset(spec, &alc883_presets[board_config]);
 +      if (board_config != ALC882_AUTO)
 +              setup_preset(spec, &alc882_presets[board_config]);
  
 -      switch (codec->vendor_id) {
 -      case 0x10ec0888:
 -              if (!spec->num_adc_nids) {
 -                      spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
 -                      spec->adc_nids = alc883_adc_nids;
 -              }
 -              if (!spec->capsrc_nids)
 -                      spec->capsrc_nids = alc883_capsrc_nids;
 +      spec->stream_analog_playback = &alc882_pcm_analog_playback;
 +      spec->stream_analog_capture = &alc882_pcm_analog_capture;
 +      /* FIXME: setup DAC5 */
 +      /*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/
 +      spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
 +
 +      spec->stream_digital_playback = &alc882_pcm_digital_playback;
 +      spec->stream_digital_capture = &alc882_pcm_digital_capture;
 +
 +      if (codec->vendor_id == 0x10ec0888)
                spec->init_amp = ALC_INIT_DEFAULT; /* always initialize */
 -              break;
 -      case 0x10ec0889:
 -              if (!spec->num_adc_nids) {
 -                      spec->num_adc_nids = ARRAY_SIZE(alc889_adc_nids);
 -                      spec->adc_nids = alc889_adc_nids;
 -              }
 -              if (!spec->capsrc_nids)
 -                      spec->capsrc_nids = alc889_capsrc_nids;
 -              break;
 -      default:
 -              if (!spec->num_adc_nids) {
 -                      spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
 -                      spec->adc_nids = alc883_adc_nids;
 +
 +      if (!spec->adc_nids && spec->input_mux) {
 +              int i;
 +              spec->num_adc_nids = 0;
 +              for (i = 0; i < ARRAY_SIZE(alc882_adc_nids); i++) {
 +                      hda_nid_t cap;
 +                      hda_nid_t nid = alc882_adc_nids[i];
 +                      unsigned int wcap = get_wcaps(codec, nid);
 +                      /* get type */
 +                      wcap = get_wcaps_type(wcap);
 +                      if (wcap != AC_WID_AUD_IN)
 +                              continue;
 +                      spec->private_adc_nids[spec->num_adc_nids] = nid;
 +                      err = snd_hda_get_connections(codec, nid, &cap, 1);
 +                      if (err < 0)
 +                              continue;
 +                      spec->private_capsrc_nids[spec->num_adc_nids] = cap;
 +                      spec->num_adc_nids++;
                }
 -              if (!spec->capsrc_nids)
 -                      spec->capsrc_nids = alc883_capsrc_nids;
 -              break;
 +              spec->adc_nids = spec->private_adc_nids;
 +              spec->capsrc_nids = spec->private_capsrc_nids;
        }
  
 -      spec->stream_analog_playback = &alc883_pcm_analog_playback;
 -      spec->stream_analog_capture = &alc883_pcm_analog_capture;
 -      spec->stream_analog_alt_capture = &alc883_pcm_analog_alt_capture;
 -
 -      spec->stream_digital_playback = &alc883_pcm_digital_playback;
 -      spec->stream_digital_capture = &alc883_pcm_digital_capture;
 -
 -      if (!spec->cap_mixer)
 -              set_capture_mixer(spec);
 +      set_capture_mixer(spec);
        set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
  
        spec->vmaster_nid = 0x0c;
  
        codec->patch_ops = alc_patch_ops;
 -      if (board_config == ALC883_AUTO)
 -              spec->init_hook = alc883_auto_init;
 -
 +      if (board_config == ALC882_AUTO)
 +              spec->init_hook = alc882_auto_init;
  #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
 -              spec->loopback.amplist = alc883_loopbacks;
 +              spec->loopback.amplist = alc882_loopbacks;
  #endif
        codec->proc_widget_hook = print_realtek_coef;
  
        return 0;
  }
  
 +
  /*
   * ALC262 support
   */
@@@ -10149,6 -10359,12 +10149,6 @@@ static struct hda_verb alc262_eapd_verb
        { }
  };
  
 -static struct hda_verb alc262_hippo_unsol_verbs[] = {
 -      {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
 -      {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
 -      {}
 -};
 -
  static struct hda_verb alc262_hippo1_unsol_verbs[] = {
        {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
        {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
@@@ -11190,7 -11406,7 +11190,7 @@@ static struct alc_config_preset alc262_
        },
        [ALC262_HIPPO] = {
                .mixers = { alc262_hippo_mixer },
 -              .init_verbs = { alc262_init_verbs, alc262_hippo_unsol_verbs},
 +              .init_verbs = { alc262_init_verbs, alc_hp15_unsol_verbs},
                .num_dacs = ARRAY_SIZE(alc262_dac_nids),
                .dac_nids = alc262_dac_nids,
                .hp_nid = 0x03,
        },
        [ALC262_BENQ_T31] = {
                .mixers = { alc262_benq_t31_mixer },
 -              .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs, alc262_hippo_unsol_verbs },
 +              .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs,
 +                              alc_hp15_unsol_verbs },
                .num_dacs = ARRAY_SIZE(alc262_dac_nids),
                .dac_nids = alc262_dac_nids,
                .hp_nid = 0x03,
@@@ -11433,8 -11648,8 +11433,8 @@@ static int patch_alc262(struct hda_code
                                                  alc262_cfg_tbl);
  
        if (board_config < 0) {
 -              printk(KERN_INFO "hda_codec: Unknown model for %s, "
 -                     "trying auto-probe from BIOS...\n", codec->chip_name);
 +              printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                     codec->chip_name);
                board_config = ALC262_AUTO;
        }
  
                        unsigned int wcap = get_wcaps(codec, 0x07);
  
                        /* get type */
 -                      wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 +                      wcap = get_wcaps_type(wcap);
                        if (wcap != AC_WID_AUD_IN) {
                                spec->adc_nids = alc262_adc_nids_alt;
                                spec->num_adc_nids =
@@@ -12054,38 -12269,26 +12054,38 @@@ static int alc268_new_analog_output(str
                                    const char *ctlname, int idx)
  {
        char name[32];
 +      hda_nid_t dac;
        int err;
  
        sprintf(name, "%s Playback Volume", ctlname);
 -      if (nid == 0x14) {
 -              err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
 -                                HDA_COMPOSE_AMP_VAL(0x02, 3, idx,
 -                                                    HDA_OUTPUT));
 -              if (err < 0)
 -                      return err;
 -      } else if (nid == 0x15) {
 +      switch (nid) {
 +      case 0x14:
 +      case 0x16:
 +              dac = 0x02;
 +              break;
 +      case 0x15:
 +              dac = 0x03;
 +              break;
 +      default:
 +              return 0;
 +      }
 +      if (spec->multiout.dac_nids[0] != dac &&
 +          spec->multiout.dac_nids[1] != dac) {
                err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
 -                                HDA_COMPOSE_AMP_VAL(0x03, 3, idx,
 +                                HDA_COMPOSE_AMP_VAL(dac, 3, idx,
                                                      HDA_OUTPUT));
                if (err < 0)
                        return err;
 -      } else
 -              return -1;
 +              spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
 +      }
 +
        sprintf(name, "%s Playback Switch", ctlname);
 -      err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
 +      if (nid != 0x16)
 +              err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
                          HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
 +      else /* mono */
 +              err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
 +                        HDA_COMPOSE_AMP_VAL(nid, 2, idx, HDA_OUTPUT));
        if (err < 0)
                return err;
        return 0;
@@@ -12098,19 -12301,14 +12098,19 @@@ static int alc268_auto_create_multi_out
        hda_nid_t nid;
        int err;
  
 -      spec->multiout.num_dacs = 2;    /* only use one dac */
        spec->multiout.dac_nids = spec->private_dac_nids;
 -      spec->multiout.dac_nids[0] = 2;
 -      spec->multiout.dac_nids[1] = 3;
  
        nid = cfg->line_out_pins[0];
 -      if (nid)
 -              alc268_new_analog_output(spec, nid, "Front", 0);
 +      if (nid) {
 +              const char *name;
 +              if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
 +                      name = "Speaker";
 +              else
 +                      name = "Front";
 +              err = alc268_new_analog_output(spec, nid, name, 0);
 +              if (err < 0)
 +                      return err;
 +      }
  
        nid = cfg->speaker_pins[0];
        if (nid == 0x1d) {
                                  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
                if (err < 0)
                        return err;
 +      } else {
 +              err = alc268_new_analog_output(spec, nid, "Speaker", 0);
 +              if (err < 0)
 +                      return err;
        }
        nid = cfg->hp_pins[0];
 -      if (nid)
 -              alc268_new_analog_output(spec, nid, "Headphone", 0);
 +      if (nid) {
 +              err = alc268_new_analog_output(spec, nid, "Headphone", 0);
 +              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",
 -                                HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_INPUT));
 +                                HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT));
                if (err < 0)
                        return err;
        }
@@@ -12506,8 -12697,8 +12506,8 @@@ static int patch_alc268(struct hda_code
                                                  alc268_cfg_tbl);
  
        if (board_config < 0 || board_config >= ALC268_MODEL_LAST) {
 -              printk(KERN_INFO "hda_codec: Unknown model for %s, "
 -                     "trying auto-probe from BIOS...\n", codec->chip_name);
 +              printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                     codec->chip_name);
                board_config = ALC268_AUTO;
        }
  
                int i;
  
                /* get type */
 -              wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 +              wcap = get_wcaps_type(wcap);
                if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
                        spec->adc_nids = alc268_adc_nids_alt;
                        spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);
@@@ -13324,8 -13515,8 +13324,8 @@@ static int patch_alc269(struct hda_code
                                                  alc269_cfg_tbl);
  
        if (board_config < 0) {
 -              printk(KERN_INFO "hda_codec: Unknown model for %s, "
 -                     "trying auto-probe from BIOS...\n", codec->chip_name);
 +              printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                     codec->chip_name);
                board_config = ALC269_AUTO;
        }
  
@@@ -13917,23 -14108,23 +13917,23 @@@ static struct hda_verb alc861_auto_init
        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
  
 -      {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -      {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -      {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -      {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 +      {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +      {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 +      {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +      {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 +      {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +      {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 +      {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 +      {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
  
        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 -      {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
 -      {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
 +      {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
 +      {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
        {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
        {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 -      {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
 -      {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
 +      {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
 +      {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
  
        {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},  /* set Mic 1 */
  
@@@ -14005,96 -14196,64 +14005,96 @@@ static struct hda_input_mux alc861_capt
        },
  };
  
 +static hda_nid_t alc861_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
 +{
 +      struct alc_spec *spec = codec->spec;
 +      hda_nid_t mix, srcs[5];
 +      int i, j, num;
 +
 +      if (snd_hda_get_connections(codec, pin, &mix, 1) != 1)
 +              return 0;
 +      num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
 +      if (num < 0)
 +              return 0;
 +      for (i = 0; i < num; i++) {
 +              unsigned int type;
 +              type = get_wcaps_type(get_wcaps(codec, srcs[i]));
 +              if (type != AC_WID_AUD_OUT)
 +                      continue;
 +              for (j = 0; j < spec->multiout.num_dacs; j++)
 +                      if (spec->multiout.dac_nids[j] == srcs[i])
 +                              break;
 +              if (j >= spec->multiout.num_dacs)
 +                      return srcs[i];
 +      }
 +      return 0;
 +}
 +
  /* fill in the dac_nids table from the parsed pin configuration */
 -static int alc861_auto_fill_dac_nids(struct alc_spec *spec,
 +static int alc861_auto_fill_dac_nids(struct hda_codec *codec,
                                     const struct auto_pin_cfg *cfg)
  {
 +      struct alc_spec *spec = codec->spec;
        int i;
 -      hda_nid_t nid;
 +      hda_nid_t nid, dac;
  
        spec->multiout.dac_nids = spec->private_dac_nids;
        for (i = 0; i < cfg->line_outs; i++) {
                nid = cfg->line_out_pins[i];
 -              if (nid) {
 -                      if (i >= ARRAY_SIZE(alc861_dac_nids))
 -                              continue;
 -                      spec->multiout.dac_nids[i] = alc861_dac_nids[i];
 -              }
 +              dac = alc861_look_for_dac(codec, nid);
 +              if (!dac)
 +                      continue;
 +              spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
        }
 -      spec->multiout.num_dacs = cfg->line_outs;
        return 0;
  }
  
 +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,
 +                         HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
 +}
 +
  /* add playback controls from the parsed DAC table */
 -static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec,
 +static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
                                             const struct auto_pin_cfg *cfg)
  {
 -      char name[32];
 +      struct alc_spec *spec = codec->spec;
        static const char *chname[4] = {
                "Front", "Surround", NULL /*CLFE*/, "Side"
        };
        hda_nid_t nid;
 -      int i, idx, err;
 +      int i, err;
 +
 +      if (cfg->line_outs == 1) {
 +              const char *pfx = NULL;
 +              if (!cfg->hp_outs)
 +                      pfx = "Master";
 +              else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
 +                      pfx = "Speaker";
 +              if (pfx) {
 +                      nid = spec->multiout.dac_nids[0];
 +                      return alc861_create_out_sw(codec, pfx, nid, 3);
 +              }
 +      }
  
        for (i = 0; i < cfg->line_outs; i++) {
                nid = spec->multiout.dac_nids[i];
                if (!nid)
                        continue;
 -              if (nid == 0x05) {
 +              if (i == 2) {
                        /* Center/LFE */
 -                      err = add_control(spec, ALC_CTL_BIND_MUTE,
 -                                        "Center Playback Switch",
 -                                        HDA_COMPOSE_AMP_VAL(nid, 1, 0,
 -                                                            HDA_OUTPUT));
 +                      err = alc861_create_out_sw(codec, "Center", nid, 1);
                        if (err < 0)
                                return err;
 -                      err = add_control(spec, ALC_CTL_BIND_MUTE,
 -                                        "LFE Playback Switch",
 -                                        HDA_COMPOSE_AMP_VAL(nid, 2, 0,
 -                                                            HDA_OUTPUT));
 +                      err = alc861_create_out_sw(codec, "LFE", nid, 2);
                        if (err < 0)
                                return err;
                } else {
 -                      for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1;
 -                           idx++)
 -                              if (nid == alc861_dac_nids[idx])
 -                                      break;
 -                      sprintf(name, "%s Playback Switch", chname[idx]);
 -                      err = add_control(spec, ALC_CTL_BIND_MUTE, name,
 -                                        HDA_COMPOSE_AMP_VAL(nid, 3, 0,
 -                                                            HDA_OUTPUT));
 +                      err = alc861_create_out_sw(codec, chname[i], nid, 3);
                        if (err < 0)
                                return err;
                }
        return 0;
  }
  
 -static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
 +static int alc861_auto_create_hp_ctls(struct hda_codec *codec, hda_nid_t pin)
  {
 +      struct alc_spec *spec = codec->spec;
        int err;
        hda_nid_t nid;
  
                return 0;
  
        if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
 -              nid = 0x03;
 -              err = add_control(spec, ALC_CTL_WIDGET_MUTE,
 -                                "Headphone Playback Switch",
 -                                HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
 -              if (err < 0)
 -                      return err;
 -              spec->multiout.hp_nid = nid;
 +              nid = alc861_look_for_dac(codec, pin);
 +              if (nid) {
 +                      err = alc861_create_out_sw(codec, "Headphone", nid, 3);
 +                      if (err < 0)
 +                              return err;
 +                      spec->multiout.hp_nid = nid;
 +              }
        }
        return 0;
  }
  
  /* create playback/capture controls for input pins */
 -static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec,
 +static int alc861_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
  {
 +      struct alc_spec *spec = codec->spec;
        struct hda_input_mux *imux = &spec->private_imux[0];
        int i, err, idx, idx1;
  
  
  static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
                                              hda_nid_t nid,
 -                                            int pin_type, int dac_idx)
 +                                            int pin_type, hda_nid_t dac)
  {
 +      hda_nid_t mix, srcs[5];
 +      int i, num;
 +
        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
                            pin_type);
 -      snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE,
 +      snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE,
                            AMP_OUT_UNMUTE);
 +      if (snd_hda_get_connections(codec, nid, &mix, 1) != 1)
 +              return;
 +      num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
 +      if (num < 0)
 +              return;
 +      for (i = 0; i < num; i++) {
 +              unsigned int mute;
 +              if (srcs[i] == dac || srcs[i] == 0x15)
 +                      mute = AMP_IN_UNMUTE(i);
 +              else
 +                      mute = AMP_IN_MUTE(i);
 +              snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
 +                                  mute);
 +      }
  }
  
  static void alc861_auto_init_multi_out(struct hda_codec *codec)
@@@ -14216,13 -14356,12 +14216,13 @@@ static void alc861_auto_init_hp_out(str
        hda_nid_t pin;
  
        pin = spec->autocfg.hp_pins[0];
 -      if (pin) /* connect to front */
 +      if (pin)
                alc861_auto_set_output_and_unmute(codec, pin, PIN_HP,
 -                                                spec->multiout.dac_nids[0]);
 +                                                spec->multiout.hp_nid);
        pin = spec->autocfg.speaker_pins[0];
        if (pin)
 -              alc861_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 +              alc861_auto_set_output_and_unmute(codec, pin, PIN_OUT,
 +                                                spec->multiout.dac_nids[0]);
  }
  
  static void alc861_auto_init_analog_input(struct hda_codec *codec)
@@@ -14254,16 -14393,16 +14254,16 @@@ static int alc861_parse_auto_config(str
        if (!spec->autocfg.line_outs)
                return 0; /* can't find valid BIOS pin config */
  
 -      err = alc861_auto_fill_dac_nids(spec, &spec->autocfg);
 +      err = alc861_auto_fill_dac_nids(codec, &spec->autocfg);
        if (err < 0)
                return err;
 -      err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg);
 +      err = alc861_auto_create_multi_out_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 -      err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
 +      err = alc861_auto_create_hp_ctls(codec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
 -      err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg);
 +      err = alc861_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
  
@@@ -14475,8 -14614,8 +14475,8 @@@ static int patch_alc861(struct hda_code
                                                  alc861_cfg_tbl);
  
        if (board_config < 0) {
 -              printk(KERN_INFO "hda_codec: Unknown model for %s, "
 -                     "trying auto-probe from BIOS...\n", codec->chip_name);
 +              printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                     codec->chip_name);
                board_config = ALC861_AUTO;
        }
  
@@@ -15018,7 -15157,7 +15018,7 @@@ static struct snd_pci_quirk alc861vd_cf
        SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
        SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
        /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
-       SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS),
+       SND_PCI_QUIRK(0x1179, 0xff01, "Toshiba A135", ALC861VD_LENOVO),
        SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
        SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
        SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
@@@ -15399,8 -15538,8 +15399,8 @@@ static int patch_alc861vd(struct hda_co
                                                  alc861vd_cfg_tbl);
  
        if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) {
 -              printk(KERN_INFO "hda_codec: Unknown model for %s, "
 -                     "trying auto-probe from BIOS...\n", codec->chip_name);
 +              printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                     codec->chip_name);
                board_config = ALC861VD_AUTO;
        }
  
@@@ -17323,8 -17462,8 +17323,8 @@@ static int patch_alc662(struct hda_code
                                                  alc662_models,
                                                  alc662_cfg_tbl);
        if (board_config < 0) {
 -              printk(KERN_INFO "hda_codec: Unknown model for %s, "
 -                     "trying auto-probe from BIOS...\n", codec->chip_name);
 +              printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                     codec->chip_name);
                board_config = ALC662_AUTO;
        }
  
@@@ -17398,23 -17537,23 +17398,23 @@@ static struct hda_codec_preset snd_hda_
        { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
        { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
        { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
 -        .patch = patch_alc883 },
 +        .patch = patch_alc882 },
        { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
          .patch = patch_alc662 },
        { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
        { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
        { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
 -      { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
 +      { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
        { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
 -        .patch = patch_alc882 }, /* should be patch_alc883() in future */
 +        .patch = patch_alc882 },
        { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
 -        .patch = patch_alc882 }, /* should be patch_alc883() in future */
 +        .patch = patch_alc882 },
        { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
 -      { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc883 },
 +      { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 },
        { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
 -        .patch = patch_alc883 },
 -      { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
 -      { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
 +        .patch = patch_alc882 },
 +      { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc882 },
 +      { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
        {} /* terminator */
  };
  
@@@ -40,8 -40,6 +40,8 @@@ enum 
        STAC_INSERT_EVENT,
        STAC_PWR_EVENT,
        STAC_HP_EVENT,
 +      STAC_LO_EVENT,
 +      STAC_MIC_EVENT,
  };
  
  enum {
@@@ -178,12 -176,6 +178,12 @@@ struct sigmatel_jack 
        struct snd_jack *jack;
  };
  
 +struct sigmatel_mic_route {
 +      hda_nid_t pin;
 +      unsigned char mux_idx;
 +      unsigned char dmux_idx;
 +};
 +
  struct sigmatel_spec {
        struct snd_kcontrol_new *mixers[4];
        unsigned int num_mixers;
        unsigned int hp_detect: 1;
        unsigned int spdif_mute: 1;
        unsigned int check_volume_offset:1;
 +      unsigned int auto_mic:1;
  
        /* gpio lines */
        unsigned int eapd_mask;
        unsigned int num_dmuxes;
        hda_nid_t *smux_nids;
        unsigned int num_smuxes;
 +
 +      unsigned long *capvols; /* amp-volume attr: HDA_COMPOSE_AMP_VAL() */
 +      unsigned long *capsws; /* amp-mute attr: HDA_COMPOSE_AMP_VAL() */
 +      unsigned int num_caps; /* number of capture volume/switch elements */
 +
 +      struct sigmatel_mic_route ext_mic;
 +      struct sigmatel_mic_route int_mic;
 +
        const char **spdif_labels;
  
        hda_nid_t dig_in_nid;
@@@ -351,13 -334,6 +351,13 @@@ static hda_nid_t stac92hd73xx_smux_nids
        0x22, 0x23,
  };
  
 +#define STAC92HD73XX_NUM_CAPS 2
 +static unsigned long stac92hd73xx_capvols[] = {
 +      HDA_COMPOSE_AMP_VAL(0x20, 3, 0, HDA_OUTPUT),
 +      HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
 +};
 +#define stac92hd73xx_capsws   stac92hd73xx_capvols
 +
  #define STAC92HD83XXX_NUM_DMICS       2
  static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = {
        0x11, 0x12, 0
@@@ -389,13 -365,6 +389,13 @@@ static hda_nid_t stac92hd83xxx_amp_nids
        0xc,
  };
  
 +#define STAC92HD83XXX_NUM_CAPS        2
 +static unsigned long stac92hd83xxx_capvols[] = {
 +      HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
 +      HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_OUTPUT),
 +};
 +#define stac92hd83xxx_capsws  stac92hd83xxx_capvols
 +
  static hda_nid_t stac92hd71bxx_pwr_nids[3] = {
        0x0a, 0x0d, 0x0f
  };
@@@ -425,13 -394,6 +425,13 @@@ static hda_nid_t stac92hd71bxx_slave_di
        0x22, 0
  };
  
 +#define STAC92HD71BXX_NUM_CAPS                2
 +static unsigned long stac92hd71bxx_capvols[] = {
 +      HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_OUTPUT),
 +      HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT),
 +};
 +#define stac92hd71bxx_capsws  stac92hd71bxx_capvols
 +
  static hda_nid_t stac925x_adc_nids[1] = {
          0x03,
  };
@@@ -453,13 -415,6 +453,13 @@@ static hda_nid_t stac925x_dmux_nids[1] 
        0x14,
  };
  
 +static unsigned long stac925x_capvols[] = {
 +      HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_OUTPUT),
 +};
 +static unsigned long stac925x_capsws[] = {
 +      HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
 +};
 +
  static hda_nid_t stac922x_adc_nids[2] = {
          0x06, 0x07,
  };
@@@ -468,13 -423,6 +468,13 @@@ static hda_nid_t stac922x_mux_nids[2] 
          0x12, 0x13,
  };
  
 +#define STAC922X_NUM_CAPS     2
 +static unsigned long stac922x_capvols[] = {
 +      HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT),
 +      HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT),
 +};
 +#define stac922x_capsws               stac922x_capvols
 +
  static hda_nid_t stac927x_slave_dig_outs[2] = {
        0x1f, 0,
  };
@@@ -504,18 -452,6 +504,18 @@@ static hda_nid_t stac927x_dmic_nids[STA
        0x13, 0x14, 0
  };
  
 +#define STAC927X_NUM_CAPS     3
 +static unsigned long stac927x_capvols[] = {
 +      HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT),
 +      HDA_COMPOSE_AMP_VAL(0x19, 3, 0, HDA_INPUT),
 +      HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_INPUT),
 +};
 +static unsigned long stac927x_capsws[] = {
 +      HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
 +      HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_OUTPUT),
 +      HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT),
 +};
 +
  static const char *stac927x_spdif_labels[5] = {
        "Digital Playback", "ADAT", "Analog Mux 1",
        "Analog Mux 2", "Analog Mux 3"
@@@ -542,16 -478,6 +542,16 @@@ static hda_nid_t stac9205_dmic_nids[STA
          0x17, 0x18, 0
  };
  
 +#define STAC9205_NUM_CAPS     2
 +static unsigned long stac9205_capvols[] = {
 +      HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_INPUT),
 +      HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_INPUT),
 +};
 +static unsigned long stac9205_capsws[] = {
 +      HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT),
 +      HDA_COMPOSE_AMP_VAL(0x1e, 3, 0, HDA_OUTPUT),
 +};
 +
  static hda_nid_t stac9200_pin_nids[8] = {
        0x08, 0x09, 0x0d, 0x0e, 
        0x0f, 0x10, 0x11, 0x12,
@@@ -998,6 -924,19 +998,6 @@@ static struct hda_verb stac92hd71bxx_co
        {}
  };
  
 -#define HD_DISABLE_PORTF 1
 -static struct hda_verb stac92hd71bxx_analog_core_init[] = {
 -      /* start of config #1 */
 -
 -      /* connect port 0f to audio mixer */
 -      { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2},
 -      /* start of config #2 */
 -
 -      /* set master volume and direct control */
 -      { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
 -      {}
 -};
 -
  static struct hda_verb stac92hd71bxx_unmute_core_init[] = {
        /* unmute right and left channels for nodes 0x0f, 0xa, 0x0d */
        { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@@ -1130,6 -1069,12 +1130,6 @@@ static struct snd_kcontrol_new stac92hd
        HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT),
        HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT),
  
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT),
 -
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x21, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x21, 0x0, HDA_OUTPUT),
 -
        { } /* end */
  };
  
@@@ -1149,6 -1094,12 +1149,6 @@@ static struct snd_kcontrol_new stac92hd
  };
  
  static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = {
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT),
 -
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x21, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x21, 0x0, HDA_OUTPUT),
 -
        HDA_CODEC_VOLUME("Front Mic Mixer Capture Volume", 0x1d, 0, HDA_INPUT),
        HDA_CODEC_MUTE("Front Mic Mixer Capture Switch", 0x1d, 0, HDA_INPUT),
  
  };
  
  static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = {
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT),
 -
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x21, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x21, 0x0, HDA_OUTPUT),
 -
        HDA_CODEC_VOLUME("Front Mic Mixer Capture Volume", 0x1d, 0, HDA_INPUT),
        HDA_CODEC_MUTE("Front Mic Mixer Capture Switch", 0x1d, 0, HDA_INPUT),
  
  
  
  static struct snd_kcontrol_new stac92hd83xxx_mixer[] = {
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_OUTPUT),
 -
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_OUTPUT),
 -
        HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x1b, 0x3, HDA_INPUT),
        HDA_CODEC_MUTE("DAC0 Capture Switch", 0x1b, 0x3, HDA_INPUT),
  
  };
  
  static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT),
 -
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1d, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT),
 -      /* analog pc-beep replaced with digital beep support */
 -      /*
 -      HDA_CODEC_VOLUME("PC Beep Volume", 0x17, 0x2, HDA_INPUT),
 -      HDA_CODEC_MUTE("PC Beep Switch", 0x17, 0x2, HDA_INPUT),
 -      */
 -
        HDA_CODEC_MUTE("Import0 Mux Capture Switch", 0x17, 0x0, HDA_INPUT),
        HDA_CODEC_VOLUME("Import0 Mux Capture Volume", 0x17, 0x0, HDA_INPUT),
  
@@@ -1224,9 -1198,29 +1224,9 @@@ static struct snd_kcontrol_new stac92hd
        STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2)
  };
  
 -static struct snd_kcontrol_new stac92hd71bxx_mixer[] = {
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT),
 -
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1d, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT),
 -      { } /* end */
 -};
 -
  static struct snd_kcontrol_new stac925x_mixer[] = {
        HDA_CODEC_VOLUME("Master Playback Volume", 0x0e, 0, HDA_OUTPUT),
        HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT),
 -      HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE("Capture Switch", 0x14, 0, HDA_OUTPUT),
 -      { } /* end */
 -};
 -
 -static struct snd_kcontrol_new stac9205_mixer[] = {
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT),
 -
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1c, 0x0, HDA_INPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1e, 0x0, HDA_OUTPUT),
        { } /* end */
  };
  
@@@ -1235,6 -1229,29 +1235,6 @@@ static struct snd_kcontrol_new stac9205
        {}
  };
  
 -/* This needs to be generated dynamically based on sequence */
 -static struct snd_kcontrol_new stac922x_mixer[] = {
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT),
 -
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_INPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_INPUT),
 -      { } /* end */
 -};
 -
 -
 -static struct snd_kcontrol_new stac927x_mixer[] = {
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT),
 -
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x19, 0x0, HDA_INPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1c, 0x0, HDA_OUTPUT),
 -
 -      HDA_CODEC_VOLUME_IDX("Capture Volume", 0x2, 0x1A, 0x0, HDA_INPUT),
 -      HDA_CODEC_MUTE_IDX("Capture Switch", 0x2, 0x1d, 0x0, HDA_OUTPUT),
 -      { } /* end */
 -};
 -
  static struct snd_kcontrol_new stac927x_loopback[] = {
        STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1),
        {}
@@@ -1292,18 -1309,16 +1292,18 @@@ static int stac92xx_build_controls(stru
        int err;
        int i;
  
 -      err = snd_hda_add_new_ctls(codec, spec->mixer);
 -      if (err < 0)
 -              return err;
 +      if (spec->mixer) {
 +              err = snd_hda_add_new_ctls(codec, spec->mixer);
 +              if (err < 0)
 +                      return err;
 +      }
  
        for (i = 0; i < spec->num_mixers; i++) {
                err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
                if (err < 0)
                        return err;
        }
 -      if (spec->num_dmuxes > 0) {
 +      if (!spec->auto_mic && spec->num_dmuxes > 0) {
                stac_dmux_mixer.count = spec->num_dmuxes;
                err = snd_hda_ctl_add(codec,
                                  snd_ctl_new1(&stac_dmux_mixer, codec));
@@@ -2251,7 -2266,7 +2251,7 @@@ static struct snd_pci_quirk stac927x_cf
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0227, "Dell Vostro 1400  ", STAC_DELL_BIOS),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x022e, "Dell     ", STAC_DELL_BIOS),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x022f, "Dell Inspiron 1525", STAC_DELL_3ST),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x022f, "Dell Inspiron 1525", STAC_DELL_BIOS),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0242, "Dell     ", STAC_DELL_BIOS),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0243, "Dell     ", STAC_DELL_BIOS),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x02ff, "Dell     ", STAC_DELL_BIOS),
@@@ -2621,7 -2636,8 +2621,7 @@@ static int stac92xx_hp_switch_get(struc
        return 0;
  }
  
 -static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid,
 -                                 unsigned char type);
 +static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid);
  
  static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_value *ucontrol)
        /* check to be sure that the ports are upto date with
         * switch changes
         */
 -      stac_issue_unsol_event(codec, nid, STAC_HP_EVENT);
 +      stac_issue_unsol_event(codec, nid);
  
        return 1;
  }
@@@ -2768,7 -2784,7 +2768,7 @@@ static int stac92xx_io_switch_put(struc
         * appropriately according to the pin direction
         */
        if (spec->hp_detect)
 -              stac_issue_unsol_event(codec, nid, STAC_HP_EVENT);
 +              stac_issue_unsol_event(codec, nid);
  
          return 1;
  }
@@@ -2951,8 -2967,6 +2951,8 @@@ static int stac92xx_add_input_source(st
        struct snd_kcontrol_new *knew;
        struct hda_input_mux *imux = &spec->private_imux;
  
 +      if (spec->auto_mic)
 +              return 0; /* no need for input source */
        if (!spec->num_adcs || imux->num_items <= 1)
                return 0; /* no need for input source control */
        knew = stac_control_new(spec, &stac_input_src_temp,
@@@ -3046,7 -3060,7 +3046,7 @@@ static hda_nid_t get_unassigned_dac(str
                                           HDA_MAX_CONNECTIONS);
        for (j = 0; j < conn_len; j++) {
                wcaps = get_wcaps(codec, conn[j]);
 -              wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 +              wtype = get_wcaps_type(wcaps);
                /* we check only analog outputs */
                if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL))
                        continue;
@@@ -3305,21 -3319,6 +3305,21 @@@ static int create_multi_out_ctls(struc
        return 0;
  }
  
 +static int stac92xx_add_capvol_ctls(struct hda_codec *codec, unsigned long vol,
 +                                  unsigned long sw, int idx)
 +{
 +      int err;
 +      err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx,
 +                                     "Capture Volume", vol);
 +      if (err < 0)
 +              return err;
 +      err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_MUTE, idx,
 +                                     "Capture Switch", sw);
 +      if (err < 0)
 +              return err;
 +      return 0;
 +}
 +
  /* add playback controls from the parsed DAC table */
  static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
                                               const struct auto_pin_cfg *cfg)
@@@ -3393,7 -3392,7 +3393,7 @@@ static int stac92xx_auto_create_mono_ou
                                spec->mono_nid,
                                con_lst,
                                HDA_MAX_NUM_INPUTS);
 -      if (!num_cons || num_cons > ARRAY_SIZE(stac92xx_mono_labels))
 +      if (num_cons <= 0 || num_cons > ARRAY_SIZE(stac92xx_mono_labels))
                return -EINVAL;
  
        for (i = 0; i < num_cons; i++) {
@@@ -3539,7 -3538,7 +3539,7 @@@ static int stac92xx_auto_create_spdif_m
                                spec->smux_nids[0],
                                con_lst,
                                HDA_MAX_NUM_INPUTS);
 -      if (!num_cons)
 +      if (num_cons <= 0)
                return -EINVAL;
  
        if (!labels)
@@@ -3560,26 -3559,14 +3560,26 @@@ static const char *stac92xx_dmic_labels
        "Digital Mic 3", "Digital Mic 4"
  };
  
 +static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
 +                              hda_nid_t nid)
 +{
 +      hda_nid_t conn[HDA_MAX_NUM_INPUTS];
 +      int i, nums;
 +
 +      nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
 +      for (i = 0; i < nums; i++)
 +              if (conn[i] == nid)
 +                      return i;
 +      return -1;
 +}
 +
  /* create playback/capture controls for input pins on dmic capable codecs */
  static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
  {
        struct sigmatel_spec *spec = codec->spec;
        struct hda_input_mux *dimux = &spec->private_dimux;
 -      hda_nid_t con_lst[HDA_MAX_NUM_INPUTS];
 -      int err, i, j;
 +      int err, i;
        char name[32];
  
        dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0];
        for (i = 0; i < spec->num_dmics; i++) {
                hda_nid_t nid;
                int index;
 -              int num_cons;
                unsigned int wcaps;
                unsigned int def_conf;
  
                        continue;
  
                nid = spec->dmic_nids[i];
 -              num_cons = snd_hda_get_connections(codec,
 -                              spec->dmux_nids[0],
 -                              con_lst,
 -                              HDA_MAX_NUM_INPUTS);
 -              for (j = 0; j < num_cons; j++)
 -                      if (con_lst[j] == nid) {
 -                              index = j;
 -                              goto found;
 -                      }
 -              continue;
 -found:
 +              index = get_connection_index(codec, spec->dmux_nids[0], nid);
 +              if (index < 0)
 +                      continue;
 +
                wcaps = get_wcaps(codec, nid) &
                        (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP);
  
        return 0;
  }
  
 +static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid,
 +                       hda_nid_t *fixed, hda_nid_t *ext)
 +{
 +      unsigned int cfg;
 +
 +      if (!nid)
 +              return 0;
 +      cfg = snd_hda_codec_get_pincfg(codec, nid);
 +      switch (get_defcfg_connect(cfg)) {
 +      case AC_JACK_PORT_FIXED:
 +              if (*fixed)
 +                      return 1; /* already occupied */
 +              *fixed = nid;
 +              break;
 +      case AC_JACK_PORT_COMPLEX:
 +              if (*ext)
 +                      return 1; /* already occupied */
 +              *ext = nid;
 +              break;
 +      }
 +      return 0;
 +}
 +
 +static int set_mic_route(struct hda_codec *codec,
 +                       struct sigmatel_mic_route *mic,
 +                       hda_nid_t pin)
 +{
 +      struct sigmatel_spec *spec = codec->spec;
 +      struct auto_pin_cfg *cfg = &spec->autocfg;
 +      int i;
 +
 +      mic->pin = pin;
 +      for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++)
 +              if (pin == cfg->input_pins[i])
 +                      break;
 +      if (i <= AUTO_PIN_FRONT_MIC) {
 +              /* analog pin */
 +              mic->dmux_idx = 0;
 +              i = get_connection_index(codec, spec->mux_nids[0], pin);
 +              if (i < 0)
 +                      return -1;
 +              mic->mux_idx = i;
 +      }  else {
 +              /* digital pin */
 +              mic->mux_idx = 0;
 +              i = get_connection_index(codec, spec->dmux_nids[0], pin);
 +              if (i < 0)
 +                      return -1;
 +              mic->dmux_idx = i;
 +      }
 +      return 0;
 +}
 +
 +/* return non-zero if the device is for automatic mic switch */
 +static int stac_check_auto_mic(struct hda_codec *codec)
 +{
 +      struct sigmatel_spec *spec = codec->spec;
 +      struct auto_pin_cfg *cfg = &spec->autocfg;
 +      hda_nid_t fixed, ext;
 +      int i;
 +
 +      for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++) {
 +              if (cfg->input_pins[i])
 +                      return 0; /* must be exclusively mics */
 +      }
 +      fixed = ext = 0;
 +      for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++)
 +              if (check_mic_pin(codec, cfg->input_pins[i], &fixed, &ext))
 +                      return 0;
 +      for (i = 0; i < spec->num_dmics; i++)
 +              if (check_mic_pin(codec, spec->dmic_nids[i], &fixed, &ext))
 +                      return 0;
 +      if (!fixed || !ext)
 +              return 0;
 +      if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
 +              return 0; /* no unsol support */
 +      if (set_mic_route(codec, &spec->ext_mic, ext) ||
 +          set_mic_route(codec, &spec->int_mic, fixed))
 +              return 0; /* something is wrong */
 +      return 1;
 +}
 +
  /* create playback/capture controls for input pins */
  static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
  {
@@@ -3792,7 -3705,7 +3792,7 @@@ static int stac92xx_parse_auto_config(s
  {
        struct sigmatel_spec *spec = codec->spec;
        int hp_swap = 0;
 -      int err;
 +      int i, err;
  
        if ((err = snd_hda_parse_pin_def_config(codec,
                                                &spec->autocfg,
                if (snd_hda_get_connections(codec,
                                spec->autocfg.mono_out_pin, conn_list, 1) &&
                                snd_hda_get_connections(codec, conn_list[0],
 -                              conn_list, 1)) {
 +                              conn_list, 1) > 0) {
  
                                int wcaps = get_wcaps(codec, conn_list[0]);
 -                              int wid_type = (wcaps & AC_WCAP_TYPE)
 -                                      >> AC_WCAP_TYPE_SHIFT;
 +                              int wid_type = get_wcaps_type(wcaps);
                                /* LR swap check, some stac925x have a mux that
                                 * changes the DACs output path instead of the
                                 * mono-mux path.
                spec->autocfg.line_outs = 0;
        }
  
 +      if (stac_check_auto_mic(codec)) {
 +              spec->auto_mic = 1;
 +              /* only one capture for auto-mic */
 +              spec->num_adcs = 1;
 +              spec->num_caps = 1;
 +              spec->num_muxes = 1;
 +      }
 +
 +      for (i = 0; i < spec->num_caps; i++) {
 +              err = stac92xx_add_capvol_ctls(codec, spec->capvols[i],
 +                                             spec->capsws[i], i);
 +              if (err < 0)
 +                      return err;
 +      }
 +
        err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
@@@ -4203,14 -4102,14 +4203,14 @@@ static int stac_add_event(struct sigmat
  }
  
  static struct sigmatel_event *stac_get_event(struct hda_codec *codec,
 -                                           hda_nid_t nid, unsigned char type)
 +                                           hda_nid_t nid)
  {
        struct sigmatel_spec *spec = codec->spec;
        struct sigmatel_event *event = spec->events.list;
        int i;
  
        for (i = 0; i < spec->events.used; i++, event++) {
 -              if (event->nid == nid && event->type == type)
 +              if (event->nid == nid)
                        return event;
        }
        return NULL;
@@@ -4230,32 -4129,24 +4230,32 @@@ static struct sigmatel_event *stac_get_
        return NULL;
  }
  
 -static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
 -                            unsigned int type)
 +/* check if given nid is a valid pin and no other events are assigned
 + * to it.  If OK, assign the event, set the unsol flag, and returns 1.
 + * Otherwise, returns zero.
 + */
 +static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
 +                           unsigned int type)
  {
        struct sigmatel_event *event;
        int tag;
  
        if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
 -              return;
 -      event = stac_get_event(codec, nid, type);
 -      if (event)
 +              return 0;
 +      event = stac_get_event(codec, nid);
 +      if (event) {
 +              if (event->type != type)
 +                      return 0;
                tag = event->tag;
 -      else
 +      } else {
                tag = stac_add_event(codec->spec, nid, type, 0);
 -      if (tag < 0)
 -              return;
 +              if (tag < 0)
 +                      return 0;
 +      }
        snd_hda_codec_write_cache(codec, nid, 0,
                                  AC_VERB_SET_UNSOLICITED_ENABLE,
                                  AC_USRSP_EN | tag);
 +      return 1;
  }
  
  static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
@@@ -4348,34 -4239,20 +4348,34 @@@ static int stac92xx_init(struct hda_cod
                        hda_nid_t nid = cfg->hp_pins[i];
                        enable_pin_detect(codec, nid, STAC_HP_EVENT);
                }
 +              if (cfg->line_out_type == AUTO_PIN_LINE_OUT) {
 +                      /* enable pin-detect for line-outs as well */
 +                      for (i = 0; i < cfg->hp_outs; i++) {
 +                              hda_nid_t nid = cfg->hp_pins[i];
 +                              enable_pin_detect(codec, nid, STAC_LO_EVENT);
 +                      }
 +              }
 +
                /* force to enable the first line-out; the others are set up
                 * in unsol_event
                 */
                stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0],
                                AC_PINCTL_OUT_EN);
                /* fake event to set up pins */
 -              stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0],
 -                                     STAC_HP_EVENT);
 +              stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0]);
        } else {
                stac92xx_auto_init_multi_out(codec);
                stac92xx_auto_init_hp_out(codec);
                for (i = 0; i < cfg->hp_outs; i++)
                        stac_toggle_power_map(codec, cfg->hp_pins[i], 1);
        }
 +      if (spec->auto_mic) {
 +              /* initialize connection to analog input */
 +              snd_hda_codec_write_cache(codec, spec->dmux_nids[0], 0,
 +                                        AC_VERB_SET_CONNECT_SEL, 0);
 +              if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT))
 +                      stac_issue_unsol_event(codec, spec->ext_mic.pin);
 +      }
        for (i = 0; i < AUTO_PIN_LAST; i++) {
                hda_nid_t nid = cfg->input_pins[i];
                if (nid) {
                        }
                        conf = snd_hda_codec_get_pincfg(codec, nid);
                        if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
 -                              enable_pin_detect(codec, nid,
 -                                                STAC_INSERT_EVENT);
 -                              stac_issue_unsol_event(codec, nid,
 -                                                     STAC_INSERT_EVENT);
 +                              if (enable_pin_detect(codec, nid,
 +                                                    STAC_INSERT_EVENT))
 +                                      stac_issue_unsol_event(codec, nid);
                        }
                }
        }
                                stac_toggle_power_map(codec, nid, 1);
                        continue;
                }
 -              if (!stac_get_event(codec, nid, STAC_INSERT_EVENT)) {
 -                      enable_pin_detect(codec, nid, STAC_PWR_EVENT);
 -                      stac_issue_unsol_event(codec, nid, STAC_PWR_EVENT);
 -              }
 +              if (enable_pin_detect(codec, nid, STAC_PWR_EVENT))
 +                      stac_issue_unsol_event(codec, nid);
        }
        if (spec->dac_list)
                stac92xx_power_down(codec);
@@@ -4554,48 -4434,6 +4554,48 @@@ static int get_pin_presence(struct hda_
        return 0;
  }
  
 +static void stac92xx_line_out_detect(struct hda_codec *codec,
 +                                   int presence)
 +{
 +      struct sigmatel_spec *spec = codec->spec;
 +      struct auto_pin_cfg *cfg = &spec->autocfg;
 +      int i;
 +
 +      for (i = 0; i < cfg->line_outs; i++) {
 +              if (presence)
 +                      break;
 +              presence = get_pin_presence(codec, cfg->line_out_pins[i]);
 +              if (presence) {
 +                      unsigned int pinctl;
 +                      pinctl = snd_hda_codec_read(codec,
 +                                                  cfg->line_out_pins[i], 0,
 +                                          AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
 +                      if (pinctl & AC_PINCTL_IN_EN)
 +                              presence = 0; /* mic- or line-input */
 +              }
 +      }
 +
 +      if (presence) {
 +              /* disable speakers */
 +              for (i = 0; i < cfg->speaker_outs; i++)
 +                      stac92xx_reset_pinctl(codec, cfg->speaker_pins[i],
 +                                              AC_PINCTL_OUT_EN);
 +              if (spec->eapd_mask && spec->eapd_switch)
 +                      stac_gpio_set(codec, spec->gpio_mask,
 +                              spec->gpio_dir, spec->gpio_data &
 +                              ~spec->eapd_mask);
 +      } else {
 +              /* enable speakers */
 +              for (i = 0; i < cfg->speaker_outs; i++)
 +                      stac92xx_set_pinctl(codec, cfg->speaker_pins[i],
 +                                              AC_PINCTL_OUT_EN);
 +              if (spec->eapd_mask && spec->eapd_switch)
 +                      stac_gpio_set(codec, spec->gpio_mask,
 +                              spec->gpio_dir, spec->gpio_data |
 +                              spec->eapd_mask);
 +      }
 +} 
 +
  /* return non-zero if the hp-pin of the given array index isn't
   * a jack-detection target
   */
@@@ -4648,6 -4486,13 +4648,6 @@@ static void stac92xx_hp_detect(struct h
                for (i = 0; i < cfg->line_outs; i++)
                        stac92xx_reset_pinctl(codec, cfg->line_out_pins[i],
                                                AC_PINCTL_OUT_EN);
 -              for (i = 0; i < cfg->speaker_outs; i++)
 -                      stac92xx_reset_pinctl(codec, cfg->speaker_pins[i],
 -                                              AC_PINCTL_OUT_EN);
 -              if (spec->eapd_mask && spec->eapd_switch)
 -                      stac_gpio_set(codec, spec->gpio_mask,
 -                              spec->gpio_dir, spec->gpio_data &
 -                              ~spec->eapd_mask);
        } else {
                /* enable lineouts */
                if (spec->hp_switch)
                for (i = 0; i < cfg->line_outs; i++)
                        stac92xx_set_pinctl(codec, cfg->line_out_pins[i],
                                                AC_PINCTL_OUT_EN);
 -              for (i = 0; i < cfg->speaker_outs; i++)
 -                      stac92xx_set_pinctl(codec, cfg->speaker_pins[i],
 -                                              AC_PINCTL_OUT_EN);
 -              if (spec->eapd_mask && spec->eapd_switch)
 -                      stac_gpio_set(codec, spec->gpio_mask,
 -                              spec->gpio_dir, spec->gpio_data |
 -                              spec->eapd_mask);
        }
 +      stac92xx_line_out_detect(codec, presence);
        /* toggle hp outs */
        for (i = 0; i < cfg->hp_outs; i++) {
                unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN;
@@@ -4742,28 -4593,10 +4742,28 @@@ static void stac92xx_report_jack(struc
        }
  }
  
 -static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid,
 -                                 unsigned char type)
 +static void stac92xx_mic_detect(struct hda_codec *codec)
 +{
 +      struct sigmatel_spec *spec = codec->spec;
 +      struct sigmatel_mic_route *mic;
 +
 +      if (get_pin_presence(codec, spec->ext_mic.pin))
 +              mic = &spec->ext_mic;
 +      else
 +              mic = &spec->int_mic;
 +      if (mic->dmux_idx)
 +              snd_hda_codec_write_cache(codec, spec->dmux_nids[0], 0,
 +                                        AC_VERB_SET_CONNECT_SEL,
 +                                        mic->dmux_idx);
 +      else
 +              snd_hda_codec_write_cache(codec, spec->mux_nids[0], 0,
 +                                        AC_VERB_SET_CONNECT_SEL,
 +                                        mic->mux_idx);
 +}
 +
 +static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid)
  {
 -      struct sigmatel_event *event = stac_get_event(codec, nid, type);
 +      struct sigmatel_event *event = stac_get_event(codec, nid);
        if (!event)
                return;
        codec->patch_ops.unsol_event(codec, (unsigned)event->tag << 26);
@@@ -4783,19 -4616,7 +4783,19 @@@ static void stac92xx_unsol_event(struc
        switch (event->type) {
        case STAC_HP_EVENT:
                stac92xx_hp_detect(codec);
 -              /* fallthru */
 +              break;
 +      case STAC_LO_EVENT:
 +              stac92xx_line_out_detect(codec, 0);
 +              break;
 +      case STAC_MIC_EVENT:
 +              stac92xx_mic_detect(codec);
 +              break;
 +      }
 +
 +      switch (event->type) {
 +      case STAC_HP_EVENT:
 +      case STAC_LO_EVENT:
 +      case STAC_MIC_EVENT:
        case STAC_INSERT_EVENT:
        case STAC_PWR_EVENT:
                if (spec->num_pwrs > 0)
@@@ -4886,7 -4707,8 +4886,7 @@@ static int stac92xx_resume(struct hda_c
        snd_hda_codec_resume_cache(codec);
        /* fake event to set up pins again to override cached values */
        if (spec->hp_detect)
 -              stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0],
 -                                     STAC_HP_EVENT);
 +              stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0]);
        return 0;
  }
  
@@@ -4926,19 -4748,6 +4926,19 @@@ 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 &
@@@ -4975,8 -4784,7 +4975,8 @@@ static int patch_stac9200(struct hda_co
                                                        stac9200_models,
                                                        stac9200_cfg_tbl);
        if (spec->board_config < 0)
 -              snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n");
 +              snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                          codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                         stac9200_brd_tbl[spec->board_config]);
@@@ -5048,8 -4856,8 +5048,8 @@@ static int patch_stac925x(struct hda_co
                                                        stac925x_cfg_tbl);
   again:
        if (spec->board_config < 0)
 -              snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x,"
 -                                    "using BIOS defaults\n");
 +              snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                          codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                         stac925x_brd_tbl[spec->board_config]);
  
        spec->init = stac925x_core_init;
        spec->mixer = stac925x_mixer;
 +      spec->num_caps = 1;
 +      spec->capvols = stac925x_capvols;
 +      spec->capsws = stac925x_capsws;
  
        err = stac92xx_parse_auto_config(codec, 0x8, 0x7);
        if (!err) {
@@@ -5134,8 -4939,8 +5134,8 @@@ static int patch_stac92hd73xx(struct hd
                                                        stac92hd73xx_cfg_tbl);
  again:
        if (spec->board_config < 0)
 -              snd_printdd(KERN_INFO "hda_codec: Unknown model for"
 -                      " STAC92HD73XX, using BIOS defaults\n");
 +              snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                          codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                stac92hd73xx_brd_tbl[spec->board_config]);
        memcpy(&spec->private_dimux, &stac92hd73xx_dmux,
                        sizeof(stac92hd73xx_dmux));
  
 +      spec->num_caps = STAC92HD73XX_NUM_CAPS;
 +      spec->capvols = stac92hd73xx_capvols;
 +      spec->capsws = stac92hd73xx_capsws;
 +
        switch (spec->board_config) {
        case STAC_DELL_EQ:
                spec->init = dell_eq_core_init;
@@@ -5308,18 -5109,14 +5308,18 @@@ static int patch_stac92hd83xxx(struct h
        spec->num_dmics = STAC92HD83XXX_NUM_DMICS;
        spec->dinput_mux = &stac92hd83xxx_dmux;
        spec->pin_nids = stac92hd83xxx_pin_nids;
 +      spec->num_caps = STAC92HD83XXX_NUM_CAPS;
 +      spec->capvols = stac92hd83xxx_capvols;
 +      spec->capsws = stac92hd83xxx_capsws;
 +
        spec->board_config = snd_hda_check_board_config(codec,
                                                        STAC_92HD83XXX_MODELS,
                                                        stac92hd83xxx_models,
                                                        stac92hd83xxx_cfg_tbl);
  again:
        if (spec->board_config < 0)
 -              snd_printdd(KERN_INFO "hda_codec: Unknown model for"
 -                      " STAC92HD83XXX, using BIOS defaults\n");
 +              snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                          codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                stac92hd83xxx_brd_tbl[spec->board_config]);
  
        num_dacs = snd_hda_get_connections(codec, nid,
                                conn, STAC92HD83_DAC_COUNT + 1) - 1;
 +      if (num_dacs < 0)
 +              num_dacs = STAC92HD83_DAC_COUNT;
  
        /* set port X to select the last DAC
         */
@@@ -5484,8 -5279,8 +5484,8 @@@ static int patch_stac92hd71bxx(struct h
                                                        stac92hd71bxx_cfg_tbl);
  again:
        if (spec->board_config < 0)
 -              snd_printdd(KERN_INFO "hda_codec: Unknown model for"
 -                      " STAC92HD71BXX, using BIOS defaults\n");
 +              snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                          codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                stac92hd71bxx_brd_tbl[spec->board_config]);
        spec->dmic_nids = stac92hd71bxx_dmic_nids;
        spec->dmux_nids = stac92hd71bxx_dmux_nids;
  
 +      spec->num_caps = STAC92HD71BXX_NUM_CAPS;
 +      spec->capvols = stac92hd71bxx_capvols;
 +      spec->capsws = stac92hd71bxx_capsws;
 +
        switch (codec->vendor_id) {
        case 0x111d76b6: /* 4 Port without Analog Mixer */
        case 0x111d76b7:
        case 0x111d76b5:
                memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_nomixer,
                       sizeof(stac92hd71bxx_dmux_nomixer));
 -              spec->mixer = stac92hd71bxx_mixer;
                spec->init = stac92hd71bxx_core_init;
                codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
                spec->num_dmics = stac92hd71bxx_connected_ports(codec,
                }
                break;
        case 0x111d7608: /* 5 Port with Analog Mixer */
 -              memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer,
 -                     sizeof(stac92hd71bxx_dmux_amixer));
                spec->private_dimux.num_items--;
                switch (spec->board_config) {
                case STAC_HP_M4:
  
                /* no output amps */
                spec->num_pwrs = 0;
 -              spec->mixer = stac92hd71bxx_analog_mixer;
 -              spec->dinput_mux = &spec->private_dimux;
 -
 +              if (snd_hda_get_bool_hint(codec, "analog_mixer") == 1) {
 +                      spec->mixer = stac92hd71bxx_analog_mixer;
 +                      memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer,
 +                             sizeof(stac92hd71bxx_dmux_amixer));
 +              } else {
 +                      memcpy(&spec->private_dimux,
 +                             &stac92hd71bxx_dmux_nomixer,
 +                             sizeof(stac92hd71bxx_dmux_nomixer));
 +              }
                /* disable VSW */
 -              spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF];
 +              spec->init = stac92hd71bxx_core_init;
                unmute_init++;
                snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0);
                snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3);
                spec->num_dmics = stac92hd71bxx_connected_ports(codec,
                                        stac92hd71bxx_dmic_nids,
                                        STAC92HD71BXX_NUM_DMICS - 1);
 -              spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
 -              ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 2;
 +              if (spec->num_dmics) {
 +                      spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
 +                      spec->dinput_mux = &spec->private_dimux;
 +                      ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 2;
 +              }
                break;
        case 0x111d7603: /* 6 Port with Analog Mixer */
                if ((codec->revision_id & 0xf) == 1)
                spec->num_pwrs = 0;
                /* fallthru */
        default:
 -              memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer,
 -                     sizeof(stac92hd71bxx_dmux_amixer));
 -              spec->dinput_mux = &spec->private_dimux;
 -              spec->mixer = stac92hd71bxx_analog_mixer;
 -              spec->init = stac92hd71bxx_analog_core_init;
 +              if (snd_hda_get_bool_hint(codec, "analog_mixer") == 1) {
 +                      spec->mixer = stac92hd71bxx_analog_mixer;
 +                      memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer,
 +                             sizeof(stac92hd71bxx_dmux_amixer));
 +              } else {
 +                      memcpy(&spec->private_dimux,
 +                             &stac92hd71bxx_dmux_nomixer,
 +                             sizeof(stac92hd71bxx_dmux_nomixer));
 +              }
 +              spec->init = stac92hd71bxx_core_init;
                codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
                spec->num_dmics = stac92hd71bxx_connected_ports(codec,
                                        stac92hd71bxx_dmic_nids,
                                        STAC92HD71BXX_NUM_DMICS);
 -              spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
 -              ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1;
 +              if (spec->num_dmics) {
 +                      spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
 +                      spec->dinput_mux = &spec->private_dimux;
 +                      ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1;
 +              }
        }
  
        if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP)
@@@ -5758,8 -5535,8 +5758,8 @@@ static int patch_stac922x(struct hda_co
  
   again:
        if (spec->board_config < 0)
 -              snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, "
 -                      "using BIOS defaults\n");
 +              snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                          codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                stac922x_brd_tbl[spec->board_config]);
        spec->num_pwrs = 0;
  
        spec->init = stac922x_core_init;
 -      spec->mixer = stac922x_mixer;
 +
 +      spec->num_caps = STAC922X_NUM_CAPS;
 +      spec->capvols = stac922x_capvols;
 +      spec->capsws = stac922x_capsws;
  
        spec->multiout.dac_nids = spec->dac_nids;
        
@@@ -5824,8 -5598,8 +5824,8 @@@ static int patch_stac927x(struct hda_co
                                                        stac927x_cfg_tbl);
   again:
        if (spec->board_config < 0)
 -              snd_printdd(KERN_INFO "hda_codec: Unknown model for"
 -                          "STAC927x, using BIOS defaults\n");
 +              snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                          codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                stac927x_brd_tbl[spec->board_config]);
                spec->num_dmics = 0;
  
                spec->init = d965_core_init;
 -              spec->mixer = stac927x_mixer;
                break;
        case STAC_DELL_BIOS:
                switch (codec->subsystem_id) {
                /* GPIO2 High = Enable EAPD */
                spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x04;
                spec->gpio_data = 0x04;
+               switch (codec->subsystem_id) {
+               case 0x1028022f:
+                       /* correct EAPD to be GPIO0 */
+                       spec->eapd_mask = spec->gpio_mask = 0x01;
+                       spec->gpio_dir = spec->gpio_data = 0x01;
+                       break;
+               };
                spec->dmic_nids = stac927x_dmic_nids;
                spec->num_dmics = STAC927X_NUM_DMICS;
  
                spec->init = d965_core_init;
 -              spec->mixer = stac927x_mixer;
                spec->dmux_nids = stac927x_dmux_nids;
                spec->num_dmuxes = ARRAY_SIZE(stac927x_dmux_nids);
                break;
                spec->num_dmics = 0;
  
                spec->init = stac927x_core_init;
 -              spec->mixer = stac927x_mixer;
        }
  
 +      spec->num_caps = STAC927X_NUM_CAPS;
 +      spec->capvols = stac927x_capvols;
 +      spec->capsws = stac927x_capsws;
 +
        spec->num_pwrs = 0;
        spec->aloopback_ctl = stac927x_loopback;
        spec->aloopback_mask = 0x40;
@@@ -5953,8 -5733,7 +5960,8 @@@ static int patch_stac9205(struct hda_co
                                                        stac9205_cfg_tbl);
   again:
        if (spec->board_config < 0)
 -              snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n");
 +              snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                          codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                         stac9205_brd_tbl[spec->board_config]);
        spec->num_pwrs = 0;
  
        spec->init = stac9205_core_init;
 -      spec->mixer = stac9205_mixer;
        spec->aloopback_ctl = stac9205_loopback;
  
 +      spec->num_caps = STAC9205_NUM_CAPS;
 +      spec->capvols = stac9205_capvols;
 +      spec->capsws = stac9205_capsws;
 +
        spec->aloopback_mask = 0x40;
        spec->aloopback_shift = 0;
        /* Turn on/off EAPD per HP plugging */
@@@ -6053,6 -5829,12 +6060,6 @@@ static struct hda_verb stac9872_core_in
        {}
  };
  
 -static struct snd_kcontrol_new stac9872_mixer[] = {
 -      HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
 -      HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
 -      { } /* end */
 -};
 -
  static hda_nid_t stac9872_pin_nids[] = {
        0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0x11, 0x13, 0x14,
@@@ -6066,11 -5848,6 +6073,11 @@@ static hda_nid_t stac9872_mux_nids[] = 
        0x15
  };
  
 +static unsigned long stac9872_capvols[] = {
 +      HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
 +};
 +#define stac9872_capsws               stac9872_capvols
 +
  static unsigned int stac9872_vaio_pin_configs[9] = {
        0x03211020, 0x411111f0, 0x411111f0, 0x03a15030,
        0x411111f0, 0x90170110, 0x411111f0, 0x411111f0,
@@@ -6108,8 -5885,8 +6115,8 @@@ static int patch_stac9872(struct hda_co
                                                        stac9872_models,
                                                        stac9872_cfg_tbl);
        if (spec->board_config < 0)
 -              snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9872, "
 -                          "using BIOS defaults\n");
 +              snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 +                          codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                         stac9872_brd_tbl[spec->board_config]);
        spec->adc_nids = stac9872_adc_nids;
        spec->num_muxes = ARRAY_SIZE(stac9872_mux_nids);
        spec->mux_nids = stac9872_mux_nids;
 -      spec->mixer = stac9872_mixer;
        spec->init = stac9872_core_init;
 +      spec->num_caps = 1;
 +      spec->capvols = stac9872_capvols;
 +      spec->capsws = stac9872_capsws;
  
        err = stac92xx_parse_auto_config(codec, 0x10, 0x12);
        if (err < 0) {