| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | */ | 
| Takashi Iwai | d01ce99 | 2007-07-27 16:52:19 +0200 | [diff] [blame] | 29 | #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ | 
|  | 30 | ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19)) | 
| Takashi Iwai | 985be54 | 2005-11-02 18:26:49 +0100 | [diff] [blame] | 31 | /* mono volume with index (index=0,1,...) (channel=1,2) */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 32 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 
|  | 33 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx,  \ | 
| Jaroslav Kysela | 302e9c5 | 2006-07-05 17:39:49 +0200 | [diff] [blame] | 34 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | 
|  | 35 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | 
|  | 36 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 37 | .info = snd_hda_mixer_amp_volume_info, \ | 
|  | 38 | .get = snd_hda_mixer_amp_volume_get, \ | 
|  | 39 | .put = snd_hda_mixer_amp_volume_put, \ | 
| Takashi Iwai | 7cf0a95 | 2006-08-17 16:23:07 +0200 | [diff] [blame] | 40 | .tlv = { .c = snd_hda_mixer_amp_tlv },		\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 41 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } | 
| Takashi Iwai | 985be54 | 2005-11-02 18:26:49 +0100 | [diff] [blame] | 42 | /* stereo volume with index */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 43 | #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ | 
|  | 44 | HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction) | 
| Takashi Iwai | 985be54 | 2005-11-02 18:26:49 +0100 | [diff] [blame] | 45 | /* mono volume */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 46 | #define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \ | 
|  | 47 | HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction) | 
| Takashi Iwai | 985be54 | 2005-11-02 18:26:49 +0100 | [diff] [blame] | 48 | /* stereo volume */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 49 | #define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \ | 
|  | 50 | HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction) | 
| Takashi Iwai | 985be54 | 2005-11-02 18:26:49 +0100 | [diff] [blame] | 51 | /* mono mute switch with index (index=0,1,...) (channel=1,2) */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 52 | #define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 
|  | 53 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 
|  | 54 | .info = snd_hda_mixer_amp_switch_info, \ | 
|  | 55 | .get = snd_hda_mixer_amp_switch_get, \ | 
|  | 56 | .put = snd_hda_mixer_amp_switch_put, \ | 
|  | 57 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } | 
| Takashi Iwai | 985be54 | 2005-11-02 18:26:49 +0100 | [diff] [blame] | 58 | /* stereo mute switch with index */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 59 | #define HDA_CODEC_MUTE_IDX(xname, xcidx, nid, xindex, direction) \ | 
|  | 60 | HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, 3, xindex, direction) | 
| Takashi Iwai | 985be54 | 2005-11-02 18:26:49 +0100 | [diff] [blame] | 61 | /* mono mute switch */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 62 | #define HDA_CODEC_MUTE_MONO(xname, nid, channel, xindex, direction) \ | 
|  | 63 | HDA_CODEC_MUTE_MONO_IDX(xname, 0, nid, channel, xindex, direction) | 
| Takashi Iwai | 985be54 | 2005-11-02 18:26:49 +0100 | [diff] [blame] | 64 | /* stereo mute switch */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 65 | #define HDA_CODEC_MUTE(xname, nid, xindex, direction) \ | 
|  | 66 | HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction) | 
|  | 67 |  | 
| Takashi Iwai | d01ce99 | 2007-07-27 16:52:19 +0200 | [diff] [blame] | 68 | int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, | 
|  | 69 | struct snd_ctl_elem_info *uinfo); | 
|  | 70 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, | 
|  | 71 | struct snd_ctl_elem_value *ucontrol); | 
|  | 72 | int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, | 
|  | 73 | struct snd_ctl_elem_value *ucontrol); | 
|  | 74 | int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | 
|  | 75 | unsigned int size, unsigned int __user *tlv); | 
|  | 76 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, | 
|  | 77 | struct snd_ctl_elem_info *uinfo); | 
|  | 78 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, | 
|  | 79 | struct snd_ctl_elem_value *ucontrol); | 
|  | 80 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | 
|  | 81 | struct snd_ctl_elem_value *ucontrol); | 
| Takashi Iwai | 834be88 | 2006-03-01 14:16:17 +0100 | [diff] [blame] | 82 | /* lowlevel accessor with caching; use carefully */ | 
|  | 83 | int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, | 
|  | 84 | int direction, int index); | 
|  | 85 | int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | 
|  | 86 | int direction, int idx, int mask, int val); | 
| Takashi Iwai | 47fd830 | 2007-08-10 17:11:07 +0200 | [diff] [blame] | 87 | int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | 
|  | 88 | int dir, int idx, int mask, int val); | 
| Takashi Iwai | cb53c62 | 2007-08-10 17:21:45 +0200 | [diff] [blame] | 89 | #ifdef SND_HDA_NEEDS_RESUME | 
| Takashi Iwai | b3ac563 | 2007-08-10 17:03:40 +0200 | [diff] [blame] | 90 | void snd_hda_codec_resume_amp(struct hda_codec *codec); | 
| Takashi Iwai | 82beb8f | 2007-08-10 17:09:26 +0200 | [diff] [blame] | 91 | #endif | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 92 |  | 
| Takashi Iwai | 2134ea4 | 2008-01-10 16:53:55 +0100 | [diff] [blame] | 93 | void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, | 
|  | 94 | unsigned int *tlv); | 
|  | 95 | struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | 
|  | 96 | const char *name); | 
|  | 97 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 
|  | 98 | unsigned int *tlv, const char **slaves); | 
|  | 99 |  | 
| Takashi Iwai | 47fd830 | 2007-08-10 17:11:07 +0200 | [diff] [blame] | 100 | /* amp value bits */ | 
|  | 101 | #define HDA_AMP_MUTE	0x80 | 
|  | 102 | #define HDA_AMP_UNMUTE	0x00 | 
|  | 103 | #define HDA_AMP_VOLMASK	0x7f | 
|  | 104 |  | 
| Takashi Iwai | 985be54 | 2005-11-02 18:26:49 +0100 | [diff] [blame] | 105 | /* mono switch binding multiple inputs */ | 
|  | 106 | #define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ | 
|  | 107 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \ | 
|  | 108 | .info = snd_hda_mixer_amp_switch_info, \ | 
|  | 109 | .get = snd_hda_mixer_bind_switch_get, \ | 
|  | 110 | .put = snd_hda_mixer_bind_switch_put, \ | 
|  | 111 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } | 
|  | 112 |  | 
|  | 113 | /* stereo switch binding multiple inputs */ | 
| Takashi Iwai | d01ce99 | 2007-07-27 16:52:19 +0200 | [diff] [blame] | 114 | #define HDA_BIND_MUTE(xname,nid,indices,dir) \ | 
|  | 115 | HDA_BIND_MUTE_MONO(xname,nid,3,indices,dir) | 
| Takashi Iwai | 985be54 | 2005-11-02 18:26:49 +0100 | [diff] [blame] | 116 |  | 
| Takashi Iwai | d01ce99 | 2007-07-27 16:52:19 +0200 | [diff] [blame] | 117 | int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, | 
|  | 118 | struct snd_ctl_elem_value *ucontrol); | 
|  | 119 | int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, | 
|  | 120 | struct snd_ctl_elem_value *ucontrol); | 
| Takashi Iwai | 985be54 | 2005-11-02 18:26:49 +0100 | [diff] [blame] | 121 |  | 
| Takashi Iwai | 532d538 | 2007-07-27 19:02:40 +0200 | [diff] [blame] | 122 | /* more generic bound controls */ | 
|  | 123 | struct hda_ctl_ops { | 
|  | 124 | snd_kcontrol_info_t *info; | 
|  | 125 | snd_kcontrol_get_t *get; | 
|  | 126 | snd_kcontrol_put_t *put; | 
|  | 127 | snd_kcontrol_tlv_rw_t *tlv; | 
|  | 128 | }; | 
|  | 129 |  | 
|  | 130 | extern struct hda_ctl_ops snd_hda_bind_vol;	/* for bind-volume with TLV */ | 
|  | 131 | extern struct hda_ctl_ops snd_hda_bind_sw;	/* for bind-switch */ | 
|  | 132 |  | 
|  | 133 | struct hda_bind_ctls { | 
|  | 134 | struct hda_ctl_ops *ops; | 
|  | 135 | long values[]; | 
|  | 136 | }; | 
|  | 137 |  | 
|  | 138 | int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, | 
|  | 139 | struct snd_ctl_elem_info *uinfo); | 
|  | 140 | int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, | 
|  | 141 | struct snd_ctl_elem_value *ucontrol); | 
|  | 142 | int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, | 
|  | 143 | struct snd_ctl_elem_value *ucontrol); | 
|  | 144 | int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, | 
|  | 145 | unsigned int size, unsigned int __user *tlv); | 
|  | 146 |  | 
|  | 147 | #define HDA_BIND_VOL(xname, bindrec) \ | 
|  | 148 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 
|  | 149 | .name = xname, \ | 
|  | 150 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | 
|  | 151 | SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | 
|  | 152 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,\ | 
|  | 153 | .info = snd_hda_mixer_bind_ctls_info,\ | 
|  | 154 | .get =  snd_hda_mixer_bind_ctls_get,\ | 
|  | 155 | .put = snd_hda_mixer_bind_ctls_put,\ | 
|  | 156 | .tlv = { .c = snd_hda_mixer_bind_tlv },\ | 
|  | 157 | .private_value = (long) (bindrec) } | 
|  | 158 | #define HDA_BIND_SW(xname, bindrec) \ | 
|  | 159 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ | 
|  | 160 | .name = xname, \ | 
|  | 161 | .info = snd_hda_mixer_bind_ctls_info,\ | 
|  | 162 | .get =  snd_hda_mixer_bind_ctls_get,\ | 
|  | 163 | .put = snd_hda_mixer_bind_ctls_put,\ | 
|  | 164 | .private_value = (long) (bindrec) } | 
|  | 165 |  | 
|  | 166 | /* | 
|  | 167 | * SPDIF I/O | 
|  | 168 | */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 169 | int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid); | 
|  | 170 | int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid); | 
|  | 171 |  | 
|  | 172 | /* | 
|  | 173 | * input MUX helper | 
|  | 174 | */ | 
| Takashi Iwai | 54d1740 | 2005-11-21 16:33:22 +0100 | [diff] [blame] | 175 | #define HDA_MAX_NUM_INPUTS	16 | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 176 | struct hda_input_mux_item { | 
|  | 177 | const char *label; | 
|  | 178 | unsigned int index; | 
|  | 179 | }; | 
|  | 180 | struct hda_input_mux { | 
|  | 181 | unsigned int num_items; | 
|  | 182 | struct hda_input_mux_item items[HDA_MAX_NUM_INPUTS]; | 
|  | 183 | }; | 
|  | 184 |  | 
| Takashi Iwai | d01ce99 | 2007-07-27 16:52:19 +0200 | [diff] [blame] | 185 | int snd_hda_input_mux_info(const struct hda_input_mux *imux, | 
|  | 186 | struct snd_ctl_elem_info *uinfo); | 
|  | 187 | int snd_hda_input_mux_put(struct hda_codec *codec, | 
|  | 188 | const struct hda_input_mux *imux, | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 189 | struct snd_ctl_elem_value *ucontrol, hda_nid_t nid, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 190 | unsigned int *cur_val); | 
|  | 191 |  | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 192 | /* | 
| Takashi Iwai | d2a6d7d | 2005-11-17 11:06:29 +0100 | [diff] [blame] | 193 | * Channel mode helper | 
|  | 194 | */ | 
|  | 195 | struct hda_channel_mode { | 
|  | 196 | int channels; | 
|  | 197 | const struct hda_verb *sequence; | 
|  | 198 | }; | 
|  | 199 |  | 
| Takashi Iwai | d01ce99 | 2007-07-27 16:52:19 +0200 | [diff] [blame] | 200 | int snd_hda_ch_mode_info(struct hda_codec *codec, | 
|  | 201 | struct snd_ctl_elem_info *uinfo, | 
|  | 202 | const struct hda_channel_mode *chmode, | 
|  | 203 | int num_chmodes); | 
|  | 204 | int snd_hda_ch_mode_get(struct hda_codec *codec, | 
|  | 205 | struct snd_ctl_elem_value *ucontrol, | 
|  | 206 | const struct hda_channel_mode *chmode, | 
|  | 207 | int num_chmodes, | 
| Takashi Iwai | d2a6d7d | 2005-11-17 11:06:29 +0100 | [diff] [blame] | 208 | int max_channels); | 
| Takashi Iwai | d01ce99 | 2007-07-27 16:52:19 +0200 | [diff] [blame] | 209 | int snd_hda_ch_mode_put(struct hda_codec *codec, | 
|  | 210 | struct snd_ctl_elem_value *ucontrol, | 
|  | 211 | const struct hda_channel_mode *chmode, | 
|  | 212 | int num_chmodes, | 
| Takashi Iwai | d2a6d7d | 2005-11-17 11:06:29 +0100 | [diff] [blame] | 213 | int *max_channelsp); | 
|  | 214 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 215 | /* | 
|  | 216 | * Multi-channel / digital-out PCM helper | 
|  | 217 | */ | 
|  | 218 |  | 
|  | 219 | enum { HDA_FRONT, HDA_REAR, HDA_CLFE, HDA_SIDE }; /* index for dac_nidx */ | 
|  | 220 | enum { HDA_DIG_NONE, HDA_DIG_EXCLUSIVE, HDA_DIG_ANALOG_DUP }; /* dig_out_used */ | 
|  | 221 |  | 
|  | 222 | struct hda_multi_out { | 
|  | 223 | int num_dacs;		/* # of DACs, must be more than 1 */ | 
|  | 224 | hda_nid_t *dac_nids;	/* DAC list */ | 
|  | 225 | hda_nid_t hp_nid;	/* optional DAC for HP, 0 when not exists */ | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 226 | hda_nid_t extra_out_nid[3];	/* optional DACs, 0 when not exists */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 227 | hda_nid_t dig_out_nid;	/* digital out audio widget */ | 
|  | 228 | int max_channels;	/* currently supported analog channels */ | 
|  | 229 | int dig_out_used;	/* current usage of digital out (HDA_DIG_XXX) */ | 
| Takashi Iwai | d29240c | 2007-10-26 12:35:56 +0200 | [diff] [blame] | 230 | int no_share_stream;	/* don't share a stream with multiple pins */ | 
| Takashi Iwai | 9a08160 | 2008-02-12 18:37:26 +0100 | [diff] [blame] | 231 | int share_spdif;	/* share SPDIF pin */ | 
|  | 232 | /* PCM information for both analog and SPDIF DACs */ | 
|  | 233 | unsigned int analog_rates; | 
|  | 234 | unsigned int analog_maxbps; | 
|  | 235 | u64 analog_formats; | 
|  | 236 | unsigned int spdif_rates; | 
|  | 237 | unsigned int spdif_maxbps; | 
|  | 238 | u64 spdif_formats; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 239 | }; | 
|  | 240 |  | 
| Takashi Iwai | 9a08160 | 2008-02-12 18:37:26 +0100 | [diff] [blame] | 241 | int snd_hda_create_spdif_share_sw(struct hda_codec *codec, | 
|  | 242 | struct hda_multi_out *mout); | 
| Takashi Iwai | d01ce99 | 2007-07-27 16:52:19 +0200 | [diff] [blame] | 243 | int snd_hda_multi_out_dig_open(struct hda_codec *codec, | 
|  | 244 | struct hda_multi_out *mout); | 
|  | 245 | int snd_hda_multi_out_dig_close(struct hda_codec *codec, | 
|  | 246 | struct hda_multi_out *mout); | 
| Takashi Iwai | 6b97eb4 | 2007-04-05 14:51:48 +0200 | [diff] [blame] | 247 | int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, | 
|  | 248 | struct hda_multi_out *mout, | 
|  | 249 | unsigned int stream_tag, | 
|  | 250 | unsigned int format, | 
|  | 251 | struct snd_pcm_substream *substream); | 
| Takashi Iwai | d01ce99 | 2007-07-27 16:52:19 +0200 | [diff] [blame] | 252 | int snd_hda_multi_out_analog_open(struct hda_codec *codec, | 
|  | 253 | struct hda_multi_out *mout, | 
| Takashi Iwai | 9a08160 | 2008-02-12 18:37:26 +0100 | [diff] [blame] | 254 | struct snd_pcm_substream *substream, | 
|  | 255 | struct hda_pcm_stream *hinfo); | 
| Takashi Iwai | d01ce99 | 2007-07-27 16:52:19 +0200 | [diff] [blame] | 256 | int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, | 
|  | 257 | struct hda_multi_out *mout, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 258 | unsigned int stream_tag, | 
|  | 259 | unsigned int format, | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 260 | struct snd_pcm_substream *substream); | 
| Takashi Iwai | d01ce99 | 2007-07-27 16:52:19 +0200 | [diff] [blame] | 261 | int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, | 
|  | 262 | struct hda_multi_out *mout); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 263 |  | 
|  | 264 | /* | 
|  | 265 | * generic codec parser | 
|  | 266 | */ | 
| Takashi Iwai | 35a1e0c | 2007-10-19 08:13:40 +0200 | [diff] [blame] | 267 | #ifdef CONFIG_SND_HDA_GENERIC | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 268 | int snd_hda_parse_generic_codec(struct hda_codec *codec); | 
| Takashi Iwai | 35a1e0c | 2007-10-19 08:13:40 +0200 | [diff] [blame] | 269 | #else | 
|  | 270 | static inline int snd_hda_parse_generic_codec(struct hda_codec *codec) | 
|  | 271 | { | 
|  | 272 | return -ENODEV; | 
|  | 273 | } | 
|  | 274 | #endif | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 275 |  | 
|  | 276 | /* | 
|  | 277 | * generic proc interface | 
|  | 278 | */ | 
|  | 279 | #ifdef CONFIG_PROC_FS | 
|  | 280 | int snd_hda_codec_proc_new(struct hda_codec *codec); | 
|  | 281 | #else | 
|  | 282 | static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; } | 
|  | 283 | #endif | 
|  | 284 |  | 
|  | 285 | /* | 
|  | 286 | * Misc | 
|  | 287 | */ | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 288 | int snd_hda_check_board_config(struct hda_codec *codec, int num_configs, | 
|  | 289 | const char **modelnames, | 
|  | 290 | const struct snd_pci_quirk *pci_list); | 
| Takashi Iwai | d01ce99 | 2007-07-27 16:52:19 +0200 | [diff] [blame] | 291 | int snd_hda_add_new_ctls(struct hda_codec *codec, | 
|  | 292 | struct snd_kcontrol_new *knew); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 293 |  | 
|  | 294 | /* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 295 | * unsolicited event handler | 
|  | 296 | */ | 
|  | 297 |  | 
|  | 298 | #define HDA_UNSOL_QUEUE_SIZE	64 | 
|  | 299 |  | 
|  | 300 | struct hda_bus_unsolicited { | 
|  | 301 | /* ring buffer */ | 
|  | 302 | u32 queue[HDA_UNSOL_QUEUE_SIZE * 2]; | 
|  | 303 | unsigned int rp, wp; | 
|  | 304 |  | 
|  | 305 | /* workqueue */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 306 | struct work_struct work; | 
| David Howells | c402895 | 2006-11-22 14:57:56 +0000 | [diff] [blame] | 307 | struct hda_bus *bus; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 308 | }; | 
|  | 309 |  | 
| Takashi Iwai | e9edcee | 2005-06-13 14:16:38 +0200 | [diff] [blame] | 310 | /* | 
|  | 311 | * Helper for automatic ping configuration | 
|  | 312 | */ | 
|  | 313 |  | 
|  | 314 | enum { | 
|  | 315 | AUTO_PIN_MIC, | 
|  | 316 | AUTO_PIN_FRONT_MIC, | 
|  | 317 | AUTO_PIN_LINE, | 
|  | 318 | AUTO_PIN_FRONT_LINE, | 
|  | 319 | AUTO_PIN_CD, | 
|  | 320 | AUTO_PIN_AUX, | 
|  | 321 | AUTO_PIN_LAST | 
|  | 322 | }; | 
|  | 323 |  | 
| Takashi Iwai | d258e24 | 2007-04-23 17:16:21 +0200 | [diff] [blame] | 324 | enum { | 
|  | 325 | AUTO_PIN_LINE_OUT, | 
|  | 326 | AUTO_PIN_SPEAKER_OUT, | 
|  | 327 | AUTO_PIN_HP_OUT | 
|  | 328 | }; | 
|  | 329 |  | 
| Takashi Iwai | 4a471b7 | 2005-12-07 13:56:29 +0100 | [diff] [blame] | 330 | extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST]; | 
|  | 331 |  | 
| Takashi Iwai | 41923e4 | 2007-10-22 17:20:10 +0200 | [diff] [blame] | 332 | #define AUTO_CFG_MAX_OUTS	5 | 
|  | 333 |  | 
| Takashi Iwai | e9edcee | 2005-06-13 14:16:38 +0200 | [diff] [blame] | 334 | struct auto_pin_cfg { | 
|  | 335 | int line_outs; | 
| Takashi Iwai | 41923e4 | 2007-10-22 17:20:10 +0200 | [diff] [blame] | 336 | /* sorted in the order of Front/Surr/CLFE/Side */ | 
|  | 337 | hda_nid_t line_out_pins[AUTO_CFG_MAX_OUTS]; | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 338 | int speaker_outs; | 
| Takashi Iwai | 41923e4 | 2007-10-22 17:20:10 +0200 | [diff] [blame] | 339 | hda_nid_t speaker_pins[AUTO_CFG_MAX_OUTS]; | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 340 | int hp_outs; | 
| Takashi Iwai | d258e24 | 2007-04-23 17:16:21 +0200 | [diff] [blame] | 341 | int line_out_type;	/* AUTO_PIN_XXX_OUT */ | 
| Takashi Iwai | 41923e4 | 2007-10-22 17:20:10 +0200 | [diff] [blame] | 342 | hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS]; | 
| Takashi Iwai | e9edcee | 2005-06-13 14:16:38 +0200 | [diff] [blame] | 343 | hda_nid_t input_pins[AUTO_PIN_LAST]; | 
|  | 344 | hda_nid_t dig_out_pin; | 
|  | 345 | hda_nid_t dig_in_pin; | 
| Matthew Ranostay | 90da78b | 2008-01-24 11:48:01 +0100 | [diff] [blame] | 346 | hda_nid_t mono_out_pin; | 
| Takashi Iwai | e9edcee | 2005-06-13 14:16:38 +0200 | [diff] [blame] | 347 | }; | 
|  | 348 |  | 
| Takashi Iwai | d01ce99 | 2007-07-27 16:52:19 +0200 | [diff] [blame] | 349 | #define get_defcfg_connect(cfg) \ | 
|  | 350 | ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) | 
|  | 351 | #define get_defcfg_association(cfg) \ | 
|  | 352 | ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT) | 
|  | 353 | #define get_defcfg_location(cfg) \ | 
|  | 354 | ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) | 
|  | 355 | #define get_defcfg_sequence(cfg) \ | 
|  | 356 | (cfg & AC_DEFCFG_SEQUENCE) | 
|  | 357 | #define get_defcfg_device(cfg) \ | 
|  | 358 | ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) | 
| Takashi Iwai | e9edcee | 2005-06-13 14:16:38 +0200 | [diff] [blame] | 359 |  | 
| Takashi Iwai | d01ce99 | 2007-07-27 16:52:19 +0200 | [diff] [blame] | 360 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, | 
|  | 361 | struct auto_pin_cfg *cfg, | 
| Kailang Yang | df694da | 2005-12-05 19:42:22 +0100 | [diff] [blame] | 362 | hda_nid_t *ignore_nids); | 
| Takashi Iwai | e9edcee | 2005-06-13 14:16:38 +0200 | [diff] [blame] | 363 |  | 
| Takashi Iwai | 8d88bc3 | 2005-11-17 11:09:23 +0100 | [diff] [blame] | 364 | /* amp values */ | 
|  | 365 | #define AMP_IN_MUTE(idx)	(0x7080 | ((idx)<<8)) | 
|  | 366 | #define AMP_IN_UNMUTE(idx)	(0x7000 | ((idx)<<8)) | 
|  | 367 | #define AMP_OUT_MUTE	0xb080 | 
|  | 368 | #define AMP_OUT_UNMUTE	0xb000 | 
|  | 369 | #define AMP_OUT_ZERO	0xb000 | 
|  | 370 | /* pinctl values */ | 
| Robin H. Johnson | 35e8901 | 2008-09-13 16:54:59 -0700 | [diff] [blame] | 371 | #define PIN_IN			(AC_PINCTL_IN_EN) | 
|  | 372 | #define PIN_VREFHIZ	(AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ) | 
|  | 373 | #define PIN_VREF50		(AC_PINCTL_IN_EN | AC_PINCTL_VREF_50) | 
|  | 374 | #define PIN_VREFGRD	(AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD) | 
|  | 375 | #define PIN_VREF80		(AC_PINCTL_IN_EN | AC_PINCTL_VREF_80) | 
|  | 376 | #define PIN_VREF100	(AC_PINCTL_IN_EN | AC_PINCTL_VREF_100) | 
|  | 377 | #define PIN_OUT		(AC_PINCTL_OUT_EN) | 
|  | 378 | #define PIN_HP			(AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN) | 
|  | 379 | #define PIN_HP_AMP		(AC_PINCTL_HP_EN) | 
| Takashi Iwai | 8d88bc3 | 2005-11-17 11:09:23 +0100 | [diff] [blame] | 380 |  | 
| Takashi Iwai | 54d1740 | 2005-11-21 16:33:22 +0100 | [diff] [blame] | 381 | /* | 
|  | 382 | * get widget capabilities | 
|  | 383 | */ | 
|  | 384 | static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid) | 
|  | 385 | { | 
|  | 386 | if (nid < codec->start_nid || | 
|  | 387 | nid >= codec->start_nid + codec->num_nodes) | 
| Takashi Iwai | dca008f | 2008-01-22 15:37:13 +0100 | [diff] [blame] | 388 | return 0; | 
| Takashi Iwai | 54d1740 | 2005-11-21 16:33:22 +0100 | [diff] [blame] | 389 | return codec->wcaps[nid - codec->start_nid]; | 
|  | 390 | } | 
|  | 391 |  | 
| Matthew Ranostay | 09a9995 | 2008-01-24 11:49:21 +0100 | [diff] [blame] | 392 | u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); | 
| Takashi Iwai | 897cc18 | 2007-05-29 19:01:37 +0200 | [diff] [blame] | 393 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | 
|  | 394 | unsigned int caps); | 
| Takashi Iwai | 54d1740 | 2005-11-21 16:33:22 +0100 | [diff] [blame] | 395 |  | 
| Takashi Iwai | 2807314 | 2007-07-27 18:58:06 +0200 | [diff] [blame] | 396 | /* | 
|  | 397 | * hwdep interface | 
|  | 398 | */ | 
|  | 399 | int snd_hda_create_hwdep(struct hda_codec *codec); | 
|  | 400 |  | 
| Takashi Iwai | cb53c62 | 2007-08-10 17:21:45 +0200 | [diff] [blame] | 401 | /* | 
|  | 402 | * power-management | 
|  | 403 | */ | 
|  | 404 |  | 
|  | 405 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 
|  | 406 | void snd_hda_schedule_power_save(struct hda_codec *codec); | 
|  | 407 |  | 
|  | 408 | struct hda_amp_list { | 
|  | 409 | hda_nid_t nid; | 
|  | 410 | unsigned char dir; | 
|  | 411 | unsigned char idx; | 
|  | 412 | }; | 
|  | 413 |  | 
|  | 414 | struct hda_loopback_check { | 
|  | 415 | struct hda_amp_list *amplist; | 
|  | 416 | int power_on; | 
|  | 417 | }; | 
|  | 418 |  | 
|  | 419 | int snd_hda_check_amp_list_power(struct hda_codec *codec, | 
|  | 420 | struct hda_loopback_check *check, | 
|  | 421 | hda_nid_t nid); | 
|  | 422 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | 
|  | 423 |  | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 424 | /* | 
|  | 425 | * AMP control callbacks | 
|  | 426 | */ | 
|  | 427 | /* retrieve parameters from private_value */ | 
|  | 428 | #define get_amp_nid(kc)		((kc)->private_value & 0xffff) | 
|  | 429 | #define get_amp_channels(kc)	(((kc)->private_value >> 16) & 0x3) | 
|  | 430 | #define get_amp_direction(kc)	(((kc)->private_value >> 18) & 0x1) | 
|  | 431 | #define get_amp_index(kc)	(((kc)->private_value >> 19) & 0xf) | 
|  | 432 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 433 | #endif /* __SOUND_HDA_LOCAL_H */ |