mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 01:10:04 +00:00
[ALSA] hda - Add ALC663 support
Added the support of ALC663 codec, including specific models for ASUS M51VA, ASUS G71V, ASUS H13 and ASUS G50V. Signed-off-by: Kailang Yang <kailang@realtek.com.tw> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
abbc9d1b25
commit
6dda9f4a95
2 changed files with 291 additions and 4 deletions
|
@ -845,7 +845,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
ALC269
|
||||
basic Basic preset
|
||||
|
||||
ALC662
|
||||
ALC662/663
|
||||
3stack-dig 3-stack (2-channel) with SPDIF
|
||||
3stack-6ch 3-stack (6-channel)
|
||||
3stack-6ch-dig 3-stack (6-channel) with SPDIF
|
||||
|
@ -853,6 +853,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
lenovo-101e Lenovo laptop
|
||||
eeepc-p701 ASUS Eeepc P701
|
||||
eeepc-ep20 ASUS Eeepc EP20
|
||||
m51va ASUS M51VA
|
||||
g71v ASUS G71V
|
||||
h13 ASUS H13
|
||||
g50v ASUS G50V
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
ALC882/885
|
||||
|
|
|
@ -163,6 +163,10 @@ enum {
|
|||
ALC662_LENOVO_101E,
|
||||
ALC662_ASUS_EEEPC_P701,
|
||||
ALC662_ASUS_EEEPC_EP20,
|
||||
ALC663_ASUS_M51VA,
|
||||
ALC663_ASUS_G71V,
|
||||
ALC663_ASUS_H13,
|
||||
ALC663_ASUS_G50V,
|
||||
ALC662_AUTO,
|
||||
ALC662_MODEL_LAST,
|
||||
};
|
||||
|
@ -13251,6 +13255,23 @@ static struct hda_input_mux alc662_eeepc_capture_source = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct hda_input_mux alc663_capture_source = {
|
||||
.num_items = 3,
|
||||
.items = {
|
||||
{ "Mic", 0x0 },
|
||||
{ "Front Mic", 0x1 },
|
||||
{ "Line", 0x2 },
|
||||
},
|
||||
};
|
||||
|
||||
static struct hda_input_mux alc663_m51va_capture_source = {
|
||||
.num_items = 2,
|
||||
.items = {
|
||||
{ "Ext-Mic", 0x0 },
|
||||
{ "D-Mic", 0x9 },
|
||||
},
|
||||
};
|
||||
|
||||
#define alc662_mux_enum_info alc_mux_enum_info
|
||||
#define alc662_mux_enum_get alc_mux_enum_get
|
||||
#define alc662_mux_enum_put alc882_mux_enum_put
|
||||
|
@ -13431,6 +13452,44 @@ static struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
|
|||
{ } /* end */
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new alc663_m51va_mixer[] = {
|
||||
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("DMic Playback Switch", 0x23, 0x9, HDA_INPUT),
|
||||
{ } /* end */
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new alc663_g71v_mixer[] = {
|
||||
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_VOLUME("Front Playback Volume", 0x03, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
|
||||
|
||||
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
|
||||
{ } /* end */
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new alc663_g50v_mixer[] = {
|
||||
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
|
||||
|
||||
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
|
||||
{ } /* end */
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new alc662_chmode_mixer[] = {
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
|
@ -13501,6 +13560,11 @@ static struct hda_verb alc662_init_verbs[] = {
|
|||
{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(4)},
|
||||
|
||||
/* always trun on EAPD */
|
||||
{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
|
||||
{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
|
||||
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -13571,6 +13635,43 @@ static struct hda_verb alc662_auto_init_verbs[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
static struct hda_verb alc663_m51va_init_verbs[] = {
|
||||
{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
|
||||
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
|
||||
{0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
|
||||
|
||||
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
|
||||
|
||||
{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
|
||||
{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct hda_verb alc663_g71v_init_verbs[] = {
|
||||
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
|
||||
/* {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
|
||||
/* {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, */ /* Headphone */
|
||||
|
||||
{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
|
||||
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
|
||||
{0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
|
||||
|
||||
{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
|
||||
{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_MIC_EVENT},
|
||||
{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct hda_verb alc663_g50v_init_verbs[] = {
|
||||
{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
|
||||
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
|
||||
{0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
|
||||
|
||||
{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
|
||||
{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
|
||||
{}
|
||||
};
|
||||
|
||||
/* capture mixer elements */
|
||||
static struct snd_kcontrol_new alc662_capture_mixer[] = {
|
||||
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
|
||||
|
@ -13692,6 +13793,125 @@ static void alc662_eeepc_ep20_inithook(struct hda_codec *codec)
|
|||
alc662_eeepc_ep20_automute(codec);
|
||||
}
|
||||
|
||||
static void alc663_m51va_speaker_automute(struct hda_codec *codec)
|
||||
{
|
||||
unsigned int present;
|
||||
unsigned char bits;
|
||||
|
||||
present = snd_hda_codec_read(codec, 0x21, 0,
|
||||
AC_VERB_GET_PIN_SENSE, 0)
|
||||
& AC_PINSENSE_PRESENCE;
|
||||
bits = present ? HDA_AMP_MUTE : 0;
|
||||
snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
|
||||
HDA_AMP_MUTE, bits);
|
||||
}
|
||||
|
||||
static void alc663_m51va_mic_automute(struct hda_codec *codec)
|
||||
{
|
||||
unsigned int present;
|
||||
|
||||
present = snd_hda_codec_read(codec, 0x18, 0,
|
||||
AC_VERB_GET_PIN_SENSE, 0)
|
||||
& AC_PINSENSE_PRESENCE;
|
||||
snd_hda_codec_write_cache(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
|
||||
0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
|
||||
snd_hda_codec_write_cache(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
|
||||
0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
|
||||
snd_hda_codec_write_cache(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
|
||||
0x7000 | (0x09 << 8) | (present ? 0x80 : 0));
|
||||
snd_hda_codec_write_cache(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
|
||||
0x7000 | (0x09 << 8) | (present ? 0x80 : 0));
|
||||
}
|
||||
|
||||
static void alc663_m51va_unsol_event(struct hda_codec *codec,
|
||||
unsigned int res)
|
||||
{
|
||||
switch (res >> 26) {
|
||||
case ALC880_HP_EVENT:
|
||||
alc663_m51va_speaker_automute(codec);
|
||||
break;
|
||||
case ALC880_MIC_EVENT:
|
||||
alc663_m51va_mic_automute(codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void alc663_m51va_inithook(struct hda_codec *codec)
|
||||
{
|
||||
alc663_m51va_speaker_automute(codec);
|
||||
alc663_m51va_mic_automute(codec);
|
||||
}
|
||||
|
||||
static void alc663_g71v_hp_automute(struct hda_codec *codec)
|
||||
{
|
||||
unsigned int present;
|
||||
unsigned char bits;
|
||||
|
||||
present = snd_hda_codec_read(codec, 0x21, 0,
|
||||
AC_VERB_GET_PIN_SENSE, 0)
|
||||
& AC_PINSENSE_PRESENCE;
|
||||
bits = present ? HDA_AMP_MUTE : 0;
|
||||
snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
|
||||
HDA_AMP_MUTE, bits);
|
||||
snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
|
||||
HDA_AMP_MUTE, bits);
|
||||
}
|
||||
|
||||
static void alc663_g71v_front_automute(struct hda_codec *codec)
|
||||
{
|
||||
unsigned int present;
|
||||
unsigned char bits;
|
||||
|
||||
present = snd_hda_codec_read(codec, 0x15, 0,
|
||||
AC_VERB_GET_PIN_SENSE, 0)
|
||||
& AC_PINSENSE_PRESENCE;
|
||||
bits = present ? HDA_AMP_MUTE : 0;
|
||||
snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
|
||||
HDA_AMP_MUTE, bits);
|
||||
}
|
||||
|
||||
static void alc663_g71v_unsol_event(struct hda_codec *codec,
|
||||
unsigned int res)
|
||||
{
|
||||
switch (res >> 26) {
|
||||
case ALC880_HP_EVENT:
|
||||
alc663_g71v_hp_automute(codec);
|
||||
break;
|
||||
case ALC880_FRONT_EVENT:
|
||||
alc663_g71v_front_automute(codec);
|
||||
break;
|
||||
case ALC880_MIC_EVENT:
|
||||
alc662_eeepc_mic_automute(codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void alc663_g71v_inithook(struct hda_codec *codec)
|
||||
{
|
||||
alc663_g71v_front_automute(codec);
|
||||
alc663_g71v_hp_automute(codec);
|
||||
alc662_eeepc_mic_automute(codec);
|
||||
}
|
||||
|
||||
static void alc663_g50v_unsol_event(struct hda_codec *codec,
|
||||
unsigned int res)
|
||||
{
|
||||
switch (res >> 26) {
|
||||
case ALC880_HP_EVENT:
|
||||
alc663_m51va_speaker_automute(codec);
|
||||
break;
|
||||
case ALC880_MIC_EVENT:
|
||||
alc662_eeepc_mic_automute(codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void alc663_g50v_inithook(struct hda_codec *codec)
|
||||
{
|
||||
alc663_m51va_speaker_automute(codec);
|
||||
alc662_eeepc_mic_automute(codec);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SND_HDA_POWER_SAVE
|
||||
#define alc662_loopbacks alc880_loopbacks
|
||||
#endif
|
||||
|
@ -13714,14 +13934,24 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
|
|||
[ALC662_LENOVO_101E] = "lenovo-101e",
|
||||
[ALC662_ASUS_EEEPC_P701] = "eeepc-p701",
|
||||
[ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",
|
||||
[ALC663_ASUS_M51VA] = "m51va",
|
||||
[ALC663_ASUS_G71V] = "g71v",
|
||||
[ALC663_ASUS_H13] = "h13",
|
||||
[ALC663_ASUS_G50V] = "g50v",
|
||||
[ALC662_AUTO] = "auto",
|
||||
};
|
||||
|
||||
static struct snd_pci_quirk alc662_cfg_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS G71V", ALC663_ASUS_G71V),
|
||||
SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
|
||||
SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS M51VA", ALC663_ASUS_G50V),
|
||||
SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
|
||||
SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
|
||||
SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
|
||||
SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
|
||||
SND_PCI_QUIRK(0x1854, 0x2000, "ASUS H13-2000", ALC663_ASUS_H13),
|
||||
SND_PCI_QUIRK(0x1854, 0x2001, "ASUS H13-2001", ALC663_ASUS_H13),
|
||||
SND_PCI_QUIRK(0x1854, 0x2002, "ASUS H13-2002", ALC663_ASUS_H13),
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -13809,7 +14039,53 @@ static struct alc_config_preset alc662_presets[] = {
|
|||
.unsol_event = alc662_eeepc_ep20_unsol_event,
|
||||
.init_hook = alc662_eeepc_ep20_inithook,
|
||||
},
|
||||
|
||||
[ALC663_ASUS_M51VA] = {
|
||||
.mixers = { alc663_m51va_mixer, alc662_capture_mixer},
|
||||
.init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
|
||||
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
|
||||
.dac_nids = alc662_dac_nids,
|
||||
.dig_out_nid = ALC662_DIGOUT_NID,
|
||||
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
|
||||
.channel_mode = alc662_3ST_2ch_modes,
|
||||
.input_mux = &alc663_m51va_capture_source,
|
||||
.unsol_event = alc663_m51va_unsol_event,
|
||||
.init_hook = alc663_m51va_inithook,
|
||||
},
|
||||
[ALC663_ASUS_G71V] = {
|
||||
.mixers = { alc663_g71v_mixer, alc662_capture_mixer},
|
||||
.init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs },
|
||||
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
|
||||
.dac_nids = alc662_dac_nids,
|
||||
.dig_out_nid = ALC662_DIGOUT_NID,
|
||||
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
|
||||
.channel_mode = alc662_3ST_2ch_modes,
|
||||
.input_mux = &alc662_eeepc_capture_source,
|
||||
.unsol_event = alc663_g71v_unsol_event,
|
||||
.init_hook = alc663_g71v_inithook,
|
||||
},
|
||||
[ALC663_ASUS_H13] = {
|
||||
.mixers = { alc663_m51va_mixer, alc662_capture_mixer},
|
||||
.init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
|
||||
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
|
||||
.dac_nids = alc662_dac_nids,
|
||||
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
|
||||
.channel_mode = alc662_3ST_2ch_modes,
|
||||
.input_mux = &alc663_m51va_capture_source,
|
||||
.unsol_event = alc663_m51va_unsol_event,
|
||||
.init_hook = alc663_m51va_inithook,
|
||||
},
|
||||
[ALC663_ASUS_G50V] = {
|
||||
.mixers = { alc663_g50v_mixer, alc662_capture_mixer},
|
||||
.init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs },
|
||||
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
|
||||
.dac_nids = alc662_dac_nids,
|
||||
.dig_out_nid = ALC662_DIGOUT_NID,
|
||||
.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
|
||||
.channel_mode = alc662_3ST_6ch_modes,
|
||||
.input_mux = &alc663_capture_source,
|
||||
.unsol_event = alc663_g50v_unsol_event,
|
||||
.init_hook = alc663_g50v_inithook,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
@ -14108,11 +14384,17 @@ static int patch_alc662(struct hda_codec *codec)
|
|||
if (board_config != ALC662_AUTO)
|
||||
setup_preset(spec, &alc662_presets[board_config]);
|
||||
|
||||
spec->stream_name_analog = "ALC662 Analog";
|
||||
if (codec->vendor_id == 0x10ec0663) {
|
||||
spec->stream_name_analog = "ALC663 Analog";
|
||||
spec->stream_name_digital = "ALC663 Digital";
|
||||
} else {
|
||||
spec->stream_name_analog = "ALC662 Analog";
|
||||
spec->stream_name_digital = "ALC662 Digital";
|
||||
}
|
||||
|
||||
spec->stream_analog_playback = &alc662_pcm_analog_playback;
|
||||
spec->stream_analog_capture = &alc662_pcm_analog_capture;
|
||||
|
||||
spec->stream_name_digital = "ALC662 Digital";
|
||||
spec->stream_digital_playback = &alc662_pcm_digital_playback;
|
||||
spec->stream_digital_capture = &alc662_pcm_digital_capture;
|
||||
|
||||
|
@ -14151,6 +14433,7 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
|
|||
.patch = patch_alc883 },
|
||||
{ .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 },
|
||||
|
|
Loading…
Reference in a new issue