📄 patch_analog.c
字号:
/* mute internal speaker if HP is plugged */static void ad1981_hp_automute(struct hda_codec *codec){ unsigned int present; present = snd_hda_codec_read(codec, 0x06, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, 0x80, present ? 0x80 : 0); snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, 0x80, present ? 0x80 : 0);}/* toggle input of built-in and mic jack appropriately */static void ad1981_hp_automic(struct hda_codec *codec){ static struct hda_verb mic_jack_on[] = { {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, {} }; static struct hda_verb mic_jack_off[] = { {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, {} }; unsigned int present; present = snd_hda_codec_read(codec, 0x08, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; if (present) snd_hda_sequence_write(codec, mic_jack_on); else snd_hda_sequence_write(codec, mic_jack_off);}/* unsolicited event for HP jack sensing */static void ad1981_hp_unsol_event(struct hda_codec *codec, unsigned int res){ res >>= 26; switch (res) { case AD1981_HP_EVENT: ad1981_hp_automute(codec); break; case AD1981_MIC_EVENT: ad1981_hp_automic(codec); break; }}static struct hda_input_mux ad1981_hp_capture_source = { .num_items = 3, .items = { { "Mic", 0x0 }, { "Docking-Station", 0x1 }, { "Mix", 0x2 }, },};static struct snd_kcontrol_new ad1981_hp_mixers[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Volume", .info = snd_hda_mixer_amp_volume_info, .get = snd_hda_mixer_amp_volume_get, .put = ad1981_hp_master_vol_put, .private_value = HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Switch", .info = ad198x_eapd_info, .get = ad198x_eapd_get, .put = ad1981_hp_master_sw_put, .private_value = 0x05, }, HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),#if 0 /* FIXME: analog mic/line loopback doesn't work with my tests... * (although recording is OK) */ HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), /* FIXME: does this laptop have analog CD connection? */ HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),#endif HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", .info = ad198x_mux_enum_info, .get = ad198x_mux_enum_get, .put = ad198x_mux_enum_put, }, { } /* end */};/* initialize jack-sensing, too */static int ad1981_hp_init(struct hda_codec *codec){ ad198x_init(codec); ad1981_hp_automute(codec); ad1981_hp_automic(codec); return 0;}/* models */enum { AD1981_BASIC, AD1981_HP };static struct hda_board_config ad1981_cfg_tbl[] = { { .modelname = "hp", .config = AD1981_HP }, /* All HP models */ { .pci_subvendor = 0x103c, .config = AD1981_HP }, { .modelname = "basic", .config = AD1981_BASIC }, {}};static int patch_ad1981(struct hda_codec *codec){ struct ad198x_spec *spec; int board_config; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) return -ENOMEM; mutex_init(&spec->amp_mutex); codec->spec = spec; spec->multiout.max_channels = 2; spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids); spec->multiout.dac_nids = ad1981_dac_nids; spec->multiout.dig_out_nid = AD1981_SPDIF_OUT; spec->num_adc_nids = 1; spec->adc_nids = ad1981_adc_nids; spec->capsrc_nids = ad1981_capsrc_nids; spec->input_mux = &ad1981_capture_source; spec->num_mixers = 1; spec->mixers[0] = ad1981_mixers; spec->num_init_verbs = 1; spec->init_verbs[0] = ad1981_init_verbs; spec->spdif_route = 0; codec->patch_ops = ad198x_patch_ops; /* override some parameters */ board_config = snd_hda_check_board_config(codec, ad1981_cfg_tbl); switch (board_config) { case AD1981_HP: spec->mixers[0] = ad1981_hp_mixers; spec->num_init_verbs = 2; spec->init_verbs[1] = ad1981_hp_init_verbs; spec->multiout.dig_out_nid = 0; spec->input_mux = &ad1981_hp_capture_source; codec->patch_ops.init = ad1981_hp_init; codec->patch_ops.unsol_event = ad1981_hp_unsol_event; break; } return 0;}/* * AD1988 * * Output pins and routes * * Pin Mix Sel DAC (*) * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06 * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06 * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a * port-D 0x12 (mute/hp) <- 0x29 <- 04 * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a * port-F 0x16 (mute) <- 0x2a <- 06 * port-G 0x24 (mute) <- 0x27 <- 05 * port-H 0x25 (mute) <- 0x28 <- 0a * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06 * * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug. * * Input pins and routes * * pin boost mix input # / adc input # * port-A 0x11 -> 0x38 -> mix 2, ADC 0 * port-B 0x14 -> 0x39 -> mix 0, ADC 1 * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2 * port-D 0x12 -> 0x3d -> mix 3, ADC 8 * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4 * port-F 0x16 -> 0x3b -> mix 5, ADC 3 * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6 * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7 * * * DAC assignment * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03 * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03 * * Inputs of Analog Mix (0x20) * 0:Port-B (front mic) * 1:Port-C/G/H (line-in) * 2:Port-A * 3:Port-D (line-in/2) * 4:Port-E/G/H (mic-in) * 5:Port-F (mic2-in) * 6:CD * 7:Beep * * ADC selection * 0:Port-A * 1:Port-B (front mic-in) * 2:Port-C (line-in) * 3:Port-F (mic2-in) * 4:Port-E (mic-in) * 5:CD * 6:Port-G * 7:Port-H * 8:Port-D (line-in/2) * 9:Mix * * Proposed pin assignments by the datasheet * * 6-stack * Port-A front headphone * B front mic-in * C rear line-in * D rear front-out * E rear mic-in * F rear surround * G rear CLFE * H rear side * * 3-stack * Port-A front headphone * B front mic * C rear line-in/surround * D rear front-out * E rear mic-in/CLFE * * laptop * Port-A headphone * B mic-in * C docking station * D internal speaker (with EAPD) * E/F quad mic array *//* models */enum { AD1988_6STACK, AD1988_6STACK_DIG, AD1988_3STACK, AD1988_3STACK_DIG, AD1988_LAPTOP, AD1988_LAPTOP_DIG, AD1988_AUTO, AD1988_MODEL_LAST,};/* reivision id to check workarounds */#define AD1988A_REV2 0x100200#define is_rev2(codec) \ ((codec)->vendor_id == 0x11d41988 && \ (codec)->revision_id == AD1988A_REV2)/* * mixers */static hda_nid_t ad1988_6stack_dac_nids[4] = { 0x04, 0x06, 0x05, 0x0a};static hda_nid_t ad1988_3stack_dac_nids[3] = { 0x04, 0x05, 0x0a};/* for AD1988A revision-2, DAC2-4 are swapped */static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = { 0x04, 0x05, 0x0a, 0x06};static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = { 0x04, 0x0a, 0x06};static hda_nid_t ad1988_adc_nids[3] = { 0x08, 0x09, 0x0f};static hda_nid_t ad1988_capsrc_nids[3] = { 0x0c, 0x0d, 0x0e};#define AD1988_SPDIF_OUT 0x02#define AD1988_SPDIF_IN 0x07static struct hda_input_mux ad1988_6stack_capture_source = { .num_items = 5, .items = { { "Front Mic", 0x0 }, { "Line", 0x1 }, { "Mic", 0x4 }, { "CD", 0x5 }, { "Mix", 0x9 }, },};static struct hda_input_mux ad1988_laptop_capture_source = { .num_items = 3, .items = { { "Mic/Line", 0x0 }, { "CD", 0x5 }, { "Mix", 0x9 }, },};/* */static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct ad198x_spec *spec = codec->spec; return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, spec->num_channel_mode);}static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct ad198x_spec *spec = codec->spec; return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, spec->num_channel_mode, spec->multiout.max_channels);}static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct ad198x_spec *spec = codec->spec; if (spec->need_dac_fix) spec->multiout.num_dacs = spec->multiout.max_channels / 2; return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, spec->num_channel_mode, &spec->multiout.max_channels);}/* 6-stack mode */static struct snd_kcontrol_new ad1988_6stack_mixers1[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT), { } /* end */};static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT), { } /* end */};static struct snd_kcontrol_new ad1988_6stack_mixers2[] = { HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT), HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT), HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT), HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT), HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT), HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT), HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -