1 /* $OpenBSD: ac97.c,v 1.81 2015/08/28 00:03:53 deraadt 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 void 611 ac97_get_default_params(struct audio_params *params) 612 { 613 *params = ac97_audio_default; 614 } 615 616 int 617 ac97_read(struct ac97_softc *as, u_int8_t reg, u_int16_t *val) 618 { 619 int error; 620 621 if (((as->host_flags & AC97_HOST_DONT_READ) && 622 (reg != AC97_REG_VENDOR_ID1 && reg != AC97_REG_VENDOR_ID2 && 623 reg != AC97_REG_RESET)) || 624 (as->host_flags & AC97_HOST_DONT_READANY)) { 625 *val = as->shadow_reg[reg >> 1]; 626 return (0); 627 } 628 629 if ((error = as->host_if->read(as->host_if->arg, reg, val))) 630 *val = as->shadow_reg[reg >> 1]; 631 return (error); 632 } 633 634 int 635 ac97_write(struct ac97_softc *as, u_int8_t reg, u_int16_t val) 636 { 637 as->shadow_reg[reg >> 1] = val; 638 return (as->host_if->write(as->host_if->arg, reg, val)); 639 } 640 641 void 642 ac97_setup_defaults(struct ac97_softc *as) 643 { 644 int idx; 645 646 bzero(as->shadow_reg, sizeof(as->shadow_reg)); 647 648 for (idx = 0; idx < nitems(source_info); idx++) { 649 const struct ac97_source_info *si = &source_info[idx]; 650 651 ac97_write(as, si->reg, si->default_value); 652 } 653 } 654 655 void 656 ac97_restore_shadow(struct ac97_codec_if *self) 657 { 658 struct ac97_softc *as = (struct ac97_softc *)self; 659 int idx; 660 661 for (idx = 0; idx < nitems(source_info); idx++) { 662 const struct ac97_source_info *si = &source_info[idx]; 663 664 ac97_write(as, si->reg, as->shadow_reg[si->reg >> 1]); 665 } 666 } 667 668 int 669 ac97_str_equal(const char *a, const char *b) 670 { 671 return ((a == b) || (a && b && (!strcmp(a, b)))); 672 } 673 674 int 675 ac97_check_capability(struct ac97_softc *as, int check) 676 { 677 switch (check) { 678 case CHECK_NONE: 679 return 1; 680 case CHECK_SURROUND: 681 return as->ext_id & AC97_EXT_AUDIO_SDAC; 682 case CHECK_CENTER: 683 return as->ext_id & AC97_EXT_AUDIO_CDAC; 684 case CHECK_LFE: 685 return as->ext_id & AC97_EXT_AUDIO_LDAC; 686 case CHECK_SPDIF: 687 return as->ext_id & AC97_EXT_AUDIO_SPDIF; 688 case CHECK_HEADPHONES: 689 return as->caps & AC97_CAPS_HEADPHONES; 690 case CHECK_TONE: 691 return as->caps & AC97_CAPS_TONECTRL; 692 case CHECK_MIC: 693 return as->caps & AC97_CAPS_MICIN; 694 case CHECK_LOUDNESS: 695 return as->caps & AC97_CAPS_LOUDNESS; 696 case CHECK_3D: 697 return AC97_CAPS_ENHANCEMENT(as->caps) != 0; 698 default: 699 printf("%s: internal error: feature=%d\n", __func__, check); 700 return 0; 701 } 702 } 703 704 void 705 ac97_setup_source_info(struct ac97_softc *as) 706 { 707 struct ac97_source_info *si, *si2; 708 int idx, ouridx; 709 710 for (idx = 0, ouridx = 0; idx < nitems(source_info); idx++) { 711 si = &as->source_info[ouridx]; 712 713 if (!ac97_check_capability(as, source_info[idx].req_feature)) 714 continue; 715 716 bcopy(&source_info[idx], si, sizeof(*si)); 717 718 switch (si->type) { 719 case AUDIO_MIXER_CLASS: 720 si->mixer_class = ouridx; 721 ouridx++; 722 break; 723 case AUDIO_MIXER_VALUE: 724 /* Todo - Test to see if it works */ 725 ouridx++; 726 727 /* Add an entry for mute, if necessary */ 728 if (si->mute) { 729 si = &as->source_info[ouridx]; 730 bcopy(&source_info[idx], si, sizeof(*si)); 731 si->qualifier = AudioNmute; 732 si->type = AUDIO_MIXER_ENUM; 733 si->info = &ac97_on_off; 734 si->info_size = sizeof(ac97_on_off); 735 si->bits = 1; 736 si->ofs = 15; 737 si->mute = 0; 738 si->polarity = 0; 739 ouridx++; 740 } 741 break; 742 case AUDIO_MIXER_ENUM: 743 /* Todo - Test to see if it works */ 744 ouridx++; 745 break; 746 default: 747 printf ("ac97: shouldn't get here\n"); 748 break; 749 } 750 } 751 752 as->num_source_info = ouridx; 753 754 for (idx = 0; idx < as->num_source_info; idx++) { 755 int idx2, previdx; 756 757 si = &as->source_info[idx]; 758 759 /* Find mixer class */ 760 for (idx2 = 0; idx2 < as->num_source_info; idx2++) { 761 si2 = &as->source_info[idx2]; 762 763 if (si2->type == AUDIO_MIXER_CLASS && 764 ac97_str_equal(si->class, si2->class)) { 765 si->mixer_class = idx2; 766 } 767 } 768 769 770 /* Setup prev and next pointers */ 771 if (si->prev != 0 || si->qualifier) 772 continue; 773 774 si->prev = AUDIO_MIXER_LAST; 775 previdx = idx; 776 777 for (idx2 = 0; idx2 < as->num_source_info; idx2++) { 778 if (idx2 == idx) 779 continue; 780 781 si2 = &as->source_info[idx2]; 782 783 if (!si2->prev && 784 ac97_str_equal(si->class, si2->class) && 785 ac97_str_equal(si->device, si2->device)) { 786 as->source_info[previdx].next = idx2; 787 as->source_info[idx2].prev = previdx; 788 789 previdx = idx2; 790 } 791 } 792 793 as->source_info[previdx].next = AUDIO_MIXER_LAST; 794 } 795 } 796 797 int 798 ac97_attach(struct ac97_host_if *host_if) 799 { 800 struct ac97_softc *as; 801 u_int16_t id1, id2, val; 802 u_int32_t id; 803 u_int16_t extstat, rate; 804 mixer_ctrl_t ctl; 805 int error, i; 806 void (*initfunc)(struct ac97_softc *, int); 807 808 initfunc = NULL; 809 810 if (!(as = malloc(sizeof(*as), M_DEVBUF, M_NOWAIT | M_ZERO))) 811 return (ENOMEM); 812 813 as->codec_if.as = as; 814 as->codec_if.vtbl = &ac97civ; 815 as->host_if = host_if; 816 817 if ((error = host_if->attach(host_if->arg, &as->codec_if))) { 818 free(as, M_DEVBUF, sizeof(*as)); 819 return (error); 820 } 821 822 host_if->reset(host_if->arg); 823 DELAY(1000); 824 825 host_if->write(host_if->arg, AC97_REG_POWER, 0); 826 host_if->write(host_if->arg, AC97_REG_RESET, 0); 827 DELAY(10000); 828 829 if (host_if->flags) 830 as->host_flags = host_if->flags(host_if->arg); 831 832 ac97_setup_defaults(as); 833 ac97_read(as, AC97_REG_VENDOR_ID1, &id1); 834 ac97_read(as, AC97_REG_VENDOR_ID2, &id2); 835 ac97_read(as, AC97_REG_RESET, &as->caps); 836 837 id = (id1 << 16) | id2; 838 if (id) { 839 register const struct ac97_vendorid *vendor; 840 register const struct ac97_codecid *codec; 841 842 printf("ac97: codec id 0x%08x", id); 843 for (vendor = &ac97_vendors[sizeof(ac97_vendors) / 844 sizeof(ac97_vendors[0]) - 1]; 845 vendor >= ac97_vendors; vendor--) { 846 if (vendor->id == (id & AC97_VENDOR_ID_MASK)) { 847 printf(" (%s", vendor->name); 848 for (codec = &vendor->codecs[vendor->num-1]; 849 codec >= vendor->codecs; codec--) { 850 if (codec->id == (id & codec->mask)) 851 break; 852 } 853 if (codec >= vendor->codecs && codec->mask) { 854 printf(" %s", codec->name); 855 initfunc = codec->init; 856 } else 857 printf(" <%02x>", id & 0xff); 858 if (codec >= vendor->codecs && codec->rev) 859 printf(" rev %d", id & codec->rev); 860 printf(")"); 861 break; 862 } 863 } 864 printf("\n"); 865 } else 866 printf("ac97: codec id not read\n"); 867 868 if (as->caps) { 869 printf("ac97: codec features "); 870 for (i = 0; i < 10; i++) { 871 if (as->caps & (1 << i)) 872 printf("%s, ", ac97feature[i]); 873 } 874 printf("%s\n", 875 ac97enhancement[AC97_CAPS_ENHANCEMENT(as->caps)]); 876 } 877 878 879 as->ac97_clock = AC97_STANDARD_CLOCK; 880 ac97_read(as, AC97_REG_EXT_AUDIO_ID, &as->ext_id); 881 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA 882 | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM 883 | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC 884 | AC97_EXT_AUDIO_LDAC)) { 885 886 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat); 887 extstat &= ~AC97_EXT_AUDIO_DRA; 888 889 if (as->ext_id & AC97_EXT_AUDIO_VRM) 890 extstat |= AC97_EXT_AUDIO_VRM; 891 892 if (as->ext_id & AC97_EXT_AUDIO_LDAC) 893 extstat |= AC97_EXT_AUDIO_LDAC; 894 if (as->ext_id & AC97_EXT_AUDIO_SDAC) 895 extstat |= AC97_EXT_AUDIO_SDAC; 896 if (as->ext_id & AC97_EXT_AUDIO_CDAC) 897 extstat |= AC97_EXT_AUDIO_CDAC; 898 if (as->ext_id & AC97_EXT_AUDIO_SPDIF) { 899 /* XXX S/PDIF gets same data as DAC? 900 * maybe this should be settable? 901 * default is SPSAAB (10/11) on AD1980 and ALC codecs. 902 */ 903 extstat &= ~AC97_EXT_AUDIO_SPSA_MASK; 904 extstat |= AC97_EXT_AUDIO_SPSA34; 905 ac97_read(as, AC97_REG_SPDIF_CTRL, &val); 906 val = (val & ~AC97_SPDIF_SPSR_MASK) | 907 AC97_SPDIF_SPSR_48K; 908 ac97_write(as, AC97_REG_SPDIF_CTRL, val); 909 } 910 if (as->ext_id & AC97_EXT_AUDIO_VRA) 911 extstat |= AC97_EXT_AUDIO_VRA; 912 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat); 913 if (as->ext_id & AC97_EXT_AUDIO_VRA) { 914 /* VRA should be enabled. */ 915 /* so it claims to do variable rate, let's make sure */ 916 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE, 44100); 917 ac97_read(as, AC97_REG_PCM_FRONT_DAC_RATE, &rate); 918 if (rate != 44100) { 919 /* We can't believe ext_id */ 920 as->ext_id = 0; 921 } 922 /* restore the default value */ 923 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE, 924 AC97_SINGLE_RATE); 925 } 926 } 927 928 ac97_setup_source_info(as); 929 930 DELAY(900 * 1000); 931 932 /* use initfunc for specific device */ 933 as->codec_if.initfunc = initfunc; 934 if (initfunc != NULL) 935 initfunc(as, 0); 936 937 /* Just enable the DAC and master volumes by default */ 938 bzero(&ctl, sizeof(ctl)); 939 940 ctl.type = AUDIO_MIXER_ENUM; 941 ctl.un.ord = 0; /* off */ 942 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs, 943 AudioNmaster, AudioNmute); 944 ac97_mixer_set_port(&as->codec_if, &ctl); 945 946 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCinputs, 947 AudioNdac, AudioNmute); 948 ac97_mixer_set_port(&as->codec_if, &ctl); 949 950 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord, 951 AudioNvolume, AudioNmute); 952 ac97_mixer_set_port(&as->codec_if, &ctl); 953 954 ctl.type = AUDIO_MIXER_ENUM; 955 ctl.un.ord = 0; 956 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord, 957 AudioNsource, NULL); 958 ac97_mixer_set_port(&as->codec_if, &ctl); 959 960 return (0); 961 } 962 963 int 964 ac97_resume(struct ac97_host_if *host_if, struct ac97_codec_if *codec_if) 965 { 966 struct ac97_softc *as = codec_if->as; 967 u_int16_t val, extstat; 968 969 host_if->reset(host_if->arg); 970 DELAY(1000); 971 972 host_if->write(host_if->arg, AC97_REG_POWER, 0); 973 host_if->write(host_if->arg, AC97_REG_RESET, 0); 974 DELAY(10000); 975 976 codec_if->vtbl->restore_ports(codec_if); 977 978 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA 979 | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM 980 | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC 981 | AC97_EXT_AUDIO_LDAC)) { 982 983 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat); 984 extstat &= ~AC97_EXT_AUDIO_DRA; 985 986 if (as->ext_id & AC97_EXT_AUDIO_VRM) 987 extstat |= AC97_EXT_AUDIO_VRM; 988 989 if (as->ext_id & AC97_EXT_AUDIO_LDAC) 990 extstat |= AC97_EXT_AUDIO_LDAC; 991 if (as->ext_id & AC97_EXT_AUDIO_SDAC) 992 extstat |= AC97_EXT_AUDIO_SDAC; 993 if (as->ext_id & AC97_EXT_AUDIO_CDAC) 994 extstat |= AC97_EXT_AUDIO_CDAC; 995 996 if (as->ext_id & AC97_EXT_AUDIO_SPDIF) { 997 extstat &= ~AC97_EXT_AUDIO_SPSA_MASK; 998 extstat |= AC97_EXT_AUDIO_SPSA34; 999 ac97_read(as, AC97_REG_SPDIF_CTRL, &val); 1000 val = (val & ~AC97_SPDIF_SPSR_MASK) | 1001 AC97_SPDIF_SPSR_48K; 1002 ac97_write(as, AC97_REG_SPDIF_CTRL, val); 1003 } 1004 if (as->ext_id & AC97_EXT_AUDIO_VRA) 1005 extstat |= AC97_EXT_AUDIO_VRA; 1006 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat); 1007 } 1008 1009 /* use initfunc for specific device */ 1010 if (as->codec_if.initfunc != NULL) 1011 as->codec_if.initfunc(as, 1); 1012 1013 return (0); 1014 } 1015 1016 void 1017 ac97_lock(struct ac97_codec_if *codec_if) 1018 { 1019 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1020 as->lock_counter++; 1021 } 1022 1023 void 1024 ac97_unlock(struct ac97_codec_if *codec_if) 1025 { 1026 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1027 as->lock_counter--; 1028 } 1029 1030 int 1031 ac97_query_devinfo(struct ac97_codec_if *codec_if, mixer_devinfo_t *dip) 1032 { 1033 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1034 1035 if (dip->index < as->num_source_info && dip->index >= 0) { 1036 struct ac97_source_info *si = &as->source_info[dip->index]; 1037 const char *name; 1038 1039 dip->type = si->type; 1040 dip->mixer_class = si->mixer_class; 1041 dip->prev = si->prev; 1042 dip->next = si->next; 1043 1044 if (si->qualifier) 1045 name = si->qualifier; 1046 else if (si->device) 1047 name = si->device; 1048 else if (si->class) 1049 name = si->class; 1050 else 1051 name = NULL; 1052 1053 if (name) 1054 strlcpy(dip->label.name, name, sizeof dip->label.name); 1055 1056 bcopy(si->info, &dip->un, si->info_size); 1057 1058 /* Set the delta for volume sources */ 1059 if (dip->type == AUDIO_MIXER_VALUE) 1060 dip->un.v.delta = 1 << (8 - si->bits); 1061 1062 return (0); 1063 } 1064 1065 return (ENXIO); 1066 } 1067 1068 int 1069 ac97_mixer_set_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp) 1070 { 1071 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1072 struct ac97_source_info *si = &as->source_info[cp->dev]; 1073 u_int16_t mask; 1074 u_int16_t val, newval; 1075 int error, spdif; 1076 1077 if (cp->dev < 0 || cp->dev >= as->num_source_info || 1078 cp->type == AUDIO_MIXER_CLASS || cp->type != si->type) 1079 return (EINVAL); 1080 1081 spdif = si->req_feature == CHECK_SPDIF && 1082 si->reg == AC97_REG_EXT_AUDIO_CTRL; 1083 if (spdif && as->lock_counter >= 0) 1084 return EBUSY; 1085 1086 ac97_read(as, si->reg, &val); 1087 1088 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val)); 1089 1090 mask = (1 << si->bits) - 1; 1091 1092 switch (cp->type) { 1093 case AUDIO_MIXER_ENUM: 1094 if (cp->un.ord > mask || cp->un.ord < 0) 1095 return (EINVAL); 1096 1097 newval = (cp->un.ord << si->ofs); 1098 if (si->reg == AC97_REG_RECORD_SELECT) { 1099 newval |= (newval << (8 + si->ofs)); 1100 mask |= (mask << 8); 1101 mask = mask << si->ofs; 1102 } else if (si->reg == AC97_REG_SURR_MASTER) { 1103 newval = cp->un.ord ? 0x8080 : 0x0000; 1104 mask = 0x8080; 1105 } else 1106 mask = mask << si->ofs; 1107 1108 if (si->mute) { 1109 newval |= newval << 8; 1110 mask |= mask << 8; 1111 } 1112 1113 break; 1114 case AUDIO_MIXER_VALUE: 1115 { 1116 const struct audio_mixer_value *value = si->info; 1117 u_int16_t l, r; 1118 1119 if (cp->un.value.num_channels <= 0 || 1120 cp->un.value.num_channels > value->num_channels) 1121 return (EINVAL); 1122 1123 if (cp->un.value.num_channels == 1) { 1124 l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 1125 } else { 1126 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) { 1127 l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1128 r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1129 } else { 1130 r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1131 l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1132 } 1133 } 1134 1135 if (!si->polarity) { 1136 l = 255 - l; 1137 r = 255 - r; 1138 } 1139 1140 l >>= 8 - si->bits; 1141 r >>= 8 - si->bits; 1142 1143 newval = ((l & mask) << si->ofs); 1144 if (value->num_channels == 2) { 1145 newval |= ((r & mask) << (si->ofs + 8)); 1146 mask |= (mask << 8); 1147 } 1148 mask = mask << si->ofs; 1149 break; 1150 } 1151 default: 1152 return (EINVAL); 1153 } 1154 1155 error = ac97_write(as, si->reg, (val & ~mask) | newval); 1156 if (error) 1157 return (error); 1158 1159 if (spdif && as->host_if->spdif_event != NULL) 1160 as->host_if->spdif_event(as->host_if->arg, cp->un.ord); 1161 1162 return (0); 1163 } 1164 1165 1166 int 1167 ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_long *rate) 1168 { 1169 struct ac97_softc *as; 1170 u_long value; 1171 u_int16_t ext_stat; 1172 u_int16_t actual; 1173 u_int16_t power; 1174 u_int16_t power_bit; 1175 1176 as = (struct ac97_softc *)codec_if; 1177 1178 if ((target == AC97_REG_PCM_SURR_DAC_RATE) && 1179 !(as->ext_id & AC97_EXT_AUDIO_SDAC)) 1180 return 0; 1181 if ((target == AC97_REG_PCM_LFE_DAC_RATE) && 1182 !(as->ext_id & AC97_EXT_AUDIO_LDAC)) 1183 return 0; 1184 if (target == AC97_REG_PCM_MIC_ADC_RATE) { 1185 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) { 1186 *rate = AC97_SINGLE_RATE; 1187 return 0; 1188 } 1189 } else { 1190 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) { 1191 *rate = AC97_SINGLE_RATE; 1192 return 0; 1193 } 1194 } 1195 if (as->ac97_clock == 0) 1196 as->ac97_clock = AC97_STANDARD_CLOCK; 1197 value = *rate * AC97_STANDARD_CLOCK / as->ac97_clock; 1198 ext_stat = 0; 1199 /* 1200 * PCM_FRONT_DAC_RATE/PCM_SURR_DAC_RATE/PCM_LFE_DAC_RATE 1201 * Check VRA, DRA 1202 * PCM_LR_ADC_RATE 1203 * Check VRA 1204 * PCM_MIC_ADC_RATE 1205 * Check VRM 1206 */ 1207 switch (target) { 1208 case AC97_REG_PCM_FRONT_DAC_RATE: 1209 case AC97_REG_PCM_SURR_DAC_RATE: 1210 case AC97_REG_PCM_LFE_DAC_RATE: 1211 power_bit = AC97_POWER_OUT; 1212 if (as->ext_id & AC97_EXT_AUDIO_DRA) { 1213 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &ext_stat); 1214 if (value > 0x1ffff) { 1215 return EINVAL; 1216 } else if (value > 0xffff) { 1217 /* Enable DRA */ 1218 ext_stat |= AC97_EXT_AUDIO_DRA; 1219 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat); 1220 value /= 2; 1221 } else { 1222 /* Disable DRA */ 1223 ext_stat &= ~AC97_EXT_AUDIO_DRA; 1224 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat); 1225 } 1226 } else { 1227 if (value > 0xffff) 1228 return EINVAL; 1229 } 1230 break; 1231 case AC97_REG_PCM_LR_ADC_RATE: 1232 power_bit = AC97_POWER_IN; 1233 if (value > 0xffff) 1234 return EINVAL; 1235 break; 1236 case AC97_REG_PCM_MIC_ADC_RATE: 1237 power_bit = AC97_POWER_IN; 1238 if (value > 0xffff) 1239 return EINVAL; 1240 break; 1241 default: 1242 printf("%s: Unknown register: 0x%x\n", __func__, target); 1243 return EINVAL; 1244 } 1245 1246 ac97_read(as, AC97_REG_POWER, &power); 1247 ac97_write(as, AC97_REG_POWER, power | power_bit); 1248 1249 ac97_write(as, target, (u_int16_t)value); 1250 ac97_read(as, target, &actual); 1251 actual = (u_int32_t)actual * as->ac97_clock / AC97_STANDARD_CLOCK; 1252 1253 ac97_write(as, AC97_REG_POWER, power); 1254 if (ext_stat & AC97_EXT_AUDIO_DRA) { 1255 *rate = actual * 2; 1256 } else { 1257 *rate = actual; 1258 } 1259 return 0; 1260 } 1261 1262 void 1263 ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock) 1264 { 1265 struct ac97_softc *as; 1266 1267 as = (struct ac97_softc *)codec_if; 1268 as->ac97_clock = clock; 1269 } 1270 1271 u_int16_t 1272 ac97_get_extcaps(struct ac97_codec_if *codec_if) 1273 { 1274 struct ac97_softc *as; 1275 1276 as = (struct ac97_softc *)codec_if; 1277 return as->ext_id; 1278 } 1279 1280 int 1281 ac97_add_port(struct ac97_softc *as, struct ac97_source_info *src) 1282 { 1283 struct ac97_source_info *si; 1284 int ouridx, idx; 1285 1286 if (as->num_source_info >= MAX_SOURCES) { 1287 printf("%s: internal error: increase MAX_SOURCES in %s\n", 1288 __func__, __FILE__); 1289 return -1; 1290 } 1291 if (!ac97_check_capability(as, src->req_feature)) 1292 return -1; 1293 ouridx = as->num_source_info; 1294 si = &as->source_info[ouridx]; 1295 memcpy(si, src, sizeof(*si)); 1296 1297 switch (si->type) { 1298 case AUDIO_MIXER_CLASS: 1299 case AUDIO_MIXER_VALUE: 1300 printf("%s: adding class/value is not supported yet.\n", 1301 __func__); 1302 return -1; 1303 case AUDIO_MIXER_ENUM: 1304 break; 1305 default: 1306 printf("%s: unknown type: %d\n", __func__, si->type); 1307 return -1; 1308 } 1309 as->num_source_info++; 1310 1311 si->mixer_class = ac97_get_portnum_by_name(&as->codec_if, si->class, 1312 NULL, NULL); 1313 /* Find the root of the device */ 1314 idx = ac97_get_portnum_by_name(&as->codec_if, si->class, 1315 si->device, NULL); 1316 /* Find the last item */ 1317 while (as->source_info[idx].next != AUDIO_MIXER_LAST) 1318 idx = as->source_info[idx].next; 1319 /* Append */ 1320 as->source_info[idx].next = ouridx; 1321 si->prev = idx; 1322 si->next = AUDIO_MIXER_LAST; 1323 1324 return 0; 1325 } 1326 1327 int 1328 ac97_get_portnum_by_name(struct ac97_codec_if *codec_if, char *class, 1329 char *device, char *qualifier) 1330 { 1331 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1332 int idx; 1333 1334 for (idx = 0; idx < as->num_source_info; idx++) { 1335 struct ac97_source_info *si = &as->source_info[idx]; 1336 if (ac97_str_equal(class, si->class) && 1337 ac97_str_equal(device, si->device) && 1338 ac97_str_equal(qualifier, si->qualifier)) 1339 return (idx); 1340 } 1341 1342 return (-1); 1343 } 1344 1345 int 1346 ac97_mixer_get_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp) 1347 { 1348 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1349 struct ac97_source_info *si = &as->source_info[cp->dev]; 1350 u_int16_t mask; 1351 u_int16_t val; 1352 1353 if (cp->dev < 0 || cp->dev >= as->num_source_info || 1354 cp->type != si->type) 1355 return (EINVAL); 1356 1357 ac97_read(as, si->reg, &val); 1358 1359 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val)); 1360 1361 mask = (1 << si->bits) - 1; 1362 1363 switch (cp->type) { 1364 case AUDIO_MIXER_ENUM: 1365 cp->un.ord = (val >> si->ofs) & mask; 1366 DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n", val, si->ofs, 1367 mask, cp->un.ord)); 1368 break; 1369 case AUDIO_MIXER_VALUE: 1370 { 1371 const struct audio_mixer_value *value = si->info; 1372 u_int16_t l, r; 1373 1374 if ((cp->un.value.num_channels <= 0) || 1375 (cp->un.value.num_channels > value->num_channels)) 1376 return (EINVAL); 1377 1378 if (value->num_channels == 1) 1379 l = r = (val >> si->ofs) & mask; 1380 else { 1381 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) { 1382 l = (val >> si->ofs) & mask; 1383 r = (val >> (si->ofs + 8)) & mask; 1384 } else { 1385 r = (val >> si->ofs) & mask; 1386 l = (val >> (si->ofs + 8)) & mask; 1387 } 1388 } 1389 1390 l <<= 8 - si->bits; 1391 r <<= 8 - si->bits; 1392 if (!si->polarity) { 1393 l = 255 - l; 1394 r = 255 - r; 1395 } 1396 1397 /* 1398 * The EAP driver averages l and r for stereo 1399 * channels that are requested in MONO mode. Does this 1400 * make sense? 1401 */ 1402 if (cp->un.value.num_channels == 1) { 1403 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l; 1404 } else if (cp->un.value.num_channels == 2) { 1405 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l; 1406 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r; 1407 } 1408 1409 break; 1410 } 1411 default: 1412 return (EINVAL); 1413 } 1414 1415 return (0); 1416 } 1417 1418 1419 /* 1420 * Codec-dependent initialization 1421 */ 1422 1423 void 1424 ac97_ad1885_init(struct ac97_softc *as, int resuming) 1425 { 1426 int i; 1427 1428 if (resuming) 1429 return; 1430 1431 for (i = 0; i < as->num_source_info; i++) { 1432 if (as->source_info[i].reg == AC97_REG_HEADPHONE_VOLUME) 1433 as->source_info[i].reg = AC97_REG_MASTER_VOLUME; 1434 else if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME) 1435 as->source_info[i].reg = AC97_REG_HEADPHONE_VOLUME; 1436 } 1437 } 1438 1439 #define AC97_AD1886_JACK_SENSE 0x72 1440 1441 void 1442 ac97_ad1886_init(struct ac97_softc *as, int resuming) 1443 { 1444 ac97_write(as, AC97_AD1886_JACK_SENSE, 0x0010); 1445 } 1446 1447 void 1448 ac97_ad198x_init(struct ac97_softc *as, int resuming) 1449 { 1450 int i; 1451 u_int16_t misc; 1452 1453 ac97_read(as, AC97_AD_REG_MISC, &misc); 1454 ac97_write(as, AC97_AD_REG_MISC, 1455 misc|AC97_AD_MISC_HPSEL|AC97_AD_MISC_LOSEL); 1456 1457 if (resuming) 1458 return; 1459 1460 for (i = 0; i < as->num_source_info; i++) { 1461 if (as->source_info[i].reg == AC97_REG_SURR_MASTER) 1462 as->source_info[i].reg = AC97_REG_MASTER_VOLUME; 1463 else if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME) 1464 as->source_info[i].reg = AC97_REG_SURR_MASTER; 1465 } 1466 } 1467 1468 void 1469 ac97_alc650_init(struct ac97_softc *as, int resuming) 1470 { 1471 u_int16_t misc; 1472 1473 ac97_read(as, AC97_ALC650_REG_MISC, &misc); 1474 if (as->host_flags & AC97_HOST_ALC650_PIN47_IS_EAPD) 1475 misc &= ~AC97_ALC650_MISC_PIN47; 1476 misc &= ~AC97_ALC650_MISC_VREFDIS; 1477 ac97_write(as, AC97_ALC650_REG_MISC, misc); 1478 1479 if (resuming) 1480 return; 1481 1482 struct ac97_source_info sources[3] = { 1483 { AudioCoutputs, AudioNsurround, "lineinjack", 1484 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1485 AC97_ALC650_REG_MULTI_CHANNEL_CONTROL, 1486 0x0000, 1, 9, 0, 0, CHECK_SURROUND }, 1487 { AudioCoutputs, AudioNcenter, "micjack", 1488 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1489 AC97_ALC650_REG_MULTI_CHANNEL_CONTROL, 1490 0x0000, 1, 10, 0, 0, CHECK_CENTER }, 1491 { AudioCoutputs, AudioNlfe, "micjack", 1492 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1493 AC97_ALC650_REG_MULTI_CHANNEL_CONTROL, 1494 0x0000, 1, 10, 0, 0, CHECK_LFE }}; 1495 1496 ac97_add_port(as, &sources[0]); 1497 ac97_add_port(as, &sources[1]); 1498 ac97_add_port(as, &sources[2]); 1499 } 1500 1501 void 1502 ac97_cx20468_init(struct ac97_softc *as, int resuming) 1503 { 1504 u_int16_t misc; 1505 1506 ac97_read(as, AC97_CX_REG_MISC, &misc); 1507 ac97_write(as, AC97_CX_REG_MISC, misc & 1508 ~(AC97_CX_SPDIFEN | AC97_CX_COPYRIGHT | AC97_CX_MASK)); 1509 } 1510 1511 void 1512 ac97_vt1616_init(struct ac97_softc *as, int resuming) 1513 { 1514 u_int16_t reg; 1515 1516 if (as->host_flags & AC97_HOST_VT1616_DYNEX) { 1517 ac97_read(as, AC97_VT_REG_TEST, ®); 1518 1519 /* disable 'hp' mixer controls controlling the surround pins */ 1520 reg &= ~(AC97_VT_LVL); 1521 1522 /* disable downmixing */ 1523 reg &= ~(AC97_VT_LCTF | AC97_VT_STF); 1524 1525 /* enable DC offset removal */ 1526 reg |= AC97_VT_BPDC; 1527 1528 ac97_write(as, AC97_VT_REG_TEST, reg); 1529 } 1530 } 1531