Merge branch 'fix/hda' into for-linus
authorTakashi Iwai <tiwai@suse.de>
Tue, 18 Jan 2011 06:44:55 +0000 (07:44 +0100)
committerTakashi Iwai <tiwai@suse.de>
Tue, 18 Jan 2011 06:44:55 +0000 (07:44 +0100)
1  2 
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_via.c

@@@ -1235,8 -1235,7 +1235,8 @@@ static int azx_setup_periods(struct az
                        pos_adj = 0;
                } else {
                        ofs = setup_bdle(substream, azx_dev,
 -                                       &bdl, ofs, pos_adj, 1);
 +                                       &bdl, ofs, pos_adj,
 +                                       !substream->runtime->no_period_wakeup);
                        if (ofs < 0)
                                goto error;
                }
                                         period_bytes - pos_adj, 0);
                else
                        ofs = setup_bdle(substream, azx_dev, &bdl, ofs,
 -                                       period_bytes, 1);
 +                                       period_bytes,
 +                                       !substream->runtime->no_period_wakeup);
                if (ofs < 0)
                        goto error;
        }
@@@ -1517,8 -1515,7 +1517,8 @@@ static struct snd_pcm_hardware azx_pcm_
                                 /* No full-resume yet implemented */
                                 /* SNDRV_PCM_INFO_RESUME |*/
                                 SNDRV_PCM_INFO_PAUSE |
 -                               SNDRV_PCM_INFO_SYNC_START),
 +                               SNDRV_PCM_INFO_SYNC_START |
 +                               SNDRV_PCM_INFO_NO_PERIOD_WAKEUP),
        .formats =              SNDRV_PCM_FMTBIT_S16_LE,
        .rates =                SNDRV_PCM_RATE_48000,
        .rate_min =             48000,
@@@ -2809,6 -2806,8 +2809,8 @@@ static DEFINE_PCI_DEVICE_TABLE(azx_ids
  #endif
        /* Vortex86MX */
        { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC },
+       /* VMware HDAudio */
+       { PCI_DEVICE(0x15ad, 0x1977), .driver_data = AZX_DRIVER_GENERIC },
        /* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */
        { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID),
          .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
@@@ -303,6 -303,8 +303,8 @@@ struct alc_customize_define 
        unsigned int  fixup:1; /* Means that this sku is set by driver, not read from hw */
  };
  
