diff options
author | Kailang Yang <kailang@realtek.com.tw> | 2007-05-08 09:19:08 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2007-05-11 10:56:18 -0400 |
commit | bdd148a307e230517bf891c108e0eec68ba5d10f (patch) | |
tree | 7fa88c608913978f52d8b76a6b1b5d6f537857f3 /sound/pci/hda/patch_realtek.c | |
parent | 0bbed758c024bb72cec8219879dc87cb04c6dd5c (diff) |
[ALSA] hda-codec - Add ALC861VD Lenovo support
- Added ALC861VD Lenovo support (17aa:3802, 17aa:2066)
- Modify alc_subsystem_id
Signed-off-by: Kailang Yang <kailang@realtek.com.tw>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 164 |
1 files changed, 159 insertions, 5 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8c0b4fbc1448..a4ede27af021 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -117,6 +117,7 @@ enum { | |||
117 | ALC861VD_3ST, | 117 | ALC861VD_3ST, |
118 | ALC861VD_3ST_DIG, | 118 | ALC861VD_3ST_DIG, |
119 | ALC861VD_6ST_DIG, | 119 | ALC861VD_6ST_DIG, |
120 | ALC861VD_LENOVO, | ||
120 | ALC861VD_AUTO, | 121 | ALC861VD_AUTO, |
121 | ALC861VD_MODEL_LAST, | 122 | ALC861VD_MODEL_LAST, |
122 | }; | 123 | }; |
@@ -137,6 +138,7 @@ enum { | |||
137 | ALC882_3ST_DIG, | 138 | ALC882_3ST_DIG, |
138 | ALC882_6ST_DIG, | 139 | ALC882_6ST_DIG, |
139 | ALC882_ARIMA, | 140 | ALC882_ARIMA, |
141 | ALC882_W2JC, | ||
140 | ALC882_AUTO, | 142 | ALC882_AUTO, |
141 | ALC885_MACPRO, | 143 | ALC885_MACPRO, |
142 | ALC882_MODEL_LAST, | 144 | ALC882_MODEL_LAST, |
@@ -635,6 +637,13 @@ static struct hda_verb alc_gpio2_init_verbs[] = { | |||
635 | { } | 637 | { } |
636 | }; | 638 | }; |
637 | 639 | ||
640 | static struct hda_verb alc_gpio3_init_verbs[] = { | ||
641 | {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, | ||
642 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, | ||
643 | {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, | ||
644 | { } | ||
645 | }; | ||
646 | |||
638 | /* 32-bit subsystem ID for BIOS loading in HD Audio codec. | 647 | /* 32-bit subsystem ID for BIOS loading in HD Audio codec. |
639 | * 31 ~ 16 : Manufacture ID | 648 | * 31 ~ 16 : Manufacture ID |
640 | * 15 ~ 8 : SKU ID | 649 | * 15 ~ 8 : SKU ID |
@@ -660,7 +669,22 @@ static void alc_subsystem_id(struct hda_codec *codec, | |||
660 | case 3: | 669 | case 3: |
661 | snd_hda_sequence_write(codec, alc_gpio2_init_verbs); | 670 | snd_hda_sequence_write(codec, alc_gpio2_init_verbs); |
662 | break; | 671 | break; |
672 | case 7: | ||
673 | snd_hda_sequence_write(codec, alc_gpio3_init_verbs); | ||
674 | break; | ||
663 | case 5: | 675 | case 5: |
676 | switch (codec->vendor_id) { | ||
677 | case 0x10ec0862: | ||
678 | case 0x10ec0660: | ||
679 | case 0x10ec0662: | ||
680 | case 0x10ec0267: | ||
681 | case 0x10ec0268: | ||
682 | snd_hda_codec_write(codec, 0x14, 0, | ||
683 | AC_VERB_SET_EAPD_BTLENABLE, 2); | ||
684 | snd_hda_codec_write(codec, 0x15, 0, | ||
685 | AC_VERB_SET_EAPD_BTLENABLE, 2); | ||
686 | return; | ||
687 | } | ||
664 | case 6: | 688 | case 6: |
665 | if (ass & 4) { /* bit 2 : 0 = Desktop, 1 = Laptop */ | 689 | if (ass & 4) { /* bit 2 : 0 = Desktop, 1 = Laptop */ |
666 | hda_nid_t port = 0; | 690 | hda_nid_t port = 0; |
@@ -4785,6 +4809,21 @@ static struct snd_kcontrol_new alc882_base_mixer[] = { | |||
4785 | { } /* end */ | 4809 | { } /* end */ |
4786 | }; | 4810 | }; |
4787 | 4811 | ||
4812 | static struct snd_kcontrol_new alc882_w2jc_mixer[] = { | ||
4813 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
4814 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
4815 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
4816 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
4817 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
4818 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
4819 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
4820 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
4821 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
4822 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
4823 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
4824 | { } /* end */ | ||
4825 | }; | ||
4826 | |||
4788 | static struct snd_kcontrol_new alc882_chmode_mixer[] = { | 4827 | static struct snd_kcontrol_new alc882_chmode_mixer[] = { |
4789 | { | 4828 | { |
4790 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 4829 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -5104,6 +5143,7 @@ static const char *alc882_models[ALC882_MODEL_LAST] = { | |||
5104 | [ALC882_3ST_DIG] = "3stack-dig", | 5143 | [ALC882_3ST_DIG] = "3stack-dig", |
5105 | [ALC882_6ST_DIG] = "6stack-dig", | 5144 | [ALC882_6ST_DIG] = "6stack-dig", |
5106 | [ALC882_ARIMA] = "arima", | 5145 | [ALC882_ARIMA] = "arima", |
5146 | [ALC882_W2JC] = "w2jc", | ||
5107 | [ALC885_MACPRO] = "macpro", | 5147 | [ALC885_MACPRO] = "macpro", |
5108 | [ALC882_AUTO] = "auto", | 5148 | [ALC882_AUTO] = "auto", |
5109 | }; | 5149 | }; |
@@ -5114,6 +5154,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { | |||
5114 | SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG), | 5154 | SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG), |
5115 | SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), | 5155 | SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), |
5116 | SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), | 5156 | SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), |
5157 | SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC), | ||
5117 | {} | 5158 | {} |
5118 | }; | 5159 | }; |
5119 | 5160 | ||
@@ -5150,6 +5191,18 @@ static struct alc_config_preset alc882_presets[] = { | |||
5150 | .channel_mode = alc882_sixstack_modes, | 5191 | .channel_mode = alc882_sixstack_modes, |
5151 | .input_mux = &alc882_capture_source, | 5192 | .input_mux = &alc882_capture_source, |
5152 | }, | 5193 | }, |
5194 | [ALC882_W2JC] = { | ||
5195 | .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer }, | ||
5196 | .init_verbs = { alc882_init_verbs, alc882_eapd_verbs, | ||
5197 | alc880_gpio1_init_verbs }, | ||
5198 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
5199 | .dac_nids = alc882_dac_nids, | ||
5200 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
5201 | .channel_mode = alc880_threestack_modes, | ||
5202 | .need_dac_fix = 1, | ||
5203 | .input_mux = &alc882_capture_source, | ||
5204 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
5205 | }, | ||
5153 | [ALC885_MACPRO] = { | 5206 | [ALC885_MACPRO] = { |
5154 | .mixers = { alc882_macpro_mixer }, | 5207 | .mixers = { alc882_macpro_mixer }, |
5155 | .init_verbs = { alc882_macpro_init_verbs }, | 5208 | .init_verbs = { alc882_macpro_init_verbs }, |
@@ -8708,6 +8761,27 @@ static struct snd_kcontrol_new alc861vd_3st_mixer[] = { | |||
8708 | { } /* end */ | 8761 | { } /* end */ |
8709 | }; | 8762 | }; |
8710 | 8763 | ||
8764 | static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = { | ||
8765 | HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), | ||
8766 | /*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/ | ||
8767 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
8768 | |||
8769 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
8770 | |||
8771 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
8772 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
8773 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
8774 | |||
8775 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | ||
8776 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
8777 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
8778 | |||
8779 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
8780 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
8781 | |||
8782 | { } /* end */ | ||
8783 | }; | ||
8784 | |||
8711 | /* | 8785 | /* |
8712 | * generic initialization of ADC, input mixers and output mixers | 8786 | * generic initialization of ADC, input mixers and output mixers |
8713 | */ | 8787 | */ |
@@ -8729,10 +8803,10 @@ static struct hda_verb alc861vd_volume_init_verbs[] = { | |||
8729 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 8803 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, |
8730 | 8804 | ||
8731 | /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */ | 8805 | /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */ |
8806 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8807 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
8808 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
8732 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 8809 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, |
8733 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, | ||
8734 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, | ||
8735 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(8)}, | ||
8736 | 8810 | ||
8737 | /* | 8811 | /* |
8738 | * Set up output mixers (0x02 - 0x05) | 8812 | * Set up output mixers (0x02 - 0x05) |
@@ -8833,6 +8907,68 @@ static struct hda_verb alc861vd_6stack_init_verbs[] = { | |||
8833 | { } | 8907 | { } |
8834 | }; | 8908 | }; |
8835 | 8909 | ||
8910 | static struct hda_verb alc861vd_eapd_verbs[] = { | ||
8911 | {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
8912 | { } | ||
8913 | }; | ||
8914 | |||
8915 | static struct hda_verb alc861vd_lenovo_unsol_verbs[] = { | ||
8916 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8917 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
8918 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, | ||
8919 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
8920 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, | ||
8921 | {} | ||
8922 | }; | ||
8923 | |||
8924 | /* toggle speaker-output according to the hp-jack state */ | ||
8925 | static void alc861vd_lenovo_hp_automute(struct hda_codec *codec) | ||
8926 | { | ||
8927 | unsigned int present; | ||
8928 | unsigned char bits; | ||
8929 | |||
8930 | present = snd_hda_codec_read(codec, 0x1b, 0, | ||
8931 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
8932 | bits = present ? 0x80 : 0; | ||
8933 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | ||
8934 | 0x80, bits); | ||
8935 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
8936 | 0x80, bits); | ||
8937 | } | ||
8938 | |||
8939 | static void alc861vd_lenovo_mic_automute(struct hda_codec *codec) | ||
8940 | { | ||
8941 | unsigned int present; | ||
8942 | unsigned char bits; | ||
8943 | |||
8944 | present = snd_hda_codec_read(codec, 0x18, 0, | ||
8945 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
8946 | bits = present ? 0x80 : 0; | ||
8947 | snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1, | ||
8948 | 0x80, bits); | ||
8949 | snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1, | ||
8950 | 0x80, bits); | ||
8951 | } | ||
8952 | |||
8953 | static void alc861vd_lenovo_automute(struct hda_codec *codec) | ||
8954 | { | ||
8955 | alc861vd_lenovo_hp_automute(codec); | ||
8956 | alc861vd_lenovo_mic_automute(codec); | ||
8957 | } | ||
8958 | |||
8959 | static void alc861vd_lenovo_unsol_event(struct hda_codec *codec, | ||
8960 | unsigned int res) | ||
8961 | { | ||
8962 | switch (res >> 26) { | ||
8963 | case ALC880_HP_EVENT: | ||
8964 | alc861vd_lenovo_hp_automute(codec); | ||
8965 | break; | ||
8966 | case ALC880_MIC_EVENT: | ||
8967 | alc861vd_lenovo_mic_automute(codec); | ||
8968 | break; | ||
8969 | } | ||
8970 | } | ||
8971 | |||
8836 | /* pcm configuration: identiacal with ALC880 */ | 8972 | /* pcm configuration: identiacal with ALC880 */ |
8837 | #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback | 8973 | #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback |
8838 | #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture | 8974 | #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture |
@@ -8847,6 +8983,7 @@ static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { | |||
8847 | [ALC861VD_3ST] = "3stack", | 8983 | [ALC861VD_3ST] = "3stack", |
8848 | [ALC861VD_3ST_DIG] = "3stack-digout", | 8984 | [ALC861VD_3ST_DIG] = "3stack-digout", |
8849 | [ALC861VD_6ST_DIG] = "6stack-digout", | 8985 | [ALC861VD_6ST_DIG] = "6stack-digout", |
8986 | [ALC861VD_LENOVO] = "lenovo", | ||
8850 | [ALC861VD_AUTO] = "auto", | 8987 | [ALC861VD_AUTO] = "auto", |
8851 | }; | 8988 | }; |
8852 | 8989 | ||
@@ -8856,7 +8993,8 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = { | |||
8856 | SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), | 8993 | SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), |
8857 | SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST), | 8994 | SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST), |
8858 | 8995 | ||
8859 | SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_3ST), | 8996 | SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), |
8997 | SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), | ||
8860 | {} | 8998 | {} |
8861 | }; | 8999 | }; |
8862 | 9000 | ||
@@ -8905,6 +9043,22 @@ static struct alc_config_preset alc861vd_presets[] = { | |||
8905 | .channel_mode = alc861vd_6stack_modes, | 9043 | .channel_mode = alc861vd_6stack_modes, |
8906 | .input_mux = &alc861vd_capture_source, | 9044 | .input_mux = &alc861vd_capture_source, |
8907 | }, | 9045 | }, |
9046 | [ALC861VD_LENOVO] = { | ||
9047 | .mixers = { alc861vd_lenovo_mixer }, | ||
9048 | .init_verbs = { alc861vd_volume_init_verbs, | ||
9049 | alc861vd_3stack_init_verbs, | ||
9050 | alc861vd_eapd_verbs, | ||
9051 | alc861vd_lenovo_unsol_verbs }, | ||
9052 | .num_dacs = ARRAY_SIZE(alc660vd_dac_nids), | ||
9053 | .dac_nids = alc660vd_dac_nids, | ||
9054 | .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), | ||
9055 | .adc_nids = alc861vd_adc_nids, | ||
9056 | .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), | ||
9057 | .channel_mode = alc861vd_3stack_2ch_modes, | ||
9058 | .input_mux = &alc861vd_capture_source, | ||
9059 | .unsol_event = alc861vd_lenovo_unsol_event, | ||
9060 | .init_hook = alc861vd_lenovo_automute, | ||
9061 | }, | ||
8908 | }; | 9062 | }; |
8909 | 9063 | ||
8910 | /* | 9064 | /* |
@@ -9028,7 +9182,7 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
9028 | return err; | 9182 | return err; |
9029 | sprintf(name, "%s Playback Switch", chname[i]); | 9183 | sprintf(name, "%s Playback Switch", chname[i]); |
9030 | err = add_control(spec, ALC_CTL_BIND_MUTE, name, | 9184 | err = add_control(spec, ALC_CTL_BIND_MUTE, name, |
9031 | HDA_COMPOSE_AMP_VAL(nid_v, 3, 2, | 9185 | HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, |
9032 | HDA_INPUT)); | 9186 | HDA_INPUT)); |
9033 | if (err < 0) | 9187 | if (err < 0) |
9034 | return err; | 9188 | return err; |