]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'fix/hda' into topic/hda
authorTakashi Iwai <tiwai@suse.de>
Mon, 20 Dec 2010 09:28:51 +0000 (10:28 +0100)
committerTakashi Iwai <tiwai@suse.de>
Mon, 20 Dec 2010 09:28:51 +0000 (10:28 +0100)
1  2 
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c

index 96b286aebde671c5fe9c898dcd3489f9d4fd2566,76bd58a0e2b637e2c17a79cc94ab54e0747de227..e584b3dd7aa8826558bf3b601f985886e1832fbc
@@@ -2111,11 -2111,6 +2111,11 @@@ static struct hda_channel_mode cxt5066_
        { 2, NULL },
  };
  
 +#define HP_PRESENT_PORT_A     (1 << 0)
 +#define HP_PRESENT_PORT_D     (1 << 1)
 +#define hp_port_a_present(spec)       ((spec)->hp_present & HP_PRESENT_PORT_A)
 +#define hp_port_d_present(spec)       ((spec)->hp_present & HP_PRESENT_PORT_D)
 +
  static void cxt5066_update_speaker(struct hda_codec *codec)
  {
        struct conexant_spec *spec = codec->spec;
                    spec->hp_present, spec->cur_eapd);
  
        /* Port A (HP) */
 -      pinctl = ((spec->hp_present & 1) && spec->cur_eapd) ? PIN_HP : 0;
 +      pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0;
        snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
                        pinctl);
  
        /* Port D (HP/LO) */
 -      if (spec->dell_automute) {
 -              /* DELL AIO Port Rule: PortA>  PortD>  IntSpk */
 -              pinctl = (!(spec->hp_present & 1) && spec->cur_eapd)
 -                      ? PIN_OUT : 0;
 -      } else if (spec->thinkpad) {
 -              if (spec->cur_eapd)
 -                      pinctl = spec->port_d_mode;
 -              /* Mute dock line-out if Port A (laptop HP) is present */
 -              if (spec->hp_present&  1)
 +      pinctl = spec->cur_eapd ? spec->port_d_mode : 0;
 +      if (spec->dell_automute || spec->thinkpad) {
 +              /* Mute if Port A is connected */
 +              if (hp_port_a_present(spec))
                        pinctl = 0;
        } else {
 -              pinctl = ((spec->hp_present & 2) && spec->cur_eapd)
 -                      ? spec->port_d_mode : 0;
 +              /* Thinkpad/Dell doesn't give pin-D status */
 +              if (!hp_port_d_present(spec))
 +                      pinctl = 0;
        }
        snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
                        pinctl);
@@@ -2380,8 -2379,8 +2380,8 @@@ static void cxt5066_hp_automute(struct 
        /* Port D */
        portD = snd_hda_jack_detect(codec, 0x1c);
  
 -      spec->hp_present = !!(portA);
 -      spec->hp_present |= portD ? 2 : 0;
 +      spec->hp_present = portA ? HP_PRESENT_PORT_A : 0;
 +      spec->hp_present |= portD ? HP_PRESENT_PORT_D : 0;
        snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n",
                portA, portD, spec->hp_present);
        cxt5066_update_speaker(codec);
@@@ -3097,8 -3096,7 +3097,7 @@@ static const char *cxt5066_models[CXT50
  static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO),
-       SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
-                     CXT5066_DELL_LAPTOP),
+       SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO),
        SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
