]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - sound/pci/hda/patch_realtek.c
ALSA: hda - Add auto mic switch in realtek auto-probe mode
[linux-2.6.git] / sound / pci / hda / patch_realtek.c
index 5c80a27bfc8adf3bfb6fe3e0f412db4af2757f13..80c3f6420072f0695bb95c747b0944c945278583 100644 (file)
@@ -822,6 +822,27 @@ static void alc_sku_automute(struct hda_codec *codec)
                            spec->jack_present ? 0 : PIN_OUT);
 }
 
+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);
+}
+
 /* unsolicited event for HP jack sensing */
 static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
 {
@@ -829,10 +850,17 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
                res >>= 28;
        else
                res >>= 26;
-       if (res != ALC880_HP_EVENT)
-               return;
+       if (res == ALC880_HP_EVENT)
+               alc_sku_automute(codec);
 
+       if (res == ALC880_MIC_EVENT)
+               alc_mic_automute(codec);
+}
+
+static void alc_inithook(struct hda_codec *codec)
+{
        alc_sku_automute(codec);
+       alc_mic_automute(codec);
 }
 
 /* additional initialization for ALC888 variants */
@@ -1018,10 +1046,17 @@ do_sku:
                else
                        return;
        }
+       if (spec->autocfg.hp_pins[0])
+               snd_hda_codec_write(codec, spec->autocfg.hp_pins[0], 0,
+                       AC_VERB_SET_UNSOLICITED_ENABLE,
+                       AC_USRSP_EN | ALC880_HP_EVENT);
 
-       snd_hda_codec_write(codec, spec->autocfg.hp_pins[0], 0,
-                           AC_VERB_SET_UNSOLICITED_ENABLE,
-                           AC_USRSP_EN | ALC880_HP_EVENT);
+       if (spec->autocfg.input_pins[AUTO_PIN_MIC] &&
+               spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC])
+               snd_hda_codec_write(codec,
+                       spec->autocfg.input_pins[AUTO_PIN_MIC], 0,
+                       AC_VERB_SET_UNSOLICITED_ENABLE,
+                       AC_USRSP_EN | ALC880_MIC_EVENT);
 
        spec->unsol_event = alc_sku_unsol_event;
 }
@@ -3808,7 +3843,7 @@ static void alc880_auto_init(struct hda_codec *codec)
        alc880_auto_init_extra_out(codec);
        alc880_auto_init_analog_input(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 /*
@@ -5219,7 +5254,7 @@ static void alc260_auto_init(struct hda_codec *codec)
        alc260_auto_init_multi_out(codec);
        alc260_auto_init_analog_input(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -6629,7 +6664,7 @@ static void alc882_auto_init(struct hda_codec *codec)
        alc882_auto_init_analog_input(codec);
        alc882_auto_init_input_src(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 static int patch_alc883(struct hda_codec *codec); /* called in patch_alc882() */
@@ -6656,16 +6691,19 @@ static int patch_alc882(struct hda_codec *codec)
                        board_config = ALC885_MACPRO;
                        break;
                case 0x106b1000: /* iMac 24 */
+               case 0x106b2800: /* AppleTV */
                        board_config = ALC885_IMAC24;
                        break;
                case 0x106b00a1: /* Macbook (might be wrong - PCI SSID?) */
+               case 0x106b00a4: /* MacbookPro4,1 */
                case 0x106b2c00: /* Macbook Pro rev3 */
                case 0x106b3600: /* Macbook 3.1 */
                        board_config = ALC885_MBP3;
                        break;
                default:
                        /* ALC889A is handled better as ALC888-compatible */
-                       if (codec->revision_id == 0x100103) {
+                       if (codec->revision_id == 0x100101 ||
+                           codec->revision_id == 0x100103) {
                                alc_free(codec);
                                return patch_alc883(codec);
                        }
@@ -8755,7 +8793,7 @@ static void alc883_auto_init(struct hda_codec *codec)
        alc883_auto_init_analog_input(codec);
        alc883_auto_init_input_src(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 static int patch_alc883(struct hda_codec *codec)
@@ -10282,7 +10320,7 @@ static void alc262_auto_init(struct hda_codec *codec)
        alc262_auto_init_analog_input(codec);
        alc262_auto_init_input_src(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 /*
@@ -11414,7 +11452,7 @@ static void alc268_auto_init(struct hda_codec *codec)
        alc268_auto_init_mono_speaker_out(codec);
        alc268_auto_init_analog_input(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 /*
@@ -12197,7 +12235,7 @@ static void alc269_auto_init(struct hda_codec *codec)
        alc269_auto_init_hp_out(codec);
        alc269_auto_init_analog_input(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 /*
@@ -13278,7 +13316,7 @@ static void alc861_auto_init(struct hda_codec *codec)
        alc861_auto_init_hp_out(codec);
        alc861_auto_init_analog_input(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -14390,7 +14428,7 @@ static void alc861vd_auto_init(struct hda_codec *codec)
        alc861vd_auto_init_analog_input(codec);
        alc861vd_auto_init_input_src(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 static int patch_alc861vd(struct hda_codec *codec)
@@ -15699,9 +15737,16 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6),
        SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6),
        SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6),
+       SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
+                     ALC662_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
        SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS),
        SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
+       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
+                     ALC662_3ST_6ch_DIG),
+       SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
+       SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0",
+                                       ALC662_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x1854, 0x2000, "ASUS H13-2000", ALC663_ASUS_H13),
        SND_PCI_QUIRK(0x1854, 0x2001, "ASUS H13-2001", ALC663_ASUS_H13),
        SND_PCI_QUIRK(0x1854, 0x2002, "ASUS H13-2002", ALC663_ASUS_H13),
@@ -15972,15 +16017,15 @@ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec,
                                                              HDA_OUTPUT));
                        if (err < 0)
                                return err;
-                       err = add_control(spec, ALC_CTL_BIND_MUTE,
+                       err = add_control(spec, ALC_CTL_WIDGET_MUTE,
                                          "Center Playback Switch",
-                                         HDA_COMPOSE_AMP_VAL(nid, 1, 2,
+                                         HDA_COMPOSE_AMP_VAL(0x0e, 1, 0,
                                                              HDA_INPUT));
                        if (err < 0)
                                return err;
-                       err = add_control(spec, ALC_CTL_BIND_MUTE,
+                       err = add_control(spec, ALC_CTL_WIDGET_MUTE,
                                          "LFE Playback Switch",
-                                         HDA_COMPOSE_AMP_VAL(nid, 2, 2,
+                                         HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,
                                                              HDA_INPUT));
                        if (err < 0)
                                return err;
@@ -15992,9 +16037,9 @@ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec,
                        if (err < 0)
                                return err;
                        sprintf(name, "%s Playback Switch", chname[i]);
-                       err = add_control(spec, ALC_CTL_BIND_MUTE, name,
-                                         HDA_COMPOSE_AMP_VAL(nid, 3, 2,
-                                                             HDA_INPUT));
+                       err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
+                               HDA_COMPOSE_AMP_VAL(alc880_idx_to_mixer(i),
+                                                   3, 0, HDA_INPUT));
                        if (err < 0)
                                return err;
                }
@@ -16213,7 +16258,7 @@ static void alc662_auto_init(struct hda_codec *codec)
        alc662_auto_init_analog_input(codec);
        alc662_auto_init_input_src(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 static int patch_alc662(struct hda_codec *codec)
@@ -16308,6 +16353,8 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
        { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
        { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
+       { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
+         .patch = patch_alc882 }, /* should be patch_alc883() in future */
        { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
          .patch = patch_alc882 }, /* should be patch_alc883() in future */
        { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },