1 /* 2 * AC97 interface 3 * 4 * Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de> 5 * Copyright (c) 2008, Jérôme Duval 6 * 7 * All rights reserved. 8 * Redistribution and use in source and binary forms, with or without modification, 9 * are permitted provided that the following conditions are met: 10 * 11 * - Redistributions of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * - Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 #ifndef _AC97_H_ 30 #define _AC97_H_ 31 32 enum AC97_REGISTER { 33 /* Baseline audio register set */ 34 AC97_RESET = 0x00, 35 AC97_MASTER_VOLUME = 0x02, 36 AC97_AUX_OUT_VOLUME = 0x04, 37 AC97_MONO_VOLUME = 0x06, 38 AC97_MASTER_TONE = 0x08, 39 AC97_PC_BEEP_VOLUME = 0x0A, 40 AC97_PHONE_VOLUME = 0x0C, 41 AC97_MIC_VOLUME = 0x0E, 42 AC97_LINE_IN_VOLUME = 0x10, 43 AC97_CD_VOLUME = 0x12, 44 AC97_VIDEO_VOLUME = 0x14, 45 AC97_AUX_IN_VOLUME = 0x16, 46 AC97_PCM_OUT_VOLUME = 0x18, 47 AC97_RECORD_SELECT = 0x1A, 48 AC97_RECORD_GAIN = 0x1C, 49 AC97_RECORD_GAIN_MIC = 0x1E, 50 AC97_GENERAL_PURPOSE = 0x20, 51 AC97_3D_CONTROL = 0x22, 52 AC97_PAGING = 0x24, 53 AC97_POWERDOWN = 0x26, 54 55 /* Extended audio register set */ 56 AC97_EXTENDED_ID = 0x28, 57 AC97_EXTENDED_STAT_CTRL = 0x2A, 58 AC97_PCM_FRONT_DAC_RATE = 0x2C, 59 AC97_PCM_SURR_DAC_RATE = 0x2E, 60 AC97_PCM_LFE_DAC_RATE = 0x30, 61 AC97_PCM_L_R_ADC_RATE = 0x32, 62 AC97_MIC_ADC_RATE = 0x34, 63 AC97_CENTER_LFE_VOLUME = 0x36, 64 AC97_SURR_VOLUME = 0x38, 65 AC97_SPDIF_CONTROL = 0x3A, 66 67 /* Vendor ID */ 68 AC97_VENDOR_ID1 = 0x7C, 69 AC97_VENDOR_ID2 = 0x7E, 70 71 /* Analog Devices */ 72 AC97_AD_JACK_SENSE = 0x72, 73 AC97_AD_SERIAL_CONFIG = 0x74, 74 AC97_AD_MISC_CONTROL = 0x76, 75 AC97_AD_SAMPLE_RATE_0 = 0x78, 76 AC97_AD_SAMPLE_RATE_1 = 0x7a, 77 78 /* Realtek ALC650 */ 79 AC97_ALC650_SPDIF_INPUT_CHAN_STATUS_LO = 0x60, /* only ALC650 Rev. E and later */ 80 AC97_ALC650_SPDIF_INPUT_CHAN_STATUS_HI = 0x62, /* only ALC650 Rev. E and later */ 81 AC97_ALC650_SURR_VOLUME = 0x64, 82 AC97_ALC650_CEN_LFE_VOLUME = 0x66, 83 AC97_ALC650_MULTI_CHAN_CTRL = 0x6A, 84 AC97_ALC650_MISC_CONTROL = 0x74, 85 AC97_ALC650_GPIO_SETUP = 0x76, 86 AC97_ALC650_GPIO_STATUS = 0x78, 87 AC97_ALC650_CLOCK_SOURCE = 0x7A 88 }; 89 90 // AC97_EXTENDED_ID bits 91 enum { 92 EXID_VRA = 0x0001, 93 EXID_DRA = 0x0002, 94 EXID_SPDIF = 0x0004, 95 EXID_VRM = 0x0008, 96 EXID_DSA0 = 0x0010, 97 EXID_DSA1 = 0x0020, 98 EXID_CDAC = 0x0040, 99 EXID_SDAC = 0x0080, 100 EXID_LDAC = 0x0100, 101 EXID_AMAP = 0x0200, 102 EXID_REV0 = 0x0400, 103 EXID_REV1 = 0x0800, 104 EXID_bit12 = 0x1000, 105 EXID_bit13 = 0x2000, 106 EXID_ID0 = 0x4000, 107 EXID_ID1 = 0x8000 108 }; 109 110 // some codec_ids 111 enum { 112 CODEC_ID_ALC201A = 0x414c4710, 113 CODEC_ID_AK4540 = 0x414b4d00, 114 CODEC_ID_AK4542 = 0x414b4d01, 115 CODEC_ID_AK4543 = 0x414b4d02, 116 CODEC_ID_AD1819 = 0x41445303, // ok, AD1819A, AD1819B 117 CODEC_ID_AD1881 = 0x41445340, // ok, AD1881 118 CODEC_ID_AD1881A = 0x41445348, // ok, AD1881A 119 CODEC_ID_AD1885 = 0x41445360, // ok, AD1885 120 CODEC_ID_AD1886 = 0x41445361, // ok, AD1886 121 CODEC_ID_AD1886A = 0x41445363, // ok, AD1886A 122 CODEC_ID_AD1887 = 0x41445362, // ok, AD1887 123 CODEC_ID_AD1888 = 0x41445368, // ok, AD1888 124 CODEC_ID_AD1980 = 0x41445370, // ok, AD1980 125 CODEC_ID_AD1981B = 0x41445374, // ok, AD1981B 126 CODEC_ID_AD1985 = 0x41445375, // ok, AD1985 127 CODEC_ID_AD1986 = 0x41445378, // ok, AD1986 128 CODEC_ID_CS4299A = 0x43525931, 129 CODEC_ID_CS4299C = 0x43525933, 130 CODEC_ID_CS4299D = 0x43525934, 131 CODEC_ID_STAC9700 = 0x83847600, // ok, STAC9700 132 CODEC_ID_STAC9704 = 0x83847604, // STAC9701/03, STAC9704/07, STAC9705 (???) 133 CODEC_ID_STAC9705 = 0x83847605, // ??? 134 CODEC_ID_STAC9708 = 0x83847608, // ok, STAC9708/11 135 CODEC_ID_STAC9721 = 0x83847609, // ok, STAC9721/23 136 CODEC_ID_STAC9744 = 0x83847644, // ok, STAC9744 137 CODEC_ID_STAC9750 = 0x83847650, // ok, STAC9750/51 138 CODEC_ID_STAC9752 = 0x83847652, // ok, STAC9752/53 139 CODEC_ID_STAC9756 = 0x83847656, // ok, STAC9756/57 140 CODEC_ID_STAC9758 = 0x83847658, // ????, STAC9758/59 141 CODEC_ID_STAC9766 = 0x83847666, // ok, STAC9766/67 142 }; 143 144 // capabilities 145 enum ac97_capability { 146 CAP_PCM_MIC = 0x0000000000000001ULL, /* dedicated mic PCM channel */ 147 CAP_BASS_TREBLE_CTRL = 0x0000000000000002ULL, 148 CAP_SIMULATED_STEREO = 0x0000000000000004ULL, 149 CAP_HEADPHONE_OUT = 0x0000000000000008ULL, 150 CAP_LAUDNESS = 0x0000000000000010ULL, 151 CAP_DAC_18BIT = 0x0000000000000020ULL, 152 CAP_DAC_20BIT = 0x0000000000000040ULL, 153 CAP_ADC_18BIT = 0x0000000000000080ULL, 154 CAP_ADC_20BIT = 0x0000000000000100ULL, 155 CAP_3D_ENHANCEMENT = 0x0000000000000200ULL, 156 CAP_VARIABLE_PCM = 0x0000000000000400ULL, /* variable rate PCM */ 157 CAP_DOUBLE_PCM = 0x0000000000000800ULL, /* double rate PCM */ 158 CAP_SPDIF = 0x0000000000001000ULL, 159 CAP_VARIABLE_MIC = 0x0000000000002000ULL, /* variable rate mic PCM */ 160 CAP_CENTER_DAC = 0x0000000000004000ULL, 161 CAP_SURR_DAC = 0x0000000000008000ULL, 162 CAP_LFE_DAC = 0x0000000000010000ULL, 163 CAP_AMAP = 0x0000000000020000ULL, 164 CAP_REV21 = 0x0000000000040000ULL, 165 CAP_REV22 = 0x0000000000080000ULL, 166 CAP_REV23 = 0x0000000000100000ULL, 167 CAP_PCM_RATE_CONTINUOUS = 0x0000000000200000ULL, 168 CAP_PCM_RATE_8000 = 0x0000000000400000ULL, 169 CAP_PCM_RATE_11025 = 0x0000000000800000ULL, 170 CAP_PCM_RATE_12000 = 0x0000000001000000ULL, 171 CAP_PCM_RATE_16000 = 0x0000000002000000ULL, 172 CAP_PCM_RATE_22050 = 0x0000000004000000ULL, 173 CAP_PCM_RATE_24000 = 0x0000000008000000ULL, 174 CAP_PCM_RATE_32000 = 0x0000000010000000ULL, 175 CAP_PCM_RATE_44100 = 0x0000000020000000ULL, 176 CAP_PCM_RATE_48000 = 0x0000000040000000ULL, 177 CAP_PCM_RATE_88200 = 0x0000000080000000ULL, 178 CAP_PCM_RATE_96000 = 0x0000000100000000ULL, 179 CAP_PCM_RATE_MASK = ( CAP_PCM_RATE_CONTINUOUS | CAP_PCM_RATE_8000 | CAP_PCM_RATE_11025 | 180 CAP_PCM_RATE_12000 | CAP_PCM_RATE_16000 | CAP_PCM_RATE_22050 | 181 CAP_PCM_RATE_24000 | CAP_PCM_RATE_32000 | CAP_PCM_RATE_44100 | 182 CAP_PCM_RATE_48000 | CAP_PCM_RATE_88200 | CAP_PCM_RATE_96000) 183 }; 184 185 struct ac97_dev; 186 typedef struct ac97_dev ac97_dev; 187 188 typedef void (* codec_init)(ac97_dev * dev); 189 typedef uint16 (* codec_reg_read)(void * cookie, uint8 reg); 190 typedef void (* codec_reg_write)(void * cookie, uint8 reg, uint16 value); 191 typedef bool (* codec_set_rate)(ac97_dev *dev, uint8 reg, uint32 rate); 192 typedef bool (* codec_get_rate)(ac97_dev *dev, uint8 reg, uint32 *rate); 193 194 struct ac97_dev { 195 uint16 reg_cache[0x7f]; 196 197 void * cookie; 198 199 uint32 codec_id; 200 const char * codec_info; 201 const char * codec_3d_stereo_enhancement; 202 203 codec_init init; 204 codec_reg_read reg_read; 205 codec_reg_write reg_write; 206 codec_set_rate set_rate; 207 codec_get_rate get_rate; 208 209 uint32 max_vsr; 210 uint32 min_vsr; 211 uint32 clock; 212 uint64 capabilities; 213 bool reversed_eamp_polarity; 214 uint32 subsystem; 215 }; 216 217 #ifdef __cplusplus 218 extern "C" { 219 #endif 220 221 void ac97_attach(ac97_dev **dev, codec_reg_read reg_read, 222 codec_reg_write reg_write, void *cookie, ushort subvendor_id, 223 ushort subsystem_id); 224 void ac97_detach(ac97_dev *dev); 225 void ac97_suspend(ac97_dev *dev); 226 void ac97_resume(ac97_dev *dev); 227 228 void ac97_reg_cached_write(ac97_dev *dev, uint8 reg, uint16 value); 229 uint16 ac97_reg_cached_read(ac97_dev *dev, uint8 reg); 230 void ac97_reg_uncached_write(ac97_dev *dev, uint8 reg, uint16 value); 231 uint16 ac97_reg_uncached_read(ac97_dev *dev, uint8 reg); 232 233 bool ac97_reg_update(ac97_dev *dev, uint8 reg, uint16 value); 234 bool ac97_reg_update_bits(ac97_dev *dev, uint8 reg, uint16 mask, 235 uint16 value); 236 237 bool ac97_set_rate(ac97_dev *dev, uint8 reg, uint32 rate); 238 bool ac97_get_rate(ac97_dev *dev, uint8 reg, uint32 *rate); 239 240 bool ac97_has_capability(ac97_dev *dev, uint64 cap); 241 242 void ac97_set_clock(ac97_dev *dev, uint32 clock); 243 244 #ifdef __cplusplus 245 } 246 #endif 247 248 // multi support 249 250 typedef enum { 251 B_MIX_GAIN = 1 << 0, 252 B_MIX_MUTE = 1 << 1, 253 B_MIX_MONO = 1 << 2, 254 B_MIX_STEREO = 1 << 3, 255 B_MIX_MUX = 1 << 4, 256 B_MIX_MICBOOST = 1 << 5, 257 B_MIX_RECORDMUX = 1 << 6 258 } ac97_mixer_type; 259 260 typedef struct _ac97_source_info { 261 const char *name; 262 ac97_mixer_type type; 263 264 int32 id; 265 uint8 reg; 266 uint16 default_value; 267 uint8 bits:3; 268 uint8 ofs:4; 269 uint8 mute:1; 270 uint8 polarity:1; // max_gain -> 0 271 float min_gain; 272 float max_gain; 273 float granularity; 274 } ac97_source_info; 275 276 extern const ac97_source_info source_info[]; 277 extern const int32 source_info_size; 278 279 #endif 280