+ struct alc_fixup;
  struct alc_spec {
        /* codec parameterization */
        struct snd_kcontrol_new *mixers[5];     /* mixer arrays */
        /* for PLL fix */
        hda_nid_t pll_nid;
        unsigned int pll_coef_idx, pll_coef_bit;
+       /* fix-up list */
+       int fixup_id;
+       const struct alc_fixup *fixup_list;
+       const char *fixup_name;
  };
  
  /*
@@@ -1683,88 -1690,131 +1690,131 @@@ struct alc_model_fixup 
  };
  
  struct alc_fixup {
-       unsigned int sku;
-       const struct alc_pincfg *pins;
-       const struct hda_verb *verbs;
-       void (*func)(struct hda_codec *codec, const struct alc_fixup *fix,
-                    int pre_init);
+       int type;
+       bool chained;
+       int chain_id;
+       union {
+               unsigned int sku;
+               const struct alc_pincfg *pins;
+               const struct hda_verb *verbs;
+               void (*func)(struct hda_codec *codec,
+                            const struct alc_fixup *fix,
+                            int action);
+       } v;
  };
  
- static void __alc_pick_fixup(struct hda_codec *codec,
-                            const struct alc_fixup *fix,
-                            const char *modelname,
-                            int pre_init)
+ enum {
+       ALC_FIXUP_INVALID,
+       ALC_FIXUP_SKU,
+       ALC_FIXUP_PINS,
+       ALC_FIXUP_VERBS,
+       ALC_FIXUP_FUNC,
+ };
+ enum {
+       ALC_FIXUP_ACT_PRE_PROBE,
+       ALC_FIXUP_ACT_PROBE,
+       ALC_FIXUP_ACT_INIT,
+ };
+ static void alc_apply_fixup(struct hda_codec *codec, int action)
  {
-       const struct alc_pincfg *cfg;
-       struct alc_spec *spec;
+       struct alc_spec *spec = codec->spec;
+       int id = spec->fixup_id;
+       const char *modelname = spec->fixup_name;
+       int depth = 0;
  
-       cfg = fix->pins;
-       if (pre_init && fix->sku) {
- #ifdef CONFIG_SND_DEBUG_VERBOSE
-               snd_printdd(KERN_INFO "hda_codec: %s: Apply sku override for %s\n",
-                           codec->chip_name, modelname);
- #endif
-               spec = codec->spec;
-               spec->cdefine.sku_cfg = fix->sku;
-               spec->cdefine.fixup = 1;
-       }
-       if (pre_init && cfg) {
- #ifdef CONFIG_SND_DEBUG_VERBOSE
-               snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n",
-                           codec->chip_name, modelname);
- #endif
-               for (; cfg->nid; cfg++)
-                       snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
-       }
-       if (!pre_init && fix->verbs) {
- #ifdef CONFIG_SND_DEBUG_VERBOSE
-               snd_printdd(KERN_INFO "hda_codec: %s: Apply fix-verbs for %s\n",
-                           codec->chip_name, modelname);
- #endif
-               add_verb(codec->spec, fix->verbs);
-       }
-       if (fix->func) {
- #ifdef CONFIG_SND_DEBUG_VERBOSE
-               snd_printdd(KERN_INFO "hda_codec: %s: Apply fix-func for %s\n",
-                           codec->chip_name, modelname);
- #endif
-               fix->func(codec, fix, pre_init);
+       if (!spec->fixup_list)
+               return;
+       while (id >= 0) {
+               const struct alc_fixup *fix = spec->fixup_list + id;
+               const struct alc_pincfg *cfg;
+               switch (fix->type) {
+               case ALC_FIXUP_SKU:
+                       if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
+                               break;;
+                       snd_printdd(KERN_INFO "hda_codec: %s: "
+                                   "Apply sku override for %s\n",
+                                   codec->chip_name, modelname);
+                       spec->cdefine.sku_cfg = fix->v.sku;
+                       spec->cdefine.fixup = 1;
+                       break;
+               case ALC_FIXUP_PINS:
+                       cfg = fix->v.pins;
+                       if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
+                               break;
+                       snd_printdd(KERN_INFO "hda_codec: %s: "
+                                   "Apply pincfg for %s\n",
+                                   codec->chip_name, modelname);
+                       for (; cfg->nid; cfg++)
+                               snd_hda_codec_set_pincfg(codec, cfg->nid,
+                                                        cfg->val);
+                       break;
+               case ALC_FIXUP_VERBS:
+                       if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
+                               break;
+                       snd_printdd(KERN_INFO "hda_codec: %s: "
+                                   "Apply fix-verbs for %s\n",
+                                   codec->chip_name, modelname);
+                       add_verb(codec->spec, fix->v.verbs);
+                       break;
+               case ALC_FIXUP_FUNC:
+                       if (!fix->v.func)
+                               break;
+                       snd_printdd(KERN_INFO "hda_codec: %s: "
+                                   "Apply fix-func for %s\n",
+                                   codec->chip_name, modelname);
+                       fix->v.func(codec, fix, action);
+                       break;
+               default:
+                       snd_printk(KERN_ERR "hda_codec: %s: "
+                                  "Invalid fixup type %d\n",
+                                  codec->chip_name, fix->type);
+                       break;
+               }
+               if (!fix[id].chained)
+                       break;
+               if (++depth > 10)
+                       break;
+               id = fix[id].chain_id;
        }
  }
  
  static void alc_pick_fixup(struct hda_codec *codec,
-                                const struct snd_pci_quirk *quirk,
-                                const struct alc_fixup *fix,
-                                int pre_init)
+                          const struct alc_model_fixup *models,
+                          const struct snd_pci_quirk *quirk,
+                          const struct alc_fixup *fixlist)
  {
-       quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
-       if (quirk) {
-               fix += quirk->value;
- #ifdef CONFIG_SND_DEBUG_VERBOSE
-               __alc_pick_fixup(codec, fix, quirk->name, pre_init);
- #else
-               __alc_pick_fixup(codec, fix, NULL, pre_init);
- #endif
-       }
- }
+       struct alc_spec *spec = codec->spec;
+       int id = -1;
+       const char *name = NULL;
  
- static void alc_pick_fixup_model(struct hda_codec *codec,
-                                const struct alc_model_fixup *models,
-                                const struct snd_pci_quirk *quirk,
-                                const struct alc_fixup *fix,
-                                int pre_init)
- {
        if (codec->modelname && models) {
                while (models->name) {
                        if (!strcmp(codec->modelname, models->name)) {
-                               fix += models->id;
+                               id = models->id;
+                               name = models->name;
                                break;
                        }
                        models++;
                }
-               __alc_pick_fixup(codec, fix, codec->modelname, pre_init);
-       } else {
-               alc_pick_fixup(codec, quirk, fix, pre_init);
+       }
+       if (id < 0) {
+               quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
+               if (quirk) {
+                       id = quirk->value;
+ #ifdef CONFIG_SND_DEBUG_VERBOSE
+                       name = quirk->name;
+ #endif
+               }
+       }
+       spec->fixup_id = id;
+       if (id >= 0) {
+               spec->fixup_list = fixlist;
+               spec->fixup_name = name;
        }
  }
  
@@@ -2866,7 -2916,7 +2916,7 @@@ static struct snd_kcontrol_new alc880_u
  /*
   * slave controls for virtual master
   */
