diff options
author | Kailang Yang <kailang@realtek.com.tw> | 2008-01-10 07:03:59 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-01-31 11:29:49 -0500 |
commit | 8c427226ed549af67396794e86246bf2d361ff8f (patch) | |
tree | dc2e241110e5e530bfb63f693ab7b93405f0ad4a /sound/pci/hda/patch_realtek.c | |
parent | 17596a80d3b57763f6d111fa95416559bad9c8dc (diff) |
[ALSA] hda-codec - Update realtek codec support
1. Support HP rp5700
2. Fixed alc_subsystem_id function (Bug fixed and support Desktop)
3. Support ASUS EP20
Signed-off-by: Kailang Yang <kailang@realtek.com.tw>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 151 |
1 files changed, 146 insertions, 5 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5e36462ac0f9..17784952acdd 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -92,6 +92,7 @@ enum { | |||
92 | ALC262_HP_BPC_D7000_WL, | 92 | ALC262_HP_BPC_D7000_WL, |
93 | ALC262_HP_BPC_D7000_WF, | 93 | ALC262_HP_BPC_D7000_WF, |
94 | ALC262_HP_TC_T5735, | 94 | ALC262_HP_TC_T5735, |
95 | ALC262_HP_RP5700, | ||
95 | ALC262_BENQ_ED8, | 96 | ALC262_BENQ_ED8, |
96 | ALC262_SONY_ASSAMD, | 97 | ALC262_SONY_ASSAMD, |
97 | ALC262_BENQ_T31, | 98 | ALC262_BENQ_T31, |
@@ -155,6 +156,7 @@ enum { | |||
155 | ALC662_5ST_DIG, | 156 | ALC662_5ST_DIG, |
156 | ALC662_LENOVO_101E, | 157 | ALC662_LENOVO_101E, |
157 | ALC662_ASUS_EEEPC_P701, | 158 | ALC662_ASUS_EEEPC_P701, |
159 | ALC662_ASUS_EEEPC_EP20, | ||
158 | ALC662_AUTO, | 160 | ALC662_AUTO, |
159 | ALC662_MODEL_LAST, | 161 | ALC662_MODEL_LAST, |
160 | }; | 162 | }; |
@@ -804,7 +806,7 @@ static void alc_subsystem_id(struct hda_codec *codec, | |||
804 | /* check sum */ | 806 | /* check sum */ |
805 | tmp = 0; | 807 | tmp = 0; |
806 | for (i = 1; i < 16; i++) { | 808 | for (i = 1; i < 16; i++) { |
807 | if ((ass >> i) && 1) | 809 | if ((ass >> i) & 1) |
808 | tmp++; | 810 | tmp++; |
809 | } | 811 | } |
810 | if (((ass >> 16) & 0xf) != tmp) | 812 | if (((ass >> 16) & 0xf) != tmp) |
@@ -893,10 +895,10 @@ do_sku: | |||
893 | break; | 895 | break; |
894 | } | 896 | } |
895 | 897 | ||
896 | /* is laptop and enable the function "Mute internal speaker | 898 | /* is laptop or Desktop and enable the function "Mute internal speaker |
897 | * when the external headphone out jack is plugged" | 899 | * when the external headphone out jack is plugged" |
898 | */ | 900 | */ |
899 | if (!(ass & 0x4) || !(ass & 0x8000)) | 901 | if (!(ass & 0x8000)) |
900 | return; | 902 | return; |
901 | /* | 903 | /* |
902 | * 10~8 : Jack location | 904 | * 10~8 : Jack location |
@@ -906,9 +908,9 @@ do_sku: | |||
906 | * when the external headphone out jack is plugged" | 908 | * when the external headphone out jack is plugged" |
907 | */ | 909 | */ |
908 | if (!spec->autocfg.speaker_pins[0]) { | 910 | if (!spec->autocfg.speaker_pins[0]) { |
909 | if (spec->multiout.dac_nids[0]) | 911 | if (spec->autocfg.line_out_pins[0]) |
910 | spec->autocfg.speaker_pins[0] = | 912 | spec->autocfg.speaker_pins[0] = |
911 | spec->multiout.dac_nids[0]; | 913 | spec->autocfg.line_out_pins[0]; |
912 | else | 914 | else |
913 | return; | 915 | return; |
914 | } | 916 | } |
@@ -7952,6 +7954,57 @@ static struct hda_verb alc262_hp_t5735_verbs[] = { | |||
7952 | { } | 7954 | { } |
7953 | }; | 7955 | }; |
7954 | 7956 | ||
7957 | static struct hda_bind_ctls alc262_hp_rp5700_bind_front_vol = { | ||
7958 | .ops = &snd_hda_bind_vol, | ||
7959 | .values = { | ||
7960 | HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT), | ||
7961 | HDA_COMPOSE_AMP_VAL(0x0e, 3, 0, HDA_OUTPUT), | ||
7962 | 0 | ||
7963 | }, | ||
7964 | }; | ||
7965 | |||
7966 | static struct hda_bind_ctls alc262_hp_rp5700_bind_front_sw = { | ||
7967 | .ops = &snd_hda_bind_sw, | ||
7968 | .values = { | ||
7969 | HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), | ||
7970 | HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_OUTPUT), | ||
7971 | 0 | ||
7972 | }, | ||
7973 | }; | ||
7974 | |||
7975 | static struct snd_kcontrol_new alc262_hp_rp5700_mixer[] = { | ||
7976 | HDA_BIND_VOL("PCM Playback Volume", &alc262_hp_rp5700_bind_front_vol), | ||
7977 | HDA_BIND_SW("PCM Playback Switch", &alc262_hp_rp5700_bind_front_sw), | ||
7978 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
7979 | HDA_CODEC_MUTE("Master Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
7980 | HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0e, 0x0, HDA_OUTPUT), | ||
7981 | HDA_CODEC_MUTE("iSpeaker Playback Switch", 0x16, 0x0, HDA_OUTPUT), | ||
7982 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT), | ||
7983 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), | ||
7984 | { } /* end */ | ||
7985 | }; | ||
7986 | |||
7987 | static struct hda_verb alc262_hp_rp5700_verbs[] = { | ||
7988 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
7989 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
7990 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
7991 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
7992 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
7993 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
7994 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
7995 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
7996 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))}, | ||
7997 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))}, | ||
7998 | {} | ||
7999 | }; | ||
8000 | |||
8001 | static struct hda_input_mux alc262_hp_rp5700_capture_source = { | ||
8002 | .num_items = 1, | ||
8003 | .items = { | ||
8004 | { "Line", 0x1 }, | ||
8005 | }, | ||
8006 | }; | ||
8007 | |||
7955 | /* bind hp and internal speaker mute (with plug check) */ | 8008 | /* bind hp and internal speaker mute (with plug check) */ |
7956 | static int alc262_sony_master_sw_put(struct snd_kcontrol *kcontrol, | 8009 | static int alc262_sony_master_sw_put(struct snd_kcontrol *kcontrol, |
7957 | struct snd_ctl_elem_value *ucontrol) | 8010 | struct snd_ctl_elem_value *ucontrol) |
@@ -8794,6 +8847,7 @@ static const char *alc262_models[ALC262_MODEL_LAST] = { | |||
8794 | [ALC262_HP_BPC] = "hp-bpc", | 8847 | [ALC262_HP_BPC] = "hp-bpc", |
8795 | [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000", | 8848 | [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000", |
8796 | [ALC262_HP_TC_T5735] = "hp-tc-t5735", | 8849 | [ALC262_HP_TC_T5735] = "hp-tc-t5735", |
8850 | [ALC262_HP_RP5700] = "hp-rp5700", | ||
8797 | [ALC262_BENQ_ED8] = "benq", | 8851 | [ALC262_BENQ_ED8] = "benq", |
8798 | [ALC262_BENQ_T31] = "benq-t31", | 8852 | [ALC262_BENQ_T31] = "benq-t31", |
8799 | [ALC262_SONY_ASSAMD] = "sony-assamd", | 8853 | [ALC262_SONY_ASSAMD] = "sony-assamd", |
@@ -8824,6 +8878,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { | |||
8824 | SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC), | 8878 | SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC), |
8825 | SND_PCI_QUIRK(0x103c, 0x302f, "HP Thin Client T5735", | 8879 | SND_PCI_QUIRK(0x103c, 0x302f, "HP Thin Client T5735", |
8826 | ALC262_HP_TC_T5735), | 8880 | ALC262_HP_TC_T5735), |
8881 | SND_PCI_QUIRK(0x103c, 0x2817, "HP RP5700", ALC262_HP_RP5700), | ||
8827 | SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), | 8882 | SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), |
8828 | SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO), | 8883 | SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO), |
8829 | SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD), | 8884 | SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD), |
@@ -8929,6 +8984,15 @@ static struct alc_config_preset alc262_presets[] = { | |||
8929 | .input_mux = &alc262_capture_source, | 8984 | .input_mux = &alc262_capture_source, |
8930 | .unsol_event = alc262_hp_t5735_unsol_event, | 8985 | .unsol_event = alc262_hp_t5735_unsol_event, |
8931 | .init_hook = alc262_hp_t5735_init_hook, | 8986 | .init_hook = alc262_hp_t5735_init_hook, |
8987 | }, | ||
8988 | [ALC262_HP_RP5700] = { | ||
8989 | .mixers = { alc262_hp_rp5700_mixer }, | ||
8990 | .init_verbs = { alc262_init_verbs, alc262_hp_rp5700_verbs }, | ||
8991 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), | ||
8992 | .dac_nids = alc262_dac_nids, | ||
8993 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | ||
8994 | .channel_mode = alc262_modes, | ||
8995 | .input_mux = &alc262_hp_rp5700_capture_source, | ||
8932 | }, | 8996 | }, |
8933 | [ALC262_BENQ_ED8] = { | 8997 | [ALC262_BENQ_ED8] = { |
8934 | .mixers = { alc262_base_mixer }, | 8998 | .mixers = { alc262_base_mixer }, |
@@ -12520,6 +12584,24 @@ static struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = { | |||
12520 | { } /* end */ | 12584 | { } /* end */ |
12521 | }; | 12585 | }; |
12522 | 12586 | ||
12587 | static struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = { | ||
12588 | HDA_CODEC_VOLUME("LineOut Playback Volume", 0x02, 0x0, HDA_OUTPUT), | ||
12589 | HDA_CODEC_MUTE("LineOut Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
12590 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), | ||
12591 | HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT), | ||
12592 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT), | ||
12593 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT), | ||
12594 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT), | ||
12595 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT), | ||
12596 | HDA_CODEC_MUTE("iSpeaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
12597 | HDA_BIND_MUTE("MuteCtrl Playback Switch", 0x0c, 2, HDA_INPUT), | ||
12598 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
12599 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
12600 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
12601 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
12602 | { } /* end */ | ||
12603 | }; | ||
12604 | |||
12523 | static struct snd_kcontrol_new alc662_chmode_mixer[] = { | 12605 | static struct snd_kcontrol_new alc662_chmode_mixer[] = { |
12524 | { | 12606 | { |
12525 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 12607 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -12605,6 +12687,13 @@ static struct hda_verb alc662_eeepc_sue_init_verbs[] = { | |||
12605 | {} | 12687 | {} |
12606 | }; | 12688 | }; |
12607 | 12689 | ||
12690 | /* Set Unsolicited Event*/ | ||
12691 | static struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = { | ||
12692 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
12693 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
12694 | {} | ||
12695 | }; | ||
12696 | |||
12608 | /* | 12697 | /* |
12609 | * generic initialization of ADC, input mixers and output mixers | 12698 | * generic initialization of ADC, input mixers and output mixers |
12610 | */ | 12699 | */ |
@@ -12741,6 +12830,40 @@ static void alc662_eeepc_inithook(struct hda_codec *codec) | |||
12741 | alc662_eeepc_mic_automute(codec); | 12830 | alc662_eeepc_mic_automute(codec); |
12742 | } | 12831 | } |
12743 | 12832 | ||
12833 | static void alc662_eeepc_ep20_automute(struct hda_codec *codec) | ||
12834 | { | ||
12835 | unsigned int mute; | ||
12836 | unsigned int present; | ||
12837 | |||
12838 | snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0); | ||
12839 | present = snd_hda_codec_read(codec, 0x14, 0, | ||
12840 | AC_VERB_GET_PIN_SENSE, 0); | ||
12841 | present = (present & 0x80000000) != 0; | ||
12842 | if (present) { | ||
12843 | /* mute internal speaker */ | ||
12844 | snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0, | ||
12845 | HDA_AMP_MUTE, HDA_AMP_MUTE); | ||
12846 | } else { | ||
12847 | /* unmute internal speaker if necessary */ | ||
12848 | mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); | ||
12849 | snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0, | ||
12850 | HDA_AMP_MUTE, mute); | ||
12851 | } | ||
12852 | } | ||
12853 | |||
12854 | /* unsolicited event for HP jack sensing */ | ||
12855 | static void alc662_eeepc_ep20_unsol_event(struct hda_codec *codec, | ||
12856 | unsigned int res) | ||
12857 | { | ||
12858 | if ((res >> 26) == ALC880_HP_EVENT) | ||
12859 | alc662_eeepc_ep20_automute(codec); | ||
12860 | } | ||
12861 | |||
12862 | static void alc662_eeepc_ep20_inithook(struct hda_codec *codec) | ||
12863 | { | ||
12864 | alc662_eeepc_ep20_automute(codec); | ||
12865 | } | ||
12866 | |||
12744 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 12867 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
12745 | #define alc662_loopbacks alc880_loopbacks | 12868 | #define alc662_loopbacks alc880_loopbacks |
12746 | #endif | 12869 | #endif |
@@ -12762,11 +12885,13 @@ static const char *alc662_models[ALC662_MODEL_LAST] = { | |||
12762 | [ALC662_5ST_DIG] = "6stack-dig", | 12885 | [ALC662_5ST_DIG] = "6stack-dig", |
12763 | [ALC662_LENOVO_101E] = "lenovo-101e", | 12886 | [ALC662_LENOVO_101E] = "lenovo-101e", |
12764 | [ALC662_ASUS_EEEPC_P701] = "eeepc-p701", | 12887 | [ALC662_ASUS_EEEPC_P701] = "eeepc-p701", |
12888 | [ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20", | ||
12765 | [ALC662_AUTO] = "auto", | 12889 | [ALC662_AUTO] = "auto", |
12766 | }; | 12890 | }; |
12767 | 12891 | ||
12768 | static struct snd_pci_quirk alc662_cfg_tbl[] = { | 12892 | static struct snd_pci_quirk alc662_cfg_tbl[] = { |
12769 | SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701), | 12893 | SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701), |
12894 | SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20), | ||
12770 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), | 12895 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), |
12771 | {} | 12896 | {} |
12772 | }; | 12897 | }; |
@@ -12854,6 +12979,21 @@ static struct alc_config_preset alc662_presets[] = { | |||
12854 | .unsol_event = alc662_eeepc_unsol_event, | 12979 | .unsol_event = alc662_eeepc_unsol_event, |
12855 | .init_hook = alc662_eeepc_inithook, | 12980 | .init_hook = alc662_eeepc_inithook, |
12856 | }, | 12981 | }, |
12982 | [ALC662_ASUS_EEEPC_EP20] = { | ||
12983 | .mixers = { alc662_eeepc_ep20_mixer, alc662_capture_mixer, | ||
12984 | alc662_chmode_mixer }, | ||
12985 | .init_verbs = { alc662_init_verbs, | ||
12986 | alc662_eeepc_ep20_sue_init_verbs }, | ||
12987 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | ||
12988 | .dac_nids = alc662_dac_nids, | ||
12989 | .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), | ||
12990 | .adc_nids = alc662_adc_nids, | ||
12991 | .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes), | ||
12992 | .channel_mode = alc662_3ST_6ch_modes, | ||
12993 | .input_mux = &alc662_lenovo_101e_capture_source, | ||
12994 | .unsol_event = alc662_eeepc_ep20_unsol_event, | ||
12995 | .init_hook = alc662_eeepc_ep20_inithook, | ||
12996 | }, | ||
12857 | 12997 | ||
12858 | }; | 12998 | }; |
12859 | 12999 | ||
@@ -13013,6 +13153,7 @@ static void alc662_auto_init_multi_out(struct hda_codec *codec) | |||
13013 | struct alc_spec *spec = codec->spec; | 13153 | struct alc_spec *spec = codec->spec; |
13014 | int i; | 13154 | int i; |
13015 | 13155 | ||
13156 | alc_subsystem_id(codec, 0x15, 0x1b, 0x14); | ||
13016 | for (i = 0; i <= HDA_SIDE; i++) { | 13157 | for (i = 0; i <= HDA_SIDE; i++) { |
13017 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | 13158 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; |
13018 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | 13159 | int pin_type = get_pin_type(spec->autocfg.line_out_type); |