Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Universal Interface for Intel High Definition Audio Codec | |
3 | * | |
4 | * Local helper functions | |
5 | * | |
6 | * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify it | |
9 | * under the terms of the GNU General Public License as published by the Free | |
10 | * Software Foundation; either version 2 of the License, or (at your option) | |
11 | * any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
16 | * more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License along with | |
19 | * this program; if not, write to the Free Software Foundation, Inc., 59 | |
20 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
21 | */ | |
22 | ||
23 | #ifndef __SOUND_HDA_LOCAL_H | |
24 | #define __SOUND_HDA_LOCAL_H | |
25 | ||
26 | /* | |
27 | * for mixer controls | |
28 | */ | |
29 | #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19)) | |
985be54b | 30 | /* mono volume with index (index=0,1,...) (channel=1,2) */ |
1da177e4 LT |
31 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ |
32 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | |
302e9c5a JK |
33 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ |
34 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | |
35 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ | |
1da177e4 LT |
36 | .info = snd_hda_mixer_amp_volume_info, \ |
37 | .get = snd_hda_mixer_amp_volume_get, \ | |
38 | .put = snd_hda_mixer_amp_volume_put, \ | |
7cf0a953 | 39 | .tlv = { .c = snd_hda_mixer_amp_tlv }, \ |
1da177e4 | 40 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } |
985be54b | 41 | /* stereo volume with index */ |
1da177e4 LT |
42 | #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ |
43 | HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction) | |
985be54b | 44 | /* mono volume */ |
1da177e4 LT |
45 | #define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \ |
46 | HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction) | |
985be54b | 47 | /* stereo volume */ |
1da177e4 LT |
48 | #define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \ |
49 | HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction) | |
985be54b | 50 | /* mono mute switch with index (index=0,1,...) (channel=1,2) */ |
1da177e4 LT |
51 | #define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ |
52 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | |
53 | .info = snd_hda_mixer_amp_switch_info, \ | |
54 | .get = snd_hda_mixer_amp_switch_get, \ | |
55 | .put = snd_hda_mixer_amp_switch_put, \ | |
56 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } | |
985be54b | 57 | /* stereo mute switch with index */ |
1da177e4 LT |
58 | #define HDA_CODEC_MUTE_IDX(xname, xcidx, nid, xindex, direction) \ |
59 | HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, 3, xindex, direction) | |
985be54b | 60 | /* mono mute switch */ |
1da177e4 LT |
61 | #define HDA_CODEC_MUTE_MONO(xname, nid, channel, xindex, direction) \ |
62 | HDA_CODEC_MUTE_MONO_IDX(xname, 0, nid, channel, xindex, direction) | |
985be54b | 63 | /* stereo mute switch */ |
1da177e4 LT |
64 | #define HDA_CODEC_MUTE(xname, nid, xindex, direction) \ |
65 | HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction) | |
66 | ||
c8b6bf9b TI |
67 | int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); |
68 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | |
69 | int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | |
302e9c5a | 70 | int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *tlv); |
c8b6bf9b TI |
71 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); |
72 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | |
73 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | |
834be88d TI |
74 | /* lowlevel accessor with caching; use carefully */ |
75 | int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, | |
76 | int direction, int index); | |
77 | int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | |
78 | int direction, int idx, int mask, int val); | |
1da177e4 | 79 | |
985be54b TI |
80 | /* mono switch binding multiple inputs */ |
81 | #define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ | |
82 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | |
83 | .info = snd_hda_mixer_amp_switch_info, \ | |
84 | .get = snd_hda_mixer_bind_switch_get, \ | |
85 | .put = snd_hda_mixer_bind_switch_put, \ | |
86 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } | |
87 | ||
88 | /* stereo switch binding multiple inputs */ | |
89 | #define HDA_BIND_MUTE(xname,nid,indices,dir) HDA_BIND_MUTE_MONO(xname,nid,3,indices,dir) | |
90 | ||
c8b6bf9b TI |
91 | int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
92 | int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | |
985be54b | 93 | |
1da177e4 LT |
94 | int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid); |
95 | int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid); | |
96 | ||
97 | /* | |
98 | * input MUX helper | |
99 | */ | |
54d17403 | 100 | #define HDA_MAX_NUM_INPUTS 16 |
1da177e4 LT |
101 | struct hda_input_mux_item { |
102 | const char *label; | |
103 | unsigned int index; | |
104 | }; | |
105 | struct hda_input_mux { | |
106 | unsigned int num_items; | |
107 | struct hda_input_mux_item items[HDA_MAX_NUM_INPUTS]; | |
108 | }; | |
109 | ||
c8b6bf9b | 110 | int snd_hda_input_mux_info(const struct hda_input_mux *imux, struct snd_ctl_elem_info *uinfo); |
1da177e4 | 111 | int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *imux, |
c8b6bf9b | 112 | struct snd_ctl_elem_value *ucontrol, hda_nid_t nid, |
1da177e4 LT |
113 | unsigned int *cur_val); |
114 | ||
c8b6bf9b | 115 | /* |
d2a6d7dc TI |
116 | * Channel mode helper |
117 | */ | |
118 | struct hda_channel_mode { | |
119 | int channels; | |
120 | const struct hda_verb *sequence; | |
121 | }; | |
122 | ||
c8b6bf9b | 123 | int snd_hda_ch_mode_info(struct hda_codec *codec, struct snd_ctl_elem_info *uinfo, |
d2a6d7dc | 124 | const struct hda_channel_mode *chmode, int num_chmodes); |
c8b6bf9b | 125 | int snd_hda_ch_mode_get(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol, |
d2a6d7dc TI |
126 | const struct hda_channel_mode *chmode, int num_chmodes, |
127 | int max_channels); | |
c8b6bf9b | 128 | int snd_hda_ch_mode_put(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol, |
d2a6d7dc TI |
129 | const struct hda_channel_mode *chmode, int num_chmodes, |
130 | int *max_channelsp); | |
131 | ||
1da177e4 LT |
132 | /* |
133 | * Multi-channel / digital-out PCM helper | |
134 | */ | |
135 | ||
136 | enum { HDA_FRONT, HDA_REAR, HDA_CLFE, HDA_SIDE }; /* index for dac_nidx */ | |
137 | enum { HDA_DIG_NONE, HDA_DIG_EXCLUSIVE, HDA_DIG_ANALOG_DUP }; /* dig_out_used */ | |
138 | ||
139 | struct hda_multi_out { | |
140 | int num_dacs; /* # of DACs, must be more than 1 */ | |
141 | hda_nid_t *dac_nids; /* DAC list */ | |
142 | hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */ | |
82bc955f | 143 | hda_nid_t extra_out_nid[3]; /* optional DACs, 0 when not exists */ |
1da177e4 LT |
144 | hda_nid_t dig_out_nid; /* digital out audio widget */ |
145 | int max_channels; /* currently supported analog channels */ | |
146 | int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ | |
147 | }; | |
148 | ||
149 | int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout); | |
150 | int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout); | |
6b97eb45 TI |
151 | int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, |
152 | struct hda_multi_out *mout, | |
153 | unsigned int stream_tag, | |
154 | unsigned int format, | |
155 | struct snd_pcm_substream *substream); | |
1da177e4 | 156 | int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout, |
c8b6bf9b | 157 | struct snd_pcm_substream *substream); |
1da177e4 LT |
158 | int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout, |
159 | unsigned int stream_tag, | |
160 | unsigned int format, | |
c8b6bf9b | 161 | struct snd_pcm_substream *substream); |
1da177e4 LT |
162 | int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_out *mout); |
163 | ||
164 | /* | |
165 | * generic codec parser | |
166 | */ | |
167 | int snd_hda_parse_generic_codec(struct hda_codec *codec); | |
168 | ||
169 | /* | |
170 | * generic proc interface | |
171 | */ | |
172 | #ifdef CONFIG_PROC_FS | |
173 | int snd_hda_codec_proc_new(struct hda_codec *codec); | |
174 | #else | |
175 | static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; } | |
176 | #endif | |
177 | ||
178 | /* | |
179 | * Misc | |
180 | */ | |
f5fcc13c TI |
181 | int snd_hda_check_board_config(struct hda_codec *codec, int num_configs, |
182 | const char **modelnames, | |
183 | const struct snd_pci_quirk *pci_list); | |
c8b6bf9b | 184 | int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew); |
1da177e4 LT |
185 | |
186 | /* | |
187 | * power management | |
188 | */ | |
189 | #ifdef CONFIG_PM | |
c8b6bf9b | 190 | int snd_hda_resume_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew); |
1da177e4 LT |
191 | int snd_hda_resume_spdif_out(struct hda_codec *codec); |
192 | int snd_hda_resume_spdif_in(struct hda_codec *codec); | |
193 | #endif | |
194 | ||
195 | /* | |
196 | * unsolicited event handler | |
197 | */ | |
198 | ||
199 | #define HDA_UNSOL_QUEUE_SIZE 64 | |
200 | ||
201 | struct hda_bus_unsolicited { | |
202 | /* ring buffer */ | |
203 | u32 queue[HDA_UNSOL_QUEUE_SIZE * 2]; | |
204 | unsigned int rp, wp; | |
205 | ||
206 | /* workqueue */ | |
1da177e4 | 207 | struct work_struct work; |
c4028958 | 208 | struct hda_bus *bus; |
1da177e4 LT |
209 | }; |
210 | ||
e9edcee0 TI |
211 | /* |
212 | * Helper for automatic ping configuration | |
213 | */ | |
214 | ||
215 | enum { | |
216 | AUTO_PIN_MIC, | |
217 | AUTO_PIN_FRONT_MIC, | |
218 | AUTO_PIN_LINE, | |
219 | AUTO_PIN_FRONT_LINE, | |
220 | AUTO_PIN_CD, | |
221 | AUTO_PIN_AUX, | |
222 | AUTO_PIN_LAST | |
223 | }; | |
224 | ||
d258e24a TI |
225 | enum { |
226 | AUTO_PIN_LINE_OUT, | |
227 | AUTO_PIN_SPEAKER_OUT, | |
228 | AUTO_PIN_HP_OUT | |
229 | }; | |
230 | ||
4a471b7d TI |
231 | extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST]; |
232 | ||
e9edcee0 TI |
233 | struct auto_pin_cfg { |
234 | int line_outs; | |
df694daa | 235 | hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ |
82bc955f TI |
236 | int speaker_outs; |
237 | hda_nid_t speaker_pins[5]; | |
eb06ed8f | 238 | int hp_outs; |
d258e24a | 239 | int line_out_type; /* AUTO_PIN_XXX_OUT */ |
eb06ed8f | 240 | hda_nid_t hp_pins[5]; |
e9edcee0 TI |
241 | hda_nid_t input_pins[AUTO_PIN_LAST]; |
242 | hda_nid_t dig_out_pin; | |
243 | hda_nid_t dig_in_pin; | |
244 | }; | |
245 | ||
246 | #define get_defcfg_connect(cfg) ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) | |
247 | #define get_defcfg_association(cfg) ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT) | |
248 | #define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) | |
249 | #define get_defcfg_sequence(cfg) (cfg & AC_DEFCFG_SEQUENCE) | |
250 | #define get_defcfg_device(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) | |
251 | ||
df694daa KY |
252 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg, |
253 | hda_nid_t *ignore_nids); | |
e9edcee0 | 254 | |
8d88bc3d TI |
255 | /* amp values */ |
256 | #define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8)) | |
257 | #define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8)) | |
258 | #define AMP_OUT_MUTE 0xb080 | |
259 | #define AMP_OUT_UNMUTE 0xb000 | |
260 | #define AMP_OUT_ZERO 0xb000 | |
261 | /* pinctl values */ | |
262 | #define PIN_IN 0x20 | |
263 | #define PIN_VREF80 0x24 | |
264 | #define PIN_VREF50 0x21 | |
265 | #define PIN_OUT 0x40 | |
266 | #define PIN_HP 0xc0 | |
267 | #define PIN_HP_AMP 0x80 | |
268 | ||
54d17403 TI |
269 | /* |
270 | * get widget capabilities | |
271 | */ | |
272 | static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid) | |
273 | { | |
274 | if (nid < codec->start_nid || | |
275 | nid >= codec->start_nid + codec->num_nodes) | |
276 | return snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); | |
277 | return codec->wcaps[nid - codec->start_nid]; | |
278 | } | |
279 | ||
897cc188 TI |
280 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, |
281 | unsigned int caps); | |
54d17403 | 282 | |
1da177e4 | 283 | #endif /* __SOUND_HDA_LOCAL_H */ |