aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKailang Yang <kailang@realtek.com.tw>2007-12-13 10:52:54 -0500
committerJaroslav Kysela <perex@perex.cz>2008-01-31 11:29:33 -0500
commitf6a92248aef841f14a5806cc299c431e7809c733 (patch)
tree550d98d41205723b8a6c32be8be5375d1629a847
parentf7278fd0a57ea6cde4988ab820851b01be20daef (diff)
[ALSA] hda-codec - Add ALC889/ALC267/ALC269 support
Added the support of new Realtek codecs: 1. New ALC889 Support 2. New ALC267 Support 3. New ALC269 Support 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>
-rw-r--r--sound/pci/hda/patch_realtek.c365
1 files changed, 365 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 0287bcc71a40..eba9be443857 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -110,6 +110,13 @@ enum {
110 ALC268_MODEL_LAST /* last tag */ 110 ALC268_MODEL_LAST /* last tag */
111}; 111};
112 112
113/* ALC269 models */
114enum {
115 ALC269_BASIC,
116 ALC269_AUTO,
117 ALC269_MODEL_LAST /* last tag */
118};
119
113/* ALC861 models */ 120/* ALC861 models */
114enum { 121enum {
115 ALC861_3ST, 122 ALC861_3ST,
@@ -9574,6 +9581,361 @@ static int patch_alc268(struct hda_codec *codec)
9574} 9581}
9575 9582
9576/* 9583/*
9584 * ALC269 channel source setting (2 channel)
9585 */
9586#define ALC269_DIGOUT_NID ALC880_DIGOUT_NID
9587
9588#define alc269_dac_nids alc260_dac_nids
9589
9590static hda_nid_t alc269_adc_nids[1] = {
9591 /* ADC1 */
9592 0x07,
9593};
9594
9595#define alc269_modes alc260_modes
9596#define alc269_capture_source alc880_lg_lw_capture_source
9597
9598static struct snd_kcontrol_new alc269_base_mixer[] = {
9599 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
9600 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
9601 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
9602 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
9603 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
9604 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
9605 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
9606 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
9607 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
9608 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
9609 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
9610 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
9611 { } /* end */
9612};
9613
9614/* capture mixer elements */
9615static struct snd_kcontrol_new alc269_capture_mixer[] = {
9616 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
9617 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
9618 {
9619 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9620 /* The multiple "Capture Source" controls confuse alsamixer
9621 * So call somewhat different..
9622 * FIXME: the controls appear in the "playback" view!
9623 */
9624 /* .name = "Capture Source", */
9625 .name = "Input Source",
9626 .count = 1,
9627 .info = alc_mux_enum_info,
9628 .get = alc_mux_enum_get,
9629 .put = alc_mux_enum_put,
9630 },
9631 { } /* end */
9632};
9633
9634/*
9635 * generic initialization of ADC, input mixers and output mixers
9636 */
9637static struct hda_verb alc269_init_verbs[] = {
9638 /*
9639 * Unmute ADC0 and set the default input to mic-in
9640 */
9641 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9642
9643 /* Mute input amps (PCBeep, Line In, Mic 1 & Mic 2) of the
9644 * analog-loopback mixer widget
9645 * Note: PASD motherboards uses the Line In 2 as the input for
9646 * front panel mic (mic 2)
9647 */
9648 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
9649 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
9650 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9651 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
9652 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
9653 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
9654
9655 /*
9656 * Set up output mixers (0x0c - 0x0e)
9657 */
9658 /* set vol=0 to output mixers */
9659 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9660 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
9661
9662 /* set up input amps for analog loopback */
9663 /* Amp Indices: DAC = 0, mixer = 1 */
9664 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9665 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9666 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9667 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9668 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9669 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
9670
9671 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9672 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
9673 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
9674 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
9675 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
9676 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9677 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
9678
9679 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9680 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
9681 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9682 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9683 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9684 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9685 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
9686
9687 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
9688 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
9689
9690 /* FIXME: use matrix-type input source selection */
9691 /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
9692 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
9693 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
9694 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
9695 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
9696 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
9697
9698 /* set EAPD */
9699 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
9700 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
9701 { }
9702};
9703
9704/* add playback controls from the parsed DAC table */
9705static int alc269_auto_create_multi_out_ctls(struct alc_spec *spec,
9706 const struct auto_pin_cfg *cfg)
9707{
9708 hda_nid_t nid;
9709 int err;
9710
9711 spec->multiout.num_dacs = 1; /* only use one dac */
9712 spec->multiout.dac_nids = spec->private_dac_nids;
9713 spec->multiout.dac_nids[0] = 2;
9714
9715 nid = cfg->line_out_pins[0];
9716 if (nid) {
9717 err = add_control(spec, ALC_CTL_WIDGET_VOL,
9718 "Front Playback Volume",
9719 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT));
9720 if (err < 0)
9721 return err;
9722 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
9723 "Front Playback Switch",
9724 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
9725 if (err < 0)
9726 return err;
9727 }
9728
9729 nid = cfg->speaker_pins[0];
9730 if (nid) {
9731 if (!cfg->line_out_pins[0]) {
9732 err = add_control(spec, ALC_CTL_WIDGET_VOL,
9733 "Speaker Playback Volume",
9734 HDA_COMPOSE_AMP_VAL(0x02, 3, 0,
9735 HDA_OUTPUT));
9736 if (err < 0)
9737 return err;
9738 }
9739 if (nid == 0x16) {
9740 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
9741 "Speaker Playback Switch",
9742 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
9743 HDA_OUTPUT));
9744 if (err < 0)
9745 return err;
9746 } else {
9747 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
9748 "Speaker Playback Switch",
9749 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
9750 HDA_OUTPUT));
9751 if (err < 0)
9752 return err;
9753 }
9754 }
9755 nid = cfg->hp_pins[0];
9756 if (nid) {
9757 /* spec->multiout.hp_nid = 2; */
9758 if (!cfg->line_out_pins[0] && !cfg->speaker_pins[0]) {
9759 err = add_control(spec, ALC_CTL_WIDGET_VOL,
9760 "Headphone Playback Volume",
9761 HDA_COMPOSE_AMP_VAL(0x02, 3, 0,
9762 HDA_OUTPUT));
9763 if (err < 0)
9764 return err;
9765 }
9766 if (nid == 0x16) {
9767 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
9768 "Headphone Playback Switch",
9769 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
9770 HDA_OUTPUT));
9771 if (err < 0)
9772 return err;
9773 } else {
9774 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
9775 "Headphone Playback Switch",
9776 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
9777 HDA_OUTPUT));
9778 if (err < 0)
9779 return err;
9780 }
9781 }
9782 return 0;
9783}
9784
9785#define alc269_auto_create_analog_input_ctls \
9786 alc880_auto_create_analog_input_ctls
9787
9788#ifdef CONFIG_SND_HDA_POWER_SAVE
9789#define alc269_loopbacks alc880_loopbacks
9790#endif
9791
9792/* pcm configuration: identiacal with ALC880 */
9793#define alc269_pcm_analog_playback alc880_pcm_analog_playback
9794#define alc269_pcm_analog_capture alc880_pcm_analog_capture
9795#define alc269_pcm_digital_playback alc880_pcm_digital_playback
9796#define alc269_pcm_digital_capture alc880_pcm_digital_capture
9797
9798/*
9799 * BIOS auto configuration
9800 */
9801static int alc269_parse_auto_config(struct hda_codec *codec)
9802{
9803 struct alc_spec *spec = codec->spec;
9804 int err;
9805 static hda_nid_t alc269_ignore[] = { 0x1d, 0 };
9806
9807 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
9808 alc269_ignore);
9809 if (err < 0)
9810 return err;
9811
9812 err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg);
9813 if (err < 0)
9814 return err;
9815 err = alc269_auto_create_analog_input_ctls(spec, &spec->autocfg);
9816 if (err < 0)
9817 return err;
9818
9819 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
9820
9821 if (spec->autocfg.dig_out_pin)
9822 spec->multiout.dig_out_nid = ALC269_DIGOUT_NID;
9823
9824 if (spec->kctl_alloc)
9825 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
9826
9827 spec->init_verbs[spec->num_init_verbs++] = alc269_init_verbs;
9828 spec->num_mux_defs = 1;
9829 spec->input_mux = &spec->private_imux;
9830
9831 err = alc_auto_add_mic_boost(codec);
9832 if (err < 0)
9833 return err;
9834
9835 return 1;
9836}
9837
9838#define alc269_auto_init_multi_out alc882_auto_init_multi_out
9839#define alc269_auto_init_hp_out alc882_auto_init_hp_out
9840#define alc269_auto_init_analog_input alc882_auto_init_analog_input
9841
9842
9843/* init callback for auto-configuration model -- overriding the default init */
9844static void alc269_auto_init(struct hda_codec *codec)
9845{
9846 alc269_auto_init_multi_out(codec);
9847 alc269_auto_init_hp_out(codec);
9848 alc269_auto_init_analog_input(codec);
9849}
9850
9851/*
9852 * configuration and preset
9853 */
9854static const char *alc269_models[ALC269_MODEL_LAST] = {
9855 [ALC269_BASIC] = "basic",
9856};
9857
9858static struct snd_pci_quirk alc269_cfg_tbl[] = {
9859 {}
9860};
9861
9862static struct alc_config_preset alc269_presets[] = {
9863 [ALC269_BASIC] = {
9864 .mixers = { alc269_base_mixer },
9865 .init_verbs = { alc269_init_verbs },
9866 .num_dacs = ARRAY_SIZE(alc269_dac_nids),
9867 .dac_nids = alc269_dac_nids,
9868 .hp_nid = 0x03,
9869 .num_channel_mode = ARRAY_SIZE(alc269_modes),
9870 .channel_mode = alc269_modes,
9871 .input_mux = &alc269_capture_source,
9872 },
9873};
9874
9875static int patch_alc269(struct hda_codec *codec)
9876{
9877 struct alc_spec *spec;
9878 int board_config;
9879 int err;
9880
9881 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
9882 if (spec == NULL)
9883 return -ENOMEM;
9884
9885 codec->spec = spec;
9886
9887 board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
9888 alc269_models,
9889 alc269_cfg_tbl);
9890
9891 if (board_config < 0) {
9892 printk(KERN_INFO "hda_codec: Unknown model for ALC269, "
9893 "trying auto-probe from BIOS...\n");
9894 board_config = ALC269_AUTO;
9895 }
9896
9897 if (board_config == ALC269_AUTO) {
9898 /* automatic parse from the BIOS config */
9899 err = alc269_parse_auto_config(codec);
9900 if (err < 0) {
9901 alc_free(codec);
9902 return err;
9903 } else if (!err) {
9904 printk(KERN_INFO
9905 "hda_codec: Cannot set up configuration "
9906 "from BIOS. Using base mode...\n");
9907 board_config = ALC269_BASIC;
9908 }
9909 }
9910
9911 if (board_config != ALC269_AUTO)
9912 setup_preset(spec, &alc269_presets[board_config]);
9913
9914 spec->stream_name_analog = "ALC269 Analog";
9915 spec->stream_analog_playback = &alc269_pcm_analog_playback;
9916 spec->stream_analog_capture = &alc269_pcm_analog_capture;
9917
9918 spec->stream_name_digital = "ALC269 Digital";
9919 spec->stream_digital_playback = &alc269_pcm_digital_playback;
9920 spec->stream_digital_capture = &alc269_pcm_digital_capture;
9921
9922 spec->adc_nids = alc269_adc_nids;
9923 spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
9924 spec->mixers[spec->num_mixers] = alc269_capture_mixer;
9925 spec->num_mixers++;
9926
9927 codec->patch_ops = alc_patch_ops;
9928 if (board_config == ALC269_AUTO)
9929 spec->init_hook = alc269_auto_init;
9930#ifdef CONFIG_SND_HDA_POWER_SAVE
9931 if (!spec->loopback.amplist)
9932 spec->loopback.amplist = alc269_loopbacks;
9933#endif
9934
9935 return 0;
9936}
9937
9938/*
9577 * ALC861 channel source setting (2/6 channel selection for 3-stack) 9939 * ALC861 channel source setting (2/6 channel selection for 3-stack)
9578 */ 9940 */
9579 9941
@@ -12653,7 +13015,9 @@ static int patch_alc662(struct hda_codec *codec)
12653struct hda_codec_preset snd_hda_preset_realtek[] = { 13015struct hda_codec_preset snd_hda_preset_realtek[] = {
12654 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, 13016 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
12655 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, 13017 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
13018 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
12656 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 }, 13019 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
13020 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
12657 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", 13021 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
12658 .patch = patch_alc861 }, 13022 .patch = patch_alc861 },
12659 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, 13023 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
@@ -12668,5 +13032,6 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
12668 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 }, 13032 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
12669 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, 13033 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
12670 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 }, 13034 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
13035 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
12671 {} /* terminator */ 13036 {} /* terminator */
12672}; 13037};