aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-03-12 07:51:09 -0400
committerTakashi Iwai <tiwai@suse.de>2008-04-24 06:00:23 -0400
commitbb9f76cd5909b9da6b4d31b55a4086cc35614fe0 (patch)
tree73f526b6c1980ccc910d5b5ef7f189426ebab50f
parent9f2f0f7c4e997a74ff9fb8e2e2ed0daa21962e97 (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.c132
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 */
8872static struct snd_kcontrol_new alc262_ultra_mixer[] = { 8872static 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
8882static struct hda_verb alc262_ultra_verbs[] = { 8882static 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
8897static 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 */
8905static void alc262_ultra_automute(struct hda_codec *codec) 8916static 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
8950static struct hda_input_mux alc262_ultra_capture_source = {
8951 .num_items = 2,
8952 .items = {
8953 { "Mic", 0x1 },
8954 { "Headphone", 0x7 },
8955 },
8956};
8957
8958static 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
8976static 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 */
8938static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, 8990static 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 },