1 /* $OpenBSD: ac97.c,v 1.82 2016/09/14 06:12:19 ratchov Exp $ */ 2 3 /* 4 * Copyright (c) 1999, 2000 Constantine Sapuntzakis 5 * 6 * Author: Constantine Sapuntzakis <csapuntz@stanford.edu> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote 17 * products derived from this software without specific prior written 18 * permission. 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS 20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 25 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 26 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 29 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 * DAMAGE. */ 31 32 /* Partially inspired by FreeBSD's sys/dev/pcm/ac97.c. It came with 33 the following copyright */ 34 35 /* 36 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 37 * All rights reserved. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * $FreeBSD$ 61 */ 62 63 #include <sys/param.h> 64 #include <sys/systm.h> 65 #include <sys/kernel.h> 66 #include <sys/malloc.h> 67 68 #include <sys/audioio.h> 69 #include <dev/audio_if.h> 70 #include <dev/ic/ac97.h> 71 72 73 /* default parameters; supported by all ac97 codecs */ 74 const struct audio_params ac97_audio_default = { 75 48000, /* sample_rate */ 76 AUDIO_ENCODING_SLINEAR_LE, /* encoding */ 77 16, /* precision */ 78 2, /* bps */ 79 1, /* msb */ 80 2 /* channels */ 81 }; 82 83 const struct audio_mixer_enum ac97_on_off = { 84 2, 85 { { { AudioNoff } , 0 }, 86 { { AudioNon } , 1 } } 87 }; 88 89 const struct audio_mixer_enum ac97_mic_select = { 90 2, 91 { { { AudioNmicrophone "0" }, 0 }, 92 { { AudioNmicrophone "1" }, 1 } } 93 }; 94 95 const struct audio_mixer_enum ac97_mono_select = { 96 2, 97 { { { AudioNmixerout }, 0 }, 98 { { AudioNmicrophone }, 1 } } 99 }; 100 101 const struct audio_mixer_enum ac97_source = { 102 8, 103 { { { AudioNmicrophone } , 0 }, 104 { { AudioNcd }, 1 }, 105 { { "video" }, 2 }, 106 { { AudioNaux }, 3 }, 107 { { AudioNline }, 4 }, 108 { { AudioNmixerout }, 5 }, 109 { { AudioNmixerout AudioNmono }, 6 }, 110 { { "phone" }, 7 }} 111 }; 112 113 /* 114 * Due to different values for each source that uses these structures, 115 * the ac97_query_devinfo function sets delta in mixer_devinfo_t using 116 * ac97_source_info.bits. 117 */ 118 const struct audio_mixer_value ac97_volume_stereo = { 119 { AudioNvolume }, 120 2 121 }; 122 123 const struct audio_mixer_value ac97_volume_mono = { 124 { AudioNvolume }, 125 1 126 }; 127 128 #define AudioNspdif "spdif" 129 130 #define WRAP(a) &a, sizeof(a) 131 132 const struct ac97_source_info { 133 char *class; 134 char *device; 135 char *qualifier; 136 int type; 137 138 const void *info; 139 int16_t info_size; 140 141 u_int8_t reg; 142 u_int16_t default_value; 143 u_int8_t bits:3; 144 u_int8_t ofs:4; 145 u_int8_t mute:1; 146 u_int8_t polarity:1; /* Does 0 == MAX or MIN */ 147 enum { 148 CHECK_NONE = 0, 149 CHECK_SURROUND, 150 CHECK_CENTER, 151 CHECK_LFE, 152 CHECK_HEADPHONES, 153 CHECK_TONE, 154 CHECK_MIC, 155 CHECK_LOUDNESS, 156 CHECK_3D, 157 CHECK_SPDIF 158 } req_feature; 159 160 int16_t prev; 161 int16_t next; 162 int16_t mixer_class; 163 } source_info[] = { 164 { AudioCinputs, NULL, NULL, 165 AUDIO_MIXER_CLASS, }, 166 { AudioCoutputs, NULL, NULL, 167 AUDIO_MIXER_CLASS, }, 168 { AudioCrecord, NULL, NULL, 169 AUDIO_MIXER_CLASS, }, 170 /* Stereo master volume*/ 171 { AudioCoutputs, AudioNmaster, NULL, 172 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 173 AC97_REG_MASTER_VOLUME, 0x8000, 5, 0, 1, 174 }, 175 /* Mono volume */ 176 { AudioCoutputs, AudioNmono, NULL, 177 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 178 AC97_REG_MASTER_VOLUME_MONO, 0x8000, 6, 0, 1, 179 }, 180 { AudioCoutputs, AudioNmono, AudioNsource, 181 AUDIO_MIXER_ENUM, WRAP(ac97_mono_select), 182 AC97_REG_GP, 0x0000, 1, 9, 0, 183 }, 184 /* Headphone volume */ 185 { AudioCoutputs, AudioNheadphone, NULL, 186 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 187 AC97_REG_HEADPHONE_VOLUME, 0x8000, 6, 0, 1, 0, CHECK_HEADPHONES 188 }, 189 /* Surround volume - logic hard coded for mute */ 190 { AudioCoutputs, AudioNsurround, NULL, 191 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 192 AC97_REG_SURR_MASTER, 0x8080, 5, 0, 1, 0, CHECK_SURROUND 193 }, 194 /* Center volume*/ 195 { AudioCoutputs, AudioNcenter, NULL, 196 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 197 AC97_REG_CENTER_LFE_MASTER, 0x8080, 5, 0, 0, 0, CHECK_CENTER 198 }, 199 { AudioCoutputs, AudioNcenter, AudioNmute, 200 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 201 AC97_REG_CENTER_LFE_MASTER, 0x8080, 1, 7, 0, 0, CHECK_CENTER 202 }, 203 /* LFE volume*/ 204 { AudioCoutputs, AudioNlfe, NULL, 205 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 206 AC97_REG_CENTER_LFE_MASTER, 0x8080, 5, 8, 0, 0, CHECK_LFE 207 }, 208 { AudioCoutputs, AudioNlfe, AudioNmute, 209 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 210 AC97_REG_CENTER_LFE_MASTER, 0x8080, 1, 15, 0, 0, CHECK_LFE 211 }, 212 /* Tone */ 213 { AudioCoutputs, "tone", NULL, 214 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 215 AC97_REG_MASTER_TONE, 0x0f0f, 4, 0, 0, 0, CHECK_TONE 216 }, 217 /* PC Beep Volume */ 218 { AudioCinputs, AudioNspeaker, NULL, 219 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 220 AC97_REG_PCBEEP_VOLUME, 0x0000, 4, 1, 1, 221 }, 222 223 /* Phone */ 224 { AudioCinputs, "phone", NULL, 225 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 226 AC97_REG_PHONE_VOLUME, 0x8008, 5, 0, 1, 227 }, 228 /* Mic Volume */ 229 { AudioCinputs, AudioNmicrophone, NULL, 230 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 231 AC97_REG_MIC_VOLUME, 0x8008, 5, 0, 1, 232 }, 233 { AudioCinputs, AudioNmicrophone, AudioNpreamp, 234 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 235 AC97_REG_MIC_VOLUME, 0x8008, 1, 6, 0, 236 }, 237 { AudioCinputs, AudioNmicrophone, AudioNsource, 238 AUDIO_MIXER_ENUM, WRAP(ac97_mic_select), 239 AC97_REG_GP, 0x0000, 1, 8, 0, 240 }, 241 /* Line in Volume */ 242 { AudioCinputs, AudioNline, NULL, 243 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 244 AC97_REG_LINEIN_VOLUME, 0x8808, 5, 0, 1, 245 }, 246 /* CD Volume */ 247 { AudioCinputs, AudioNcd, NULL, 248 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 249 AC97_REG_CD_VOLUME, 0x8808, 5, 0, 1, 250 }, 251 /* Video Volume */ 252 { AudioCinputs, AudioNvideo, NULL, 253 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 254 AC97_REG_VIDEO_VOLUME, 0x8808, 5, 0, 1, 255 }, 256 /* AUX volume */ 257 { AudioCinputs, AudioNaux, NULL, 258 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 259 AC97_REG_AUX_VOLUME, 0x8808, 5, 0, 1, 260 }, 261 /* PCM out volume */ 262 { AudioCinputs, AudioNdac, NULL, 263 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 264 AC97_REG_PCMOUT_VOLUME, 0x8808, 5, 0, 1, 265 }, 266 /* Record Source - some logic for this is hard coded - see below */ 267 { AudioCrecord, AudioNsource, NULL, 268 AUDIO_MIXER_ENUM, WRAP(ac97_source), 269 AC97_REG_RECORD_SELECT, 0x0000, 3, 0, 0, 270 }, 271 /* Record Gain */ 272 { AudioCrecord, AudioNvolume, NULL, 273 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 274 AC97_REG_RECORD_GAIN, 0x8000, 4, 0, 1, 275 }, 276 /* Record Gain mic */ 277 { AudioCrecord, AudioNmicrophone, NULL, 278 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 279 AC97_REG_RECORD_GAIN_MIC, 0x8000, 4, 0, 1, 1, CHECK_MIC 280 }, 281 /* */ 282 { AudioCoutputs, AudioNloudness, NULL, 283 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 284 AC97_REG_GP, 0x0000, 1, 12, 0, 0, CHECK_LOUDNESS 285 }, 286 { AudioCoutputs, AudioNspatial, NULL, 287 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 288 AC97_REG_GP, 0x0000, 1, 13, 0, 1, CHECK_3D 289 }, 290 { AudioCoutputs, AudioNspatial, "center", 291 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 292 AC97_REG_3D_CONTROL, 0x0000, 4, 8, 0, 1, CHECK_3D 293 }, 294 { AudioCoutputs, AudioNspatial, "depth", 295 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 296 AC97_REG_3D_CONTROL, 0x0000, 4, 0, 0, 1, CHECK_3D 297 }, 298 /* External Amp */ 299 { AudioCoutputs, AudioNextamp, NULL, 300 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 301 AC97_REG_POWER, 0x0000, 1, 15, 0, 0 302 }, 303 /* S/PDIF output enable */ 304 { AudioCoutputs, AudioNspdif, NULL, 305 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 306 AC97_REG_EXT_AUDIO_CTRL, 0x0000, 1, 2, 0, 0, CHECK_SPDIF 307 } 308 309 /* Missing features: Simulated Stereo, POP, Loopback mode */ 310 }; 311 312 /* 313 * Check out http://www.intel.com/technology/computing/audio/index.htm 314 * for information on AC-97 315 */ 316 317 struct ac97_softc { 318 /* ac97_codec_if must be at the first of ac97_softc. */ 319 struct ac97_codec_if codec_if; 320 struct ac97_host_if *host_if; 321 #define MAX_SOURCES (2 * nitems(source_info)) 322 struct ac97_source_info source_info[MAX_SOURCES]; 323 int num_source_info; 324 enum ac97_host_flags host_flags; 325 unsigned int ac97_clock; /* usually 48000 */ 326 #define AC97_STANDARD_CLOCK 48000U 327 u_int16_t caps; /* -> AC97_REG_RESET */ 328 u_int16_t ext_id; /* -> AC97_REG_EXT_AUDIO_ID */ 329 u_int16_t shadow_reg[128]; 330 int lock_counter; 331 }; 332 333 int ac97_mixer_get_port(struct ac97_codec_if *, mixer_ctrl_t *); 334 int ac97_mixer_set_port(struct ac97_codec_if *, mixer_ctrl_t *); 335 void ac97_lock(struct ac97_codec_if *); 336 void ac97_unlock(struct ac97_codec_if *); 337 int ac97_query_devinfo(struct ac97_codec_if *, mixer_devinfo_t *); 338 int ac97_get_portnum_by_name(struct ac97_codec_if *, char *, char *, 339 char *); 340 void ac97_restore_shadow(struct ac97_codec_if *); 341 int ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_long *rate); 342 void ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock); 343 u_int16_t ac97_get_extcaps(struct ac97_codec_if *codec_if); 344 int ac97_add_port(struct ac97_softc *as, struct ac97_source_info *src); 345 346 void ac97_ad1885_init(struct ac97_softc *, int); 347 void ac97_ad1886_init(struct ac97_softc *, int); 348 void ac97_ad198x_init(struct ac97_softc *, int); 349 void ac97_alc650_init(struct ac97_softc *, int); 350 void ac97_cx20468_init(struct ac97_softc *, int); 351 void ac97_vt1616_init(struct ac97_softc *, int); 352 353 struct ac97_codec_if_vtbl ac97civ = { 354 ac97_mixer_get_port, 355 ac97_mixer_set_port, 356 ac97_query_devinfo, 357 ac97_get_portnum_by_name, 358 ac97_restore_shadow, 359 ac97_get_extcaps, 360 ac97_set_rate, 361 ac97_set_clock, 362 ac97_lock, 363 ac97_unlock 364 }; 365 366 const struct ac97_codecid { 367 u_int8_t id; 368 u_int8_t mask; 369 u_int8_t rev; 370 u_int8_t shift; /* no use yet */ 371 char * const name; 372 void (*init)(struct ac97_softc *, int); 373 } ac97_ad[] = { 374 { 0x03, 0xff, 0, 0, "AD1819" }, 375 { 0x40, 0xff, 0, 0, "AD1881" }, 376 { 0x48, 0xff, 0, 0, "AD1881A" }, 377 { 0x60, 0xff, 0, 0, "AD1885", ac97_ad1885_init }, 378 { 0x61, 0xff, 0, 0, "AD1886", ac97_ad1886_init }, 379 { 0x63, 0xff, 0, 0, "AD1886A" }, 380 { 0x68, 0xff, 0, 0, "AD1888", ac97_ad198x_init }, 381 { 0x70, 0xff, 0, 0, "AD1980", ac97_ad198x_init }, 382 { 0x72, 0xff, 0, 0, "AD1981A" }, 383 { 0x74, 0xff, 0, 0, "AD1981B" }, 384 { 0x75, 0xff, 0, 0, "AD1985", ac97_ad198x_init }, 385 }, ac97_ak[] = { 386 { 0x00, 0xfe, 1, 0, "AK4540" }, 387 { 0x01, 0xfe, 1, 0, "AK4540" }, 388 { 0x02, 0xff, 0, 0, "AK4543" }, 389 { 0x05, 0xff, 0, 0, "AK4544" }, 390 { 0x06, 0xff, 0, 0, "AK4544A" }, 391 { 0x07, 0xff, 0, 0, "AK4545" }, 392 }, ac97_av[] = { 393 { 0x10, 0xff, 0, 0, "ALC200" }, 394 { 0x20, 0xff, 0, 0, "ALC650" }, 395 { 0x21, 0xff, 0, 0, "ALC650D" }, 396 { 0x22, 0xff, 0, 0, "ALC650E" }, 397 { 0x23, 0xff, 0, 0, "ALC650F" }, 398 { 0x30, 0xff, 0, 0, "ALC101" }, 399 { 0x40, 0xff, 0, 0, "ALC202" }, 400 { 0x50, 0xff, 0, 0, "ALC250" }, 401 { 0x52, 0xff, 0, 0, "ALC250A?" }, 402 { 0x60, 0xf0, 0xf, 0, "ALC655", ac97_alc650_init }, 403 { 0x70, 0xf0, 0xf, 0, "ALC203" }, 404 { 0x80, 0xf0, 0xf, 0, "ALC658", ac97_alc650_init }, 405 { 0x90, 0xf0, 0xf, 0, "ALC850" }, 406 }, ac97_rl[] = { 407 { 0x00, 0xf0, 0xf, 0, "RL5306" }, 408 { 0x10, 0xf0, 0xf, 0, "RL5382" }, 409 { 0x20, 0xf0, 0xf, 0, "RL5383" }, 410 }, ac97_cm[] = { 411 { 0x41, 0xff, 0, 0, "CMI9738" }, 412 { 0x61, 0xff, 0, 0, "CMI9739" }, 413 { 0x78, 0xff, 0, 0, "CMI9761A" }, 414 { 0x82, 0xff, 0, 0, "CMI9761B" }, 415 { 0x83, 0xff, 0, 0, "CMI9761A+" }, 416 }, ac97_cr[] = { 417 { 0x84, 0xff, 0, 0, "EV1938" }, 418 }, ac97_cs[] = { 419 { 0x00, 0xf8, 7, 0, "CS4297" }, 420 { 0x10, 0xf8, 7, 0, "CS4297A" }, 421 { 0x20, 0xf8, 7, 0, "CS4298" }, 422 { 0x28, 0xf8, 7, 0, "CS4294" }, 423 { 0x30, 0xf8, 7, 0, "CS4299" }, 424 { 0x48, 0xf8, 7, 0, "CS4201" }, 425 { 0x58, 0xf8, 7, 0, "CS4205" }, 426 { 0x60, 0xf8, 7, 0, "CS4291" }, 427 { 0x70, 0xf8, 7, 0, "CS4202" }, 428 }, ac97_cx[] = { 429 { 0x21, 0xff, 0, 0, "HSD11246" }, 430 { 0x28, 0xf8, 7, 0, "CX20468", ac97_cx20468_init }, 431 { 0x30, 0xff, 0, 0, "CXT48", }, 432 { 0x42, 0xff, 0, 0, "CXT66", }, 433 }, ac97_dt[] = { 434 { 0x00, 0xff, 0, 0, "DT0398" }, 435 }, ac97_em[] = { 436 { 0x23, 0xff, 0, 0, "EM28023" }, 437 { 0x28, 0xff, 0, 0, "EM28028" }, 438 }, ac97_es[] = { 439 { 0x08, 0xff, 0, 0, "ES1921" }, 440 }, ac97_is[] = { 441 { 0x00, 0xff, 0, 0, "HMP9701" }, 442 }, ac97_ic[] = { 443 { 0x01, 0xff, 0, 0, "ICE1230" }, 444 { 0x11, 0xff, 0, 0, "ICE1232" }, 445 { 0x14, 0xff, 0, 0, "ICE1232A" }, 446 { 0x51, 0xff, 0, 0, "VIA VT1616" }, 447 { 0x52, 0xff, 0, 0, "VIA VT1616i", ac97_vt1616_init }, 448 }, ac97_it[] = { 449 { 0x20, 0xff, 0, 0, "ITE2226E" }, 450 { 0x60, 0xff, 0, 0, "ITE2646E" }, 451 }, ac97_ns[] = { 452 { 0x00, 0xff, 0, 0, "LM454[03568]" }, 453 { 0x31, 0xff, 0, 0, "LM4549" }, 454 { 0x40, 0xff, 0, 0, "LM4540" }, 455 { 0x43, 0xff, 0, 0, "LM4543" }, 456 { 0x46, 0xff, 0, 0, "LM4546A" }, 457 { 0x48, 0xff, 0, 0, "LM4548A" }, 458 { 0x49, 0xff, 0, 0, "LM4549A" }, 459 { 0x50, 0xff, 0, 0, "LM4550" }, 460 }, ac97_ps[] = { 461 { 0x01, 0xff, 0, 0, "UCB1510" }, 462 { 0x04, 0xff, 0, 0, "UCB1400" }, 463 }, ac97_sl[] = { 464 { 0x20, 0xe0, 0, 0, "Si3036/38" }, 465 }, ac97_st[] = { 466 { 0x00, 0xff, 0, 0, "STAC9700" }, 467 { 0x04, 0xff, 0, 0, "STAC970[135]" }, 468 { 0x05, 0xff, 0, 0, "STAC9704" }, 469 { 0x08, 0xff, 0, 0, "STAC9708/11" }, 470 { 0x09, 0xff, 0, 0, "STAC9721/23" }, 471 { 0x44, 0xff, 0, 0, "STAC9744/45" }, 472 { 0x50, 0xff, 0, 0, "STAC9750/51" }, 473 { 0x52, 0xff, 0, 0, "STAC9752/53" }, 474 { 0x56, 0xff, 0, 0, "STAC9756/57" }, 475 { 0x58, 0xff, 0, 0, "STAC9758/59" }, 476 { 0x60, 0xff, 0, 0, "STAC9760/61" }, 477 { 0x62, 0xff, 0, 0, "STAC9762/63" }, 478 { 0x66, 0xff, 0, 0, "STAC9766/67" }, 479 { 0x84, 0xff, 0, 0, "STAC9784/85" }, 480 }, ac97_vi[] = { 481 { 0x61, 0xff, 0, 0, "VT1612A" }, 482 { 0x70, 0xff, 0, 0, "VT1617" }, 483 }, ac97_tt[] = { 484 { 0x02, 0xff, 0, 0, "TR28022" }, 485 { 0x03, 0xff, 0, 0, "TR28023" }, 486 { 0x06, 0xff, 0, 0, "TR28026" }, 487 { 0x08, 0xff, 0, 0, "TR28028" }, 488 { 0x23, 0xff, 0, 0, "TR28602" }, 489 }, ac97_ti[] = { 490 { 0x20, 0xff, 0, 0, "TLC320AD9xC" }, 491 }, ac97_wb[] = { 492 { 0x01, 0xff, 0, 0, "W83971D" }, 493 }, ac97_wo[] = { 494 { 0x00, 0xff, 0, 0, "WM9701A" }, 495 { 0x03, 0xff, 0, 0, "WM9704M/Q-0" }, /* & WM9703 */ 496 { 0x04, 0xff, 0, 0, "WM9704M/Q-1" }, 497 { 0x05, 0xff, 0, 0, "WM9705/10" }, 498 { 0x09, 0xff, 0, 0, "WM9709" }, 499 { 0x12, 0xff, 0, 0, "WM9711/12" }, 500 }, ac97_ym[] = { 501 { 0x00, 0xff, 0, 0, "YMF743-S" }, 502 { 0x02, 0xff, 0, 0, "YMF752-S" }, 503 { 0x03, 0xff, 0, 0, "YMF753-S" }, 504 }; 505 506 #define cl(n) n, nitems(n) 507 const struct ac97_vendorid { 508 u_int32_t id; 509 char * const name; 510 const struct ac97_codecid * const codecs; 511 u_int8_t num; 512 } ac97_vendors[] = { 513 { 0x01408300, "Creative", cl(ac97_cr) }, 514 { 0x41445300, "Analog Devices", cl(ac97_ad) }, 515 { 0x414b4D00, "Asahi Kasei", cl(ac97_ak) }, 516 { 0x414c4300, "Realtek", cl(ac97_rl) }, 517 { 0x414c4700, "Avance Logic", cl(ac97_av) }, 518 { 0x434d4900, "C-Media Electronics", cl(ac97_cm) }, 519 { 0x43525900, "Cirrus Logic", cl(ac97_cs) }, 520 { 0x43585400, "Conexant", cl(ac97_cx) }, 521 { 0x44543000, "Diamond Technology", cl(ac97_dt) }, 522 { 0x454d4300, "eMicro", cl(ac97_em) }, 523 { 0x45838300, "ESS Technology", cl(ac97_es) }, 524 { 0x48525300, "Intersil", cl(ac97_is) }, 525 { 0x49434500, "ICEnsemble", cl(ac97_ic) }, 526 { 0x49544500, "ITE, Inc.", cl(ac97_it) }, 527 { 0x4e534300, "National Semiconductor", cl(ac97_ns) }, 528 { 0x50534300, "Philips Semiconductor", cl(ac97_ps) }, 529 { 0x53494c00, "Silicon Laboratory", cl(ac97_sl) }, 530 { 0x54524100, "TriTech Microelectronics", cl(ac97_tt) }, 531 { 0x54584e00, "Texas Instruments", cl(ac97_ti) }, 532 { 0x56494100, "VIA Technologies", cl(ac97_vi) }, 533 { 0x57454300, "Winbond", cl(ac97_wb) }, 534 { 0x574d4c00, "Wolfson", cl(ac97_wo) }, 535 { 0x594d4800, "Yamaha", cl(ac97_ym) }, 536 { 0x83847600, "SigmaTel", cl(ac97_st) }, 537 }; 538 #undef cl 539 540 const char * const ac97enhancement[] = { 541 "No 3D Stereo", 542 "Analog Devices Phat Stereo", 543 "Creative", 544 "National Semi 3D", 545 "Yamaha Ymersion", 546 "BBE 3D", 547 "Crystal Semi 3D", 548 "Qsound QXpander", 549 "Spatializer 3D", 550 "SRS 3D", 551 "Platform Tech 3D", 552 "AKM 3D", 553 "Aureal", 554 "AZTECH 3D", 555 "Binaura 3D", 556 "ESS Technology", 557 "Harman International VMAx", 558 "Nvidea 3D", 559 "Philips Incredible Sound", 560 "Texas Instruments 3D", 561 "VLSI Technology 3D", 562 "TriTech 3D", 563 "Realtek 3D", 564 "Samsung 3D", 565 "Wolfson Microelectronics 3D", 566 "Delta Integration 3D", 567 "SigmaTel 3D", 568 "KS Waves 3D", 569 "Rockwell 3D", 570 "Unknown 3D", 571 "Unknown 3D", 572 "Unknown 3D" 573 }; 574 575 const char * const ac97feature[] = { 576 "mic channel", 577 "reserved", 578 "tone", 579 "simulated stereo", 580 "headphone", 581 "bass boost", 582 "18 bit DAC", 583 "20 bit DAC", 584 "18 bit ADC", 585 "20 bit ADC" 586 }; 587 588 589 int ac97_str_equal(const char *, const char *); 590 int ac97_check_capability(struct ac97_softc *, int); 591 void ac97_setup_source_info(struct ac97_softc *); 592 void ac97_setup_defaults(struct ac97_softc *); 593 int ac97_read(struct ac97_softc *, u_int8_t, u_int16_t *); 594 int ac97_write(struct ac97_softc *, u_int8_t, u_int16_t); 595 596 597 #ifdef AUDIO_DEBUG 598 #define DPRINTF(x) if (ac97debug) printf x 599 #define DPRINTFN(n,x) if (ac97debug>(n)) printf x 600 #ifdef AC97_DEBUG 601 int ac97debug = 1; 602 #else 603 int ac97debug = 0; 604 #endif 605 #else 606 #define DPRINTF(x) 607 #define DPRINTFN(n,x) 608 #endif 609 610 int 611 ac97_read(struct ac97_softc *as, u_int8_t reg, u_int16_t *val) 612 { 613 int error; 614 615 if (((as->host_flags & AC97_HOST_DONT_READ) && 616 (reg != AC97_REG_VENDOR_ID1 && reg != AC97_REG_VENDOR_ID2 && 617 reg != AC97_REG_RESET)) || 618 (as->host_flags & AC97_HOST_DONT_READANY)) { 619 *val = as->shadow_reg[reg >> 1]; 620 return (0); 621 } 622 623 if ((error = as->host_if->read(as->host_if->arg, reg, val))) 624 *val = as->shadow_reg[reg >> 1]; 625 return (error); 626 } 627 628 int 629 ac97_write(struct ac97_softc *as, u_int8_t reg, u_int16_t val) 630 { 631 as->shadow_reg[reg >> 1] = val; 632 return (as->host_if->write(as->host_if->arg, reg, val)); 633 } 634 635 void 636 ac97_setup_defaults(struct ac97_softc *as) 637 { 638 int idx; 639 640 bzero(as->shadow_reg, sizeof(as->shadow_reg)); 641 642 for (idx = 0; idx < nitems(source_info); idx++) { 643 const struct ac97_source_info *si = &source_info[idx]; 644 645 ac97_write(as, si->reg, si->default_value); 646 } 647 } 648 649 void 650 ac97_restore_shadow(struct ac97_codec_if *self) 651 { 652 struct ac97_softc *as = (struct ac97_softc *)self; 653 int idx; 654 655 for (idx = 0; idx < nitems(source_info); idx++) { 656 const struct ac97_source_info *si = &source_info[idx]; 657 658 ac97_write(as, si->reg, as->shadow_reg[si->reg >> 1]); 659 } 660 } 661 662 int 663 ac97_str_equal(const char *a, const char *b) 664 { 665 return ((a == b) || (a && b && (!strcmp(a, b)))); 666 } 667 668 int 669 ac97_check_capability(struct ac97_softc *as, int check) 670 { 671 switch (check) { 672 case CHECK_NONE: 673 return 1; 674 case CHECK_SURROUND: 675 return as->ext_id & AC97_EXT_AUDIO_SDAC; 676 case CHECK_CENTER: 677 return as->ext_id & AC97_EXT_AUDIO_CDAC; 678 case CHECK_LFE: 679 return as->ext_id & AC97_EXT_AUDIO_LDAC; 680 case CHECK_SPDIF: 681 return as->ext_id & AC97_EXT_AUDIO_SPDIF; 682 case CHECK_HEADPHONES: 683 return as->caps & AC97_CAPS_HEADPHONES; 684 case CHECK_TONE: 685 return as->caps & AC97_CAPS_TONECTRL; 686 case CHECK_MIC: 687 return as->caps & AC97_CAPS_MICIN; 688 case CHECK_LOUDNESS: 689 return as->caps & AC97_CAPS_LOUDNESS; 690 case CHECK_3D: 691 return AC97_CAPS_ENHANCEMENT(as->caps) != 0; 692 default: 693 printf("%s: internal error: feature=%d\n", __func__, check); 694 return 0; 695 } 696 } 697 698 void 699 ac97_setup_source_info(struct ac97_softc *as) 700 { 701 struct ac97_source_info *si, *si2; 702 int idx, ouridx; 703 704 for (idx = 0, ouridx = 0; idx < nitems(source_info); idx++) { 705 si = &as->source_info[ouridx]; 706 707 if (!ac97_check_capability(as, source_info[idx].req_feature)) 708 continue; 709 710 bcopy(&source_info[idx], si, sizeof(*si)); 711 712 switch (si->type) { 713 case AUDIO_MIXER_CLASS: 714 si->mixer_class = ouridx; 715 ouridx++; 716 break; 717 case AUDIO_MIXER_VALUE: 718 /* Todo - Test to see if it works */ 719 ouridx++; 720 721 /* Add an entry for mute, if necessary */ 722 if (si->mute) { 723 si = &as->source_info[ouridx]; 724 bcopy(&source_info[idx], si, sizeof(*si)); 725 si->qualifier = AudioNmute; 726 si->type = AUDIO_MIXER_ENUM; 727 si->info = &ac97_on_off; 728 si->info_size = sizeof(ac97_on_off); 729 si->bits = 1; 730 si->ofs = 15; 731 si->mute = 0; 732 si->polarity = 0; 733 ouridx++; 734 } 735 break; 736 case AUDIO_MIXER_ENUM: 737 /* Todo - Test to see if it works */ 738 ouridx++; 739 break; 740 default: 741 printf ("ac97: shouldn't get here\n"); 742 break; 743 } 744 } 745 746 as->num_source_info = ouridx; 747 748 for (idx = 0; idx < as->num_source_info; idx++) { 749 int idx2, previdx; 750 751 si = &as->source_info[idx]; 752 753 /* Find mixer class */ 754 for (idx2 = 0; idx2 < as->num_source_info; idx2++) { 755 si2 = &as->source_info[idx2]; 756 757 if (si2->type == AUDIO_MIXER_CLASS && 758 ac97_str_equal(si->class, si2->class)) { 759 si->mixer_class = idx2; 760 } 761 } 762 763 764 /* Setup prev and next pointers */ 765 if (si->prev != 0 || si->qualifier) 766 continue; 767 768 si->prev = AUDIO_MIXER_LAST; 769 previdx = idx; 770 771 for (idx2 = 0; idx2 < as->num_source_info; idx2++) { 772 if (idx2 == idx) 773 continue; 774 775 si2 = &as->source_info[idx2]; 776 777 if (!si2->prev && 778 ac97_str_equal(si->class, si2->class) && 779 ac97_str_equal(si->device, si2->device)) { 780 as->source_info[previdx].next = idx2; 781 as->source_info[idx2].prev = previdx; 782 783 previdx = idx2; 784 } 785 } 786 787 as->source_info[previdx].next = AUDIO_MIXER_LAST; 788 } 789 } 790 791 int 792 ac97_attach(struct ac97_host_if *host_if) 793 { 794 struct ac97_softc *as; 795 u_int16_t id1, id2, val; 796 u_int32_t id; 797 u_int16_t extstat, rate; 798 mixer_ctrl_t ctl; 799 int error, i; 800 void (*initfunc)(struct ac97_softc *, int); 801 802 initfunc = NULL; 803 804 if (!(as = malloc(sizeof(*as), M_DEVBUF, M_NOWAIT | M_ZERO))) 805 return (ENOMEM); 806 807 as->codec_if.as = as; 808 as->codec_if.vtbl = &ac97civ; 809 as->host_if = host_if; 810 811 if ((error = host_if->attach(host_if->arg, &as->codec_if))) { 812 free(as, M_DEVBUF, sizeof(*as)); 813 return (error); 814 } 815 816 host_if->reset(host_if->arg); 817 DELAY(1000); 818 819 host_if->write(host_if->arg, AC97_REG_POWER, 0); 820 host_if->write(host_if->arg, AC97_REG_RESET, 0); 821 DELAY(10000); 822 823 if (host_if->flags) 824 as->host_flags = host_if->flags(host_if->arg); 825 826 ac97_setup_defaults(as); 827 ac97_read(as, AC97_REG_VENDOR_ID1, &id1); 828 ac97_read(as, AC97_REG_VENDOR_ID2, &id2); 829 ac97_read(as, AC97_REG_RESET, &as->caps); 830 831 id = (id1 << 16) | id2; 832 if (id) { 833 register const struct ac97_vendorid *vendor; 834 register const struct ac97_codecid *codec; 835 836 printf("ac97: codec id 0x%08x", id); 837 for (vendor = &ac97_vendors[sizeof(ac97_vendors) / 838 sizeof(ac97_vendors[0]) - 1]; 839 vendor >= ac97_vendors; vendor--) { 840 if (vendor->id == (id & AC97_VENDOR_ID_MASK)) { 841 printf(" (%s", vendor->name); 842 for (codec = &vendor->codecs[vendor->num-1]; 843 codec >= vendor->codecs; codec--) { 844 if (codec->id == (id & codec->mask)) 845 break; 846 } 847 if (codec >= vendor->codecs && codec->mask) { 848 printf(" %s", codec->name); 849 initfunc = codec->init; 850 } else 851 printf(" <%02x>", id & 0xff); 852 if (codec >= vendor->codecs && codec->rev) 853 printf(" rev %d", id & codec->rev); 854 printf(")"); 855 break; 856 } 857 } 858 printf("\n"); 859 } else 860 printf("ac97: codec id not read\n"); 861 862 if (as->caps) { 863 printf("ac97: codec features "); 864 for (i = 0; i < 10; i++) { 865 if (as->caps & (1 << i)) 866 printf("%s, ", ac97feature[i]); 867 } 868 printf("%s\n", 869 ac97enhancement[AC97_CAPS_ENHANCEMENT(as->caps)]); 870 } 871 872 873 as->ac97_clock = AC97_STANDARD_CLOCK; 874 ac97_read(as, AC97_REG_EXT_AUDIO_ID, &as->ext_id); 875 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA 876 | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM 877 | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC 878 | AC97_EXT_AUDIO_LDAC)) { 879 880 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat); 881 extstat &= ~AC97_EXT_AUDIO_DRA; 882 883 if (as->ext_id & AC97_EXT_AUDIO_VRM) 884 extstat |= AC97_EXT_AUDIO_VRM; 885 886 if (as->ext_id & AC97_EXT_AUDIO_LDAC) 887 extstat |= AC97_EXT_AUDIO_LDAC; 888 if (as->ext_id & AC97_EXT_AUDIO_SDAC) 889 extstat |= AC97_EXT_AUDIO_SDAC; 890 if (as->ext_id & AC97_EXT_AUDIO_CDAC) 891 extstat |= AC97_EXT_AUDIO_CDAC; 892 if (as->ext_id & AC97_EXT_AUDIO_SPDIF) { 893 /* XXX S/PDIF gets same data as DAC? 894 * maybe this should be settable? 895 * default is SPSAAB (10/11) on AD1980 and ALC codecs. 896 */ 897 extstat &= ~AC97_EXT_AUDIO_SPSA_MASK; 898 extstat |= AC97_EXT_AUDIO_SPSA34; 899 ac97_read(as, AC97_REG_SPDIF_CTRL, &val); 900 val = (val & ~AC97_SPDIF_SPSR_MASK) | 901 AC97_SPDIF_SPSR_48K; 902 ac97_write(as, AC97_REG_SPDIF_CTRL, val); 903 } 904 if (as->ext_id & AC97_EXT_AUDIO_VRA) 905 extstat |= AC97_EXT_AUDIO_VRA; 906 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat); 907 if (as->ext_id & AC97_EXT_AUDIO_VRA) { 908 /* VRA should be enabled. */ 909 /* so it claims to do variable rate, let's make sure */ 910 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE, 44100); 911 ac97_read(as, AC97_REG_PCM_FRONT_DAC_RATE, &rate); 912 if (rate != 44100) { 913 /* We can't believe ext_id */ 914 as->ext_id = 0; 915 } 916 /* restore the default value */ 917 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE, 918 AC97_SINGLE_RATE); 919 } 920 } 921 922 ac97_setup_source_info(as); 923 924 DELAY(900 * 1000); 925 926 /* use initfunc for specific device */ 927 as->codec_if.initfunc = initfunc; 928 if (initfunc != NULL) 929 initfunc(as, 0); 930 931 /* Just enable the DAC and master volumes by default */ 932 bzero(&ctl, sizeof(ctl)); 933 934 ctl.type = AUDIO_MIXER_ENUM; 935 ctl.un.ord = 0; /* off */ 936 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs, 937 AudioNmaster, AudioNmute); 938 ac97_mixer_set_port(&as->codec_if, &ctl); 939 940 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCinputs, 941 AudioNdac, AudioNmute); 942 ac97_mixer_set_port(&as->codec_if, &ctl); 943 944 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord, 945 AudioNvolume, AudioNmute); 946 ac97_mixer_set_port(&as->codec_if, &ctl); 947 948 ctl.type = AUDIO_MIXER_ENUM; 949 ctl.un.ord = 0; 950 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord, 951 AudioNsource, NULL); 952 ac97_mixer_set_port(&as->codec_if, &ctl); 953 954 return (0); 955 } 956 957 int 958 ac97_resume(struct ac97_host_if *host_if, struct ac97_codec_if *codec_if) 959 { 960 struct ac97_softc *as = codec_if->as; 961 u_int16_t val, extstat; 962 963 host_if->reset(host_if->arg); 964 DELAY(1000); 965 966 host_if->write(host_if->arg, AC97_REG_POWER, 0); 967 host_if->write(host_if->arg, AC97_REG_RESET, 0); 968 DELAY(10000); 969 970 codec_if->vtbl->restore_ports(codec_if); 971 972 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA 973 | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM 974 | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC 975 | AC97_EXT_AUDIO_LDAC)) { 976 977 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat); 978 extstat &= ~AC97_EXT_AUDIO_DRA; 979 980 if (as->ext_id & AC97_EXT_AUDIO_VRM) 981 extstat |= AC97_EXT_AUDIO_VRM; 982 983 if (as->ext_id & AC97_EXT_AUDIO_LDAC) 984 extstat |= AC97_EXT_AUDIO_LDAC; 985 if (as->ext_id & AC97_EXT_AUDIO_SDAC) 986 extstat |= AC97_EXT_AUDIO_SDAC; 987 if (as->ext_id & AC97_EXT_AUDIO_CDAC) 988 extstat |= AC97_EXT_AUDIO_CDAC; 989 990 if (as->ext_id & AC97_EXT_AUDIO_SPDIF) { 991 extstat &= ~AC97_EXT_AUDIO_SPSA_MASK; 992 extstat |= AC97_EXT_AUDIO_SPSA34; 993 ac97_read(as, AC97_REG_SPDIF_CTRL, &val); 994 val = (val & ~AC97_SPDIF_SPSR_MASK) | 995 AC97_SPDIF_SPSR_48K; 996 ac97_write(as, AC97_REG_SPDIF_CTRL, val); 997 } 998 if (as->ext_id & AC97_EXT_AUDIO_VRA) 999 extstat |= AC97_EXT_AUDIO_VRA; 1000 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat); 1001 } 1002 1003 /* use initfunc for specific device */ 1004 if (as->codec_if.initfunc != NULL) 1005 as->codec_if.initfunc(as, 1); 1006 1007 return (0); 1008 } 1009 1010 void 1011 ac97_lock(struct ac97_codec_if *codec_if) 1012 { 1013 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1014 as->lock_counter++; 1015 } 1016 1017 void 1018 ac97_unlock(struct ac97_codec_if *codec_if) 1019 { 1020 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1021 as->lock_counter--; 1022 } 1023 1024 int 1025 ac97_query_devinfo(struct ac97_codec_if *codec_if, mixer_devinfo_t *dip) 1026 { 1027 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1028 1029 if (dip->index < as->num_source_info && dip->index >= 0) { 1030 struct ac97_source_info *si = &as->source_info[dip->index]; 1031 const char *name; 1032 1033 dip->type = si->type; 1034 dip->mixer_class = si->mixer_class; 1035 dip->prev = si->prev; 1036 dip->next = si->next; 1037 1038 if (si->qualifier) 1039 name = si->qualifier; 1040 else if (si->device) 1041 name = si->device; 1042 else if (si->class) 1043 name = si->class; 1044 else 1045 name = NULL; 1046 1047 if (name) 1048 strlcpy(dip->label.name, name, sizeof dip->label.name); 1049 1050 bcopy(si->info, &dip->un, si->info_size); 1051 1052 /* Set the delta for volume sources */ 1053 if (dip->type == AUDIO_MIXER_VALUE) 1054 dip->un.v.delta = 1 << (8 - si->bits); 1055 1056 return (0); 1057 } 1058 1059 return (ENXIO); 1060 } 1061 1062 int 1063 ac97_mixer_set_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp) 1064 { 1065 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1066 struct ac97_source_info *si = &as->source_info[cp->dev]; 1067 u_int16_t mask; 1068 u_int16_t val, newval; 1069 int error, spdif; 1070 1071 if (cp->dev < 0 || cp->dev >= as->num_source_info || 1072 cp->type == AUDIO_MIXER_CLASS || cp->type != si->type) 1073 return (EINVAL); 1074 1075 spdif = si->req_feature == CHECK_SPDIF && 1076 si->reg == AC97_REG_EXT_AUDIO_CTRL; 1077 if (spdif && as->lock_counter >= 0) 1078 return EBUSY; 1079 1080 ac97_read(as, si->reg, &val); 1081 1082 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val)); 1083 1084 mask = (1 << si->bits) - 1; 1085 1086 switch (cp->type) { 1087 case AUDIO_MIXER_ENUM: 1088 if (cp->un.ord > mask || cp->un.ord < 0) 1089 return (EINVAL); 1090 1091 newval = (cp->un.ord << si->ofs); 1092 if (si->reg == AC97_REG_RECORD_SELECT) { 1093 newval |= (newval << (8 + si->ofs)); 1094 mask |= (mask << 8); 1095 mask = mask << si->ofs; 1096 } else if (si->reg == AC97_REG_SURR_MASTER) { 1097 newval = cp->un.ord ? 0x8080 : 0x0000; 1098 mask = 0x8080; 1099 } else 1100 mask = mask << si->ofs; 1101 1102 if (si->mute) { 1103 newval |= newval << 8; 1104 mask |= mask << 8; 1105 } 1106 1107 break; 1108 case AUDIO_MIXER_VALUE: 1109 { 1110 const struct audio_mixer_value *value = si->info; 1111 u_int16_t l, r; 1112 1113 if (cp->un.value.num_channels <= 0 || 1114 cp->un.value.num_channels > value->num_channels) 1115 return (EINVAL); 1116 1117 if (cp->un.value.num_channels == 1) { 1118 l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 1119 } else { 1120 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) { 1121 l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1122 r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1123 } else { 1124 r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1125 l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1126 } 1127 } 1128 1129 if (!si->polarity) { 1130 l = 255 - l; 1131 r = 255 - r; 1132 } 1133 1134 l >>= 8 - si->bits; 1135 r >>= 8 - si->bits; 1136 1137 newval = ((l & mask) << si->ofs); 1138 if (value->num_channels == 2) { 1139 newval |= ((r & mask) << (si->ofs + 8)); 1140 mask |= (mask << 8); 1141 } 1142 mask = mask << si->ofs; 1143 break; 1144 } 1145 default: 1146 return (EINVAL); 1147 } 1148 1149 error = ac97_write(as, si->reg, (val & ~mask) | newval); 1150 if (error) 1151 return (error); 1152 1153 if (spdif && as->host_if->spdif_event != NULL) 1154 as->host_if->spdif_event(as->host_if->arg, cp->un.ord); 1155 1156 return (0); 1157 } 1158 1159 1160 int 1161 ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_long *rate) 1162 { 1163 struct ac97_softc *as; 1164 u_long value; 1165 u_int16_t ext_stat; 1166 u_int16_t actual; 1167 u_int16_t power; 1168 u_int16_t power_bit; 1169 1170 as = (struct ac97_softc *)codec_if; 1171 1172 if ((target == AC97_REG_PCM_SURR_DAC_RATE) && 1173 !(as->ext_id & AC97_EXT_AUDIO_SDAC)) 1174 return 0; 1175 if ((target == AC97_REG_PCM_LFE_DAC_RATE) && 1176 !(as->ext_id & AC97_EXT_AUDIO_LDAC)) 1177 return 0; 1178 if (target == AC97_REG_PCM_MIC_ADC_RATE) { 1179 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) { 1180 *rate = AC97_SINGLE_RATE; 1181 return 0; 1182 } 1183 } else { 1184 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) { 1185 *rate = AC97_SINGLE_RATE; 1186 return 0; 1187 } 1188 } 1189 if (as->ac97_clock == 0) 1190 as->ac97_clock = AC97_STANDARD_CLOCK; 1191 value = *rate * AC97_STANDARD_CLOCK / as->ac97_clock; 1192 ext_stat = 0; 1193 /* 1194 * PCM_FRONT_DAC_RATE/PCM_SURR_DAC_RATE/PCM_LFE_DAC_RATE 1195 * Check VRA, DRA 1196 * PCM_LR_ADC_RATE 1197 * Check VRA 1198 * PCM_MIC_ADC_RATE 1199 * Check VRM 1200 */ 1201 switch (target) { 1202 case AC97_REG_PCM_FRONT_DAC_RATE: 1203 case AC97_REG_PCM_SURR_DAC_RATE: 1204 case AC97_REG_PCM_LFE_DAC_RATE: 1205 power_bit = AC97_POWER_OUT; 1206 if (as->ext_id & AC97_EXT_AUDIO_DRA) { 1207 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &ext_stat); 1208 if (value > 0x1ffff) { 1209 return EINVAL; 1210 } else if (value > 0xffff) { 1211 /* Enable DRA */ 1212 ext_stat |= AC97_EXT_AUDIO_DRA; 1213 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat); 1214 value /= 2; 1215 } else { 1216 /* Disable DRA */ 1217 ext_stat &= ~AC97_EXT_AUDIO_DRA; 1218 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat); 1219 } 1220 } else { 1221 if (value > 0xffff) 1222 return EINVAL; 1223 } 1224 break; 1225 case AC97_REG_PCM_LR_ADC_RATE: 1226 power_bit = AC97_POWER_IN; 1227 if (value > 0xffff) 1228 return EINVAL; 1229 break; 1230 case AC97_REG_PCM_MIC_ADC_RATE: 1231 power_bit = AC97_POWER_IN; 1232 if (value > 0xffff) 1233 return EINVAL; 1234 break; 1235 default: 1236 printf("%s: Unknown register: 0x%x\n", __func__, target); 1237 return EINVAL; 1238 } 1239 1240 ac97_read(as, AC97_REG_POWER, &power); 1241 ac97_write(as, AC97_REG_POWER, power | power_bit); 1242 1243 ac97_write(as, target, (u_int16_t)value); 1244 ac97_read(as, target, &actual); 1245 actual = (u_int32_t)actual * as->ac97_clock / AC97_STANDARD_CLOCK; 1246 1247 ac97_write(as, AC97_REG_POWER, power); 1248 if (ext_stat & AC97_EXT_AUDIO_DRA) { 1249 *rate = actual * 2; 1250 } else { 1251 *rate = actual; 1252 } 1253 return 0; 1254 } 1255 1256 void 1257 ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock) 1258 { 1259 struct ac97_softc *as; 1260 1261 as = (struct ac97_softc *)codec_if; 1262 as->ac97_clock = clock; 1263 } 1264 1265 u_int16_t 1266 ac97_get_extcaps(struct ac97_codec_if *codec_if) 1267 { 1268 struct ac97_softc *as; 1269 1270 as = (struct ac97_softc *)codec_if; 1271 return as->ext_id; 1272 } 1273 1274 int 1275 ac97_add_port(struct ac97_softc *as, struct ac97_source_info *src) 1276 { 1277 struct ac97_source_info *si; 1278 int ouridx, idx; 1279 1280 if (as->num_source_info >= MAX_SOURCES) { 1281 printf("%s: internal error: increase MAX_SOURCES in %s\n", 1282 __func__, __FILE__); 1283 return -1; 1284 } 1285 if (!ac97_check_capability(as, src->req_feature)) 1286 return -1; 1287 ouridx = as->num_source_info; 1288 si = &as->source_info[ouridx]; 1289 memcpy(si, src, sizeof(*si)); 1290 1291 switch (si->type) { 1292 case AUDIO_MIXER_CLASS: 1293 case AUDIO_MIXER_VALUE: 1294 printf("%s: adding class/value is not supported yet.\n", 1295 __func__); 1296 return -1; 1297 case AUDIO_MIXER_ENUM: 1298 break; 1299 default: 1300 printf("%s: unknown type: %d\n", __func__, si->type); 1301 return -1; 1302 } 1303 as->num_source_info++; 1304 1305 si->mixer_class = ac97_get_portnum_by_name(&as->codec_if, si->class, 1306 NULL, NULL); 1307 /* Find the root of the device */ 1308 idx = ac97_get_portnum_by_name(&as->codec_if, si->class, 1309 si->device, NULL); 1310 /* Find the last item */ 1311 while (as->source_info[idx].next != AUDIO_MIXER_LAST) 1312 idx = as->source_info[idx].next; 1313 /* Append */ 1314 as->source_info[idx].next = ouridx; 1315 si->prev = idx; 1316 si->next = AUDIO_MIXER_LAST; 1317 1318 return 0; 1319 } 1320 1321 int 1322 ac97_get_portnum_by_name(struct ac97_codec_if *codec_if, char *class, 1323 char *device, char *qualifier) 1324 { 1325 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1326 int idx; 1327 1328 for (idx = 0; idx < as->num_source_info; idx++) { 1329 struct ac97_source_info *si = &as->source_info[idx]; 1330 if (ac97_str_equal(class, si->class) && 1331 ac97_str_equal(device, si->device) && 1332 ac97_str_equal(qualifier, si->qualifier)) 1333 return (idx); 1334 } 1335 1336 return (-1); 1337 } 1338 1339 int 1340 ac97_mixer_get_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp) 1341 { 1342 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1343 struct ac97_source_info *si = &as->source_info[cp->dev]; 1344 u_int16_t mask; 1345 u_int16_t val; 1346 1347 if (cp->dev < 0 || cp->dev >= as->num_source_info || 1348 cp->type != si->type) 1349 return (EINVAL); 1350 1351 ac97_read(as, si->reg, &val); 1352 1353 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val)); 1354 1355 mask = (1 << si->bits) - 1; 1356 1357 switch (cp->type) { 1358 case AUDIO_MIXER_ENUM: 1359 cp->un.ord = (val >> si->ofs) & mask; 1360 DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n", val, si->ofs, 1361 mask, cp->un.ord)); 1362 break; 1363 case AUDIO_MIXER_VALUE: 1364 { 1365 const struct audio_mixer_value *value = si->info; 1366 u_int16_t l, r; 1367 1368 if ((cp->un.value.num_channels <= 0) || 1369 (cp->un.value.num_channels > value->num_channels)) 1370 return (EINVAL); 1371 1372 if (value->num_channels == 1) 1373 l = r = (val >> si->ofs) & mask; 1374 else { 1375 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) { 1376 l = (val >> si->ofs) & mask; 1377 r = (val >> (si->ofs + 8)) & mask; 1378 } else { 1379 r = (val >> si->ofs) & mask; 1380 l = (val >> (si->ofs + 8)) & mask; 1381 } 1382 } 1383 1384 l <<= 8 - si->bits; 1385 r <<= 8 - si->bits; 1386 if (!si->polarity) { 1387 l = 255 - l; 1388 r = 255 - r; 1389 } 1390 1391 /* 1392 * The EAP driver averages l and r for stereo 1393 * channels that are requested in MONO mode. Does this 1394 * make sense? 1395 */ 1396 if (cp->un.value.num_channels == 1) { 1397 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l; 1398 } else if (cp->un.value.num_channels == 2) { 1399 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l; 1400 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r; 1401 } 1402 1403 break; 1404 } 1405 default: 1406 return (EINVAL); 1407 } 1408 1409 return (0); 1410 } 1411 1412 1413 /* 1414 * Codec-dependent initialization 1415 */ 1416 1417 void 1418 ac97_ad1885_init(struct ac97_softc *as, int resuming) 1419 { 1420 int i; 1421 1422 if (resuming) 1423 return; 1424 1425 for (i = 0; i < as->num_source_info; i++) { 1426 if (as->source_info[i].reg == AC97_REG_HEADPHONE_VOLUME) 1427 as->source_info[i].reg = AC97_REG_MASTER_VOLUME; 1428 else if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME) 1429 as->source_info[i].reg = AC97_REG_HEADPHONE_VOLUME; 1430 } 1431 } 1432 1433 #define AC97_AD1886_JACK_SENSE 0x72 1434 1435 void 1436 ac97_ad1886_init(struct ac97_softc *as, int resuming) 1437 { 1438 ac97_write(as, AC97_AD1886_JACK_SENSE, 0x0010); 1439 } 1440 1441 void 1442 ac97_ad198x_init(struct ac97_softc *as, int resuming) 1443 { 1444 int i; 1445 u_int16_t misc; 1446 1447 ac97_read(as, AC97_AD_REG_MISC, &misc); 1448 ac97_write(as, AC97_AD_REG_MISC, 1449 misc|AC97_AD_MISC_HPSEL|AC97_AD_MISC_LOSEL); 1450 1451 if (resuming) 1452 return; 1453 1454 for (i = 0; i < as->num_source_info; i++) { 1455 if (as->source_info[i].reg == AC97_REG_SURR_MASTER) 1456 as->source_info[i].reg = AC97_REG_MASTER_VOLUME; 1457 else if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME) 1458 as->source_info[i].reg = AC97_REG_SURR_MASTER; 1459 } 1460 } 1461 1462 void 1463 ac97_alc650_init(struct ac97_softc *as, int resuming) 1464 { 1465 u_int16_t misc; 1466 1467 ac97_read(as, AC97_ALC650_REG_MISC, &misc); 1468 if (as->host_flags & AC97_HOST_ALC650_PIN47_IS_EAPD) 1469 misc &= ~AC97_ALC650_MISC_PIN47; 1470 misc &= ~AC97_ALC650_MISC_VREFDIS; 1471 ac97_write(as, AC97_ALC650_REG_MISC, misc); 1472 1473 if (resuming) 1474 return; 1475 1476 struct ac97_source_info sources[3] = { 1477 { AudioCoutputs, AudioNsurround, "lineinjack", 1478 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1479 AC97_ALC650_REG_MULTI_CHANNEL_CONTROL, 1480 0x0000, 1, 9, 0, 0, CHECK_SURROUND }, 1481 { AudioCoutputs, AudioNcenter, "micjack", 1482 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1483 AC97_ALC650_REG_MULTI_CHANNEL_CONTROL, 1484 0x0000, 1, 10, 0, 0, CHECK_CENTER }, 1485 { AudioCoutputs, AudioNlfe, "micjack", 1486 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1487 AC97_ALC650_REG_MULTI_CHANNEL_CONTROL, 1488 0x0000, 1, 10, 0, 0, CHECK_LFE }}; 1489 1490 ac97_add_port(as, &sources[0]); 1491 ac97_add_port(as, &sources[1]); 1492 ac97_add_port(as, &sources[2]); 1493 } 1494 1495 void 1496 ac97_cx20468_init(struct ac97_softc *as, int resuming) 1497 { 1498 u_int16_t misc; 1499 1500 ac97_read(as, AC97_CX_REG_MISC, &misc); 1501 ac97_write(as, AC97_CX_REG_MISC, misc & 1502 ~(AC97_CX_SPDIFEN | AC97_CX_COPYRIGHT | AC97_CX_MASK)); 1503 } 1504 1505 void 1506 ac97_vt1616_init(struct ac97_softc *as, int resuming) 1507 { 1508 u_int16_t reg; 1509 1510 if (as->host_flags & AC97_HOST_VT1616_DYNEX) { 1511 ac97_read(as, AC97_VT_REG_TEST, ®); 1512 1513 /* disable 'hp' mixer controls controlling the surround pins */ 1514 reg &= ~(AC97_VT_LVL); 1515 1516 /* disable downmixing */ 1517 reg &= ~(AC97_VT_LCTF | AC97_VT_STF); 1518 1519 /* enable DC offset removal */ 1520 reg |= AC97_VT_BPDC; 1521 1522 ac97_write(as, AC97_VT_REG_TEST, reg); 1523 } 1524 } 1525