@@@ -3424,9 -3422,6 +3423,9 @@@ static void cx_auto_hp_automute(struct 
                                    AC_VERB_SET_PIN_WIDGET_CONTROL,
                                    present ? 0 : PIN_OUT);
        }
 +      for (i = 0; !present && i < cfg->line_outs; i++)
 +              if (snd_hda_jack_detect(codec, cfg->line_out_pins[i]))
 +                      present = 1;
        for (i = 0; i < cfg->speaker_outs; i++) {
                snd_hda_codec_write(codec, cfg->speaker_pins[i], 0,
                                    AC_VERB_SET_PIN_WIDGET_CONTROL,
index 4e6f4f6d342f55cf9e9bb8b4f185251c0bd2617d,dd56d8833ad236373aa839ef0c3f9278d7df54cb..5baaf12111ba6e56046962666399142ffcaa2dc7
@@@ -231,6 -231,7 +231,6 @@@ enum 
        ALC888_ACER_ASPIRE_8930G,
        ALC888_ACER_ASPIRE_7730G,
        ALC883_MEDION,
 -      ALC883_MEDION_MD2,
        ALC883_MEDION_WIM2160,
        ALC883_LAPTOP_EAPD,
        ALC883_LENOVO_101E_2ch,
@@@ -1677,32 -1678,29 +1677,32 @@@ struct alc_pincfg 
        u32 val;
  };
  
 +struct alc_model_fixup {
 +      const int id;
 +      const char *name;
 +};
 +
  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);
  };
  
 -static void alc_pick_fixup(struct hda_codec *codec,
 -                         const struct snd_pci_quirk *quirk,
 -                         const struct alc_fixup *fix,
 -                         int pre_init)
 +static void __alc_pick_fixup(struct hda_codec *codec,
 +                           const struct alc_fixup *fix,
 +                           const char *modelname,
 +                           int pre_init)
  {
        const struct alc_pincfg *cfg;
        struct alc_spec *spec;
  
 -      quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
 -      if (!quirk)
 -              return;
 -      fix += quirk->value;
        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, quirk->name);
 +                          codec->chip_name, modelname);
  #endif
                spec = codec->spec;
                spec->cdefine.sku_cfg = fix->sku;
        if (pre_init && cfg) {
  #ifdef CONFIG_SND_DEBUG_VERBOSE
                snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n",
 -                          codec->chip_name, quirk->name);
 +                          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, quirk->name);
 +                          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);
 +      }
 +}
 +
 +static void alc_pick_fixup(struct hda_codec *codec,
 +                               const struct snd_pci_quirk *quirk,
 +                               const struct alc_fixup *fix,
 +                               int pre_init)
 +{
 +      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
 +      }
 +}
 +
 +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;
 +                              break;
 +                      }
 +                      models++;
 +              }
 +              __alc_pick_fixup(codec, fix, codec->modelname, pre_init);
 +      } else {
 +              alc_pick_fixup(codec, quirk, fix, pre_init);
 +      }
  }
  
  static int alc_read_coef_idx(struct hda_codec *codec,
@@@ -3352,7 -3307,7 +3352,7 @@@ static struct hda_verb alc880_beep_init
  };
  
  /* auto-toggle front mic */
 -static void alc880_uniwill_mic_automute(struct hda_codec *codec)
 +static void alc88x_simple_mic_automute(struct hda_codec *codec)
  {
        unsigned int present;
        unsigned char bits;
@@@ -3374,7 -3329,7 +3374,7 @@@ static void alc880_uniwill_setup(struc
  static void alc880_uniwill_init_hook(struct hda_codec *codec)
  {
        alc_automute_amp(codec);
 -      alc880_uniwill_mic_automute(codec);
 +      alc88x_simple_mic_automute(codec);
  }
  
  static void alc880_uniwill_unsol_event(struct hda_codec *codec,
         */
        switch (res >> 28) {
        case ALC880_MIC_EVENT:
 -              alc880_uniwill_mic_automute(codec);
 +              alc88x_simple_mic_automute(codec);
                break;
        default:
                alc_automute_amp_unsol_event(codec, res);
@@@ -9026,6 -8981,19 +9026,6 @@@ static struct snd_kcontrol_new alc883_l
        { } /* end */
  };
  
 -static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
 -      HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
 -      HDA_CODEC_MUTE("Front Playback Switch", 0x15, 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("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
 -      HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
 -      HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
 -      HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
 -      { } /* end */
 -};
 -
  static struct snd_kcontrol_new alc883_medion_wim2160_mixer[] = {
        HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
        HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@@ -9214,6 -9182,16 +9214,6 @@@ static void alc883_mitac_setup(struct h
        spec->autocfg.speaker_pins[1] = 0x17;
  }
  
 -/* auto-toggle front mic */
 -/*
 -static void alc883_mitac_mic_automute(struct hda_codec *codec)
 -{
 -      unsigned char bits = snd_hda_jack_detect(codec, 0x18) ? HDA_AMP_MUTE : 0;
 -
 -      snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
 -}
 -*/
 -
  static struct hda_verb alc883_mitac_verbs[] = {
        /* HP */
        {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
@@@ -9457,8 -9435,18 +9457,8 @@@ static void alc883_lenovo_ms7195_unsol_
                alc888_lenovo_ms7195_rca_automute(codec);
  }
  
 -static struct hda_verb alc883_medion_md2_verbs[] = {
 -      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 -
 -      {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
 -
 -      {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
 -      { } /* end */
 -};
 -
  /* toggle speaker-output according to the hp-jack state */
 -static void alc883_medion_md2_setup(struct hda_codec *codec)
 +static void alc883_lenovo_nb0763_setup(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
  
  #define alc883_targa_init_hook                alc882_targa_init_hook
  #define alc883_targa_unsol_event      alc882_targa_unsol_event
  
 -static void alc883_clevo_m720_mic_automute(struct hda_codec *codec)
 -{
 -      unsigned int present;
 -
 -      present = snd_hda_jack_detect(codec, 0x18);
 -      snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
 -                               HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
 -}
 -
  static void alc883_clevo_m720_setup(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
  static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
  {
        alc_automute_amp(codec);
 -      alc883_clevo_m720_mic_automute(codec);
 +      alc88x_simple_mic_automute(codec);
  }
  
  static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
  {
        switch (res >> 26) {
        case ALC880_MIC_EVENT:
 -              alc883_clevo_m720_mic_automute(codec);
 +              alc88x_simple_mic_automute(codec);
                break;
        default:
                alc_automute_amp_unsol_event(codec, res);
@@@ -9734,6 -9731,7 +9734,6 @@@ static const char *alc882_models[ALC882
        [ALC888_ACER_ASPIRE_8930G]      = "acer-aspire-8930g",
        [ALC888_ACER_ASPIRE_7730G]      = "acer-aspire-7730g",
        [ALC883_MEDION]         = "medion",
 -      [ALC883_MEDION_MD2]     = "medion-md2",
        [ALC883_MEDION_WIM2160] = "medion-wim2160",
        [ALC883_LAPTOP_EAPD]    = "laptop-eapd",
        [ALC883_LENOVO_101E_2ch] = "lenovo-101e",
@@@ -10381,6 -10379,19 +10381,6 @@@ static struct alc_config_preset alc882_
                .channel_mode = alc883_sixstack_modes,
                .input_mux = &alc883_capture_source,
        },
 -      [ALC883_MEDION_MD2] = {
 -              .mixers = { alc883_medion_md2_mixer},
 -              .init_verbs = { alc883_init_verbs, alc883_medion_md2_verbs},
 -              .num_dacs = ARRAY_SIZE(alc883_dac_nids),
 -              .dac_nids = alc883_dac_nids,
 -              .dig_out_nid = ALC883_DIGOUT_NID,
 -              .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 -              .channel_mode = alc883_3ST_2ch_modes,
 -              .input_mux = &alc883_capture_source,
 -              .unsol_event = alc_automute_amp_unsol_event,
 -              .setup = alc883_medion_md2_setup,
 -              .init_hook = alc_automute_amp,
 -      },
        [ALC883_MEDION_WIM2160] = {
                .mixers = { alc883_medion_wim2160_mixer },
                .init_verbs = { alc883_init_verbs, alc883_medion_wim2160_verbs },
                .need_dac_fix = 1,
                .input_mux = &alc883_lenovo_nb0763_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
 -              .setup = alc883_medion_md2_setup,
 +              .setup = alc883_lenovo_nb0763_setup,
                .init_hook = alc_automute_amp,
        },
        [ALC888_LENOVO_MS7195_DIG] = {
@@@ -10819,7 -10830,8 +10819,8 @@@ static int alc_auto_add_mic_boost(struc
  {
        struct alc_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
-       int i, err;
+       int i, err, type;
+       int type_idx = 0;
        hda_nid_t nid;
  
        for (i = 0; i < cfg->num_inputs; i++) {
                nid = cfg->inputs[i].pin;
                if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
                        char label[32];
+                       type = cfg->inputs[i].type;
+                       if (i > 0 && type == cfg->inputs[i - 1].type)
+                               type_idx++;
+                       else
+                               type_idx = 0;
                        snprintf(label, sizeof(label), "%s Boost",
                                 hda_get_autocfg_input_label(codec, cfg, i));
-                       err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0,
+                       err = add_control(spec, ALC_CTL_WIDGET_VOL, label,
+                                         type_idx,
                                  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
                        if (err < 0)
                                return err;
@@@ -14789,6 -14807,8 +14796,8 @@@ static int alc269_resume(struct hda_cod
  enum {
        ALC269_FIXUP_SONY_VAIO,
        ALC269_FIXUP_DELL_M101Z,
+       ALC269_FIXUP_SKU_IGNORE,
+       ALC269_FIXUP_ASUS_G73JW,
  };
  
  static const struct alc_fixup alc269_fixups[] = {
                        {}
                }
        },
+       [ALC269_FIXUP_SKU_IGNORE] = {
+               .sku = ALC_FIXUP_SKU_IGNORE,
+       },
+       [ALC269_FIXUP_ASUS_G73JW] = {
+               .pins = (const struct alc_pincfg[]) {
+                       { 0x17, 0x99130111 }, /* subwoofer */
+                       { }
+               }
+       },
  };
  
  static struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+       SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
+       SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
+       SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
        {}
  };
  
@@@ -16678,6 -16710,18 +16699,6 @@@ static struct hda_verb alc861vd_lenovo_
        {}
  };
  
 -static void alc861vd_lenovo_mic_automute(struct hda_codec *codec)
 -{
 -      unsigned int present;
 -      unsigned char bits;
 -
 -      present = snd_hda_jack_detect(codec, 0x18);
 -      bits = present ? HDA_AMP_MUTE : 0;
 -
 -      snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
 -                               HDA_AMP_MUTE, bits);
 -}
 -
  static void alc861vd_lenovo_setup(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
  static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
  {
        alc_automute_amp(codec);
 -      alc861vd_lenovo_mic_automute(codec);
 +      alc88x_simple_mic_automute(codec);
  }
  
  static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
  {
        switch (res >> 26) {
        case ALC880_MIC_EVENT:
 -              alc861vd_lenovo_mic_automute(codec);
 +              alc88x_simple_mic_automute(codec);
                break;
        default:
                alc_automute_amp_unsol_event(codec, res);
@@@ -19301,21 -19345,9 +19322,21 @@@ static void alc662_auto_init(struct hda
                alc_inithook(codec);
  }
  
 +static void alc272_fixup_mario(struct hda_codec *codec,
 +                             const struct alc_fixup *fix, int pre_init) {
 +      if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
 +                                    (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
 +                                    (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
 +                                    (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
 +                                    (0 << AC_AMPCAP_MUTE_SHIFT)))
 +              printk(KERN_WARNING
 +                     "hda_codec: failed to override amp caps for NID 0x2\n");
 +}
 +
  enum {
        ALC662_FIXUP_ASPIRE,
        ALC662_FIXUP_IDEAPAD,
 +      ALC272_FIXUP_MARIO,
  };
  
  static const struct alc_fixup alc662_fixups[] = {
                        { }
                }
        },
 +      [ALC272_FIXUP_MARIO] = {
 +              .func = alc272_fixup_mario,
 +      }
  };
  
  static struct snd_pci_quirk alc662_fixup_tbl[] = {
        {}
  };
  
 +static const struct alc_model_fixup alc662_fixup_models[] = {
 +      {.id = ALC272_FIXUP_MARIO, .name = "mario"},
 +      {}
 +};
  
  
  static int patch_alc662(struct hda_codec *codec)
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC662_AUTO) {
                spec->init_hook = alc662_auto_init;
 -              alc_pick_fixup(codec, alc662_fixup_tbl, alc662_fixups, 0);
 +              alc_pick_fixup_model(codec, alc662_fixup_models,
 +                                   alc662_fixup_tbl, alc662_fixups, 0);
        }
  
        alc_init_jacks(codec);