aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKailang Yang <kailang@realtek.com.tw>2007-06-05 06:30:55 -0400
committerJaroslav Kysela <perex@suse.cz>2007-07-20 05:11:24 -0400
commita361d84bfcd938208dea6c84aa19994b3d69e15d (patch)
treec3b05f27ca6331478b29dd8ecd52c3c44d468e3c
parent7d87de2db2213e6e9413532445b14c92dae42c85 (diff)
[ALSA] hda-codec - Add support of ALC268 codec
Added the support of new ALC268 codec chip. 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>
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt4
-rw-r--r--sound/pci/hda/patch_realtek.c517
2 files changed, 521 insertions, 0 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index ca3e6d5e6a53..7659e5071c41 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -822,6 +822,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
822 basic fixed pin assignment w/o SPDIF 822 basic fixed pin assignment w/o SPDIF
823 auto auto-config reading BIOS (default) 823 auto auto-config reading BIOS (default)
824 824
825 ALC268
826 3stack 3-stack model
827 auto auto-config reading BIOS (default)
828
825 ALC882/885 829 ALC882/885
826 3stack-dig 3-jack with SPDIF I/O 830 3stack-dig 3-jack with SPDIF I/O
827 6stack-dig 6-jack digital with SPDIF I/O 831 6stack-dig 6-jack digital with SPDIF I/O
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index c92c97c6cbe5..49a0fa8ec679 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -98,6 +98,13 @@ enum {
98 ALC262_MODEL_LAST /* last tag */ 98 ALC262_MODEL_LAST /* last tag */
99}; 99};
100 100
101/* ALC268 models */
102enum {
103 ALC268_3ST,
104 ALC268_AUTO,
105 ALC268_MODEL_LAST /* last tag */
106};
107
101/* ALC861 models */ 108/* ALC861 models */
102enum { 109enum {
103 ALC861_3ST, 110 ALC861_3ST,
@@ -7804,6 +7811,515 @@ static int patch_alc262(struct hda_codec *codec)
7804} 7811}
7805 7812
7806/* 7813/*
7814 * ALC268 channel source setting (2 channel)
7815 */
7816#define ALC268_DIGOUT_NID ALC880_DIGOUT_NID
7817#define alc268_modes alc260_modes
7818
7819static hda_nid_t alc268_dac_nids[2] = {
7820 /* front, hp */
7821 0x02, 0x03
7822};
7823
7824static hda_nid_t alc268_adc_nids[2] = {
7825 /* ADC0-1 */
7826 0x08, 0x07
7827};
7828
7829static hda_nid_t alc268_adc_nids_alt[1] = {
7830 /* ADC0 */
7831 0x08
7832};
7833
7834static struct snd_kcontrol_new alc268_base_mixer[] = {
7835 /* output mixer control */
7836 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
7837 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
7838 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
7839 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
7840 { }
7841};
7842
7843/*
7844 * generic initialization of ADC, input mixers and output mixers
7845 */
7846static struct hda_verb alc268_base_init_verbs[] = {
7847 /* Unmute DAC0-1 and set vol = 0 */
7848 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7849 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7850 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7851 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7852 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7853 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7854
7855 /*
7856 * Set up output mixers (0x0c - 0x0e)
7857 */
7858 /* set vol=0 to output mixers */
7859 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7860 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7861 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7862 {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
7863
7864 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7865 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7866
7867 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
7868 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
7869 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
7870 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
7871 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
7872 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
7873 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
7874 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
7875
7876 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7877 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7878 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7879 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7880 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7881 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7882 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7883 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7884
7885 /* FIXME: use matrix-type input source selection */
7886 /* Mixer elements: 0x18, 19, 1a, 1c, 14, 15, 0b */
7887 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
7888 /* Input mixer2 */
7889 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7890 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
7891 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
7892 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
7893
7894 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
7895 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
7896 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
7897 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
7898 { }
7899};
7900
7901/*
7902 * generic initialization of ADC, input mixers and output mixers
7903 */
7904static struct hda_verb alc268_volume_init_verbs[] = {
7905 /* set output DAC */
7906 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7907 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7908 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7909 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7910
7911 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
7912 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
7913 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
7914 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
7915 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
7916
7917 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
7918 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7919 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7920 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7921 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7922
7923 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7924 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7925 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7926 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
7927
7928 /* set PCBEEP vol = 0 */
7929 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0xb000 | (0x00 << 8))},
7930
7931 { }
7932};
7933
7934#define alc268_mux_enum_info alc_mux_enum_info
7935#define alc268_mux_enum_get alc_mux_enum_get
7936
7937static int alc268_mux_enum_put(struct snd_kcontrol *kcontrol,
7938 struct snd_ctl_elem_value *ucontrol)
7939{
7940 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
7941 struct alc_spec *spec = codec->spec;
7942 const struct hda_input_mux *imux = spec->input_mux;
7943 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
7944 static hda_nid_t capture_mixers[3] = { 0x23, 0x24 };
7945 hda_nid_t nid = capture_mixers[adc_idx];
7946 unsigned int *cur_val = &spec->cur_mux[adc_idx];
7947 unsigned int i, idx;
7948
7949 idx = ucontrol->value.enumerated.item[0];
7950 if (idx >= imux->num_items)
7951 idx = imux->num_items - 1;
7952 if (*cur_val == idx && !codec->in_resume)
7953 return 0;
7954 for (i = 0; i < imux->num_items; i++) {
7955 unsigned int v = (i == idx) ? 0x7000 : 0x7080;
7956 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
7957 v | (imux->items[i].index << 8));
7958 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
7959 idx );
7960 }
7961 *cur_val = idx;
7962 return 1;
7963}
7964
7965static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
7966 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
7967 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
7968 {
7969 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7970 /* The multiple "Capture Source" controls confuse alsamixer
7971 * So call somewhat different..
7972 * FIXME: the controls appear in the "playback" view!
7973 */
7974 /* .name = "Capture Source", */
7975 .name = "Input Source",
7976 .count = 1,
7977 .info = alc268_mux_enum_info,
7978 .get = alc268_mux_enum_get,
7979 .put = alc268_mux_enum_put,
7980 },
7981 { } /* end */
7982};
7983
7984static struct snd_kcontrol_new alc268_capture_mixer[] = {
7985 HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
7986 HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
7987 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT),
7988 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT),
7989 {
7990 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7991 /* The multiple "Capture Source" controls confuse alsamixer
7992 * So call somewhat different..
7993 * FIXME: the controls appear in the "playback" view!
7994 */
7995 /* .name = "Capture Source", */
7996 .name = "Input Source",
7997 .count = 2,
7998 .info = alc268_mux_enum_info,
7999 .get = alc268_mux_enum_get,
8000 .put = alc268_mux_enum_put,
8001 },
8002 { } /* end */
8003};
8004
8005static struct hda_input_mux alc268_capture_source = {
8006 .num_items = 4,
8007 .items = {
8008 { "Mic", 0x0 },
8009 { "Front Mic", 0x1 },
8010 { "Line", 0x2 },
8011 { "CD", 0x3 },
8012 },
8013};
8014
8015/* create input playback/capture controls for the given pin */
8016static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
8017 const char *ctlname, int idx)
8018{
8019 char name[32];
8020 int err;
8021
8022 sprintf(name, "%s Playback Volume", ctlname);
8023 if (nid == 0x14) {
8024 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
8025 HDA_COMPOSE_AMP_VAL(0x02, 3, idx,
8026 HDA_OUTPUT));
8027 if (err < 0)
8028 return err;
8029 } else if (nid == 0x15) {
8030 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
8031 HDA_COMPOSE_AMP_VAL(0x03, 3, idx,
8032 HDA_OUTPUT));
8033 if (err < 0)
8034 return err;
8035 } else
8036 return -1;
8037 sprintf(name, "%s Playback Switch", ctlname);
8038 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
8039 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
8040 if (err < 0)
8041 return err;
8042 return 0;
8043}
8044
8045/* add playback controls from the parsed DAC table */
8046static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
8047 const struct auto_pin_cfg *cfg)
8048{
8049 hda_nid_t nid;
8050 int err;
8051
8052 spec->multiout.num_dacs = 2; /* only use one dac */
8053 spec->multiout.dac_nids = spec->private_dac_nids;
8054 spec->multiout.dac_nids[0] = 2;
8055 spec->multiout.dac_nids[1] = 3;
8056
8057 nid = cfg->line_out_pins[0];
8058 if (nid)
8059 alc268_new_analog_output(spec, nid, "Front", 0);
8060
8061 nid = cfg->speaker_pins[0];
8062 if (nid == 0x1d) {
8063 err = add_control(spec, ALC_CTL_WIDGET_VOL,
8064 "Speaker Playback Volume",
8065 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
8066 if (err < 0)
8067 return err;
8068 }
8069 nid = cfg->hp_pins[0];
8070 if (nid)
8071 alc268_new_analog_output(spec, nid, "Headphone", 0);
8072
8073 nid = cfg->line_out_pins[1] | cfg->line_out_pins[2];
8074 if (nid == 0x16) {
8075 err = add_control(spec, ALC_CTL_WIDGET_MUTE,
8076 "Mono Playback Switch",
8077 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_INPUT));
8078 if (err < 0)
8079 return err;
8080 }
8081 return 0;
8082}
8083
8084/* create playback/capture controls for input pins */
8085static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec,
8086 const struct auto_pin_cfg *cfg)
8087{
8088 struct hda_input_mux *imux = &spec->private_imux;
8089 int i, idx1;
8090
8091 for (i = 0; i < AUTO_PIN_LAST; i++) {
8092 switch(cfg->input_pins[i]) {
8093 case 0x18:
8094 idx1 = 0; /* Mic 1 */
8095 break;
8096 case 0x19:
8097 idx1 = 1; /* Mic 2 */
8098 break;
8099 case 0x1a:
8100 idx1 = 2; /* Line In */
8101 break;
8102 case 0x1c:
8103 idx1 = 3; /* CD */
8104 break;
8105 default:
8106 continue;
8107 }
8108 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
8109 imux->items[imux->num_items].index = idx1;
8110 imux->num_items++;
8111 }
8112 return 0;
8113}
8114
8115static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)
8116{
8117 struct alc_spec *spec = codec->spec;
8118 hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
8119 hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
8120 hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
8121 unsigned int dac_vol1, dac_vol2;
8122
8123 if (speaker_nid) {
8124 snd_hda_codec_write(codec, speaker_nid, 0,
8125 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
8126 snd_hda_codec_write(codec, 0x0f, 0,
8127 AC_VERB_SET_AMP_GAIN_MUTE,
8128 AMP_IN_UNMUTE(1));
8129 snd_hda_codec_write(codec, 0x10, 0,
8130 AC_VERB_SET_AMP_GAIN_MUTE,
8131 AMP_IN_UNMUTE(1));
8132 } else {
8133 snd_hda_codec_write(codec, 0x0f, 0,
8134 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
8135 snd_hda_codec_write(codec, 0x10, 0,
8136 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
8137 }
8138
8139 dac_vol1 = dac_vol2 = 0xb000 | 0x40; /* set max volume */
8140 if (line_nid == 0x14)
8141 dac_vol2 = AMP_OUT_ZERO;
8142 else if (line_nid == 0x15)
8143 dac_vol1 = AMP_OUT_ZERO;
8144 if (hp_nid == 0x14)
8145 dac_vol2 = AMP_OUT_ZERO;
8146 else if (hp_nid == 0x15)
8147 dac_vol1 = AMP_OUT_ZERO;
8148 if (line_nid != 0x16 || hp_nid != 0x16 ||
8149 spec->autocfg.line_out_pins[1] != 0x16 ||
8150 spec->autocfg.line_out_pins[2] != 0x16)
8151 dac_vol1 = dac_vol2 = AMP_OUT_ZERO;
8152
8153 snd_hda_codec_write(codec, 0x02, 0,
8154 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol1);
8155 snd_hda_codec_write(codec, 0x03, 0,
8156 AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2);
8157}
8158
8159/* pcm configuration: identiacal with ALC880 */
8160#define alc268_pcm_analog_playback alc880_pcm_analog_playback
8161#define alc268_pcm_analog_capture alc880_pcm_analog_capture
8162#define alc268_pcm_digital_playback alc880_pcm_digital_playback
8163
8164/*
8165 * BIOS auto configuration
8166 */
8167static int alc268_parse_auto_config(struct hda_codec *codec)
8168{
8169 struct alc_spec *spec = codec->spec;
8170 int err;
8171 static hda_nid_t alc268_ignore[] = { 0 };
8172
8173 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
8174 alc268_ignore);
8175 if (err < 0)
8176 return err;
8177 if (!spec->autocfg.line_outs)
8178 return 0; /* can't find valid BIOS pin config */
8179
8180 err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg);
8181 if (err < 0)
8182 return err;
8183 err = alc268_auto_create_analog_input_ctls(spec, &spec->autocfg);
8184 if (err < 0)
8185 return err;
8186
8187 spec->multiout.max_channels = 2;
8188
8189 /* digital only support output */
8190 if (spec->autocfg.dig_out_pin)
8191 spec->multiout.dig_out_nid = ALC268_DIGOUT_NID;
8192
8193 if (spec->kctl_alloc)
8194 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
8195
8196 spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs;
8197 spec->num_mux_defs = 1;
8198 spec->input_mux = &spec->private_imux;
8199
8200 return 1;
8201}
8202
8203#define alc268_auto_init_multi_out alc882_auto_init_multi_out
8204#define alc268_auto_init_hp_out alc882_auto_init_hp_out
8205#define alc268_auto_init_analog_input alc882_auto_init_analog_input
8206
8207/* init callback for auto-configuration model -- overriding the default init */
8208static void alc268_auto_init(struct hda_codec *codec)
8209{
8210 alc268_auto_init_multi_out(codec);
8211 alc268_auto_init_hp_out(codec);
8212 alc268_auto_init_mono_speaker_out(codec);
8213 alc268_auto_init_analog_input(codec);
8214}
8215
8216/*
8217 * configuration and preset
8218 */
8219static const char *alc268_models[ALC268_MODEL_LAST] = {
8220 [ALC268_3ST] = "3stack",
8221 [ALC268_AUTO] = "auto",
8222};
8223
8224static struct snd_pci_quirk alc268_cfg_tbl[] = {
8225 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
8226 {}
8227};
8228
8229static struct alc_config_preset alc268_presets[] = {
8230 [ALC268_3ST] = {
8231 .mixers = { alc268_base_mixer, alc268_capture_alt_mixer },
8232 .init_verbs = { alc268_base_init_verbs },
8233 .num_dacs = ARRAY_SIZE(alc268_dac_nids),
8234 .dac_nids = alc268_dac_nids,
8235 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
8236 .adc_nids = alc268_adc_nids_alt,
8237 .hp_nid = 0x03,
8238 .dig_out_nid = ALC268_DIGOUT_NID,
8239 .num_channel_mode = ARRAY_SIZE(alc268_modes),
8240 .channel_mode = alc268_modes,
8241 .input_mux = &alc268_capture_source,
8242 },
8243};
8244
8245static int patch_alc268(struct hda_codec *codec)
8246{
8247 struct alc_spec *spec;
8248 int board_config;
8249 int err;
8250
8251 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
8252 if (spec == NULL)
8253 return -ENOMEM;
8254
8255 codec->spec = spec;
8256
8257 board_config = snd_hda_check_board_config(codec, ALC268_MODEL_LAST,
8258 alc268_models,
8259 alc268_cfg_tbl);
8260
8261 if (board_config < 0 || board_config >= ALC268_MODEL_LAST) {
8262 printk(KERN_INFO "hda_codec: Unknown model for ALC268, "
8263 "trying auto-probe from BIOS...\n");
8264 board_config = ALC268_AUTO;
8265 }
8266
8267 if (board_config == ALC268_AUTO) {
8268 /* automatic parse from the BIOS config */
8269 err = alc268_parse_auto_config(codec);
8270 if (err < 0) {
8271 alc_free(codec);
8272 return err;
8273 } else if (!err) {
8274 printk(KERN_INFO
8275 "hda_codec: Cannot set up configuration "
8276 "from BIOS. Using base mode...\n");
8277 board_config = ALC268_3ST;
8278 }
8279 }
8280
8281 if (board_config != ALC268_AUTO)
8282 setup_preset(spec, &alc268_presets[board_config]);
8283
8284 spec->stream_name_analog = "ALC268 Analog";
8285 spec->stream_analog_playback = &alc268_pcm_analog_playback;
8286 spec->stream_analog_capture = &alc268_pcm_analog_capture;
8287
8288 spec->stream_name_digital = "ALC268 Digital";
8289 spec->stream_digital_playback = &alc268_pcm_digital_playback;
8290
8291 if (board_config == ALC268_AUTO) {
8292 if (!spec->adc_nids && spec->input_mux) {
8293 /* check whether NID 0x07 is valid */
8294 unsigned int wcap = get_wcaps(codec, 0x07);
8295
8296 /* get type */
8297 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
8298 if (wcap != AC_WID_AUD_IN) {
8299 spec->adc_nids = alc268_adc_nids_alt;
8300 spec->num_adc_nids =
8301 ARRAY_SIZE(alc268_adc_nids_alt);
8302 spec->mixers[spec->num_mixers] =
8303 alc268_capture_alt_mixer;
8304 spec->num_mixers++;
8305 } else {
8306 spec->adc_nids = alc268_adc_nids;
8307 spec->num_adc_nids =
8308 ARRAY_SIZE(alc268_adc_nids);
8309 spec->mixers[spec->num_mixers] =
8310 alc268_capture_mixer;
8311 spec->num_mixers++;
8312 }
8313 }
8314 }
8315 codec->patch_ops = alc_patch_ops;
8316 if (board_config == ALC268_AUTO)
8317 spec->init_hook = alc268_auto_init;
8318
8319 return 0;
8320}
8321
8322/*
7807 * ALC861 channel source setting (2/6 channel selection for 3-stack) 8323 * ALC861 channel source setting (2/6 channel selection for 3-stack)
7808 */ 8324 */
7809 8325
@@ -10728,6 +11244,7 @@ static int patch_alc662(struct hda_codec *codec)
10728struct hda_codec_preset snd_hda_preset_realtek[] = { 11244struct hda_codec_preset snd_hda_preset_realtek[] = {
10729 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, 11245 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
10730 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, 11246 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
11247 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
10731 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", 11248 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
10732 .patch = patch_alc861 }, 11249 .patch = patch_alc861 },
10733 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, 11250 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },