Skip to content

Commit

Permalink
[ALSA] hda - Add ALC663 support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Kailang Yang authored and Takashi Iwai committed May 27, 2008
1 parent abbc9d1 commit 6dda9f4
Show file tree
Hide file tree
Showing 2 changed files with 291 additions and 4 deletions.
6 changes: 5 additions & 1 deletion Documentation/sound/alsa/ALSA-Configuration.txt
Original file line number Diff line number Diff line change
Expand Up @@ -845,14 +845,18 @@ 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
6stack-dig 6-stack with SPDIF
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
Expand Down
289 changes: 286 additions & 3 deletions sound/pci/hda/patch_realtek.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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},

{ }
};

Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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
Expand All @@ -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),
{}
};

Expand Down Expand Up @@ -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,
},
};


Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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 },
Expand Down

0 comments on commit 6dda9f4

Please sign in to comment.