Commit 4953550a authored by Takashi Iwai's avatar Takashi Iwai

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: default avatarTakashi Iwai <tiwai@suse.de>
parent b9791ca0
...@@ -114,8 +114,8 @@ ALC662/663/272 ...@@ -114,8 +114,8 @@ ALC662/663/272
samsung-nc10 Samsung NC10 mini notebook samsung-nc10 Samsung NC10 mini notebook
auto auto-config reading BIOS (default) auto auto-config reading BIOS (default)
ALC882/885 ALC882/883/885/888/889
========== ======================
3stack-dig 3-jack with SPDIF I/O 3stack-dig 3-jack with SPDIF I/O
6stack-dig 6-jack digital with SPDIF I/O 6stack-dig 6-jack digital with SPDIF I/O
arima Arima W820Di1 arima Arima W820Di1
...@@ -127,12 +127,8 @@ ALC882/885 ...@@ -127,12 +127,8 @@ ALC882/885
mbp3 Macbook Pro rev3 mbp3 Macbook Pro rev3
imac24 iMac 24'' with jack detection imac24 iMac 24'' with jack detection
w2jc ASUS W2JC w2jc ASUS W2JC
auto auto-config reading BIOS (default) 3stack-2ch-dig 3-jack with SPDIF I/O (ALC883)
alc883-6stack-dig 6-jack digital with SPDIF I/O (ALC883)
ALC883/888
==========
3stack-dig 3-jack with SPDIF I/O
6stack-dig 6-jack digital with SPDIF I/O
3stack-6ch 3-jack 6-channel 3stack-6ch 3-jack 6-channel
3stack-6ch-dig 3-jack 6-channel with SPDIF I/O 3stack-6ch-dig 3-jack 6-channel with SPDIF I/O
6stack-dig-demo 6-jack digital for Intel demo board 6stack-dig-demo 6-jack digital for Intel demo board
......
...@@ -208,12 +208,6 @@ enum { ...@@ -208,12 +208,6 @@ enum {
ALC885_MBP3, ALC885_MBP3,
ALC885_MB5, ALC885_MB5,
ALC885_IMAC24, ALC885_IMAC24,
ALC882_AUTO,
ALC882_MODEL_LAST,
};
/* ALC883 models */
enum {
ALC883_3ST_2ch_DIG, ALC883_3ST_2ch_DIG,
ALC883_3ST_6ch_DIG, ALC883_3ST_6ch_DIG,
ALC883_3ST_6ch, ALC883_3ST_6ch,
...@@ -246,8 +240,8 @@ enum { ...@@ -246,8 +240,8 @@ enum {
ALC889A_MB31, ALC889A_MB31,
ALC1200_ASUS_P5Q, ALC1200_ASUS_P5Q,
ALC883_SONY_VAIO_TT, ALC883_SONY_VAIO_TT,
ALC883_AUTO, ALC882_AUTO,
ALC883_MODEL_LAST, ALC882_MODEL_LAST,
}; };
/* for GPIO Poll */ /* for GPIO Poll */
...@@ -320,6 +314,8 @@ struct alc_spec { ...@@ -320,6 +314,8 @@ struct alc_spec {
struct snd_array kctls; struct snd_array kctls;
struct hda_input_mux private_imux[3]; struct hda_input_mux private_imux[3];
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; 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 */ /* hooks */
void (*init_hook)(struct hda_codec *codec); void (*init_hook)(struct hda_codec *codec);
...@@ -6295,7 +6291,7 @@ static int patch_alc260(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 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
* configuration. Each pin widget can choose any input DACs and a mixer. * configuration. Each pin widget can choose any input DACs and a mixer.
...@@ -6307,22 +6303,35 @@ static int patch_alc260(struct hda_codec *codec) ...@@ -6307,22 +6303,35 @@ static int patch_alc260(struct hda_codec *codec)
*/ */
#define ALC882_DIGOUT_NID 0x06 #define ALC882_DIGOUT_NID 0x06
#define ALC882_DIGIN_NID 0x0a #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] = { static struct hda_channel_mode alc882_ch_modes[1] = {
{ 8, NULL } { 8, NULL }
}; };
/* DACs */
static hda_nid_t alc882_dac_nids[4] = { static hda_nid_t alc882_dac_nids[4] = {
/* front, rear, clfe, rear_surr */ /* front, rear, clfe, rear_surr */
0x02, 0x03, 0x04, 0x05 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 alc880_adc_nids
#define alc882_adc_nids_alt alc880_adc_nids_alt #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[3] = { 0x24, 0x23, 0x22 };
static hda_nid_t alc882_capsrc_nids_alt[2] = { 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 */ /* input MUX */
/* FIXME: should be a matrix-type input source selection */ /* FIXME: should be a matrix-type input source selection */
...@@ -6337,6 +6346,8 @@ static struct hda_input_mux alc882_capture_source = { ...@@ -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 = { static struct hda_input_mux mb5_capture_source = {
.num_items = 3, .num_items = 3,
.items = { .items = {
...@@ -6346,6 +6357,77 @@ static struct hda_input_mux mb5_capture_source = { ...@@ -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 * 2ch mode
*/ */
...@@ -6357,6 +6439,18 @@ static struct hda_verb alc882_3ST_ch2_init[] = { ...@@ -6357,6 +6439,18 @@ static struct hda_verb alc882_3ST_ch2_init[] = {
{ } /* end */ { } /* 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 * 6ch mode
*/ */
...@@ -6370,11 +6464,14 @@ static struct hda_verb alc882_3ST_ch6_init[] = { ...@@ -6370,11 +6464,14 @@ static struct hda_verb alc882_3ST_ch6_init[] = {
{ } /* end */ { } /* 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 }, { 2, alc882_3ST_ch2_init },
{ 4, alc882_3ST_ch4_init },
{ 6, alc882_3ST_ch6_init }, { 6, alc882_3ST_ch6_init },
}; };
#define alc883_3ST_6ch_modes alc882_3ST_6ch_modes
/* /*
* 6ch mode * 6ch mode
*/ */
...@@ -6462,6 +6559,143 @@ static struct hda_channel_mode alc885_mb5_6ch_modes[2] = { ...@@ -6462,6 +6559,143 @@ static struct hda_channel_mode alc885_mb5_6ch_modes[2] = {
{ 6, alc885_mb5_ch6_init }, { 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 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
* Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
*/ */
...@@ -6597,7 +6831,7 @@ static struct snd_kcontrol_new alc882_chmode_mixer[] = { ...@@ -6597,7 +6831,7 @@ static struct snd_kcontrol_new alc882_chmode_mixer[] = {
{ } /* end */ { } /* 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) */ /* 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_OUT_ZERO},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
...@@ -6649,11 +6883,6 @@ static struct hda_verb alc882_init_verbs[] = { ...@@ -6649,11 +6883,6 @@ static struct hda_verb alc882_init_verbs[] = {
/* FIXME: use matrix-type input source selection */ /* FIXME: use matrix-type input source selection */
/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ /* 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 */ /* Input mixer2 */
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
...@@ -6664,9 +6893,6 @@ static struct hda_verb alc882_init_verbs[] = { ...@@ -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(3)},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, {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 */ /* ADC2: mute amp left and right */
{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
...@@ -6677,6 +6903,21 @@ static struct hda_verb alc882_init_verbs[] = { ...@@ -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[] = { static struct hda_verb alc882_eapd_verbs[] = {
/* change to EAPD mode */ /* change to EAPD mode */
{0x20, AC_VERB_SET_COEF_INDEX, 0x07}, {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
...@@ -6684,6 +6925,8 @@ static struct hda_verb alc882_eapd_verbs[] = { ...@@ -6684,6 +6925,8 @@ static struct hda_verb alc882_eapd_verbs[] = {
{ } { }
}; };
#define alc883_init_verbs alc882_base_init_verbs
/* Mac Pro test */ /* Mac Pro test */
static struct snd_kcontrol_new alc882_macpro_mixer[] = { static struct snd_kcontrol_new alc882_macpro_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
...@@ -7034,882 +7277,62 @@ static void alc885_imac24_init_hook(struct hda_codec *codec) ...@@ -7034,882 +7277,62 @@ static void alc885_imac24_init_hook(struct hda_codec *codec)
/* /*
* generic initialization of ADC, input mixers and output mixers * 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 * Unmute ADC0-2 and set the default input to mic-in
*/ */
{0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x09, 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 */
};
/* /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* 6ch mode * mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for
* front panel mic (mic 2)
*/ */
static struct hda_verb alc883_3ST_ch6_intel_init[] = { /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{ 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{ 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 }, {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
{ 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 * Set up output mixers (0x0c - 0x0f)
*/ */
static struct hda_verb alc883_sixstack_ch6_init[] = { /* set vol=0 to output mixers */
{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{ } /* end */ /* 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 */
* 8ch mode /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
*/ /* Input mixer2 */
static struct hda_verb alc883_sixstack_ch8_init[] = { {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Input mixer3 */
{ } /* end */ {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) */ /* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */
...@@ -7962,34 +7385,7 @@ static struct hda_verb alc883_medion_eapd_verbs[] = { ...@@ -7962,34 +7385,7 @@ static struct hda_verb alc883_medion_eapd_verbs[] = {
{ } { }
}; };
/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 #define alc883_base_mixer alc882_base_mixer
* 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 */
};
static struct snd_kcontrol_new alc883_mitac_mixer[] = { static struct snd_kcontrol_new alc883_mitac_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
...@@ -8306,116 +7702,38 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = { ...@@ -8306,116 +7702,38 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_MUTE("Line Playback Switch", 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 Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
{ } /* end */ { } /* 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)},
/* Front Pin: output 0 (0x0c) */ static struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = {
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol),
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch),
{0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, {
/* Rear Pin: output 1 (0x0d) */ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* .name = "Capture Source", */
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, .name = "Input Source",
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, .count = 1,
/* CLFE Pin: output 2 (0x0e) */ .info = alc_mux_enum_info,
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, .get = alc_mux_enum_get,
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, .put = alc_mux_enum_put,
{0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, },
/* Side Pin: output 3 (0x0f) */ { } /* end */
{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},
/* FIXME: use matrix-type input source selection */ static struct snd_kcontrol_new alc883_chmode_mixer[] = {
/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ {
/* Input mixer2 */ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, .name = "Channel Mode",
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, .info = alc_ch_mode_info,
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, .get = alc_ch_mode_get,
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, .put = alc_ch_mode_put,
/* Input mixer3 */ },
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, { } /* end */
{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)},
{ }
}; };
/* toggle speaker-output according to the hp-jack state */ /* toggle speaker-output according to the hp-jack state */
...@@ -8850,69 +8168,6 @@ static void alc883_vaiott_init_hook(struct hda_codec *codec) ...@@ -8850,69 +8168,6 @@ static void alc883_vaiott_init_hook(struct hda_codec *codec)
alc_automute_amp(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[] = { static struct hda_verb alc888_asus_m90v_verbs[] = {
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x23, 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) ...@@ -9023,25 +8278,44 @@ static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res)
alc889A_mb31_automute(codec); alc889A_mb31_automute(codec);
} }
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
#define alc883_loopbacks alc880_loopbacks #define alc882_loopbacks alc880_loopbacks
#endif #endif
/* pcm configuration: identical with ALC880 */ /* pcm configuration: identical with ALC880 */
#define alc883_pcm_analog_playback alc880_pcm_analog_playback #define alc882_pcm_analog_playback alc880_pcm_analog_playback
#define alc883_pcm_analog_capture alc880_pcm_analog_capture #define alc882_pcm_analog_capture alc880_pcm_analog_capture
#define alc883_pcm_analog_alt_capture alc880_pcm_analog_alt_capture #define alc882_pcm_digital_playback alc880_pcm_digital_playback
#define alc883_pcm_digital_playback alc880_pcm_digital_playback #define alc882_pcm_digital_capture alc880_pcm_digital_capture
#define alc883_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 * configuration and preset
*/ */
static const char *alc883_models[ALC883_MODEL_LAST] = { static const char *alc882_models[ALC882_MODEL_LAST] = {
[ALC883_3ST_2ch_DIG] = "3stack-dig", [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_DIG] = "3stack-6ch-dig",
[ALC883_3ST_6ch] = "3stack-6ch", [ALC883_3ST_6ch] = "3stack-6ch",
[ALC883_6ST_DIG] = "6stack-dig", [ALC883_6ST_DIG] = "alc883-6stack-dig",
[ALC883_TARGA_DIG] = "targa-dig", [ALC883_TARGA_DIG] = "targa-dig",
[ALC883_TARGA_2ch_DIG] = "targa-2ch-dig", [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig",
[ALC883_TARGA_8ch_DIG] = "targa-8ch-dig", [ALC883_TARGA_8ch_DIG] = "targa-8ch-dig",
...@@ -9068,11 +8342,12 @@ static const char *alc883_models[ALC883_MODEL_LAST] = { ...@@ -9068,11 +8342,12 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
[ALC1200_ASUS_P5Q] = "asus-p5q", [ALC1200_ASUS_P5Q] = "asus-p5q",
[ALC889A_MB31] = "mb31", [ALC889A_MB31] = "mb31",
[ALC883_SONY_VAIO_TT] = "sony-vaio-tt", [ALC883_SONY_VAIO_TT] = "sony-vaio-tt",
[ALC883_AUTO] = "auto", [ALC882_AUTO] = "auto",
}; };
static struct snd_pci_quirk alc883_cfg_tbl[] = { static struct snd_pci_quirk alc882_cfg_tbl[] = {
SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG), SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE), 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, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE),
SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", 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[] = { ...@@ -9087,8 +8362,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
ALC888_ACER_ASPIRE_8930G), ALC888_ACER_ASPIRE_8930G),
SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G", SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
ALC888_ACER_ASPIRE_8930G), ALC888_ACER_ASPIRE_8930G),
SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC883_AUTO), SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC882_AUTO),
SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC883_AUTO), SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC882_AUTO),
SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G", SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
ALC888_ACER_ASPIRE_6530G), ALC888_ACER_ASPIRE_6530G),
SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G", SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
...@@ -9097,30 +8372,44 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { ...@@ -9097,30 +8372,44 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
* model=auto should work fine now * model=auto should work fine now
*/ */
/* SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER), */ /* SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER), */
SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL), 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, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", 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, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP), SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP),
SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", 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, 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, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_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, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q),
SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601), 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, 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, 0x8227, "Mitac 82801H", ALC883_MITAC),
SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC), SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD), SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL), SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch), 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, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
SND_PCI_QUIRK(0x1462, 0x040d, "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, 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, 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, 0x3729, "MSI S420", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG), SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG), SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
...@@ -9142,11 +8431,13 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { ...@@ -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, 0x7327, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7350, "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(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_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, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", 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_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD),
SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), 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(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1100, "FSC AMILO Xi/Pi25xx", SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1100, "FSC AMILO Xi/Pi25xx",
ALC883_FUJITSU_PI2515), ALC883_FUJITSU_PI2515),
...@@ -9161,24 +8452,175 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { ...@@ -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(0x17c0, 0x4085, "MEDION MD96630", ALC888_LENOVO_MS7195_DIG),
SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_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(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL), SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", 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, 0x2503, "82801H", ALC883_MITAC),
SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC883_3ST_6ch_INTEL), SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC883_3ST_6ch_INTEL),
SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch), 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[] = { /* codec SSID table for Intel Mac */
ALC883_DIGOUT_NID, 0, 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] = { [ALC883_3ST_2ch_DIG] = {
.mixers = { alc883_3ST_2ch_mixer }, .mixers = { alc883_3ST_2ch_mixer },
.init_verbs = { alc883_init_verbs }, .init_verbs = { alc883_init_verbs },
...@@ -9612,10 +9054,33 @@ static struct alc_config_preset alc883_presets[] = { ...@@ -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 * 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, hda_nid_t nid, int pin_type,
int dac_idx) int dac_idx)
{ {
...@@ -9632,7 +9097,7 @@ static void alc883_auto_set_output_and_unmute(struct hda_codec *codec, ...@@ -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; struct alc_spec *spec = codec->spec;
int i; int i;
...@@ -9641,12 +9106,12 @@ static void alc883_auto_init_multi_out(struct hda_codec *codec) ...@@ -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]; hda_nid_t nid = spec->autocfg.line_out_pins[i];
int pin_type = get_pin_type(spec->autocfg.line_out_type); int pin_type = get_pin_type(spec->autocfg.line_out_type);
if (nid) if (nid)
alc883_auto_set_output_and_unmute(codec, nid, pin_type, alc882_auto_set_output_and_unmute(codec, nid, pin_type,
i); 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; struct alc_spec *spec = codec->spec;
hda_nid_t pin; hda_nid_t pin;
...@@ -9654,42 +9119,114 @@ static void alc883_auto_init_hp_out(struct hda_codec *codec) ...@@ -9654,42 +9119,114 @@ static void alc883_auto_init_hp_out(struct hda_codec *codec)
pin = spec->autocfg.hp_pins[0]; pin = spec->autocfg.hp_pins[0];
if (pin) /* connect to front */ if (pin) /* connect to front */
/* use dac 0 */ /* 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]; pin = spec->autocfg.speaker_pins[0];
if (pin) 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 alc882_is_input_pin(nid) alc880_is_input_pin(nid)
#define ALC883_PIN_CD_NID ALC880_PIN_CD_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; struct alc_spec *spec = codec->spec;
int i; int i;
for (i = 0; i < AUTO_PIN_LAST; i++) { for (i = 0; i < AUTO_PIN_LAST; i++) {
hda_nid_t nid = spec->autocfg.input_pins[i]; hda_nid_t nid = spec->autocfg.input_pins[i];
if (alc883_is_input_pin(nid)) { if (!nid)
alc_set_input_pin(codec, nid, i); continue;
if (nid != ALC883_PIN_CD_NID && alc_set_input_pin(codec, nid, AUTO_PIN_FRONT_MIC /*i*/);
(get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
snd_hda_codec_write(codec, nid, 0, snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_AMP_GAIN_MUTE, AC_VERB_SET_AMP_GAIN_MUTE,
AMP_OUT_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);
}
} }
} }
#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... */ /* 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; struct alc_spec *spec = codec->spec;
int err = alc880_parse_auto_config(codec); struct auto_pin_cfg *autocfg = &spec->autocfg;
struct auto_pin_cfg *cfg = &spec->autocfg; unsigned int wcap;
int i; int i;
int err = alc880_parse_auto_config(codec);
if (err < 0) if (err < 0)
return err; return err;
...@@ -9702,14 +9239,17 @@ static int alc883_parse_auto_config(struct hda_codec *codec) ...@@ -9702,14 +9239,17 @@ static int alc883_parse_auto_config(struct hda_codec *codec)
/* hack - override the init verbs */ /* hack - override the init verbs */
spec->init_verbs[0] = alc883_auto_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..() /* digital-mic input pin is excluded in alc880_auto_create..()
* because it's under 0x18 * because it's under 0x18
*/ */
if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 || if (autocfg->input_pins[AUTO_PIN_MIC] == 0x12 ||
cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) { autocfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) {
struct hda_input_mux *imux = &spec->private_imux[0]; struct hda_input_mux *imux = &spec->private_imux[0];
for (i = 1; i < 3; i++) for (i = 1; i < 3; i++)
memcpy(&spec->private_imux[i], memcpy(&spec->private_imux[i],
...@@ -9721,24 +9261,23 @@ static int alc883_parse_auto_config(struct hda_codec *codec) ...@@ -9721,24 +9261,23 @@ static int alc883_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 3; spec->num_mux_defs = 3;
spec->input_mux = spec->private_imux; spec->input_mux = spec->private_imux;
} }
}
return 1; /* config found */ return 1; /* config found */
} }
/* additional initialization for auto-configuration model */ /* 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; struct alc_spec *spec = codec->spec;
alc883_auto_init_multi_out(codec); alc882_auto_init_multi_out(codec);
alc883_auto_init_hp_out(codec); alc882_auto_init_hp_out(codec);
alc883_auto_init_analog_input(codec); alc882_auto_init_analog_input(codec);
alc883_auto_init_input_src(codec); alc882_auto_init_input_src(codec);
if (spec->unsol_event) if (spec->unsol_event)
alc_inithook(codec); alc_inithook(codec);
} }
static int patch_alc883(struct hda_codec *codec) static int patch_alc882(struct hda_codec *codec)
{ {
struct alc_spec *spec; struct alc_spec *spec;
int err, board_config; int err, board_config;
...@@ -9749,28 +9288,36 @@ static int patch_alc883(struct hda_codec *codec) ...@@ -9749,28 +9288,36 @@ static int patch_alc883(struct hda_codec *codec)
codec->spec = spec; codec->spec = spec;
alc_fix_pll_init(codec, 0x20, 0x0a, 10); switch (codec->vendor_id) {
case 0x10ec0882:
board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST, case 0x10ec0885:
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; break;
default: default:
printk(KERN_INFO /* ALC883 and variants */
"hda_codec: Unknown model for %s, trying " alc_fix_pll_init(codec, 0x20, 0x0a, 10);
"auto-probe from BIOS...\n", codec->chip_name); break;
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 */ /* automatic parse from the BIOS config */
err = alc883_parse_auto_config(codec); err = alc882_parse_auto_config(codec);
if (err < 0) { if (err < 0) {
alc_free(codec); alc_free(codec);
return err; return err;
...@@ -9778,7 +9325,7 @@ static int patch_alc883(struct hda_codec *codec) ...@@ -9778,7 +9325,7 @@ static int patch_alc883(struct hda_codec *codec)
printk(KERN_INFO printk(KERN_INFO
"hda_codec: Cannot set up configuration " "hda_codec: Cannot set up configuration "
"from BIOS. Using base mode...\n"); "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) ...@@ -9788,63 +9335,61 @@ static int patch_alc883(struct hda_codec *codec)
return err; return err;
} }
if (board_config != ALC883_AUTO) if (board_config != ALC882_AUTO)
setup_preset(spec, &alc883_presets[board_config]); setup_preset(spec, &alc882_presets[board_config]);
switch (codec->vendor_id) { spec->stream_analog_playback = &alc882_pcm_analog_playback;
case 0x10ec0888: spec->stream_analog_capture = &alc882_pcm_analog_capture;
if (!spec->num_adc_nids) { /* FIXME: setup DAC5 */
spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); /*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/
spec->adc_nids = alc883_adc_nids; spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
}
if (!spec->capsrc_nids) spec->stream_digital_playback = &alc882_pcm_digital_playback;
spec->capsrc_nids = alc883_capsrc_nids; spec->stream_digital_capture = &alc882_pcm_digital_capture;
if (codec->vendor_id == 0x10ec0888)
spec->init_amp = ALC_INIT_DEFAULT; /* always initialize */ spec->init_amp = ALC_INIT_DEFAULT; /* always initialize */
break;
case 0x10ec0889: if (!spec->adc_nids && spec->input_mux) {
if (!spec->num_adc_nids) { int i;
spec->num_adc_nids = ARRAY_SIZE(alc889_adc_nids); spec->num_adc_nids = 0;
spec->adc_nids = alc889_adc_nids; for (i = 0; i < ARRAY_SIZE(alc882_adc_nids); i++) {
} hda_nid_t cap;
if (!spec->capsrc_nids) hda_nid_t nid = alc882_adc_nids[i];
spec->capsrc_nids = alc889_capsrc_nids; unsigned int wcap = get_wcaps(codec, nid);
break; /* get type */
default: wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
if (!spec->num_adc_nids) { if (wcap != AC_WID_AUD_IN)
spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); continue;
spec->adc_nids = alc883_adc_nids; 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->adc_nids = spec->private_adc_nids;
spec->capsrc_nids = alc883_capsrc_nids; spec->capsrc_nids = spec->private_capsrc_nids;
break;
} }
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); set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
spec->vmaster_nid = 0x0c; spec->vmaster_nid = 0x0c;
codec->patch_ops = alc_patch_ops; codec->patch_ops = alc_patch_ops;
if (board_config == ALC883_AUTO) if (board_config == ALC882_AUTO)
spec->init_hook = alc883_auto_init; spec->init_hook = alc882_auto_init;
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
if (!spec->loopback.amplist) if (!spec->loopback.amplist)
spec->loopback.amplist = alc883_loopbacks; spec->loopback.amplist = alc882_loopbacks;
#endif #endif
codec->proc_widget_hook = print_realtek_coef; codec->proc_widget_hook = print_realtek_coef;
return 0; return 0;
} }
/* /*
* ALC262 support * ALC262 support
*/ */
...@@ -17546,23 +17091,23 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = { ...@@ -17546,23 +17091,23 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 }, { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
{ .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd }, { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
{ .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2", { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
.patch = patch_alc883 }, .patch = patch_alc882 },
{ .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1", { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
.patch = patch_alc662 }, .patch = patch_alc662 },
{ .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, { .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", { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
.patch = patch_alc882 }, /* should be patch_alc883() in future */ .patch = patch_alc882 },
{ .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A", { .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 = 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", { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
.patch = patch_alc883 }, .patch = patch_alc882 },
{ .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 }, { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc882 },
{ .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 }, { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
{} /* terminator */ {} /* terminator */
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment