From: Takashi Iwai Date: Tue, 30 Jun 2009 13:28:30 +0000 (+0200) Subject: ALSA: hda - Merge patch_alc882() and patch_alc883() X-Git-Tag: firefly_0821_release~11841^2~12^2~121 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=4953550a6ca399b644ef057626617465d8be9a7b;p=firefly-linux-kernel-4.4.55.git ALSA: hda - Merge patch_alc882() and patch_alc883() Merge patch_alc882() and patch_alc883() to the former one since both codecs have fairly similar connections but just a slight difference. Signed-off-by: Takashi Iwai --- diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 939a3dd58148..a1895d7f3cf7 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -114,8 +114,8 @@ ALC662/663/272 samsung-nc10 Samsung NC10 mini notebook auto auto-config reading BIOS (default) -ALC882/885 -========== +ALC882/883/885/888/889 +====================== 3stack-dig 3-jack with SPDIF I/O 6stack-dig 6-jack digital with SPDIF I/O arima Arima W820Di1 @@ -127,12 +127,8 @@ ALC882/885 mbp3 Macbook Pro rev3 imac24 iMac 24'' with jack detection w2jc ASUS W2JC - auto auto-config reading BIOS (default) - -ALC883/888 -========== - 3stack-dig 3-jack with SPDIF I/O - 6stack-dig 6-jack digital with SPDIF I/O + 3stack-2ch-dig 3-jack with SPDIF I/O (ALC883) + alc883-6stack-dig 6-jack digital with SPDIF I/O (ALC883) 3stack-6ch 3-jack 6-channel 3stack-6ch-dig 3-jack 6-channel with SPDIF I/O 6stack-dig-demo 6-jack digital for Intel demo board diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3a8e58c483df..6a899e8fdd0c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -208,12 +208,6 @@ enum { ALC885_MBP3, ALC885_MB5, ALC885_IMAC24, - ALC882_AUTO, - ALC882_MODEL_LAST, -}; - -/* ALC883 models */ -enum { ALC883_3ST_2ch_DIG, ALC883_3ST_6ch_DIG, ALC883_3ST_6ch, @@ -246,8 +240,8 @@ enum { ALC889A_MB31, ALC1200_ASUS_P5Q, ALC883_SONY_VAIO_TT, - ALC883_AUTO, - ALC883_MODEL_LAST, + ALC882_AUTO, + ALC882_MODEL_LAST, }; /* for GPIO Poll */ @@ -320,6 +314,8 @@ struct alc_spec { struct snd_array kctls; struct hda_input_mux private_imux[3]; hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; + hda_nid_t private_adc_nids[AUTO_CFG_MAX_OUTS]; + hda_nid_t private_capsrc_nids[AUTO_CFG_MAX_OUTS]; /* hooks */ void (*init_hook)(struct hda_codec *codec); @@ -6295,7 +6291,7 @@ static int patch_alc260(struct hda_codec *codec) /* - * ALC882 support + * ALC882/883/885/888/889 support * * ALC882 is almost identical with ALC880 but has cleaner and more flexible * configuration. Each pin widget can choose any input DACs and a mixer. @@ -6307,22 +6303,35 @@ static int patch_alc260(struct hda_codec *codec) */ #define ALC882_DIGOUT_NID 0x06 #define ALC882_DIGIN_NID 0x0a +#define ALC883_DIGOUT_NID ALC882_DIGOUT_NID +#define ALC883_DIGIN_NID ALC882_DIGIN_NID +#define ALC1200_DIGOUT_NID 0x10 + static struct hda_channel_mode alc882_ch_modes[1] = { { 8, NULL } }; +/* DACs */ static hda_nid_t alc882_dac_nids[4] = { /* front, rear, clfe, rear_surr */ 0x02, 0x03, 0x04, 0x05 }; +#define alc883_dac_nids alc882_dac_nids -/* identical with ALC880 */ +/* ADCs */ #define alc882_adc_nids alc880_adc_nids #define alc882_adc_nids_alt alc880_adc_nids_alt +#define alc883_adc_nids alc882_adc_nids_alt +static hda_nid_t alc883_adc_nids_alt[1] = { 0x08 }; +static hda_nid_t alc883_adc_nids_rev[2] = { 0x09, 0x08 }; +#define alc889_adc_nids alc880_adc_nids static hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 }; static hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 }; +#define alc883_capsrc_nids alc882_capsrc_nids_alt +static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 }; +#define alc889_capsrc_nids alc882_capsrc_nids /* input MUX */ /* FIXME: should be a matrix-type input source selection */ @@ -6337,6 +6346,8 @@ static struct hda_input_mux alc882_capture_source = { }, }; +#define alc883_capture_source alc882_capture_source + static struct hda_input_mux mb5_capture_source = { .num_items = 3, .items = { @@ -6346,6 +6357,77 @@ static struct hda_input_mux mb5_capture_source = { }, }; +static struct hda_input_mux alc883_3stack_6ch_intel = { + .num_items = 4, + .items = { + { "Mic", 0x1 }, + { "Front Mic", 0x0 }, + { "Line", 0x2 }, + { "CD", 0x4 }, + }, +}; + +static struct hda_input_mux alc883_lenovo_101e_capture_source = { + .num_items = 2, + .items = { + { "Mic", 0x1 }, + { "Line", 0x2 }, + }, +}; + +static struct hda_input_mux alc883_lenovo_nb0763_capture_source = { + .num_items = 4, + .items = { + { "Mic", 0x0 }, + { "iMic", 0x1 }, + { "Line", 0x2 }, + { "CD", 0x4 }, + }, +}; + +static struct hda_input_mux alc883_fujitsu_pi2515_capture_source = { + .num_items = 2, + .items = { + { "Mic", 0x0 }, + { "Int Mic", 0x1 }, + }, +}; + +static struct hda_input_mux alc883_lenovo_sky_capture_source = { + .num_items = 3, + .items = { + { "Mic", 0x0 }, + { "Front Mic", 0x1 }, + { "Line", 0x4 }, + }, +}; + +static struct hda_input_mux alc883_asus_eee1601_capture_source = { + .num_items = 2, + .items = { + { "Mic", 0x0 }, + { "Line", 0x2 }, + }, +}; + +static struct hda_input_mux alc889A_mb31_capture_source = { + .num_items = 2, + .items = { + { "Mic", 0x0 }, + /* Front Mic (0x01) unused */ + { "Line", 0x2 }, + /* Line 2 (0x03) unused */ + /* CD (0x04) unsused? */ + }, +}; + +/* + * 2ch mode + */ +static struct hda_channel_mode alc883_3ST_2ch_modes[1] = { + { 2, NULL } +}; + /* * 2ch mode */ @@ -6357,6 +6439,18 @@ static struct hda_verb alc882_3ST_ch2_init[] = { { } /* end */ }; +/* + * 4ch mode + */ +static struct hda_verb alc882_3ST_ch4_init[] = { + { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, + { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, + { } /* end */ +}; + /* * 6ch mode */ @@ -6370,11 +6464,14 @@ static struct hda_verb alc882_3ST_ch6_init[] = { { } /* end */ }; -static struct hda_channel_mode alc882_3ST_6ch_modes[2] = { +static struct hda_channel_mode alc882_3ST_6ch_modes[3] = { { 2, alc882_3ST_ch2_init }, + { 4, alc882_3ST_ch4_init }, { 6, alc882_3ST_ch6_init }, }; +#define alc883_3ST_6ch_modes alc882_3ST_6ch_modes + /* * 6ch mode */ @@ -6462,6 +6559,143 @@ static struct hda_channel_mode alc885_mb5_6ch_modes[2] = { { 6, alc885_mb5_ch6_init }, }; + +/* + * 2ch mode + */ +static struct hda_verb alc883_4ST_ch2_init[] = { + { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, + { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, + { } /* end */ +}; + +/* + * 4ch mode + */ +static struct hda_verb alc883_4ST_ch4_init[] = { + { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, + { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, + { } /* end */ +}; + +/* + * 6ch mode + */ +static struct hda_verb alc883_4ST_ch6_init[] = { + { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, + { } /* end */ +}; + +/* + * 8ch mode + */ +static struct hda_verb alc883_4ST_ch8_init[] = { + { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 }, + { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, + { } /* end */ +}; + +static struct hda_channel_mode alc883_4ST_8ch_modes[4] = { + { 2, alc883_4ST_ch2_init }, + { 4, alc883_4ST_ch4_init }, + { 6, alc883_4ST_ch6_init }, + { 8, alc883_4ST_ch8_init }, +}; + + +/* + * 2ch mode + */ +static struct hda_verb alc883_3ST_ch2_intel_init[] = { + { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, + { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, + { } /* end */ +}; + +/* + * 4ch mode + */ +static struct hda_verb alc883_3ST_ch4_intel_init[] = { + { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, + { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, + { } /* end */ +}; + +/* + * 6ch mode + */ +static struct hda_verb alc883_3ST_ch6_intel_init[] = { + { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 }, + { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, + { } /* end */ +}; + +static struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = { + { 2, alc883_3ST_ch2_intel_init }, + { 4, alc883_3ST_ch4_intel_init }, + { 6, alc883_3ST_ch6_intel_init }, +}; + +/* + * 6ch mode + */ +static struct hda_verb alc883_sixstack_ch6_init[] = { + { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, + { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { } /* end */ +}; + +/* + * 8ch mode + */ +static struct hda_verb alc883_sixstack_ch8_init[] = { + { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { } /* end */ +}; + +static struct hda_channel_mode alc883_sixstack_modes[2] = { + { 6, alc883_sixstack_ch6_init }, + { 8, alc883_sixstack_ch8_init }, +}; + + /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b */ @@ -6597,7 +6831,7 @@ static struct snd_kcontrol_new alc882_chmode_mixer[] = { { } /* end */ }; -static struct hda_verb alc882_init_verbs[] = { +static struct hda_verb alc882_base_init_verbs[] = { /* Front mixer: unmute input/output amp left and right (volume = 0) */ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, @@ -6649,11 +6883,6 @@ static struct hda_verb alc882_init_verbs[] = { /* FIXME: use matrix-type input source selection */ /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ - /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* Input mixer2 */ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, @@ -6664,9 +6893,6 @@ static struct hda_verb alc882_init_verbs[] = { {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - /* ADC1: mute amp left and right */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, /* ADC2: mute amp left and right */ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, @@ -6677,6 +6903,21 @@ static struct hda_verb alc882_init_verbs[] = { { } }; +static struct hda_verb alc882_adc1_init_verbs[] = { + /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ + {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, + {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, + {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, + /* ADC1: mute amp left and right */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, + { } +}; + +/* HACK - expand to two elements */ +#define alc882_init_verbs alc882_base_init_verbs, alc882_adc1_init_verbs + static struct hda_verb alc882_eapd_verbs[] = { /* change to EAPD mode */ {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, @@ -6684,6 +6925,8 @@ static struct hda_verb alc882_eapd_verbs[] = { { } }; +#define alc883_init_verbs alc882_base_init_verbs + /* Mac Pro test */ static struct snd_kcontrol_new alc882_macpro_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), @@ -7034,882 +7277,62 @@ static void alc885_imac24_init_hook(struct hda_codec *codec) /* * generic initialization of ADC, input mixers and output mixers */ -static struct hda_verb alc882_auto_init_verbs[] = { +static struct hda_verb alc883_auto_init_verbs[] = { /* * Unmute ADC0-2 and set the default input to mic-in */ - {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - - /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback - * mixer widget - * Note: PASD motherboards uses the Line In 2 as the input for - * front panel mic (mic 2) - */ - /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - - /* - * Set up output mixers (0x0c - 0x0f) - */ - /* set vol=0 to output mixers */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* set up input amps for analog loopback */ - /* Amp Indices: DAC = 0, mixer = 1 */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - - /* FIXME: use matrix-type input source selection */ - /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ - /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, - /* Input mixer2 */ - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, - /* Input mixer3 */ - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, - - { } -}; - -#ifdef CONFIG_SND_HDA_POWER_SAVE -#define alc882_loopbacks alc880_loopbacks -#endif - -/* pcm configuration: identical with ALC880 */ -#define alc882_pcm_analog_playback alc880_pcm_analog_playback -#define alc882_pcm_analog_capture alc880_pcm_analog_capture -#define alc882_pcm_digital_playback alc880_pcm_digital_playback -#define alc882_pcm_digital_capture alc880_pcm_digital_capture - -/* - * configuration and preset - */ -static const char *alc882_models[ALC882_MODEL_LAST] = { - [ALC882_3ST_DIG] = "3stack-dig", - [ALC882_6ST_DIG] = "6stack-dig", - [ALC882_ARIMA] = "arima", - [ALC882_W2JC] = "w2jc", - [ALC882_TARGA] = "targa", - [ALC882_ASUS_A7J] = "asus-a7j", - [ALC882_ASUS_A7M] = "asus-a7m", - [ALC885_MACPRO] = "macpro", - [ALC885_MB5] = "mb5", - [ALC885_MBP3] = "mbp3", - [ALC885_IMAC24] = "imac24", - [ALC882_AUTO] = "auto", -}; - -static struct snd_pci_quirk alc882_cfg_tbl[] = { - SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG), - SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J), - SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J), - SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M), - SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC), - SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG), - SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), - SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG), - SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG), - SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ - SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG), - SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), - {} -}; - -static struct alc_config_preset alc882_presets[] = { - [ALC882_3ST_DIG] = { - .mixers = { alc882_base_mixer }, - .init_verbs = { alc882_init_verbs }, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), - .dac_nids = alc882_dac_nids, - .dig_out_nid = ALC882_DIGOUT_NID, - .dig_in_nid = ALC882_DIGIN_NID, - .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), - .channel_mode = alc882_ch_modes, - .need_dac_fix = 1, - .input_mux = &alc882_capture_source, - }, - [ALC882_6ST_DIG] = { - .mixers = { alc882_base_mixer, alc882_chmode_mixer }, - .init_verbs = { alc882_init_verbs }, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), - .dac_nids = alc882_dac_nids, - .dig_out_nid = ALC882_DIGOUT_NID, - .dig_in_nid = ALC882_DIGIN_NID, - .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), - .channel_mode = alc882_sixstack_modes, - .input_mux = &alc882_capture_source, - }, - [ALC882_ARIMA] = { - .mixers = { alc882_base_mixer, alc882_chmode_mixer }, - .init_verbs = { alc882_init_verbs, alc882_eapd_verbs }, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), - .dac_nids = alc882_dac_nids, - .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), - .channel_mode = alc882_sixstack_modes, - .input_mux = &alc882_capture_source, - }, - [ALC882_W2JC] = { - .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer }, - .init_verbs = { alc882_init_verbs, alc882_eapd_verbs, - alc880_gpio1_init_verbs }, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), - .dac_nids = alc882_dac_nids, - .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), - .channel_mode = alc880_threestack_modes, - .need_dac_fix = 1, - .input_mux = &alc882_capture_source, - .dig_out_nid = ALC882_DIGOUT_NID, - }, - [ALC885_MBP3] = { - .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer }, - .init_verbs = { alc885_mbp3_init_verbs, - alc880_gpio1_init_verbs }, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), - .dac_nids = alc882_dac_nids, - .channel_mode = alc885_mbp_6ch_modes, - .num_channel_mode = ARRAY_SIZE(alc885_mbp_6ch_modes), - .input_mux = &alc882_capture_source, - .dig_out_nid = ALC882_DIGOUT_NID, - .dig_in_nid = ALC882_DIGIN_NID, - .unsol_event = alc_automute_amp_unsol_event, - .init_hook = alc885_mbp3_init_hook, - }, - [ALC885_MB5] = { - .mixers = { alc885_mb5_mixer, alc882_chmode_mixer }, - .init_verbs = { alc885_mb5_init_verbs, - alc880_gpio1_init_verbs }, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), - .dac_nids = alc882_dac_nids, - .channel_mode = alc885_mb5_6ch_modes, - .num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes), - .input_mux = &mb5_capture_source, - .dig_out_nid = ALC882_DIGOUT_NID, - .dig_in_nid = ALC882_DIGIN_NID, - }, - [ALC885_MACPRO] = { - .mixers = { alc882_macpro_mixer }, - .init_verbs = { alc882_macpro_init_verbs }, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), - .dac_nids = alc882_dac_nids, - .dig_out_nid = ALC882_DIGOUT_NID, - .dig_in_nid = ALC882_DIGIN_NID, - .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), - .channel_mode = alc882_ch_modes, - .input_mux = &alc882_capture_source, - .init_hook = alc885_macpro_init_hook, - }, - [ALC885_IMAC24] = { - .mixers = { alc885_imac24_mixer }, - .init_verbs = { alc885_imac24_init_verbs }, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), - .dac_nids = alc882_dac_nids, - .dig_out_nid = ALC882_DIGOUT_NID, - .dig_in_nid = ALC882_DIGIN_NID, - .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), - .channel_mode = alc882_ch_modes, - .input_mux = &alc882_capture_source, - .unsol_event = alc_automute_amp_unsol_event, - .init_hook = alc885_imac24_init_hook, - }, - [ALC882_TARGA] = { - .mixers = { alc882_targa_mixer, alc882_chmode_mixer }, - .init_verbs = { alc882_init_verbs, alc882_targa_verbs}, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), - .dac_nids = alc882_dac_nids, - .dig_out_nid = ALC882_DIGOUT_NID, - .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), - .adc_nids = alc882_adc_nids, - .capsrc_nids = alc882_capsrc_nids, - .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes), - .channel_mode = alc882_3ST_6ch_modes, - .need_dac_fix = 1, - .input_mux = &alc882_capture_source, - .unsol_event = alc882_targa_unsol_event, - .init_hook = alc882_targa_init_hook, - }, - [ALC882_ASUS_A7J] = { - .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer }, - .init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs}, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), - .dac_nids = alc882_dac_nids, - .dig_out_nid = ALC882_DIGOUT_NID, - .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), - .adc_nids = alc882_adc_nids, - .capsrc_nids = alc882_capsrc_nids, - .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes), - .channel_mode = alc882_3ST_6ch_modes, - .need_dac_fix = 1, - .input_mux = &alc882_capture_source, - }, - [ALC882_ASUS_A7M] = { - .mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer }, - .init_verbs = { alc882_init_verbs, alc882_eapd_verbs, - alc880_gpio1_init_verbs, - alc882_asus_a7m_verbs }, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), - .dac_nids = alc882_dac_nids, - .dig_out_nid = ALC882_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), - .channel_mode = alc880_threestack_modes, - .need_dac_fix = 1, - .input_mux = &alc882_capture_source, - }, -}; - - -/* - * Pin config fixes - */ -enum { - PINFIX_ABIT_AW9D_MAX -}; - -static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { - { 0x15, 0x01080104 }, /* side */ - { 0x16, 0x01011012 }, /* rear */ - { 0x17, 0x01016011 }, /* clfe */ - { } -}; - -static const struct alc_pincfg *alc882_pin_fixes[] = { - [PINFIX_ABIT_AW9D_MAX] = alc882_abit_aw9d_pinfix, -}; - -static struct snd_pci_quirk alc882_pinfix_tbl[] = { - SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), - {} -}; - -/* - * BIOS auto configuration - */ -static void alc882_auto_set_output_and_unmute(struct hda_codec *codec, - hda_nid_t nid, int pin_type, - int dac_idx) -{ - /* set as output */ - struct alc_spec *spec = codec->spec; - int idx; - - alc_set_pin_output(codec, nid, pin_type); - if (spec->multiout.dac_nids[dac_idx] == 0x25) - idx = 4; - else - idx = spec->multiout.dac_nids[dac_idx] - 2; - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx); - -} - -static void alc882_auto_init_multi_out(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int i; - - for (i = 0; i <= HDA_SIDE; i++) { - hda_nid_t nid = spec->autocfg.line_out_pins[i]; - int pin_type = get_pin_type(spec->autocfg.line_out_type); - if (nid) - alc882_auto_set_output_and_unmute(codec, nid, pin_type, - i); - } -} - -static void alc882_auto_init_hp_out(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - hda_nid_t pin; - - pin = spec->autocfg.hp_pins[0]; - if (pin) /* connect to front */ - /* use dac 0 */ - alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); - pin = spec->autocfg.speaker_pins[0]; - if (pin) - alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); -} - -#define alc882_is_input_pin(nid) alc880_is_input_pin(nid) -#define ALC882_PIN_CD_NID ALC880_PIN_CD_NID - -static void alc882_auto_init_analog_input(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int i; - - for (i = 0; i < AUTO_PIN_LAST; i++) { - hda_nid_t nid = spec->autocfg.input_pins[i]; - if (!nid) - continue; - alc_set_input_pin(codec, nid, AUTO_PIN_FRONT_MIC /*i*/); - if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_MUTE); - } -} - -static void alc882_auto_init_input_src(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int c; - - for (c = 0; c < spec->num_adc_nids; c++) { - hda_nid_t conn_list[HDA_MAX_NUM_INPUTS]; - hda_nid_t nid = spec->capsrc_nids[c]; - unsigned int mux_idx; - const struct hda_input_mux *imux; - int conns, mute, idx, item; - - conns = snd_hda_get_connections(codec, nid, conn_list, - ARRAY_SIZE(conn_list)); - if (conns < 0) - continue; - mux_idx = c >= spec->num_mux_defs ? 0 : c; - imux = &spec->input_mux[mux_idx]; - for (idx = 0; idx < conns; idx++) { - /* if the current connection is the selected one, - * unmute it as default - otherwise mute it - */ - mute = AMP_IN_MUTE(idx); - for (item = 0; item < imux->num_items; item++) { - if (imux->items[item].index == idx) { - if (spec->cur_mux[c] == item) - mute = AMP_IN_UNMUTE(idx); - break; - } - } - /* check if we have a selector or mixer - * we could check for the widget type instead, but - * just check for Amp-In presence (in case of mixer - * without amp-in there is something wrong, this - * function shouldn't be used or capsrc nid is wrong) - */ - if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - mute); - else if (mute != AMP_IN_MUTE(idx)) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CONNECT_SEL, - idx); - } - } -} - -/* add mic boosts if needed */ -static int alc_auto_add_mic_boost(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int err; - hda_nid_t nid; - - nid = spec->autocfg.input_pins[AUTO_PIN_MIC]; - if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) { - err = add_control(spec, ALC_CTL_WIDGET_VOL, - "Mic Boost", - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); - if (err < 0) - return err; - } - nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC]; - if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) { - err = add_control(spec, ALC_CTL_WIDGET_VOL, - "Front Mic Boost", - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); - if (err < 0) - return err; - } - return 0; -} - -/* almost identical with ALC880 parser... */ -static int alc882_parse_auto_config(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int err = alc880_parse_auto_config(codec); - - if (err < 0) - return err; - else if (!err) - return 0; /* no config found */ - - err = alc_auto_add_mic_boost(codec); - if (err < 0) - return err; - - /* hack - override the init verbs */ - spec->init_verbs[0] = alc882_auto_init_verbs; - - return 1; /* config found */ -} - -/* additional initialization for auto-configuration model */ -static void alc882_auto_init(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - alc882_auto_init_multi_out(codec); - alc882_auto_init_hp_out(codec); - alc882_auto_init_analog_input(codec); - alc882_auto_init_input_src(codec); - if (spec->unsol_event) - alc_inithook(codec); -} - -static int patch_alc883(struct hda_codec *codec); /* called in patch_alc882() */ - -static int patch_alc882(struct hda_codec *codec) -{ - struct alc_spec *spec; - int err, board_config; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST, - alc882_models, - alc882_cfg_tbl); - - if (board_config < 0 || board_config >= ALC882_MODEL_LAST) { - /* Pick up systems that don't supply PCI SSID */ - switch (codec->subsystem_id) { - case 0x106b0c00: /* Mac Pro */ - board_config = ALC885_MACPRO; - break; - case 0x106b1000: /* iMac 24 */ - case 0x106b2800: /* AppleTV */ - case 0x106b3e00: /* iMac 24 Aluminium */ - board_config = ALC885_IMAC24; - break; - case 0x106b00a0: /* MacBookPro3,1 - Another revision */ - case 0x106b00a1: /* Macbook (might be wrong - PCI SSID?) */ - case 0x106b00a4: /* MacbookPro4,1 */ - case 0x106b2c00: /* Macbook Pro rev3 */ - /* Macbook 3.1 (0x106b3600) is handled by patch_alc883() */ - case 0x106b3800: /* MacbookPro4,1 - latter revision */ - board_config = ALC885_MBP3; - break; - case 0x106b3f00: /* Macbook 5,1 */ - case 0x106b4000: /* Macbook Pro 5,1 - FIXME: HP jack sense - * seems not working, so apparently - * no perfect solution yet - */ - board_config = ALC885_MB5; - break; - default: - /* ALC889A is handled better as ALC888-compatible */ - if (codec->revision_id == 0x100101 || - codec->revision_id == 0x100103) { - alc_free(codec); - return patch_alc883(codec); - } - printk(KERN_INFO "hda_codec: Unknown model for %s, " - "trying auto-probe from BIOS...\n", - codec->chip_name); - board_config = ALC882_AUTO; - } - } - - alc_fix_pincfg(codec, alc882_pinfix_tbl, alc882_pin_fixes); - - if (board_config == ALC882_AUTO) { - /* automatic parse from the BIOS config */ - err = alc882_parse_auto_config(codec); - if (err < 0) { - alc_free(codec); - return err; - } else if (!err) { - printk(KERN_INFO - "hda_codec: Cannot set up configuration " - "from BIOS. Using base mode...\n"); - board_config = ALC882_3ST_DIG; - } - } - - err = snd_hda_attach_beep_device(codec, 0x1); - if (err < 0) { - alc_free(codec); - return err; - } - - if (board_config != ALC882_AUTO) - setup_preset(spec, &alc882_presets[board_config]); - - spec->stream_analog_playback = &alc882_pcm_analog_playback; - spec->stream_analog_capture = &alc882_pcm_analog_capture; - /* FIXME: setup DAC5 */ - /*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/ - spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture; - - spec->stream_digital_playback = &alc882_pcm_digital_playback; - spec->stream_digital_capture = &alc882_pcm_digital_capture; - - if (!spec->adc_nids && spec->input_mux) { - /* check whether NID 0x07 is valid */ - unsigned int wcap = get_wcaps(codec, 0x07); - /* get type */ - wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; - if (wcap != AC_WID_AUD_IN) { - spec->adc_nids = alc882_adc_nids_alt; - spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt); - spec->capsrc_nids = alc882_capsrc_nids_alt; - } else { - spec->adc_nids = alc882_adc_nids; - spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids); - spec->capsrc_nids = alc882_capsrc_nids; - } - } - set_capture_mixer(spec); - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); - - spec->vmaster_nid = 0x0c; - - codec->patch_ops = alc_patch_ops; - if (board_config == ALC882_AUTO) - spec->init_hook = alc882_auto_init; -#ifdef CONFIG_SND_HDA_POWER_SAVE - if (!spec->loopback.amplist) - spec->loopback.amplist = alc882_loopbacks; -#endif - codec->proc_widget_hook = print_realtek_coef; - - return 0; -} - -/* - * ALC883 support - * - * ALC883 is almost identical with ALC880 but has cleaner and more flexible - * configuration. Each pin widget can choose any input DACs and a mixer. - * Each ADC is connected from a mixer of all inputs. This makes possible - * 6-channel independent captures. - * - * In addition, an independent DAC for the multi-playback (not used in this - * driver yet). - */ -#define ALC883_DIGOUT_NID 0x06 -#define ALC883_DIGIN_NID 0x0a - -#define ALC1200_DIGOUT_NID 0x10 - -static hda_nid_t alc883_dac_nids[4] = { - /* front, rear, clfe, rear_surr */ - 0x02, 0x03, 0x04, 0x05 -}; - -static hda_nid_t alc883_adc_nids[2] = { - /* ADC1-2 */ - 0x08, 0x09, -}; - -static hda_nid_t alc883_adc_nids_alt[1] = { - /* ADC1 */ - 0x08, -}; - -static hda_nid_t alc883_adc_nids_rev[2] = { - /* ADC2-1 */ - 0x09, 0x08 -}; - -#define alc889_adc_nids alc880_adc_nids - -static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 }; - -static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 }; - -#define alc889_capsrc_nids alc882_capsrc_nids - -/* input MUX */ -/* FIXME: should be a matrix-type input source selection */ - -static struct hda_input_mux alc883_capture_source = { - .num_items = 4, - .items = { - { "Mic", 0x0 }, - { "Front Mic", 0x1 }, - { "Line", 0x2 }, - { "CD", 0x4 }, - }, -}; - -static struct hda_input_mux alc883_3stack_6ch_intel = { - .num_items = 4, - .items = { - { "Mic", 0x1 }, - { "Front Mic", 0x0 }, - { "Line", 0x2 }, - { "CD", 0x4 }, - }, -}; - -static struct hda_input_mux alc883_lenovo_101e_capture_source = { - .num_items = 2, - .items = { - { "Mic", 0x1 }, - { "Line", 0x2 }, - }, -}; - -static struct hda_input_mux alc883_lenovo_nb0763_capture_source = { - .num_items = 4, - .items = { - { "Mic", 0x0 }, - { "iMic", 0x1 }, - { "Line", 0x2 }, - { "CD", 0x4 }, - }, -}; - -static struct hda_input_mux alc883_fujitsu_pi2515_capture_source = { - .num_items = 2, - .items = { - { "Mic", 0x0 }, - { "Int Mic", 0x1 }, - }, -}; - -static struct hda_input_mux alc883_lenovo_sky_capture_source = { - .num_items = 3, - .items = { - { "Mic", 0x0 }, - { "Front Mic", 0x1 }, - { "Line", 0x4 }, - }, -}; - -static struct hda_input_mux alc883_asus_eee1601_capture_source = { - .num_items = 2, - .items = { - { "Mic", 0x0 }, - { "Line", 0x2 }, - }, -}; - -static struct hda_input_mux alc889A_mb31_capture_source = { - .num_items = 2, - .items = { - { "Mic", 0x0 }, - /* Front Mic (0x01) unused */ - { "Line", 0x2 }, - /* Line 2 (0x03) unused */ - /* CD (0x04) unsused? */ - }, -}; - -/* - * 2ch mode - */ -static struct hda_channel_mode alc883_3ST_2ch_modes[1] = { - { 2, NULL } -}; - -/* - * 2ch mode - */ -static struct hda_verb alc883_3ST_ch2_init[] = { - { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { } /* end */ -}; - -/* - * 4ch mode - */ -static struct hda_verb alc883_3ST_ch4_init[] = { - { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, - { } /* end */ -}; - -/* - * 6ch mode - */ -static struct hda_verb alc883_3ST_ch6_init[] = { - { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, - { } /* end */ -}; - -static struct hda_channel_mode alc883_3ST_6ch_modes[3] = { - { 2, alc883_3ST_ch2_init }, - { 4, alc883_3ST_ch4_init }, - { 6, alc883_3ST_ch6_init }, -}; - - -/* - * 2ch mode - */ -static struct hda_verb alc883_4ST_ch2_init[] = { - { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { } /* end */ -}; - -/* - * 4ch mode - */ -static struct hda_verb alc883_4ST_ch4_init[] = { - { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, - { } /* end */ -}; - -/* - * 6ch mode - */ -static struct hda_verb alc883_4ST_ch6_init[] = { - { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, - { } /* end */ -}; - -/* - * 8ch mode - */ -static struct hda_verb alc883_4ST_ch8_init[] = { - { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 }, - { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, - { } /* end */ -}; - -static struct hda_channel_mode alc883_4ST_8ch_modes[4] = { - { 2, alc883_4ST_ch2_init }, - { 4, alc883_4ST_ch4_init }, - { 6, alc883_4ST_ch6_init }, - { 8, alc883_4ST_ch8_init }, -}; - - -/* - * 2ch mode - */ -static struct hda_verb alc883_3ST_ch2_intel_init[] = { - { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { } /* end */ -}; - -/* - * 4ch mode - */ -static struct hda_verb alc883_3ST_ch4_intel_init[] = { - { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, - { } /* end */ -}; - -/* - * 6ch mode - */ -static struct hda_verb alc883_3ST_ch6_intel_init[] = { - { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 }, - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, - { } /* end */ -}; + {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, -static struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = { - { 2, alc883_3ST_ch2_intel_init }, - { 4, alc883_3ST_ch4_intel_init }, - { 6, alc883_3ST_ch6_intel_init }, -}; + /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback + * mixer widget + * Note: PASD motherboards uses the Line In 2 as the input for + * front panel mic (mic 2) + */ + /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, -/* - * 6ch mode - */ -static struct hda_verb alc883_sixstack_ch6_init[] = { - { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, - { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { } /* end */ -}; + /* + * Set up output mixers (0x0c - 0x0f) + */ + /* set vol=0 to output mixers */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, + /* set up input amps for analog loopback */ + /* Amp Indices: DAC = 0, mixer = 1 */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, -/* - * 8ch mode - */ -static struct hda_verb alc883_sixstack_ch8_init[] = { - { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { } /* end */ -}; + /* FIXME: use matrix-type input source selection */ + /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ + /* Input mixer2 */ + {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, + {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, + {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, + /* Input mixer3 */ + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, -static struct hda_channel_mode alc883_sixstack_modes[2] = { - { 6, alc883_sixstack_ch6_init }, - { 8, alc883_sixstack_ch8_init }, + { } }; /* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */ @@ -7962,34 +7385,7 @@ static struct hda_verb alc883_medion_eapd_verbs[] = { { } }; -/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 - * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b - */ - -static struct snd_kcontrol_new alc883_base_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - { } /* end */ -}; +#define alc883_base_mixer alc882_base_mixer static struct snd_kcontrol_new alc883_mitac_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), @@ -8309,113 +7705,35 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = { HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - { } /* end */ -}; - -static struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = { - HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol), - HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* .name = "Capture Source", */ - .name = "Input Source", - .count = 1, - .info = alc_mux_enum_info, - .get = alc_mux_enum_get, - .put = alc_mux_enum_put, - }, - { } /* end */ -}; - -static struct snd_kcontrol_new alc883_chmode_mixer[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = alc_ch_mode_info, - .get = alc_ch_mode_get, - .put = alc_ch_mode_put, - }, - { } /* end */ -}; - -static struct hda_verb alc883_init_verbs[] = { - /* ADC1: mute amp left and right */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* ADC2: mute amp left and right */ - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* Front mixer: unmute input/output amp left and right (volume = 0) */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Rear mixer */ - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* CLFE mixer */ - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Side mixer */ - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - - /* mute analog input loopbacks */ - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, + HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + { } /* end */ +}; - /* Front Pin: output 0 (0x0c) */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* Rear Pin: output 1 (0x0d) */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, - /* CLFE Pin: output 2 (0x0e) */ - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, - /* Side Pin: output 3 (0x0f) */ - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, - /* Mic (rear) pin: input vref at 80% */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Front Mic pin: input vref at 80% */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Line In pin: input */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Line-2 In: Headphone output (output 0 - 0x0c) */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* CD pin widget for input */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, +static struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = { + HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol), + HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 1, + .info = alc_mux_enum_info, + .get = alc_mux_enum_get, + .put = alc_mux_enum_put, + }, + { } /* end */ +}; - /* FIXME: use matrix-type input source selection */ - /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ - /* Input mixer2 */ - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - /* Input mixer3 */ - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - { } +static struct snd_kcontrol_new alc883_chmode_mixer[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Channel Mode", + .info = alc_ch_mode_info, + .get = alc_ch_mode_get, + .put = alc_ch_mode_put, + }, + { } /* end */ }; /* toggle speaker-output according to the hp-jack state */ @@ -8850,69 +8168,6 @@ static void alc883_vaiott_init_hook(struct hda_codec *codec) alc_automute_amp(codec); } -/* - * generic initialization of ADC, input mixers and output mixers - */ -static struct hda_verb alc883_auto_init_verbs[] = { - /* - * Unmute ADC0-2 and set the default input to mic-in - */ - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - - /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback - * mixer widget - * Note: PASD motherboards uses the Line In 2 as the input for - * front panel mic (mic 2) - */ - /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - - /* - * Set up output mixers (0x0c - 0x0f) - */ - /* set vol=0 to output mixers */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* set up input amps for analog loopback */ - /* Amp Indices: DAC = 0, mixer = 1 */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - - /* FIXME: use matrix-type input source selection */ - /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ - /* Input mixer1 */ - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */ - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, - /* Input mixer2 */ - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */ - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, - - { } -}; - static struct hda_verb alc888_asus_m90v_verbs[] = { {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, @@ -9023,25 +8278,44 @@ static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res) alc889A_mb31_automute(codec); } + #ifdef CONFIG_SND_HDA_POWER_SAVE -#define alc883_loopbacks alc880_loopbacks +#define alc882_loopbacks alc880_loopbacks #endif /* pcm configuration: identical with ALC880 */ -#define alc883_pcm_analog_playback alc880_pcm_analog_playback -#define alc883_pcm_analog_capture alc880_pcm_analog_capture -#define alc883_pcm_analog_alt_capture alc880_pcm_analog_alt_capture -#define alc883_pcm_digital_playback alc880_pcm_digital_playback -#define alc883_pcm_digital_capture alc880_pcm_digital_capture +#define alc882_pcm_analog_playback alc880_pcm_analog_playback +#define alc882_pcm_analog_capture alc880_pcm_analog_capture +#define alc882_pcm_digital_playback alc880_pcm_digital_playback +#define alc882_pcm_digital_capture alc880_pcm_digital_capture + +static hda_nid_t alc883_slave_dig_outs[] = { + ALC1200_DIGOUT_NID, 0, +}; + +static hda_nid_t alc1200_slave_dig_outs[] = { + ALC883_DIGOUT_NID, 0, +}; /* * configuration and preset */ -static const char *alc883_models[ALC883_MODEL_LAST] = { - [ALC883_3ST_2ch_DIG] = "3stack-dig", +static const char *alc882_models[ALC882_MODEL_LAST] = { + [ALC882_3ST_DIG] = "3stack-dig", + [ALC882_6ST_DIG] = "6stack-dig", + [ALC882_ARIMA] = "arima", + [ALC882_W2JC] = "w2jc", + [ALC882_TARGA] = "targa", + [ALC882_ASUS_A7J] = "asus-a7j", + [ALC882_ASUS_A7M] = "asus-a7m", + [ALC885_MACPRO] = "macpro", + [ALC885_MB5] = "mb5", + [ALC885_MBP3] = "mbp3", + [ALC885_IMAC24] = "imac24", + [ALC883_3ST_2ch_DIG] = "3stack-2ch-dig", [ALC883_3ST_6ch_DIG] = "3stack-6ch-dig", [ALC883_3ST_6ch] = "3stack-6ch", - [ALC883_6ST_DIG] = "6stack-dig", + [ALC883_6ST_DIG] = "alc883-6stack-dig", [ALC883_TARGA_DIG] = "targa-dig", [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig", [ALC883_TARGA_8ch_DIG] = "targa-8ch-dig", @@ -9068,11 +8342,12 @@ static const char *alc883_models[ALC883_MODEL_LAST] = { [ALC1200_ASUS_P5Q] = "asus-p5q", [ALC889A_MB31] = "mb31", [ALC883_SONY_VAIO_TT] = "sony-vaio-tt", - [ALC883_AUTO] = "auto", + [ALC882_AUTO] = "auto", }; -static struct snd_pci_quirk alc883_cfg_tbl[] = { - SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG), +static struct snd_pci_quirk alc882_cfg_tbl[] = { + SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG), + SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE), SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE), SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_ACER_ASPIRE), @@ -9087,8 +8362,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { ALC888_ACER_ASPIRE_8930G), SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G", ALC888_ACER_ASPIRE_8930G), - SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC883_AUTO), - SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC883_AUTO), + SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC882_AUTO), + SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC882_AUTO), SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G", ALC888_ACER_ASPIRE_6530G), SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G", @@ -9097,30 +8372,44 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { * model=auto should work fine now */ /* SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER), */ + SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL), + SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG), SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG), SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP), SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", ALC888_3ST_HP), + + SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J), + SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J), + SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M), SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V), + SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC), + SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG), + SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG), SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q), SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601), + + SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC883_SONY_VAIO_TT), SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG), - SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG), + SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG), SND_PCI_QUIRK(0x1071, 0x8227, "Mitac 82801H", ALC883_MITAC), SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC), SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD), SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL), SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch), - SND_PCI_QUIRK(0x1458, 0xa002, "MSI", ALC883_6ST_DIG), + SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG), + SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG), SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG), SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG), + SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC883_TARGA_2ch_DIG), + SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG), SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG), SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG), SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG), @@ -9142,11 +8431,13 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG), + SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720), SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720), SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD), SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), + /* SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), */ SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1100, "FSC AMILO Xi/Pi25xx", ALC883_FUJITSU_PI2515), @@ -9161,24 +8452,175 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK(0x17c0, 0x4085, "MEDION MD96630", ALC888_LENOVO_MS7195_DIG), SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66), + SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL), SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL), SND_PCI_QUIRK(0x8086, 0x2503, "82801H", ALC883_MITAC), SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC883_3ST_6ch_INTEL), SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch), - SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC883_SONY_VAIO_TT), - {} -}; -static hda_nid_t alc883_slave_dig_outs[] = { - ALC1200_DIGOUT_NID, 0, + {} }; -static hda_nid_t alc1200_slave_dig_outs[] = { - ALC883_DIGOUT_NID, 0, +/* codec SSID table for Intel Mac */ +static struct snd_pci_quirk alc882_ssid_cfg_tbl[] = { + SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3), + SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3), + SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3), + SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_MACPRO), + SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_IMAC24), + SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24), + SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3), + SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31), + SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3), + SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24), + SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5), + /* FIXME: HP jack sense seems not working for MBP 5,1, so apparently + * no perfect solution yet + */ + SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5), + {} /* terminator */ }; -static struct alc_config_preset alc883_presets[] = { +static struct alc_config_preset alc882_presets[] = { + [ALC882_3ST_DIG] = { + .mixers = { alc882_base_mixer }, + .init_verbs = { alc882_init_verbs }, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .dac_nids = alc882_dac_nids, + .dig_out_nid = ALC882_DIGOUT_NID, + .dig_in_nid = ALC882_DIGIN_NID, + .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), + .channel_mode = alc882_ch_modes, + .need_dac_fix = 1, + .input_mux = &alc882_capture_source, + }, + [ALC882_6ST_DIG] = { + .mixers = { alc882_base_mixer, alc882_chmode_mixer }, + .init_verbs = { alc882_init_verbs }, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .dac_nids = alc882_dac_nids, + .dig_out_nid = ALC882_DIGOUT_NID, + .dig_in_nid = ALC882_DIGIN_NID, + .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), + .channel_mode = alc882_sixstack_modes, + .input_mux = &alc882_capture_source, + }, + [ALC882_ARIMA] = { + .mixers = { alc882_base_mixer, alc882_chmode_mixer }, + .init_verbs = { alc882_init_verbs, alc882_eapd_verbs }, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .dac_nids = alc882_dac_nids, + .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), + .channel_mode = alc882_sixstack_modes, + .input_mux = &alc882_capture_source, + }, + [ALC882_W2JC] = { + .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer }, + .init_verbs = { alc882_init_verbs, alc882_eapd_verbs, + alc880_gpio1_init_verbs }, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .dac_nids = alc882_dac_nids, + .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), + .channel_mode = alc880_threestack_modes, + .need_dac_fix = 1, + .input_mux = &alc882_capture_source, + .dig_out_nid = ALC882_DIGOUT_NID, + }, + [ALC885_MBP3] = { + .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer }, + .init_verbs = { alc885_mbp3_init_verbs, + alc880_gpio1_init_verbs }, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .dac_nids = alc882_dac_nids, + .channel_mode = alc885_mbp_6ch_modes, + .num_channel_mode = ARRAY_SIZE(alc885_mbp_6ch_modes), + .input_mux = &alc882_capture_source, + .dig_out_nid = ALC882_DIGOUT_NID, + .dig_in_nid = ALC882_DIGIN_NID, + .unsol_event = alc_automute_amp_unsol_event, + .init_hook = alc885_mbp3_init_hook, + }, + [ALC885_MB5] = { + .mixers = { alc885_mb5_mixer, alc882_chmode_mixer }, + .init_verbs = { alc885_mb5_init_verbs, + alc880_gpio1_init_verbs }, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .dac_nids = alc882_dac_nids, + .channel_mode = alc885_mb5_6ch_modes, + .num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes), + .input_mux = &mb5_capture_source, + .dig_out_nid = ALC882_DIGOUT_NID, + .dig_in_nid = ALC882_DIGIN_NID, + }, + [ALC885_MACPRO] = { + .mixers = { alc882_macpro_mixer }, + .init_verbs = { alc882_macpro_init_verbs }, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .dac_nids = alc882_dac_nids, + .dig_out_nid = ALC882_DIGOUT_NID, + .dig_in_nid = ALC882_DIGIN_NID, + .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), + .channel_mode = alc882_ch_modes, + .input_mux = &alc882_capture_source, + .init_hook = alc885_macpro_init_hook, + }, + [ALC885_IMAC24] = { + .mixers = { alc885_imac24_mixer }, + .init_verbs = { alc885_imac24_init_verbs }, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .dac_nids = alc882_dac_nids, + .dig_out_nid = ALC882_DIGOUT_NID, + .dig_in_nid = ALC882_DIGIN_NID, + .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), + .channel_mode = alc882_ch_modes, + .input_mux = &alc882_capture_source, + .unsol_event = alc_automute_amp_unsol_event, + .init_hook = alc885_imac24_init_hook, + }, + [ALC882_TARGA] = { + .mixers = { alc882_targa_mixer, alc882_chmode_mixer }, + .init_verbs = { alc882_init_verbs, alc882_targa_verbs}, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .dac_nids = alc882_dac_nids, + .dig_out_nid = ALC882_DIGOUT_NID, + .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), + .adc_nids = alc882_adc_nids, + .capsrc_nids = alc882_capsrc_nids, + .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes), + .channel_mode = alc882_3ST_6ch_modes, + .need_dac_fix = 1, + .input_mux = &alc882_capture_source, + .unsol_event = alc882_targa_unsol_event, + .init_hook = alc882_targa_init_hook, + }, + [ALC882_ASUS_A7J] = { + .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer }, + .init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs}, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .dac_nids = alc882_dac_nids, + .dig_out_nid = ALC882_DIGOUT_NID, + .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), + .adc_nids = alc882_adc_nids, + .capsrc_nids = alc882_capsrc_nids, + .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes), + .channel_mode = alc882_3ST_6ch_modes, + .need_dac_fix = 1, + .input_mux = &alc882_capture_source, + }, + [ALC882_ASUS_A7M] = { + .mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer }, + .init_verbs = { alc882_init_verbs, alc882_eapd_verbs, + alc880_gpio1_init_verbs, + alc882_asus_a7m_verbs }, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .dac_nids = alc882_dac_nids, + .dig_out_nid = ALC882_DIGOUT_NID, + .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), + .channel_mode = alc880_threestack_modes, + .need_dac_fix = 1, + .input_mux = &alc882_capture_source, + }, [ALC883_3ST_2ch_DIG] = { .mixers = { alc883_3ST_2ch_mixer }, .init_verbs = { alc883_init_verbs }, @@ -9612,10 +9054,33 @@ static struct alc_config_preset alc883_presets[] = { }; +/* + * Pin config fixes + */ +enum { + PINFIX_ABIT_AW9D_MAX +}; + +static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { + { 0x15, 0x01080104 }, /* side */ + { 0x16, 0x01011012 }, /* rear */ + { 0x17, 0x01016011 }, /* clfe */ + { } +}; + +static const struct alc_pincfg *alc882_pin_fixes[] = { + [PINFIX_ABIT_AW9D_MAX] = alc882_abit_aw9d_pinfix, +}; + +static struct snd_pci_quirk alc882_pinfix_tbl[] = { + SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), + {} +}; + /* * BIOS auto configuration */ -static void alc883_auto_set_output_and_unmute(struct hda_codec *codec, +static void alc882_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type, int dac_idx) { @@ -9632,7 +9097,7 @@ static void alc883_auto_set_output_and_unmute(struct hda_codec *codec, } -static void alc883_auto_init_multi_out(struct hda_codec *codec) +static void alc882_auto_init_multi_out(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; int i; @@ -9641,12 +9106,12 @@ static void alc883_auto_init_multi_out(struct hda_codec *codec) hda_nid_t nid = spec->autocfg.line_out_pins[i]; int pin_type = get_pin_type(spec->autocfg.line_out_type); if (nid) - alc883_auto_set_output_and_unmute(codec, nid, pin_type, + alc882_auto_set_output_and_unmute(codec, nid, pin_type, i); } } -static void alc883_auto_init_hp_out(struct hda_codec *codec) +static void alc882_auto_init_hp_out(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; hda_nid_t pin; @@ -9654,42 +9119,114 @@ static void alc883_auto_init_hp_out(struct hda_codec *codec) pin = spec->autocfg.hp_pins[0]; if (pin) /* connect to front */ /* use dac 0 */ - alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); + alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); pin = spec->autocfg.speaker_pins[0]; if (pin) - alc883_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); + alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); } -#define alc883_is_input_pin(nid) alc880_is_input_pin(nid) -#define ALC883_PIN_CD_NID ALC880_PIN_CD_NID +#define alc882_is_input_pin(nid) alc880_is_input_pin(nid) +#define ALC882_PIN_CD_NID ALC880_PIN_CD_NID -static void alc883_auto_init_analog_input(struct hda_codec *codec) +static void alc882_auto_init_analog_input(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; int i; for (i = 0; i < AUTO_PIN_LAST; i++) { hda_nid_t nid = spec->autocfg.input_pins[i]; - if (alc883_is_input_pin(nid)) { - alc_set_input_pin(codec, nid, i); - if (nid != ALC883_PIN_CD_NID && - (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) + if (!nid) + continue; + alc_set_input_pin(codec, nid, AUTO_PIN_FRONT_MIC /*i*/); + if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, + AMP_OUT_MUTE); + } +} + +static void alc882_auto_init_input_src(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + int c; + + for (c = 0; c < spec->num_adc_nids; c++) { + hda_nid_t conn_list[HDA_MAX_NUM_INPUTS]; + hda_nid_t nid = spec->capsrc_nids[c]; + unsigned int mux_idx; + const struct hda_input_mux *imux; + int conns, mute, idx, item; + + conns = snd_hda_get_connections(codec, nid, conn_list, + ARRAY_SIZE(conn_list)); + if (conns < 0) + continue; + mux_idx = c >= spec->num_mux_defs ? 0 : c; + imux = &spec->input_mux[mux_idx]; + for (idx = 0; idx < conns; idx++) { + /* if the current connection is the selected one, + * unmute it as default - otherwise mute it + */ + mute = AMP_IN_MUTE(idx); + for (item = 0; item < imux->num_items; item++) { + if (imux->items[item].index == idx) { + if (spec->cur_mux[c] == item) + mute = AMP_IN_UNMUTE(idx); + break; + } + } + /* check if we have a selector or mixer + * we could check for the widget type instead, but + * just check for Amp-In presence (in case of mixer + * without amp-in there is something wrong, this + * function shouldn't be used or capsrc nid is wrong) + */ + if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_MUTE); + mute); + else if (mute != AMP_IN_MUTE(idx)) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_CONNECT_SEL, + idx); } } } -#define alc883_auto_init_input_src alc882_auto_init_input_src +/* add mic boosts if needed */ +static int alc_auto_add_mic_boost(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + int err; + hda_nid_t nid; + + nid = spec->autocfg.input_pins[AUTO_PIN_MIC]; + if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) { + err = add_control(spec, ALC_CTL_WIDGET_VOL, + "Mic Boost", + HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); + if (err < 0) + return err; + } + nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC]; + if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) { + err = add_control(spec, ALC_CTL_WIDGET_VOL, + "Front Mic Boost", + HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); + if (err < 0) + return err; + } + return 0; +} /* almost identical with ALC880 parser... */ -static int alc883_parse_auto_config(struct hda_codec *codec) +static int alc882_parse_auto_config(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - int err = alc880_parse_auto_config(codec); - struct auto_pin_cfg *cfg = &spec->autocfg; + struct auto_pin_cfg *autocfg = &spec->autocfg; + unsigned int wcap; int i; + int err = alc880_parse_auto_config(codec); if (err < 0) return err; @@ -9702,43 +9239,45 @@ static int alc883_parse_auto_config(struct hda_codec *codec) /* hack - override the init verbs */ spec->init_verbs[0] = alc883_auto_init_verbs; + /* if ADC 0x07 is available, initialize it, too */ + wcap = get_wcaps(codec, 0x07); + wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; + if (wcap == AC_WID_AUD_IN) + add_verb(spec, alc882_adc1_init_verbs); - /* setup input_mux for ALC889 */ - if (codec->vendor_id == 0x10ec0889) { - /* digital-mic input pin is excluded in alc880_auto_create..() - * because it's under 0x18 - */ - if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 || - cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) { - struct hda_input_mux *imux = &spec->private_imux[0]; - for (i = 1; i < 3; i++) - memcpy(&spec->private_imux[i], - &spec->private_imux[0], - sizeof(spec->private_imux[0])); - imux->items[imux->num_items].label = "Int DMic"; - imux->items[imux->num_items].index = 0x0b; - imux->num_items++; - spec->num_mux_defs = 3; - spec->input_mux = spec->private_imux; - } + /* digital-mic input pin is excluded in alc880_auto_create..() + * because it's under 0x18 + */ + if (autocfg->input_pins[AUTO_PIN_MIC] == 0x12 || + autocfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) { + struct hda_input_mux *imux = &spec->private_imux[0]; + for (i = 1; i < 3; i++) + memcpy(&spec->private_imux[i], + &spec->private_imux[0], + sizeof(spec->private_imux[0])); + imux->items[imux->num_items].label = "Int DMic"; + imux->items[imux->num_items].index = 0x0b; + imux->num_items++; + spec->num_mux_defs = 3; + spec->input_mux = spec->private_imux; } return 1; /* config found */ } /* additional initialization for auto-configuration model */ -static void alc883_auto_init(struct hda_codec *codec) +static void alc882_auto_init(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - alc883_auto_init_multi_out(codec); - alc883_auto_init_hp_out(codec); - alc883_auto_init_analog_input(codec); - alc883_auto_init_input_src(codec); + alc882_auto_init_multi_out(codec); + alc882_auto_init_hp_out(codec); + alc882_auto_init_analog_input(codec); + alc882_auto_init_input_src(codec); if (spec->unsol_event) alc_inithook(codec); } -static int patch_alc883(struct hda_codec *codec) +static int patch_alc882(struct hda_codec *codec) { struct alc_spec *spec; int err, board_config; @@ -9749,28 +9288,36 @@ static int patch_alc883(struct hda_codec *codec) codec->spec = spec; - alc_fix_pll_init(codec, 0x20, 0x0a, 10); + switch (codec->vendor_id) { + case 0x10ec0882: + case 0x10ec0885: + break; + default: + /* ALC883 and variants */ + alc_fix_pll_init(codec, 0x20, 0x0a, 10); + break; + } - board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST, - alc883_models, - alc883_cfg_tbl); - if (board_config < 0 || board_config >= ALC883_MODEL_LAST) { - /* Pick up systems that don't supply PCI SSID */ - switch (codec->subsystem_id) { - case 0x106b3600: /* Macbook 3.1 */ - board_config = ALC889A_MB31; - break; - default: - printk(KERN_INFO - "hda_codec: Unknown model for %s, trying " - "auto-probe from BIOS...\n", codec->chip_name); - board_config = ALC883_AUTO; - } + board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST, + alc882_models, + alc882_cfg_tbl); + + if (board_config < 0 || board_config >= ALC882_MODEL_LAST) + board_config = snd_hda_check_board_codec_sid_config(codec, + ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl); + + if (board_config < 0 || board_config >= ALC882_MODEL_LAST) { + printk(KERN_INFO "hda_codec: Unknown model for %s, " + "trying auto-probe from BIOS...\n", + codec->chip_name); + board_config = ALC882_AUTO; } - if (board_config == ALC883_AUTO) { + alc_fix_pincfg(codec, alc882_pinfix_tbl, alc882_pin_fixes); + + if (board_config == ALC882_AUTO) { /* automatic parse from the BIOS config */ - err = alc883_parse_auto_config(codec); + err = alc882_parse_auto_config(codec); if (err < 0) { alc_free(codec); return err; @@ -9778,7 +9325,7 @@ static int patch_alc883(struct hda_codec *codec) printk(KERN_INFO "hda_codec: Cannot set up configuration " "from BIOS. Using base mode...\n"); - board_config = ALC883_3ST_2ch_DIG; + board_config = ALC882_3ST_DIG; } } @@ -9788,63 +9335,61 @@ static int patch_alc883(struct hda_codec *codec) return err; } - if (board_config != ALC883_AUTO) - setup_preset(spec, &alc883_presets[board_config]); + if (board_config != ALC882_AUTO) + setup_preset(spec, &alc882_presets[board_config]); - switch (codec->vendor_id) { - case 0x10ec0888: - if (!spec->num_adc_nids) { - spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); - spec->adc_nids = alc883_adc_nids; - } - if (!spec->capsrc_nids) - spec->capsrc_nids = alc883_capsrc_nids; + spec->stream_analog_playback = &alc882_pcm_analog_playback; + spec->stream_analog_capture = &alc882_pcm_analog_capture; + /* FIXME: setup DAC5 */ + /*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/ + spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture; + + spec->stream_digital_playback = &alc882_pcm_digital_playback; + spec->stream_digital_capture = &alc882_pcm_digital_capture; + + if (codec->vendor_id == 0x10ec0888) spec->init_amp = ALC_INIT_DEFAULT; /* always initialize */ - break; - case 0x10ec0889: - if (!spec->num_adc_nids) { - spec->num_adc_nids = ARRAY_SIZE(alc889_adc_nids); - spec->adc_nids = alc889_adc_nids; - } - if (!spec->capsrc_nids) - spec->capsrc_nids = alc889_capsrc_nids; - break; - default: - if (!spec->num_adc_nids) { - spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); - spec->adc_nids = alc883_adc_nids; + + if (!spec->adc_nids && spec->input_mux) { + int i; + spec->num_adc_nids = 0; + for (i = 0; i < ARRAY_SIZE(alc882_adc_nids); i++) { + hda_nid_t cap; + hda_nid_t nid = alc882_adc_nids[i]; + unsigned int wcap = get_wcaps(codec, nid); + /* get type */ + wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; + if (wcap != AC_WID_AUD_IN) + continue; + spec->private_adc_nids[spec->num_adc_nids] = nid; + err = snd_hda_get_connections(codec, nid, &cap, 1); + if (err < 0) + continue; + spec->private_capsrc_nids[spec->num_adc_nids] = cap; + spec->num_adc_nids++; } - if (!spec->capsrc_nids) - spec->capsrc_nids = alc883_capsrc_nids; - break; + spec->adc_nids = spec->private_adc_nids; + spec->capsrc_nids = spec->private_capsrc_nids; } - spec->stream_analog_playback = &alc883_pcm_analog_playback; - spec->stream_analog_capture = &alc883_pcm_analog_capture; - spec->stream_analog_alt_capture = &alc883_pcm_analog_alt_capture; - - spec->stream_digital_playback = &alc883_pcm_digital_playback; - spec->stream_digital_capture = &alc883_pcm_digital_capture; - - if (!spec->cap_mixer) - set_capture_mixer(spec); + set_capture_mixer(spec); set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); spec->vmaster_nid = 0x0c; codec->patch_ops = alc_patch_ops; - if (board_config == ALC883_AUTO) - spec->init_hook = alc883_auto_init; - + if (board_config == ALC882_AUTO) + spec->init_hook = alc882_auto_init; #ifdef CONFIG_SND_HDA_POWER_SAVE if (!spec->loopback.amplist) - spec->loopback.amplist = alc883_loopbacks; + spec->loopback.amplist = alc882_loopbacks; #endif codec->proc_widget_hook = print_realtek_coef; return 0; } + /* * ALC262 support */ @@ -17546,23 +17091,23 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 }, { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd }, { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2", - .patch = patch_alc883 }, + .patch = patch_alc882 }, { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1", .patch = patch_alc662 }, { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, - { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 }, + { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A", - .patch = patch_alc882 }, /* should be patch_alc883() in future */ + .patch = patch_alc882 }, { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A", - .patch = patch_alc882 }, /* should be patch_alc883() in future */ + .patch = patch_alc882 }, { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, - { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc883 }, + { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 }, { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200", - .patch = patch_alc883 }, - { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 }, - { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 }, + .patch = patch_alc882 }, + { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc882 }, + { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 }, {} /* terminator */ };