aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorKailang Yang <kailang@realtek.com.tw>2007-05-08 09:19:08 -0400
committerJaroslav Kysela <perex@suse.cz>2007-05-11 10:56:18 -0400
commitbdd148a307e230517bf891c108e0eec68ba5d10f (patch)
tree7fa88c608913978f52d8b76a6b1b5d6f537857f3 /sound
parent0bbed758c024bb72cec8219879dc87cb04c6dd5c (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')
-rw-r--r--sound/pci/hda/patch_realtek.c164
1 files changed, 159 insertions, 5 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 8c0b4fbc144..a4ede27af02 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
640static 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
4812static 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
4788static struct snd_kcontrol_new alc882_chmode_mixer[] = { 4827static 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
8764static 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
8910static struct hda_verb alc861vd_eapd_verbs[] = {
8911 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
8912 { }
8913};
8914
8915static 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 */
8925static 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
8939static 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
8953static void alc861vd_lenovo_automute(struct hda_codec *codec)
8954{
8955 alc861vd_lenovo_hp_automute(codec);
8956 alc861vd_lenovo_mic_automute(codec);
8957}
8958
8959static 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;