Merge branch 'fix/hda' into topic/hda
authorTakashi Iwai <tiwai@suse.de>
Tue, 11 Aug 2009 06:47:38 +0000 (08:47 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 11 Aug 2009 06:47:38 +0000 (08:47 +0200)
1  2 
sound/pci/hda/patch_realtek.c

@@@ -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 */
@@@ -258,14 -262,6 +258,14 @@@ enum 
        ALC_INIT_GPIO3,
  };
  
 +struct alc_mic_route {
 +      hda_nid_t pin;
 +      unsigned char mux_idx;
 +      unsigned char amix_idx;
 +};
 +
 +#define MUX_IDX_UNDEF ((unsigned char)-1)
 +
  struct alc_spec {
        /* codec parameterization */
        struct snd_kcontrol_new *mixers[5];     /* mixer arrays */
        unsigned int num_mux_defs;
        const struct hda_input_mux *input_mux;
        unsigned int cur_mux[3];
 +      struct alc_mic_route ext_mic;
 +      struct alc_mic_route int_mic;
  
        /* channel model */
        const struct hda_channel_mode *channel_mode;
        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);
        unsigned int sense_updated: 1;
        unsigned int jack_present: 1;
        unsigned int master_sw: 1;
 +      unsigned int auto_mic:1;
  
        /* other flags */
        unsigned int no_analog :1; /* digital I/O only */
@@@ -426,7 -417,7 +426,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];
@@@ -974,79 -965,30 +974,79 @@@ static void alc_automute_pin(struct hda
        }
  }
  
 -#if 0 /* it's broken in some cases -- temporarily disabled */
 +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;
 +}
 +
 +static int set_mic_mux_idx(struct hda_codec *codec, hda_nid_t cap,
 +                         struct alc_mic_route *mic)
 +{
 +      int idx = get_connection_index(codec, cap, mic->pin);
 +      if (idx < 0)
 +              return 1; /* invalid */
 +      mic->mux_idx = idx;
 +      return 0;
 +}
 +
  static void alc_mic_automute(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
 -      unsigned int present;
 -      unsigned int mic_nid = spec->autocfg.input_pins[AUTO_PIN_MIC];
 -      unsigned int fmic_nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC];
 -      unsigned int mix_nid = spec->capsrc_nids[0];
 -      unsigned int capsrc_idx_mic, capsrc_idx_fmic;
 -
 -      capsrc_idx_mic = mic_nid - 0x18;
 -      capsrc_idx_fmic = fmic_nid - 0x18;
 -      present = snd_hda_codec_read(codec, mic_nid, 0,
 -                                   AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
 -      snd_hda_codec_write(codec, mix_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
 -                  0x7000 | (capsrc_idx_mic << 8) | (present ? 0 : 0x80));
 -      snd_hda_codec_write(codec, mix_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
 -                  0x7000 | (capsrc_idx_fmic << 8) | (present ? 0x80 : 0));
 -      snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, capsrc_idx_fmic,
 -                       HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
 +      struct alc_mic_route *dead, *alive;
 +      unsigned int present, type;
 +      hda_nid_t cap_nid;
 +
 +      if (!spec->int_mic.pin || !spec->ext_mic.pin)
 +              return;
 +      if (snd_BUG_ON(!spec->adc_nids))
 +              return;
 +
 +      cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0];
 +
 +      present = snd_hda_codec_read(codec, spec->ext_mic.pin, 0,
 +                                   AC_VERB_GET_PIN_SENSE, 0);
 +      present &= AC_PINSENSE_PRESENCE;
 +      if (present) {
 +              alive = &spec->ext_mic;
 +              dead = &spec->int_mic;
 +      } else {
 +              alive = &spec->int_mic;
 +              dead = &spec->ext_mic;
 +      }
 +
 +      if (alive->mux_idx == MUX_IDX_UNDEF &&
 +          set_mic_mux_idx(codec, cap_nid, alive))
 +              return;
 +      if (dead->mux_idx == MUX_IDX_UNDEF &&
 +          set_mic_mux_idx(codec, cap_nid, dead))
 +              return;
 +
 +      type = get_wcaps_type(get_wcaps(codec, cap_nid));
 +      if (type == AC_WID_AUD_MIX) {
 +              /* Matrix-mixer style (e.g. ALC882) */
 +              snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
 +                                       alive->mux_idx,
 +                                       HDA_AMP_MUTE, 0);
 +              snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
 +                                       dead->mux_idx,
 +                                       HDA_AMP_MUTE, HDA_AMP_MUTE);
 +      } else {
 +              /* MUX style (e.g. ALC880) */
 +              snd_hda_codec_write_cache(codec, cap_nid, 0,
 +                                        AC_VERB_SET_CONNECT_SEL,
 +                                        alive->mux_idx);
 +      }
 +
 +      /* FIXME: analog mixer */
  }
 -#else
 -#define alc_mic_automute(codec) do {} while(0) /* NOP */
 -#endif /* disabled */
  
  /* unsolicited event for HP jack sensing */
  static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
