diff options
author | Takashi Iwai <tiwai@suse.de> | 2008-03-12 07:51:09 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-04-24 06:00:23 -0400 |
commit | bb9f76cd5909b9da6b4d31b55a4086cc35614fe0 (patch) | |
tree | 73f526b6c1980ccc910d5b5ef7f189426ebab50f | |
parent | 9f2f0f7c4e997a74ff9fb8e2e2ed0daa21962e97 (diff) |
[ALSA] hda-codec - Improve ALC262 ultra model
Improved ALC262 ultra model for Samsung Q1 Ultra series.
- clean up mixers
- support of input from HP jack as a mic
- add quirk for Q1 EL
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 132 |
1 files changed, 93 insertions, 39 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index bfb336de1dcb..3965b7644ad5 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -8870,59 +8870,72 @@ static struct hda_verb alc262_benq_t31_EAPD_verbs[] = { | |||
8870 | 8870 | ||
8871 | /* Samsung Q1 Ultra Vista model setup */ | 8871 | /* Samsung Q1 Ultra Vista model setup */ |
8872 | static struct snd_kcontrol_new alc262_ultra_mixer[] = { | 8872 | static struct snd_kcontrol_new alc262_ultra_mixer[] = { |
8873 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 8873 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
8874 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 8874 | HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT), |
8875 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
8876 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 8875 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
8877 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 8876 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
8878 | HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT), | 8877 | HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT), |
8878 | HDA_CODEC_VOLUME("Headphone Mic Boost", 0x15, 0, HDA_INPUT), | ||
8879 | { } /* end */ | 8879 | { } /* end */ |
8880 | }; | 8880 | }; |
8881 | 8881 | ||
8882 | static struct hda_verb alc262_ultra_verbs[] = { | 8882 | static struct hda_verb alc262_ultra_verbs[] = { |
8883 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | 8883 | /* output mixer */ |
8884 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
8885 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
8886 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
8887 | /* speaker */ | ||
8888 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
8889 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
8890 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8891 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
8892 | /* HP */ | ||
8884 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 8893 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
8885 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 8894 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
8886 | /* Mic is on Node 0x19 */ | 8895 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
8887 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 8896 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, |
8888 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x01}, | 8897 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, |
8889 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 8898 | /* internal mic */ |
8890 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x01}, | 8899 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
8891 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 8900 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
8892 | {0x24, AC_VERB_SET_CONNECT_SEL, 0x01}, | 8901 | /* ADC, choose mic */ |
8893 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 8902 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
8903 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
8904 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
8905 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
8906 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
8907 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
8908 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, | ||
8909 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, | ||
8910 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, | ||
8911 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)}, | ||
8894 | {} | 8912 | {} |
8895 | }; | 8913 | }; |
8896 | 8914 | ||
8897 | static struct hda_input_mux alc262_ultra_capture_source = { | ||
8898 | .num_items = 1, | ||
8899 | .items = { | ||
8900 | { "Mic", 0x1 }, | ||
8901 | }, | ||
8902 | }; | ||
8903 | |||
8904 | /* mute/unmute internal speaker according to the hp jack and mute state */ | 8915 | /* mute/unmute internal speaker according to the hp jack and mute state */ |
8905 | static void alc262_ultra_automute(struct hda_codec *codec) | 8916 | static void alc262_ultra_automute(struct hda_codec *codec) |
8906 | { | 8917 | { |
8907 | struct alc_spec *spec = codec->spec; | 8918 | struct alc_spec *spec = codec->spec; |
8908 | unsigned int mute; | 8919 | unsigned int mute; |
8909 | unsigned int present; | ||
8910 | 8920 | ||
8911 | /* need to execute and sync at first */ | 8921 | mute = 0; |
8912 | snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0); | 8922 | /* auto-mute only when HP is used as HP */ |
8913 | present = snd_hda_codec_read(codec, 0x15, 0, | 8923 | if (!spec->cur_mux[0]) { |
8914 | AC_VERB_GET_PIN_SENSE, 0); | 8924 | unsigned int present; |
8915 | spec->jack_present = (present & 0x80000000) != 0; | 8925 | /* need to execute and sync at first */ |
8916 | if (spec->jack_present) { | 8926 | snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0); |
8917 | /* mute internal speaker */ | 8927 | present = snd_hda_codec_read(codec, 0x15, 0, |
8918 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | 8928 | AC_VERB_GET_PIN_SENSE, 0); |
8919 | HDA_AMP_MUTE, HDA_AMP_MUTE); | 8929 | spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0; |
8920 | } else { | 8930 | if (spec->jack_present) |
8921 | /* unmute internal speaker if necessary */ | 8931 | mute = HDA_AMP_MUTE; |
8922 | mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0); | ||
8923 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
8924 | HDA_AMP_MUTE, mute); | ||
8925 | } | 8932 | } |
8933 | /* mute/unmute internal speaker */ | ||
8934 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
8935 | HDA_AMP_MUTE, mute); | ||
8936 | /* mute/unmute HP */ | ||
8937 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, | ||
8938 | HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE); | ||
8926 | } | 8939 | } |
8927 | 8940 | ||
8928 | /* unsolicited event for HP jack sensing */ | 8941 | /* unsolicited event for HP jack sensing */ |
@@ -8934,6 +8947,45 @@ static void alc262_ultra_unsol_event(struct hda_codec *codec, | |||
8934 | alc262_ultra_automute(codec); | 8947 | alc262_ultra_automute(codec); |
8935 | } | 8948 | } |
8936 | 8949 | ||
8950 | static struct hda_input_mux alc262_ultra_capture_source = { | ||
8951 | .num_items = 2, | ||
8952 | .items = { | ||
8953 | { "Mic", 0x1 }, | ||
8954 | { "Headphone", 0x7 }, | ||
8955 | }, | ||
8956 | }; | ||
8957 | |||
8958 | static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol, | ||
8959 | struct snd_ctl_elem_value *ucontrol) | ||
8960 | { | ||
8961 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
8962 | struct alc_spec *spec = codec->spec; | ||
8963 | int ret; | ||
8964 | |||
8965 | ret = alc882_mux_enum_put(kcontrol, ucontrol); | ||
8966 | if (!ret) | ||
8967 | return 0; | ||
8968 | /* reprogram the HP pin as mic or HP according to the input source */ | ||
8969 | snd_hda_codec_write_cache(codec, 0x15, 0, | ||
8970 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
8971 | spec->cur_mux[0] ? PIN_VREF80 : PIN_HP); | ||
8972 | alc262_ultra_automute(codec); /* mute/unmute HP */ | ||
8973 | return ret; | ||
8974 | } | ||
8975 | |||
8976 | static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = { | ||
8977 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | ||
8978 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | ||
8979 | { | ||
8980 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
8981 | .name = "Capture Source", | ||
8982 | .info = alc882_mux_enum_info, | ||
8983 | .get = alc882_mux_enum_get, | ||
8984 | .put = alc262_ultra_mux_enum_put, | ||
8985 | }, | ||
8986 | { } /* end */ | ||
8987 | }; | ||
8988 | |||
8937 | /* add playback controls from the parsed DAC table */ | 8989 | /* add playback controls from the parsed DAC table */ |
8938 | static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, | 8990 | static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, |
8939 | const struct auto_pin_cfg *cfg) | 8991 | const struct auto_pin_cfg *cfg) |
@@ -9384,6 +9436,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { | |||
9384 | SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), | 9436 | SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), |
9385 | SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU), | 9437 | SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU), |
9386 | SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA), | 9438 | SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA), |
9439 | SND_PCI_QUIRK(0x144d, 0xc039, "Samsung Q1U EL", ALC262_ULTRA), | ||
9387 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), | 9440 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), |
9388 | SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31), | 9441 | SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31), |
9389 | SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1), | 9442 | SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1), |
@@ -9533,15 +9586,16 @@ static struct alc_config_preset alc262_presets[] = { | |||
9533 | .init_hook = alc262_hippo_automute, | 9586 | .init_hook = alc262_hippo_automute, |
9534 | }, | 9587 | }, |
9535 | [ALC262_ULTRA] = { | 9588 | [ALC262_ULTRA] = { |
9536 | .mixers = { alc262_ultra_mixer }, | 9589 | .mixers = { alc262_ultra_mixer, alc262_ultra_capture_mixer }, |
9537 | .init_verbs = { alc262_init_verbs, alc262_ultra_verbs }, | 9590 | .init_verbs = { alc262_ultra_verbs }, |
9538 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), | 9591 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), |
9539 | .dac_nids = alc262_dac_nids, | 9592 | .dac_nids = alc262_dac_nids, |
9540 | .hp_nid = 0x03, | ||
9541 | .dig_out_nid = ALC262_DIGOUT_NID, | ||
9542 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | 9593 | .num_channel_mode = ARRAY_SIZE(alc262_modes), |
9543 | .channel_mode = alc262_modes, | 9594 | .channel_mode = alc262_modes, |
9544 | .input_mux = &alc262_ultra_capture_source, | 9595 | .input_mux = &alc262_ultra_capture_source, |
9596 | .adc_nids = alc262_adc_nids, /* ADC0 */ | ||
9597 | .capsrc_nids = alc262_capsrc_nids, | ||
9598 | .num_adc_nids = 1, /* single ADC */ | ||
9545 | .unsol_event = alc262_ultra_unsol_event, | 9599 | .unsol_event = alc262_ultra_unsol_event, |
9546 | .init_hook = alc262_ultra_automute, | 9600 | .init_hook = alc262_ultra_automute, |
9547 | }, | 9601 | }, |