1352f7f91STakashi Iwai /* 2352f7f91STakashi Iwai * Generic BIOS auto-parser helper functions for HD-audio 3352f7f91STakashi Iwai * 4352f7f91STakashi Iwai * Copyright (c) 2012 Takashi Iwai <tiwai@suse.de> 5352f7f91STakashi Iwai * 6352f7f91STakashi Iwai * This driver is free software; you can redistribute it and/or modify 7352f7f91STakashi Iwai * it under the terms of the GNU General Public License as published by 8352f7f91STakashi Iwai * the Free Software Foundation; either version 2 of the License, or 9352f7f91STakashi Iwai * (at your option) any later version. 10352f7f91STakashi Iwai */ 11352f7f91STakashi Iwai 12352f7f91STakashi Iwai #ifndef __SOUND_HDA_GENERIC_H 13352f7f91STakashi Iwai #define __SOUND_HDA_GENERIC_H 14352f7f91STakashi Iwai 15352f7f91STakashi Iwai /* unsol event tags */ 16352f7f91STakashi Iwai enum { 17406b285dSTakashi Iwai HDA_GEN_HP_EVENT = 1, HDA_GEN_FRONT_EVENT, HDA_GEN_MIC_EVENT, 18352f7f91STakashi Iwai HDA_GEN_LAST_EVENT = HDA_GEN_MIC_EVENT 19352f7f91STakashi Iwai }; 20352f7f91STakashi Iwai 21352f7f91STakashi Iwai /* table entry for multi-io paths */ 22352f7f91STakashi Iwai struct hda_multi_io { 23352f7f91STakashi Iwai hda_nid_t pin; /* multi-io widget pin NID */ 24352f7f91STakashi Iwai hda_nid_t dac; /* DAC to be connected */ 25352f7f91STakashi Iwai unsigned int ctl_in; /* cached input-pin control value */ 26352f7f91STakashi Iwai }; 27352f7f91STakashi Iwai 28352f7f91STakashi Iwai /* Widget connection path 29352f7f91STakashi Iwai * 30352f7f91STakashi Iwai * For output, stored in the order of DAC -> ... -> pin, 31352f7f91STakashi Iwai * for input, pin -> ... -> ADC. 32352f7f91STakashi Iwai * 33352f7f91STakashi Iwai * idx[i] contains the source index number to select on of the widget path[i]; 34352f7f91STakashi Iwai * e.g. idx[1] is the index of the DAC (path[0]) selected by path[1] widget 35352f7f91STakashi Iwai * multi[] indicates whether it's a selector widget with multi-connectors 36352f7f91STakashi Iwai * (i.e. the connection selection is mandatory) 37352f7f91STakashi Iwai * vol_ctl and mute_ctl contains the NIDs for the assigned mixers 38352f7f91STakashi Iwai */ 39352f7f91STakashi Iwai 40d94ddd85STakashi Iwai #define MAX_NID_PATH_DEPTH 10 41352f7f91STakashi Iwai 42352f7f91STakashi Iwai enum { 43352f7f91STakashi Iwai NID_PATH_VOL_CTL, 44352f7f91STakashi Iwai NID_PATH_MUTE_CTL, 45352f7f91STakashi Iwai NID_PATH_BOOST_CTL, 46352f7f91STakashi Iwai NID_PATH_NUM_CTLS 47352f7f91STakashi Iwai }; 48352f7f91STakashi Iwai 49352f7f91STakashi Iwai struct nid_path { 50352f7f91STakashi Iwai int depth; 51352f7f91STakashi Iwai hda_nid_t path[MAX_NID_PATH_DEPTH]; 52352f7f91STakashi Iwai unsigned char idx[MAX_NID_PATH_DEPTH]; 53352f7f91STakashi Iwai unsigned char multi[MAX_NID_PATH_DEPTH]; 54352f7f91STakashi Iwai unsigned int ctls[NID_PATH_NUM_CTLS]; /* NID_PATH_XXX_CTL */ 55352f7f91STakashi Iwai bool active; 56f5172a7eSTakashi Iwai bool with_aa_mix; 57352f7f91STakashi Iwai }; 58352f7f91STakashi Iwai 59352f7f91STakashi Iwai /* mic/line-in auto switching entry */ 60352f7f91STakashi Iwai 61352f7f91STakashi Iwai #define MAX_AUTO_MIC_PINS 3 62352f7f91STakashi Iwai 63352f7f91STakashi Iwai struct automic_entry { 64352f7f91STakashi Iwai hda_nid_t pin; /* pin */ 65352f7f91STakashi Iwai int idx; /* imux index, -1 = invalid */ 66352f7f91STakashi Iwai unsigned int attr; /* pin attribute (INPUT_PIN_ATTR_*) */ 67352f7f91STakashi Iwai }; 68352f7f91STakashi Iwai 6938cf6f1aSTakashi Iwai /* active stream id */ 7038cf6f1aSTakashi Iwai enum { STREAM_MULTI_OUT, STREAM_INDEP_HP }; 7138cf6f1aSTakashi Iwai 72*e6b85f3cSTakashi Iwai /* PCM hook action */ 73*e6b85f3cSTakashi Iwai enum { 74*e6b85f3cSTakashi Iwai HDA_GEN_PCM_ACT_OPEN, 75*e6b85f3cSTakashi Iwai HDA_GEN_PCM_ACT_PREPARE, 76*e6b85f3cSTakashi Iwai HDA_GEN_PCM_ACT_CLEANUP, 77*e6b85f3cSTakashi Iwai HDA_GEN_PCM_ACT_CLOSE, 78*e6b85f3cSTakashi Iwai }; 79*e6b85f3cSTakashi Iwai 80352f7f91STakashi Iwai struct hda_gen_spec { 81352f7f91STakashi Iwai char stream_name_analog[32]; /* analog PCM stream */ 82352f7f91STakashi Iwai const struct hda_pcm_stream *stream_analog_playback; 83352f7f91STakashi Iwai const struct hda_pcm_stream *stream_analog_capture; 84352f7f91STakashi Iwai const struct hda_pcm_stream *stream_analog_alt_playback; 85352f7f91STakashi Iwai const struct hda_pcm_stream *stream_analog_alt_capture; 86352f7f91STakashi Iwai 87352f7f91STakashi Iwai char stream_name_digital[32]; /* digital PCM stream */ 88352f7f91STakashi Iwai const struct hda_pcm_stream *stream_digital_playback; 89352f7f91STakashi Iwai const struct hda_pcm_stream *stream_digital_capture; 90352f7f91STakashi Iwai 9138cf6f1aSTakashi Iwai /* PCM */ 9238cf6f1aSTakashi Iwai unsigned int active_streams; 9338cf6f1aSTakashi Iwai struct mutex pcm_mutex; 9438cf6f1aSTakashi Iwai 95352f7f91STakashi Iwai /* playback */ 96352f7f91STakashi Iwai struct hda_multi_out multiout; /* playback set-up 97352f7f91STakashi Iwai * max_channels, dacs must be set 98352f7f91STakashi Iwai * dig_out_nid and hp_nid are optional 99352f7f91STakashi Iwai */ 100352f7f91STakashi Iwai hda_nid_t alt_dac_nid; 101352f7f91STakashi Iwai hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */ 102352f7f91STakashi Iwai int dig_out_type; 103352f7f91STakashi Iwai 104352f7f91STakashi Iwai /* capture */ 105352f7f91STakashi Iwai unsigned int num_adc_nids; 106352f7f91STakashi Iwai hda_nid_t adc_nids[AUTO_CFG_MAX_OUTS]; 107352f7f91STakashi Iwai hda_nid_t dig_in_nid; /* digital-in NID; optional */ 108352f7f91STakashi Iwai hda_nid_t mixer_nid; /* analog-mixer NID */ 109352f7f91STakashi Iwai 110352f7f91STakashi Iwai /* capture setup for dynamic dual-adc switch */ 111352f7f91STakashi Iwai hda_nid_t cur_adc; 112352f7f91STakashi Iwai unsigned int cur_adc_stream_tag; 113352f7f91STakashi Iwai unsigned int cur_adc_format; 114352f7f91STakashi Iwai 115352f7f91STakashi Iwai /* capture source */ 116352f7f91STakashi Iwai struct hda_input_mux input_mux; 117352f7f91STakashi Iwai unsigned int cur_mux[3]; 118352f7f91STakashi Iwai 119352f7f91STakashi Iwai /* channel model */ 120352f7f91STakashi Iwai int const_channel_count; /* min. channel count (for speakers) */ 121352f7f91STakashi Iwai int ext_channel_count; /* current channel count for multi-io */ 122352f7f91STakashi Iwai 123352f7f91STakashi Iwai /* PCM information */ 124352f7f91STakashi Iwai struct hda_pcm pcm_rec[3]; /* used in build_pcms() */ 125352f7f91STakashi Iwai 126352f7f91STakashi Iwai /* dynamic controls, init_verbs and input_mux */ 127352f7f91STakashi Iwai struct auto_pin_cfg autocfg; 128352f7f91STakashi Iwai struct snd_array kctls; 129352f7f91STakashi Iwai hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; 130352f7f91STakashi Iwai hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS]; 131352f7f91STakashi Iwai unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS]; 132352f7f91STakashi Iwai hda_nid_t shared_mic_vref_pin; 133352f7f91STakashi Iwai 134352f7f91STakashi Iwai /* DAC list */ 135352f7f91STakashi Iwai int num_all_dacs; 136352f7f91STakashi Iwai hda_nid_t all_dacs[16]; 137352f7f91STakashi Iwai 138352f7f91STakashi Iwai /* path list */ 139352f7f91STakashi Iwai struct snd_array paths; 140352f7f91STakashi Iwai 141196c1766STakashi Iwai /* path indices */ 142196c1766STakashi Iwai int out_paths[AUTO_CFG_MAX_OUTS]; 143196c1766STakashi Iwai int hp_paths[AUTO_CFG_MAX_OUTS]; 144196c1766STakashi Iwai int speaker_paths[AUTO_CFG_MAX_OUTS]; 145c30aa7b2STakashi Iwai int aamix_out_paths[3]; 146196c1766STakashi Iwai int digout_paths[AUTO_CFG_MAX_OUTS]; 147196c1766STakashi Iwai int loopback_paths[HDA_MAX_NUM_INPUTS]; 1482430d7b7STakashi Iwai int digin_path; 149196c1766STakashi Iwai 150352f7f91STakashi Iwai /* auto-mic stuff */ 151352f7f91STakashi Iwai int am_num_entries; 152352f7f91STakashi Iwai struct automic_entry am_entry[MAX_AUTO_MIC_PINS]; 153352f7f91STakashi Iwai 154352f7f91STakashi Iwai /* for pin sensing */ 155352f7f91STakashi Iwai unsigned int hp_jack_present:1; 156352f7f91STakashi Iwai unsigned int line_jack_present:1; 157352f7f91STakashi Iwai unsigned int master_mute:1; 158352f7f91STakashi Iwai unsigned int auto_mic:1; 159352f7f91STakashi Iwai unsigned int automute_speaker:1; /* automute speaker outputs */ 160352f7f91STakashi Iwai unsigned int automute_lo:1; /* automute LO outputs */ 161352f7f91STakashi Iwai unsigned int detect_hp:1; /* Headphone detection enabled */ 162352f7f91STakashi Iwai unsigned int detect_lo:1; /* Line-out detection enabled */ 163352f7f91STakashi Iwai unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */ 164352f7f91STakashi Iwai unsigned int automute_lo_possible:1; /* there are line outs and HP */ 165352f7f91STakashi Iwai unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */ 166352f7f91STakashi Iwai unsigned int line_in_auto_switch:1; /* allow line-in auto switch */ 167352f7f91STakashi Iwai 168352f7f91STakashi Iwai /* other flags */ 169352f7f91STakashi Iwai unsigned int need_dac_fix:1; /* need to limit DACs for multi channels */ 170352f7f91STakashi Iwai unsigned int no_analog:1; /* digital I/O only */ 171352f7f91STakashi Iwai unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */ 172352f7f91STakashi Iwai unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ 173352f7f91STakashi Iwai unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */ 174352f7f91STakashi Iwai unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */ 175352f7f91STakashi Iwai unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */ 176731dc301STakashi Iwai unsigned int own_eapd_ctl:1; /* set EAPD by own function */ 177fd25a97aSTakashi Iwai unsigned int vmaster_mute_enum:1; /* add vmaster mute mode enum */ 17838cf6f1aSTakashi Iwai unsigned int indep_hp:1; /* independent HP supported */ 17938cf6f1aSTakashi Iwai unsigned int indep_hp_enabled:1; /* independent HP enabled */ 180352f7f91STakashi Iwai 181c30aa7b2STakashi Iwai /* loopback mixing mode */ 182c30aa7b2STakashi Iwai bool aamix_mode; 183c30aa7b2STakashi Iwai 184352f7f91STakashi Iwai /* for virtual master */ 185352f7f91STakashi Iwai hda_nid_t vmaster_nid; 186352f7f91STakashi Iwai struct hda_vmaster_mute_hook vmaster_mute; 187352f7f91STakashi Iwai #ifdef CONFIG_PM 188352f7f91STakashi Iwai struct hda_loopback_check loopback; 189352f7f91STakashi Iwai int num_loopbacks; 190352f7f91STakashi Iwai struct hda_amp_list loopback_list[8]; 191352f7f91STakashi Iwai #endif 192352f7f91STakashi Iwai 193352f7f91STakashi Iwai /* multi-io */ 194352f7f91STakashi Iwai int multi_ios; 195352f7f91STakashi Iwai struct hda_multi_io multi_io[4]; 196352f7f91STakashi Iwai 197352f7f91STakashi Iwai /* hooks */ 198352f7f91STakashi Iwai void (*init_hook)(struct hda_codec *codec); 199352f7f91STakashi Iwai void (*automute_hook)(struct hda_codec *codec); 200352f7f91STakashi Iwai void (*cap_sync_hook)(struct hda_codec *codec); 2012e03e952STakashi Iwai 202*e6b85f3cSTakashi Iwai /* PCM playback hook */ 203*e6b85f3cSTakashi Iwai void (*pcm_playback_hook)(struct hda_pcm_stream *hinfo, 204*e6b85f3cSTakashi Iwai struct hda_codec *codec, 205*e6b85f3cSTakashi Iwai struct snd_pcm_substream *substream, 206*e6b85f3cSTakashi Iwai int action); 207*e6b85f3cSTakashi Iwai 2082e03e952STakashi Iwai /* automute / autoswitch hooks */ 2092e03e952STakashi Iwai void (*hp_automute_hook)(struct hda_codec *codec, 2102e03e952STakashi Iwai struct hda_jack_tbl *tbl); 2112e03e952STakashi Iwai void (*line_automute_hook)(struct hda_codec *codec, 2122e03e952STakashi Iwai struct hda_jack_tbl *tbl); 2132e03e952STakashi Iwai void (*mic_autoswitch_hook)(struct hda_codec *codec, 2142e03e952STakashi Iwai struct hda_jack_tbl *tbl); 215352f7f91STakashi Iwai }; 216352f7f91STakashi Iwai 217352f7f91STakashi Iwai int snd_hda_gen_spec_init(struct hda_gen_spec *spec); 218352f7f91STakashi Iwai void snd_hda_gen_spec_free(struct hda_gen_spec *spec); 219352f7f91STakashi Iwai 220352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec); 221352f7f91STakashi Iwai 222352f7f91STakashi Iwai struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec, 223352f7f91STakashi Iwai hda_nid_t from_nid, hda_nid_t to_nid); 224196c1766STakashi Iwai int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path); 225196c1766STakashi Iwai struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx); 2264ac0eefaSTakashi Iwai 2274ac0eefaSTakashi Iwai enum { 2284ac0eefaSTakashi Iwai HDA_PARSE_NO_AAMIX, 2294ac0eefaSTakashi Iwai HDA_PARSE_ONLY_AAMIX, 2304ac0eefaSTakashi Iwai HDA_PARSE_ALL, 2314ac0eefaSTakashi Iwai }; 2324ac0eefaSTakashi Iwai 233352f7f91STakashi Iwai bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid, 234352f7f91STakashi Iwai hda_nid_t to_nid, int with_aa_mix, 235352f7f91STakashi Iwai struct nid_path *path); 236352f7f91STakashi Iwai struct nid_path * 237352f7f91STakashi Iwai snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid, 238352f7f91STakashi Iwai hda_nid_t to_nid, int with_aa_mix); 239352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path, 240352f7f91STakashi Iwai bool enable, bool add_aamix); 241352f7f91STakashi Iwai 24212c93df6STakashi Iwai struct snd_kcontrol_new * 24312c93df6STakashi Iwai snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name, 24412c93df6STakashi Iwai const struct snd_kcontrol_new *temp); 24512c93df6STakashi Iwai 246352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec, 2479eb413e5STakashi Iwai struct auto_pin_cfg *cfg); 248352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec); 249352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec); 250352f7f91STakashi Iwai 2515d550e15STakashi Iwai /* standard jack event callbacks */ 2525d550e15STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec, 2535d550e15STakashi Iwai struct hda_jack_tbl *jack); 2545d550e15STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec, 2555d550e15STakashi Iwai struct hda_jack_tbl *jack); 2565d550e15STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, 2575d550e15STakashi Iwai struct hda_jack_tbl *jack); 2585d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec); 2595d550e15STakashi Iwai 260352f7f91STakashi Iwai #endif /* __SOUND_HDA_GENERIC_H */ 261