@@@ -1089,16 -1031,6 +1089,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);
@@@ -1202,55 -1142,6 +1202,55 @@@ static void alc_init_auto_hp(struct hda
        spec->unsol_event = alc_sku_unsol_event;
  }
  
 +static void alc_init_auto_mic(struct hda_codec *codec)
 +{
 +      struct alc_spec *spec = codec->spec;
 +      struct auto_pin_cfg *cfg = &spec->autocfg;
 +      hda_nid_t fixed, ext;
 +      int i;
 +
 +      /* there must be only two mic inputs exclusively */
 +      for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++)
 +              if (cfg->input_pins[i])
 +                      return;
 +
 +      fixed = ext = 0;
 +      for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) {
 +              hda_nid_t nid = cfg->input_pins[i];
 +              unsigned int defcfg;
 +              if (!nid)
 +                      return;
 +              defcfg = snd_hda_codec_get_pincfg(codec, nid);
 +              switch (get_defcfg_connect(defcfg)) {
 +              case AC_JACK_PORT_FIXED:
 +                      if (fixed)
 +                              return; /* already occupied */
 +                      fixed = nid;
 +                      break;
 +              case AC_JACK_PORT_COMPLEX:
 +                      if (ext)
 +                              return; /* already occupied */
 +                      ext = nid;
 +                      break;
 +              default:
 +                      return; /* invalid entry */
 +              }
 +      }
 +      if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
 +              return; /* no unsol support */
 +      snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x\n",
 +                  ext, fixed);
 +      spec->ext_mic.pin = ext;
 +      spec->int_mic.pin = fixed;
 +      spec->ext_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
 +      spec->int_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
 +      spec->auto_mic = 1;
 +      snd_hda_codec_write_cache(codec, spec->ext_mic.pin, 0,
 +                                AC_VERB_SET_UNSOLICITED_ENABLE,
 +                                AC_USRSP_EN | ALC880_MIC_EVENT);
 +      spec->unsol_event = alc_sku_unsol_event;
 +}
 +
  /* check subsystem ID and set up device-specific initialization;
   * return 1 if initialized, 0 if invalid SSID
   */
@@@ -1352,7 -1243,6 +1352,7 @@@ do_sku
        }
  
        alc_init_auto_hp(codec);
 +      alc_init_auto_mic(codec);
        return 1;
  }
  
@@@ -1365,7 -1255,6 +1365,7 @@@ static void alc_ssid_check(struct hda_c
                           "Enable default setup for auto mode as fallback\n");
                spec->init_amp = ALC_INIT_DEFAULT;
                alc_init_auto_hp(codec);
 +              alc_init_auto_mic(codec);
        }
  }
  
@@@ -1547,25 -1436,6 +1547,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;
@@@ -4635,6 -4505,12 +4635,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 {
@@@ -4683,10 -4559,7 +4683,10 @@@ static void set_capture_mixer(struct al
        };
        if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) {
                int mux;
 -              if (spec->input_mux && spec->input_mux->num_items > 1)
 +              if (spec->auto_mic) {
 +                      mux = 0;
 +                      spec->num_adc_nids = 1; /* support only one ADC */
 +              } else if (spec->input_mux && spec->input_mux->num_items > 1)
                        mux = 1;
                else
                        mux = 0;
@@@ -4717,8 -4590,8 +4717,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);
@@@ -6361,7 -6234,8 +6361,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 */
@@@ -6482,17 -6343,6 +6482,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
   */
@@@ -6584,18 -6363,6 +6584,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
   */
@@@ -6609,14 -6376,11 +6609,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
   */
@@@ -6704,239 -6468,56 +6704,239 @@@ 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),
 +/*
 + * 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 },
 +};
 +
 +/*
 + * 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),
@@@ -7022,7 -6603,7 +7022,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},
 +      /* 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 Mic pin: input vref at 80% */
 +      /* 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 */
