From: Takashi Iwai Subject: ALSA: hda - update Analaog Device codec support Patch-mainline: 2.6.28-rc1 References: - Fix AD1988 output noises - Slave HDMI support on AD1989 - Added the support for AD1882A Signed-off-by: Takashi Iwai --- --- Documentation/sound/alsa/ALSA-Configuration.txt | 2 sound/pci/hda/patch_analog.c | 89 +++++++++++++++++++----- 2 files changed, 72 insertions(+), 19 deletions(-) --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -929,7 +929,7 @@ Prior to version 0.9.0rc4 options had a allout 5-jack in back, 2-jack in front, SPDIF out auto auto-config reading BIOS (default) - AD1882 + AD1882 / AD1882A 3stack 3-stack mode (default) 6stack 6-stack mode --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -1869,9 +1869,14 @@ static hda_nid_t ad1988_capsrc_nids[3] = 0x0c, 0x0d, 0x0e }; -#define AD1988_SPDIF_OUT 0x02 +#define AD1988_SPDIF_OUT 0x02 +#define AD1988_SPDIF_OUT_HDMI 0x0b #define AD1988_SPDIF_IN 0x07 +static hda_nid_t ad1989b_slave_dig_outs[2] = { + AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI +}; + static struct hda_input_mux ad1988_6stack_capture_source = { .num_items = 5, .items = { @@ -2186,6 +2191,7 @@ static struct snd_kcontrol_new ad1988_sp static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = { HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT), { } /* end */ }; @@ -2250,6 +2256,8 @@ static struct hda_verb ad1988_6stack_ini {0x34, AC_VERB_SET_CONNECT_SEL, 0x0}, /* Analog CD Input */ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + /* Analog Mix output amp */ + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ { } }; @@ -2383,6 +2391,8 @@ static struct hda_verb ad1988_3stack_ini {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* Analog Mix output amp */ + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ { } }; @@ -2456,6 +2466,8 @@ static struct hda_verb ad1988_laptop_ini {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* Analog Mix output amp */ + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ { } }; @@ -3023,6 +3035,7 @@ static int patch_ad1988(struct hda_codec ad1989_spdif_out_mixers; spec->init_verbs[spec->num_init_verbs++] = ad1989_spdif_init_verbs; + codec->slave_dig_outs = ad1989b_slave_dig_outs; } else { spec->mixers[spec->num_mixers++] = ad1988_spdif_out_mixers; @@ -3963,7 +3976,7 @@ static int patch_ad1884a(struct hda_code /* - * AD1882 + * AD1882 / AD1882A * * port-A - front hp-out * port-B - front mic-in @@ -4000,6 +4013,18 @@ static struct hda_input_mux ad1882_captu }, }; +/* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */ +static struct hda_input_mux ad1882a_capture_source = { + .num_items = 5, + .items = { + { "Front Mic", 0x1 }, + { "Mic", 0x4}, + { "Line", 0x2 }, + { "Digital Mic", 0x06 }, + { "Mix", 0x7 }, + }, +}; + static struct snd_kcontrol_new ad1882_base_mixers[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), @@ -4009,16 +4034,7 @@ static struct snd_kcontrol_new ad1882_ba HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT), @@ -4051,6 +4067,35 @@ static struct snd_kcontrol_new ad1882_ba { } /* end */ }; +static struct snd_kcontrol_new ad1882_loopback_mixers[] = { + HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), + HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT), + HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT), + { } /* end */ +}; + +static struct snd_kcontrol_new ad1882a_loopback_mixers[] = { + HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), + HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT), + HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT), + HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT), + { } /* end */ +}; + static struct snd_kcontrol_new ad1882_3stack_mixers[] = { HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT), @@ -4220,9 +4265,16 @@ static int patch_ad1882(struct hda_codec spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids); spec->adc_nids = ad1882_adc_nids; spec->capsrc_nids = ad1882_capsrc_nids; - spec->input_mux = &ad1882_capture_source; - spec->num_mixers = 1; + if (codec->vendor_id == 0x11d1882) + spec->input_mux = &ad1882_capture_source; + else + spec->input_mux = &ad1882a_capture_source; + spec->num_mixers = 2; spec->mixers[0] = ad1882_base_mixers; + if (codec->vendor_id == 0x11d1882) + spec->mixers[1] = ad1882_loopback_mixers; + else + spec->mixers[1] = ad1882a_loopback_mixers; spec->num_init_verbs = 1; spec->init_verbs[0] = ad1882_init_verbs; spec->spdif_route = 0; @@ -4239,8 +4291,8 @@ static int patch_ad1882(struct hda_codec switch (board_config) { default: case AD1882_3STACK: - spec->num_mixers = 2; - spec->mixers[1] = ad1882_3stack_mixers; + spec->num_mixers = 3; + spec->mixers[2] = ad1882_3stack_mixers; spec->channel_mode = ad1882_modes; spec->num_channel_mode = ARRAY_SIZE(ad1882_modes); spec->need_dac_fix = 1; @@ -4248,8 +4300,8 @@ static int patch_ad1882(struct hda_codec spec->multiout.num_dacs = 1; break; case AD1882_6STACK: - spec->num_mixers = 2; - spec->mixers[1] = ad1882_6stack_mixers; + spec->num_mixers = 3; + spec->mixers[2] = ad1882_6stack_mixers; break; } return 0; @@ -4272,6 +4324,7 @@ struct hda_codec_preset snd_hda_preset_a { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 }, { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 }, + { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 }, { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 }, { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 }, {} /* terminator */