- static const char *alc_slave_vols[] = {
+ static const char * const alc_slave_vols[] = {
        "Front Playback Volume",
        "Surround Playback Volume",
        "Center Playback Volume",
        NULL,
  };
  
- static const char *alc_slave_sws[] = {
+ static const char * const alc_slave_sws[] = {
        "Front Playback Switch",
        "Surround Playback Switch",
        "Center Playback Switch",
@@@ -3861,6 -3911,8 +3911,8 @@@ static int alc_init(struct hda_codec *c
        if (spec->init_hook)
                spec->init_hook(codec);
  
+       alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
        hda_call_check_power_status(codec, 0x01);
        return 0;
  }
@@@ -4559,7 -4611,7 +4611,7 @@@ static struct hda_verb alc880_test_init
  /*
   */
  
- static const char *alc880_models[ALC880_MODEL_LAST] = {
+ static const char * const alc880_models[ALC880_MODEL_LAST] = {
        [ALC880_3ST]            = "3stack",
        [ALC880_TCL_S700]       = "tcl",
        [ALC880_3ST_DIG]        = "3stack-digout",
@@@ -5092,7 -5144,7 +5144,7 @@@ static const char *alc_get_line_out_pfx
  static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
                                             const struct auto_pin_cfg *cfg)
  {
-       static const char *chname[4] = {
+       static const char * const chname[4] = {
                "Front", "Surround", NULL /*CLFE*/, "Side"
        };
        const char *pfx = alc_get_line_out_pfx(cfg, false);
@@@ -7090,7 -7142,8 +7142,8 @@@ enum 
  
  static const struct alc_fixup alc260_fixups[] = {
        [PINFIX_HP_DC5750] = {
-               .pins = (const struct alc_pincfg[]) {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
                        { 0x11, 0x90130110 }, /* speaker */
                        { }
                }
@@@ -7105,7 -7158,7 +7158,7 @@@ static struct snd_pci_quirk alc260_fixu
  /*
   * ALC260 configurations
   */
- static const char *alc260_models[ALC260_MODEL_LAST] = {
+ static const char * const alc260_models[ALC260_MODEL_LAST] = {
        [ALC260_BASIC]          = "basic",
        [ALC260_HP]             = "hp",
        [ALC260_HP_3013]        = "hp-3013",
@@@ -7301,8 -7354,10 +7354,10 @@@ static int patch_alc260(struct hda_code
                board_config = ALC260_AUTO;
        }
  
-       if (board_config == ALC260_AUTO)
-               alc_pick_fixup(codec, alc260_fixup_tbl, alc260_fixups, 1);
+       if (board_config == ALC260_AUTO) {
+               alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
+               alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+       }
  
        if (board_config == ALC260_AUTO) {
                /* automatic parse from the BIOS config */
        set_capture_mixer(codec);
        set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
  
-       if (board_config == ALC260_AUTO)
-               alc_pick_fixup(codec, alc260_fixup_tbl, alc260_fixups, 0);
+       alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
  
        spec->vmaster_nid = 0x08;
  
@@@ -9727,7 -9781,7 +9781,7 @@@ static hda_nid_t alc1200_slave_dig_outs
  /*
   * configuration and preset
   */
- static const char *alc882_models[ALC882_MODEL_LAST] = {
+ static const char * const alc882_models[ALC882_MODEL_LAST] = {
        [ALC882_3ST_DIG]        = "3stack-dig",
        [ALC882_6ST_DIG]        = "6stack-dig",
        [ALC882_ARIMA]          = "arima",
@@@ -10678,7 -10732,8 +10732,8 @@@ enum 
  
  static const struct alc_fixup alc882_fixups[] = {
        [PINFIX_ABIT_AW9D_MAX] = {
-               .pins = (const struct alc_pincfg[]) {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
                        { 0x15, 0x01080104 }, /* side */
                        { 0x16, 0x01011012 }, /* rear */
                        { 0x17, 0x01016011 }, /* clfe */
                }
        },
        [PINFIX_PB_M5210] = {
-               .verbs = (const struct hda_verb[]) {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
                        { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
                        {}
                }
        },
        [PINFIX_ACER_ASPIRE_7736] = {
-               .sku = ALC_FIXUP_SKU_IGNORE,
+               .type = ALC_FIXUP_SKU,
+               .v.sku = ALC_FIXUP_SKU_IGNORE,
        },
  };
  
@@@ -10873,9 -10930,6 +10930,9 @@@ static int alc_auto_add_mic_boost(struc
        return 0;
  }
  
 +static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
 +                                           const struct auto_pin_cfg *cfg);
 +
  /* almost identical with ALC880 parser... */
  static int alc882_parse_auto_config(struct hda_codec *codec)
  {
        err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
        if (err < 0)
                return err;
 -      err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
 +      if (codec->vendor_id == 0x10ec0887)
 +              err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
 +      else
 +              err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
        if (err < 0)
                return err;
        err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
@@@ -10984,8 -11035,10 +11041,10 @@@ static int patch_alc882(struct hda_code
                board_config = ALC882_AUTO;
        }
  
-       if (board_config == ALC882_AUTO)
-               alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 1);
+       if (board_config == ALC882_AUTO) {
+               alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
+               alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+       }
  
        alc_auto_parse_customize_define(codec);
  
        if (has_cdefine_beep(codec))
                set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
  
-       if (board_config == ALC882_AUTO)
-               alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 0);
+       alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
  
        spec->vmaster_nid = 0x0c;
  
@@@ -12452,19 -12504,14 +12510,14 @@@ enum 
  
  static const struct alc_fixup alc262_fixups[] = {
        [PINFIX_FSC_H270] = {
-               .pins = (const struct alc_pincfg[]) {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
                        { 0x14, 0x99130110 }, /* speaker */
                        { 0x15, 0x0221142f }, /* front HP */
                        { 0x1b, 0x0121141f }, /* rear HP */
                        { }
                }
        },
-       [PINFIX_PB_M5210] = {
-               .verbs = (const struct hda_verb[]) {
-                       { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
-                       {}
-               }
-       },
  };
  
  static struct snd_pci_quirk alc262_fixup_tbl[] = {
@@@ -12554,7 -12601,7 +12607,7 @@@ static void alc262_auto_init(struct hda
  /*
   * configuration and preset
   */
- static const char *alc262_models[ALC262_MODEL_LAST] = {
+ static const char * const alc262_models[ALC262_MODEL_LAST] = {
        [ALC262_BASIC]          = "basic",
        [ALC262_HIPPO]          = "hippo",
        [ALC262_HIPPO_1]        = "hippo_1",
@@@ -12895,8 -12942,10 +12948,10 @@@ static int patch_alc262(struct hda_code
                board_config = ALC262_AUTO;
        }
  
-       if (board_config == ALC262_AUTO)
-               alc_pick_fixup(codec, alc262_fixup_tbl, alc262_fixups, 1);
+       if (board_config == ALC262_AUTO) {
+               alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
+               alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+       }
  
        if (board_config == ALC262_AUTO) {
                /* automatic parse from the BIOS config */
        if (!spec->no_analog && has_cdefine_beep(codec))
                set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
  
-       if (board_config == ALC262_AUTO)
-               alc_pick_fixup(codec, alc262_fixup_tbl, alc262_fixups, 0);
+       alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
  
        spec->vmaster_nid = 0x0c;
  
@@@ -13741,7 -13789,7 +13795,7 @@@ static void alc268_auto_init(struct hda
  /*
   * configuration and preset
   */
- static const char *alc268_models[ALC268_MODEL_LAST] = {
+ static const char * const alc268_models[ALC268_MODEL_LAST] = {
        [ALC267_QUANTA_IL1]     = "quanta-il1",
        [ALC268_3ST]            = "3stack",
        [ALC268_TOSHIBA]        = "toshiba",
@@@ -14822,17 -14870,19 +14876,19 @@@ static int alc269_resume(struct hda_cod
  #endif /* SND_HDA_NEEDS_RESUME */
  
  static void alc269_fixup_hweq(struct hda_codec *codec,
-                              const struct alc_fixup *fix, int pre_init)
+                              const struct alc_fixup *fix, int action)
  {
        int coef;
  
+       if (action != ALC_FIXUP_ACT_INIT)
+               return;
        coef = alc_read_coef_idx(codec, 0x1e);
        alc_write_coef_idx(codec, 0x1e, coef | 0x80);
  }
  
  enum {
        ALC269_FIXUP_SONY_VAIO,
-       ALC275_FIX_SONY_VAIO_GPIO2,
+       ALC275_FIXUP_SONY_VAIO_GPIO2,
        ALC269_FIXUP_DELL_M101Z,
        ALC269_FIXUP_SKU_IGNORE,
        ALC269_FIXUP_ASUS_G73JW,
  
  static const struct alc_fixup alc269_fixups[] = {
        [ALC269_FIXUP_SONY_VAIO] = {
-               .verbs = (const struct hda_verb[]) {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
                        {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
                        {}
                }
        },
-       [ALC275_FIX_SONY_VAIO_GPIO2] = {
-               .verbs = (const struct hda_verb[]) {
+       [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
                        {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
                        {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
                        {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
-                       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
                        { }
-               }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_SONY_VAIO
        },
        [ALC269_FIXUP_DELL_M101Z] = {
-               .verbs = (const struct hda_verb[]) {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
                        /* Enables internal speaker */
                        {0x20, AC_VERB_SET_COEF_INDEX, 13},
                        {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
                }
        },
        [ALC269_FIXUP_SKU_IGNORE] = {
-               .sku = ALC_FIXUP_SKU_IGNORE,
+               .type = ALC_FIXUP_SKU,
+               .v.sku = ALC_FIXUP_SKU_IGNORE,
        },
        [ALC269_FIXUP_ASUS_G73JW] = {
-               .pins = (const struct alc_pincfg[]) {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
                        { 0x17, 0x99130111 }, /* subwoofer */
                        { }
                }
        },
        [ALC269_FIXUP_LENOVO_EAPD] = {
-               .verbs = (const struct hda_verb[]) {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
                        {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
                        {}
                }
        },
        [ALC275_FIXUP_SONY_HWEQ] = {
-               .func = alc269_fixup_hweq,
-               .verbs = (const struct hda_verb[]) {
-                       {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
-                       {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
-                       {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
-                       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
-                       { }
-               }
+               .type = ALC_FIXUP_FUNC,
+               .v.func = alc269_fixup_hweq,
+               .chained = true,
+               .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
        }
  };
  
  static struct snd_pci_quirk alc269_fixup_tbl[] = {
-       SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIX_SONY_VAIO_GPIO2),
+       SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
        SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
        SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
        SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
  /*
   * configuration and preset
   */
- static const char *alc269_models[ALC269_MODEL_LAST] = {
+ static const char * const alc269_models[ALC269_MODEL_LAST] = {
        [ALC269_BASIC]                  = "basic",
        [ALC269_QUANTA_FL1]             = "quanta",
        [ALC269_AMIC]                   = "laptop-amic",
@@@ -15184,8 -15237,10 +15243,10 @@@ static int patch_alc269(struct hda_code
                board_config = ALC269_AUTO;
        }
  
-       if (board_config == ALC269_AUTO)
-               alc_pick_fixup(codec, alc269_fixup_tbl, alc269_fixups, 1);
+       if (board_config == ALC269_AUTO) {
+               alc_pick_fixup(codec, NULL, alc269_fixup_tbl, alc269_fixups);
+               alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+       }
  
        if (board_config == ALC269_AUTO) {
                /* automatic parse from the BIOS config */
        if (has_cdefine_beep(codec))
                set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
  
-       if (board_config == ALC269_AUTO)
-               alc_pick_fixup(codec, alc269_fixup_tbl, alc269_fixups, 0);
+       alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
  
        spec->vmaster_nid = 0x02;
  
@@@ -15950,7 -16004,7 +16010,7 @@@ static int alc861_auto_create_multi_out
                                             const struct auto_pin_cfg *cfg)
  {
        struct alc_spec *spec = codec->spec;
-       static const char *chname[4] = {
+       static const char * const chname[4] = {
                "Front", "Surround", NULL /*CLFE*/, "Side"
        };
        const char *pfx = alc_get_line_out_pfx(cfg, true);
@@@ -16156,7 -16210,7 +16216,7 @@@ static struct hda_amp_list alc861_loopb
  /*
   * configuration and preset
   */
- static const char *alc861_models[ALC861_MODEL_LAST] = {
+ static const char * const alc861_models[ALC861_MODEL_LAST] = {
        [ALC861_3ST]            = "3stack",
        [ALC660_3ST]            = "3stack-660",
        [ALC861_3ST_DIG]        = "3stack-dig",
@@@ -16306,7 -16360,8 +16366,8 @@@ enum 
  
  static const struct alc_fixup alc861_fixups[] = {
        [PINFIX_FSC_AMILO_PI1505] = {
-               .pins = (const struct alc_pincfg[]) {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
                        { 0x0b, 0x0221101f }, /* HP */
                        { 0x0f, 0x90170310 }, /* speaker */
                        { }
@@@ -16341,8 -16396,10 +16402,10 @@@ static int patch_alc861(struct hda_code
                board_config = ALC861_AUTO;
        }
  
-       if (board_config == ALC861_AUTO)
-               alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups, 1);
+       if (board_config == ALC861_AUTO) {
+               alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
+               alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+       }
  
        if (board_config == ALC861_AUTO) {
                /* automatic parse from the BIOS config */
  
        spec->vmaster_nid = 0x03;
  
-       if (board_config == ALC861_AUTO)
-               alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups, 0);
+       alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
  
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC861_AUTO) {
@@@ -16857,7 -16913,7 +16919,7 @@@ static void alc861vd_dallas_setup(struc
  /*
   * configuration and preset
   */
- static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
+ static const char * const alc861vd_models[ALC861VD_MODEL_LAST] = {
        [ALC660VD_3ST]          = "3stack-660",
        [ALC660VD_3ST_DIG]      = "3stack-660-digout",
        [ALC660VD_ASUS_V1S]     = "asus-v1s",
@@@ -17072,12 -17128,14 +17134,14 @@@ static void alc861vd_auto_init_analog_i
  #define alc861vd_idx_to_mixer_switch(nid)     ((nid) + 0x0c)
  
  /* add playback controls from the parsed DAC table */
 -/* Based on ALC880 version. But ALC861VD has separate,
 +/* Based on ALC880 version. But ALC861VD and ALC887 have separate,
   * different NIDs for mute/unmute switch and volume control */
  static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
                                             const struct auto_pin_cfg *cfg)
  {
-       static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"};
+       static const char * const chname[4] = {
+               "Front", "Surround", "CLFE", "Side"
+       };
        const char *pfx = alc_get_line_out_pfx(cfg, true);
        hda_nid_t nid_v, nid_s;
        int i, err;
@@@ -17262,7 -17320,8 +17326,8 @@@ enum 
  /* reset GPIO1 */
  static const struct alc_fixup alc861vd_fixups[] = {
        [ALC660VD_FIX_ASUS_GPIO1] = {
-               .verbs = (const struct hda_verb[]) {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
                        {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
                        {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
                        {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
@@@ -17297,8 -17356,10 +17362,10 @@@ static int patch_alc861vd(struct hda_co
                board_config = ALC861VD_AUTO;
        }
  
-       if (board_config == ALC861VD_AUTO)
-               alc_pick_fixup(codec, alc861vd_fixup_tbl, alc861vd_fixups, 1);
+       if (board_config == ALC861VD_AUTO) {
+               alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
+               alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+       }
  
        if (board_config == ALC861VD_AUTO) {
                /* automatic parse from the BIOS config */
  
        spec->vmaster_nid = 0x02;
  
-       if (board_config == ALC861VD_AUTO)
-               alc_pick_fixup(codec, alc861vd_fixup_tbl, alc861vd_fixups, 0);
+       alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
  
        codec->patch_ops = alc_patch_ops;
  
@@@ -18630,7 -18690,7 +18696,7 @@@ static struct snd_kcontrol_new alc272_n
  /*
   * configuration and preset
   */
- static const char *alc662_models[ALC662_MODEL_LAST] = {
+ static const char * const alc662_models[ALC662_MODEL_LAST] = {
        [ALC662_3ST_2ch_DIG]    = "3stack-dig",
        [ALC662_3ST_6ch_DIG]    = "3stack-6ch-dig",
        [ALC662_3ST_6ch]        = "3stack-6ch",
@@@ -19145,7 -19205,7 +19211,7 @@@ static int alc662_auto_create_multi_out
                                             const struct auto_pin_cfg *cfg)
  {
        struct alc_spec *spec = codec->spec;
-       static const char *chname[4] = {
+       static const char * const chname[4] = {
                "Front", "Surround", NULL /*CLFE*/, "Side"
        };
        const char *pfx = alc_get_line_out_pfx(cfg, true);
@@@ -19378,7 -19438,10 +19444,10 @@@ static void alc662_auto_init(struct hda
  }
  
  static void alc272_fixup_mario(struct hda_codec *codec,
-                              const struct alc_fixup *fix, int pre_init) {
+                              const struct alc_fixup *fix, int action)
+ {
+       if (action != ALC_FIXUP_ACT_PROBE)
+               return;
        if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
                                      (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
                                      (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
@@@ -19396,19 -19459,22 +19465,22 @@@ enum 
  
  static const struct alc_fixup alc662_fixups[] = {
        [ALC662_FIXUP_ASPIRE] = {
-               .pins = (const struct alc_pincfg[]) {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
                        { 0x15, 0x99130112 }, /* subwoofer */
                        { }
                }
        },
        [ALC662_FIXUP_IDEAPAD] = {
-               .pins = (const struct alc_pincfg[]) {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
                        { 0x17, 0x99130112 }, /* subwoofer */
                        { }
                }
        },
        [ALC272_FIXUP_MARIO] = {
-               .func = alc272_fixup_mario,
+               .type = ALC_FIXUP_FUNC,
+               .v.func = alc272_fixup_mario,
        }
  };
  
@@@ -19462,7 -19528,9 +19534,9 @@@ static int patch_alc662(struct hda_code
        }
  
        if (board_config == ALC662_AUTO) {
-               alc_pick_fixup(codec, alc662_fixup_tbl, alc662_fixups, 1);
+               alc_pick_fixup(codec, alc662_fixup_models,
+                              alc662_fixup_tbl, alc662_fixups);
+               alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
                /* automatic parse from the BIOS config */
                err = alc662_parse_auto_config(codec);
                if (err < 0) {
        }
        spec->vmaster_nid = 0x02;
  
+       alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
        codec->patch_ops = alc_patch_ops;
-       if (board_config == ALC662_AUTO) {
+       if (board_config == ALC662_AUTO)
                spec->init_hook = alc662_auto_init;
-               alc_pick_fixup_model(codec, alc662_fixup_models,
-                                    alc662_fixup_tbl, alc662_fixups, 0);
-       }
  
        alc_init_jacks(codec);
  
@@@ -19913,7 -19980,7 +19986,7 @@@ static void alc680_auto_init(struct hda
  /*
   * configuration and preset
   */
- static const char *alc680_models[ALC680_MODEL_LAST] = {
+ static const char * const alc680_models[ALC680_MODEL_LAST] = {
        [ALC680_BASE]           = "base",
        [ALC680_AUTO]           = "auto",
  };
@@@ -263,7 -263,8 +263,7 @@@ static void vt1708_stop_hp_work(struct 
                return;
        snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81,
                            !spec->vt1708_jack_detectect);
 -      cancel_delayed_work(&spec->vt1708_hp_work);
 -      flush_scheduled_work();
 +      cancel_delayed_work_sync(&spec->vt1708_hp_work);
  }
  
  
@@@ -2281,7 -2282,9 +2281,9 @@@ static int vt1708_auto_create_multi_out
                                             const struct auto_pin_cfg *cfg)
  {
        char name[32];
-       static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
+       static const char * const chname[4] = {
+               "Front", "Surround", "C/LFE", "Side"
+       };
        hda_nid_t nid, nid_vol, nid_vols[] = {0x17, 0x19, 0x1a, 0x1b};
        int i, err;
  
@@@ -2370,7 -2373,7 +2372,7 @@@ static void create_hp_imux(struct via_s
  {
        int i;
        struct hda_input_mux *imux = &spec->private_imux[1];
-       static const char *texts[] = { "OFF", "ON", NULL};
+       static const char * const texts[] = { "OFF", "ON", NULL};
  
        /* for hp mode select */
        for (i = 0; texts[i]; i++)
@@@ -2890,7 -2893,9 +2892,9 @@@ static int vt1709_auto_create_multi_out
                                             const struct auto_pin_cfg *cfg)
  {
        char name[32];
-       static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
+       static const char * const chname[4] = {
+               "Front", "Surround", "C/LFE", "Side"
+       };
        hda_nid_t nid, nid_vol, nid_vols[] = {0x18, 0x1a, 0x1b, 0x29};
        int i, err;
  
@@@ -3433,7 -3438,9 +3437,9 @@@ static int vt1708B_auto_create_multi_ou
                                             const struct auto_pin_cfg *cfg)
  {
        char name[32];
-       static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
+       static const char * const chname[4] = {
+               "Front", "Surround", "C/LFE", "Side"
+       };
        hda_nid_t nid_vols[] = {0x16, 0x18, 0x26, 0x27};
        hda_nid_t nid, nid_vol = 0;
        int i, err;
@@@ -3861,7 -3868,9 +3867,9 @@@ static int vt1708S_auto_create_multi_ou
                                             const struct auto_pin_cfg *cfg)
  {
        char name[32];
-       static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
+       static const char * const chname[4] = {
+               "Front", "Surround", "C/LFE", "Side"
+       };
        hda_nid_t nid_vols[] = {0x10, 0x11, 0x24, 0x25};
        hda_nid_t nid_mutes[] = {0x1C, 0x18, 0x26, 0x27};
        hda_nid_t nid, nid_vol, nid_mute;
@@@ -4304,7 -4313,7 +4312,7 @@@ static int vt1702_auto_create_hp_ctls(s
  {
        int err, i;
        struct hda_input_mux *imux;
-       static const char *texts[] = { "ON", "OFF", NULL};
+       static const char * const texts[] = { "ON", "OFF", NULL};
        if (!pin)
                return 0;
        spec->multiout.hp_nid = 0x1D;
@@@ -4615,7 -4624,9 +4623,9 @@@ static int vt1718S_auto_create_multi_ou
                                             const struct auto_pin_cfg *cfg)
  {
        char name[32];
-       static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
+       static const char * const chname[4] = {
+               "Front", "Surround", "C/LFE", "Side"
+       };
        hda_nid_t nid_vols[] = {0x8, 0x9, 0xa, 0xb};
        hda_nid_t nid_mutes[] = {0x24, 0x25, 0x26, 0x27};
        hda_nid_t nid, nid_vol, nid_mute = 0;
@@@ -5064,7 -5075,9 +5074,9 @@@ static int vt1716S_auto_create_multi_ou
                                              const struct auto_pin_cfg *cfg)
  {
        char name[32];
-       static const char *chname[3] = { "Front", "Surround", "C/LFE" };
+       static const char * const chname[3] = {
+               "Front", "Surround", "C/LFE"
+       };
        hda_nid_t nid_vols[] = {0x10, 0x11, 0x25};
        hda_nid_t nid_mutes[] = {0x1C, 0x18, 0x27};
        hda_nid_t nid, nid_vol, nid_mute;