@@@ -7561,72 -7027,893 +7561,72 @@@ static void alc885_macpro_init_hook(str
        alc882_gpio_mute(codec, 1, 0);
  }
  
 -/* 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 */
 -};
 -
 +/* 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);
 +}
 +
  /*
 - * 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) */
@@@ -7679,7 -7966,34 +7679,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),
@@@ -7790,30 -8104,6 +7790,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),
@@@ -8054,6 -8344,84 +8054,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)
  {
@@@ -8483,8 -8851,71 +8483,8 @@@ static void alc883_vaiott_init_hook(str
        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)},
 -
 -      { }
 -};
 +      alc_automute_amp(codec);
 +}
  
  static struct hda_verb alc888_asus_m90v_verbs[] = {
        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
@@@ -8596,44 -9027,25 +8596,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);
  }
  
 -#define alc883_is_input_pin(nid)      alc880_is_input_pin(nid)
 -#define ALC883_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, 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 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
   */
@@@ -10263,6 -10359,12 +10263,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},
@@@ -11304,7 -11406,7 +11304,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,
@@@ -11547,8 -11648,8 +11547,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 =
@@@ -12168,38 -12269,26 +12168,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;
@@@ -12212,19 -12301,14 +12212,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;
        }
@@@ -12620,8 -12697,8 +12620,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);
@@@ -13438,8 -13515,8 +13438,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;
        }
  
@@@ -14033,23 -14110,23 +14033,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 */
  
@@@ -14121,96 -14198,64 +14121,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)
@@@ -14332,13 -14358,12 +14332,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)
@@@ -14370,16 -14395,16 +14370,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;
  
@@@ -14591,8 -14616,8 +14591,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;
        }
  
@@@ -15515,8 -15540,8 +15515,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;
        }
  
        spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
        spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
  
-       spec->adc_nids = alc861vd_adc_nids;
-       spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
-       spec->capsrc_nids = alc861vd_capsrc_nids;
+       if (!spec->adc_nids) {
+               spec->adc_nids = alc861vd_adc_nids;
+               spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
+       }
+       if (!spec->capsrc_nids)
+               spec->capsrc_nids = alc861vd_capsrc_nids;
  
        set_capture_mixer(spec);
        set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
@@@ -17232,6 -17260,25 +17235,6 @@@ static int alc662_auto_create_extra_out
        return 0;
  }
  
 -/* return the index of the src widget from the connection list of the nid.
 - * return -1 if not found
 - */
 -static int alc662_input_pin_idx(struct hda_codec *codec, hda_nid_t nid,
 -                              hda_nid_t src)
 -{
 -      hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
 -      int i, conns;
 -
 -      conns = snd_hda_get_connections(codec, nid, conn_list,
 -                                      ARRAY_SIZE(conn_list));
 -      if (conns < 0)
 -              return -1;
 -      for (i = 0; i < conns; i++)
 -              if (conn_list[i] == src)
 -                      return i;
 -      return -1;
 -}
 -
  static int alc662_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
  {
        unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
@@@ -17248,7 -17295,7 +17251,7 @@@ static int alc662_auto_create_analog_in
  
        for (i = 0; i < AUTO_PIN_LAST; i++) {
                if (alc662_is_input_pin(codec, cfg->input_pins[i])) {
 -                      idx = alc662_input_pin_idx(codec, 0x0b,
 +                      idx = get_connection_index(codec, 0x0b,
                                                   cfg->input_pins[i]);
                        if (idx >= 0) {
                                err = new_analog_input(spec, cfg->input_pins[i],
                                if (err < 0)
                                        return err;
                        }
 -                      idx = alc662_input_pin_idx(codec, 0x22,
 +                      idx = get_connection_index(codec, 0x22,
                                                   cfg->input_pins[i]);
                        if (idx >= 0) {
                                imux->items[imux->num_items].label =
@@@ -17420,8 -17467,8 +17423,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;
        }
  
        spec->stream_digital_playback = &alc662_pcm_digital_playback;
        spec->stream_digital_capture = &alc662_pcm_digital_capture;
  
-       spec->adc_nids = alc662_adc_nids;
-       spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
-       spec->capsrc_nids = alc662_capsrc_nids;
+       if (!spec->adc_nids) {
+               spec->adc_nids = alc662_adc_nids;
+               spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
+       }
+       if (!spec->capsrc_nids)
+               spec->capsrc_nids = alc662_capsrc_nids;
  
        if (!spec->cap_mixer)
                set_capture_mixer(spec);
@@@ -17495,23 -17545,23 +17501,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 */
  };