1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #ifdef HAVE_KERNEL_OPTION_HEADERS 30 #include "opt_snd.h" 31 #endif 32 33 #include <dev/sound/pcm/sound.h> 34 #include <dev/sound/pcm/ac97.h> 35 36 #include <dev/pci/pcivar.h> 37 38 #include "mixer_if.h" 39 40 static MALLOC_DEFINE(M_AC97, "ac97", "ac97 codec"); 41 42 typedef void (*ac97_patch)(struct ac97_info *); 43 44 struct ac97mixtable_entry { 45 int reg; /* register index */ 46 /* reg < 0 if inverted polarity */ 47 unsigned bits:4; /* width of control field */ 48 unsigned ofs:4; /* offset (only if stereo=0) */ 49 unsigned stereo:1; /* set for stereo controls */ 50 unsigned mute:1; /* bit15 is MUTE */ 51 unsigned recidx:4; /* index in rec mux */ 52 unsigned mask:1; /* use only masked bits */ 53 unsigned enable:1; /* entry is enabled */ 54 }; 55 56 #define AC97_MIXER_SIZE SOUND_MIXER_NRDEVICES 57 58 struct ac97_info { 59 kobj_t methods; 60 device_t dev; 61 void *devinfo; 62 u_int32_t id; 63 u_int32_t subvendor; 64 unsigned count, caps, se, extcaps, extid, extstat, noext:1; 65 u_int32_t flags; 66 struct ac97mixtable_entry mix[AC97_MIXER_SIZE]; 67 char name[16]; 68 struct mtx *lock; 69 }; 70 71 struct ac97_vendorid { 72 u_int32_t id; 73 const char *name; 74 }; 75 76 struct ac97_codecid { 77 u_int32_t id; 78 u_int8_t stepmask; 79 u_int8_t noext:1; 80 char *name; 81 ac97_patch patch; 82 }; 83 84 static const struct ac97mixtable_entry ac97mixtable_default[AC97_MIXER_SIZE] = { 85 /* [offset] reg bits of st mu re mk en */ 86 [SOUND_MIXER_VOLUME] = { AC97_MIX_MASTER, 5, 0, 1, 1, 6, 0, 1 }, 87 [SOUND_MIXER_OGAIN] = { AC97_MIX_AUXOUT, 5, 0, 1, 1, 0, 0, 0 }, 88 [SOUND_MIXER_PHONEOUT] = { AC97_MIX_MONO, 5, 0, 0, 1, 7, 0, 0 }, 89 [SOUND_MIXER_BASS] = { AC97_MIX_TONE, 4, 8, 0, 0, 0, 1, 0 }, 90 [SOUND_MIXER_TREBLE] = { AC97_MIX_TONE, 4, 0, 0, 0, 0, 1, 0 }, 91 [SOUND_MIXER_PCM] = { AC97_MIX_PCM, 5, 0, 1, 1, 0, 0, 1 }, 92 [SOUND_MIXER_SPEAKER] = { AC97_MIX_BEEP, 4, 1, 0, 1, 0, 0, 0 }, 93 [SOUND_MIXER_LINE] = { AC97_MIX_LINE, 5, 0, 1, 1, 5, 0, 1 }, 94 [SOUND_MIXER_PHONEIN] = { AC97_MIX_PHONE, 5, 0, 0, 1, 8, 0, 0 }, 95 [SOUND_MIXER_MIC] = { AC97_MIX_MIC, 5, 0, 0, 1, 1, 1, 1 }, 96 /* use igain for the mic 20dB boost */ 97 [SOUND_MIXER_IGAIN] = { -AC97_MIX_MIC, 1, 6, 0, 0, 0, 1, 1 }, 98 [SOUND_MIXER_CD] = { AC97_MIX_CD, 5, 0, 1, 1, 2, 0, 1 }, 99 [SOUND_MIXER_LINE1] = { AC97_MIX_AUX, 5, 0, 1, 1, 4, 0, 0 }, 100 [SOUND_MIXER_VIDEO] = { AC97_MIX_VIDEO, 5, 0, 1, 1, 3, 0, 0 }, 101 [SOUND_MIXER_RECLEV] = { -AC97_MIX_RGAIN, 4, 0, 1, 1, 0, 0, 1 } 102 }; 103 104 static const struct ac97_vendorid ac97vendorid[] = { 105 { 0x41445300, "Analog Devices" }, 106 { 0x414b4d00, "Asahi Kasei" }, 107 { 0x414c4300, "Realtek" }, 108 { 0x414c4700, "Avance Logic" }, 109 { 0x43525900, "Cirrus Logic" }, 110 { 0x434d4900, "C-Media Electronics" }, 111 { 0x43585400, "Conexant" }, 112 { 0x44543000, "Diamond Technology" }, 113 { 0x454d4300, "eMicro" }, 114 { 0x45838300, "ESS Technology" }, 115 { 0x48525300, "Intersil" }, 116 { 0x49434500, "ICEnsemble" }, 117 { 0x49544500, "ITE, Inc." }, 118 { 0x4e534300, "National Semiconductor" }, 119 { 0x50534300, "Philips Semiconductor" }, 120 { 0x83847600, "SigmaTel" }, 121 { 0x53494c00, "Silicon Laboratories" }, 122 { 0x54524100, "TriTech" }, 123 { 0x54584e00, "Texas Instruments" }, 124 { 0x56494100, "VIA Technologies" }, 125 { 0x57454300, "Winbond" }, 126 { 0x574d4c00, "Wolfson" }, 127 { 0x594d4800, "Yamaha" }, 128 /* 129 * XXX This is a fluke, really! The real vendor 130 * should be SigmaTel, not this! This should be 131 * removed someday! 132 */ 133 { 0x01408300, "Creative" }, 134 { 0x00000000, NULL } 135 }; 136 137 static void ad1886_patch(struct ac97_info *); 138 static void ad198x_patch(struct ac97_info *); 139 static void ad1981b_patch(struct ac97_info *); 140 static void cmi9739_patch(struct ac97_info *); 141 static void alc655_patch(struct ac97_info *); 142 143 static struct ac97_codecid ac97codecid[] = { 144 { 0x41445303, 0x00, 0, "AD1819", 0 }, 145 { 0x41445340, 0x00, 0, "AD1881", 0 }, 146 { 0x41445348, 0x00, 0, "AD1881A", 0 }, 147 { 0x41445360, 0x00, 0, "AD1885", 0 }, 148 { 0x41445361, 0x00, 0, "AD1886", ad1886_patch }, 149 { 0x41445362, 0x00, 0, "AD1887", 0 }, 150 { 0x41445363, 0x00, 0, "AD1886A", 0 }, 151 { 0x41445368, 0x00, 0, "AD1888", ad198x_patch }, 152 { 0x41445370, 0x00, 0, "AD1980", ad198x_patch }, 153 { 0x41445372, 0x00, 0, "AD1981A", 0 }, 154 { 0x41445374, 0x00, 0, "AD1981B", ad1981b_patch }, 155 { 0x41445375, 0x00, 0, "AD1985", ad198x_patch }, 156 { 0x41445378, 0x00, 0, "AD1986", ad198x_patch }, 157 { 0x414b4d00, 0x00, 1, "AK4540", 0 }, 158 { 0x414b4d01, 0x00, 1, "AK4542", 0 }, 159 { 0x414b4d02, 0x00, 1, "AK4543", 0 }, 160 { 0x414b4d06, 0x00, 0, "AK4544A", 0 }, 161 { 0x454b4d07, 0x00, 0, "AK4545", 0 }, 162 { 0x414c4320, 0x0f, 0, "ALC100", 0 }, 163 { 0x414c4730, 0x0f, 0, "ALC101", 0 }, 164 { 0x414c4710, 0x0f, 0, "ALC200", 0 }, 165 { 0x414c4740, 0x0f, 0, "ALC202", 0 }, 166 { 0x414c4720, 0x0f, 0, "ALC650", 0 }, 167 { 0x414c4752, 0x0f, 0, "ALC250", 0 }, 168 { 0x414c4760, 0x0f, 0, "ALC655", alc655_patch }, 169 { 0x414c4770, 0x0f, 0, "ALC203", 0 }, 170 { 0x414c4780, 0x0f, 0, "ALC658", 0 }, 171 { 0x414c4790, 0x0f, 0, "ALC850", 0 }, 172 { 0x43525900, 0x07, 0, "CS4297", 0 }, 173 { 0x43525910, 0x07, 0, "CS4297A", 0 }, 174 { 0x43525920, 0x07, 0, "CS4294/98", 0 }, 175 { 0x4352592d, 0x07, 0, "CS4294", 0 }, 176 { 0x43525930, 0x07, 0, "CS4299", 0 }, 177 { 0x43525940, 0x07, 0, "CS4201", 0 }, 178 { 0x43525958, 0x07, 0, "CS4205", 0 }, 179 { 0x43525960, 0x07, 0, "CS4291A", 0 }, 180 { 0x434d4961, 0x00, 0, "CMI9739", cmi9739_patch }, 181 { 0x434d4941, 0x00, 0, "CMI9738", 0 }, 182 { 0x434d4978, 0x00, 0, "CMI9761", 0 }, 183 { 0x434d4982, 0x00, 0, "CMI9761", 0 }, 184 { 0x434d4983, 0x00, 0, "CMI9761", 0 }, 185 { 0x43585421, 0x00, 0, "HSD11246", 0 }, 186 { 0x43585428, 0x07, 0, "CX20468", 0 }, 187 { 0x43585430, 0x00, 0, "CX20468-21", 0 }, 188 { 0x44543000, 0x00, 0, "DT0398", 0 }, 189 { 0x454d4323, 0x00, 0, "EM28023", 0 }, 190 { 0x454d4328, 0x00, 0, "EM28028", 0 }, 191 { 0x45838308, 0x00, 0, "ES1988", 0 }, /* Formerly ES1921(?) */ 192 { 0x48525300, 0x00, 0, "HMP9701", 0 }, 193 { 0x49434501, 0x00, 0, "ICE1230", 0 }, 194 { 0x49434511, 0x00, 0, "ICE1232", 0 }, 195 { 0x49434514, 0x00, 0, "ICE1232A", 0 }, 196 { 0x49434551, 0x03, 0, "VT1616", 0 }, /* Via badged ICE */ 197 { 0x49544520, 0x00, 0, "ITE2226E", 0 }, 198 { 0x49544560, 0x07, 0, "ITE2646E", 0 }, /* XXX: patch needed */ 199 { 0x4e534340, 0x00, 0, "LM4540", 0 }, /* Spec blank on revid */ 200 { 0x4e534343, 0x00, 0, "LM4543", 0 }, /* Ditto */ 201 { 0x4e534346, 0x00, 0, "LM4546A", 0 }, 202 { 0x4e534348, 0x00, 0, "LM4548A", 0 }, 203 { 0x4e534331, 0x00, 0, "LM4549", 0 }, 204 { 0x4e534349, 0x00, 0, "LM4549A", 0 }, 205 { 0x4e534350, 0x00, 0, "LM4550", 0 }, 206 { 0x50534301, 0x00, 0, "UCB1510", 0 }, 207 { 0x50534304, 0x00, 0, "UCB1400", 0 }, 208 { 0x83847600, 0x00, 0, "STAC9700/83/84", 0 }, 209 { 0x83847604, 0x00, 0, "STAC9701/03/04/05", 0 }, 210 { 0x83847605, 0x00, 0, "STAC9704", 0 }, 211 { 0x83847608, 0x00, 0, "STAC9708/11", 0 }, 212 { 0x83847609, 0x00, 0, "STAC9721/23", 0 }, 213 { 0x83847644, 0x00, 0, "STAC9744/45", 0 }, 214 { 0x83847650, 0x00, 0, "STAC9750/51", 0 }, 215 { 0x83847652, 0x00, 0, "STAC9752/53", 0 }, 216 { 0x83847656, 0x00, 0, "STAC9756/57", 0 }, 217 { 0x83847658, 0x00, 0, "STAC9758/59", 0 }, 218 { 0x83847660, 0x00, 0, "STAC9760/61", 0 }, /* Extrapolated */ 219 { 0x83847662, 0x00, 0, "STAC9762/63", 0 }, /* Extrapolated */ 220 { 0x83847666, 0x00, 0, "STAC9766/67", 0 }, 221 { 0x53494c22, 0x00, 0, "Si3036", 0 }, 222 { 0x53494c23, 0x00, 0, "Si3038", 0 }, 223 { 0x54524103, 0x00, 0, "TR28023", 0 }, /* Extrapolated */ 224 { 0x54524106, 0x00, 0, "TR28026", 0 }, 225 { 0x54524108, 0x00, 0, "TR28028", 0 }, 226 { 0x54524123, 0x00, 0, "TR28602", 0 }, 227 { 0x54524e03, 0x07, 0, "TLV320AIC27", 0 }, 228 { 0x54584e20, 0x00, 0, "TLC320AD90", 0 }, 229 { 0x56494161, 0x00, 0, "VIA1612A", 0 }, 230 { 0x56494170, 0x00, 0, "VIA1617A", 0 }, 231 { 0x574d4c00, 0x00, 0, "WM9701A", 0 }, 232 { 0x574d4c03, 0x00, 0, "WM9703/4/7/8", 0 }, 233 { 0x574d4c04, 0x00, 0, "WM9704Q", 0 }, 234 { 0x574d4c05, 0x00, 0, "WM9705/10", 0 }, 235 { 0x574d4d09, 0x00, 0, "WM9709", 0 }, 236 { 0x574d4c12, 0x00, 0, "WM9711/12", 0 }, /* XXX: patch needed */ 237 { 0x57454301, 0x00, 0, "W83971D", 0 }, 238 { 0x594d4800, 0x00, 0, "YMF743", 0 }, 239 { 0x594d4802, 0x00, 0, "YMF752", 0 }, 240 { 0x594d4803, 0x00, 0, "YMF753", 0 }, 241 /* 242 * XXX This is a fluke, really! The real codec 243 * should be STAC9704, not this! This should be 244 * removed someday! 245 */ 246 { 0x01408384, 0x00, 0, "EV1938", 0 }, 247 { 0, 0, 0, NULL, 0 } 248 }; 249 250 static char *ac97enhancement[] = { 251 "no 3D Stereo Enhancement", 252 "Analog Devices Phat Stereo", 253 "Creative Stereo Enhancement", 254 "National Semi 3D Stereo Enhancement", 255 "Yamaha Ymersion", 256 "BBE 3D Stereo Enhancement", 257 "Crystal Semi 3D Stereo Enhancement", 258 "Qsound QXpander", 259 "Spatializer 3D Stereo Enhancement", 260 "SRS 3D Stereo Enhancement", 261 "Platform Tech 3D Stereo Enhancement", 262 "AKM 3D Audio", 263 "Aureal Stereo Enhancement", 264 "Aztech 3D Enhancement", 265 "Binaura 3D Audio Enhancement", 266 "ESS Technology Stereo Enhancement", 267 "Harman International VMAx", 268 "Nvidea 3D Stereo Enhancement", 269 "Philips Incredible Sound", 270 "Texas Instruments 3D Stereo Enhancement", 271 "VLSI Technology 3D Stereo Enhancement", 272 "TriTech 3D Stereo Enhancement", 273 "Realtek 3D Stereo Enhancement", 274 "Samsung 3D Stereo Enhancement", 275 "Wolfson Microelectronics 3D Enhancement", 276 "Delta Integration 3D Enhancement", 277 "SigmaTel 3D Enhancement", 278 "Reserved 27", 279 "Rockwell 3D Stereo Enhancement", 280 "Reserved 29", 281 "Reserved 30", 282 "Reserved 31" 283 }; 284 285 static char *ac97feature[] = { 286 "mic channel", 287 "reserved", 288 "tone", 289 "simulated stereo", 290 "headphone", 291 "bass boost", 292 "18 bit DAC", 293 "20 bit DAC", 294 "18 bit ADC", 295 "20 bit ADC" 296 }; 297 298 static char *ac97extfeature[] = { 299 "variable rate PCM", 300 "double rate PCM", 301 "reserved 1", 302 "variable rate mic", 303 "reserved 2", 304 "reserved 3", 305 "center DAC", 306 "surround DAC", 307 "LFE DAC", 308 "AMAP", 309 "reserved 4", 310 "reserved 5", 311 "reserved 6", 312 "reserved 7", 313 }; 314 315 u_int16_t 316 ac97_rdcd(struct ac97_info *codec, int reg) 317 { 318 if (codec->flags & AC97_F_RDCD_BUG) { 319 u_int16_t i[2], j = 100; 320 321 i[0] = AC97_READ(codec->methods, codec->devinfo, reg); 322 i[1] = AC97_READ(codec->methods, codec->devinfo, reg); 323 while (i[0] != i[1] && j) 324 i[j-- & 1] = AC97_READ(codec->methods, codec->devinfo, reg); 325 return i[!(j & 1)]; 326 } 327 return AC97_READ(codec->methods, codec->devinfo, reg); 328 } 329 330 void 331 ac97_wrcd(struct ac97_info *codec, int reg, u_int16_t val) 332 { 333 AC97_WRITE(codec->methods, codec->devinfo, reg, val); 334 } 335 336 static void 337 ac97_reset(struct ac97_info *codec) 338 { 339 u_int32_t i, ps; 340 ac97_wrcd(codec, AC97_REG_RESET, 0); 341 for (i = 0; i < 500; i++) { 342 ps = ac97_rdcd(codec, AC97_REG_POWER) & AC97_POWER_STATUS; 343 if (ps == AC97_POWER_STATUS) 344 return; 345 DELAY(1000); 346 } 347 device_printf(codec->dev, "AC97 reset timed out.\n"); 348 } 349 350 int 351 ac97_setrate(struct ac97_info *codec, int which, int rate) 352 { 353 u_int16_t v; 354 355 switch(which) { 356 case AC97_REGEXT_FDACRATE: 357 case AC97_REGEXT_SDACRATE: 358 case AC97_REGEXT_LDACRATE: 359 case AC97_REGEXT_LADCRATE: 360 case AC97_REGEXT_MADCRATE: 361 break; 362 363 default: 364 return -1; 365 } 366 367 snd_mtxlock(codec->lock); 368 if (rate != 0) { 369 v = rate; 370 if (codec->extstat & AC97_EXTCAP_DRA) 371 v >>= 1; 372 ac97_wrcd(codec, which, v); 373 } 374 v = ac97_rdcd(codec, which); 375 if (codec->extstat & AC97_EXTCAP_DRA) 376 v <<= 1; 377 snd_mtxunlock(codec->lock); 378 return v; 379 } 380 381 int 382 ac97_setextmode(struct ac97_info *codec, u_int16_t mode) 383 { 384 mode &= AC97_EXTCAPS; 385 if ((mode & ~codec->extcaps) != 0) { 386 device_printf(codec->dev, "ac97 invalid mode set 0x%04x\n", 387 mode); 388 return -1; 389 } 390 snd_mtxlock(codec->lock); 391 ac97_wrcd(codec, AC97_REGEXT_STAT, mode); 392 codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS; 393 snd_mtxunlock(codec->lock); 394 return (mode == codec->extstat)? 0 : -1; 395 } 396 397 u_int16_t 398 ac97_getextmode(struct ac97_info *codec) 399 { 400 return codec->extstat; 401 } 402 403 u_int16_t 404 ac97_getextcaps(struct ac97_info *codec) 405 { 406 return codec->extcaps; 407 } 408 409 u_int16_t 410 ac97_getcaps(struct ac97_info *codec) 411 { 412 return codec->caps; 413 } 414 415 u_int32_t 416 ac97_getsubvendor(struct ac97_info *codec) 417 { 418 return codec->subvendor; 419 } 420 421 static int 422 ac97_setrecsrc(struct ac97_info *codec, int channel) 423 { 424 struct ac97mixtable_entry *e = &codec->mix[channel]; 425 426 if (e->recidx > 0) { 427 int val = e->recidx - 1; 428 val |= val << 8; 429 snd_mtxlock(codec->lock); 430 ac97_wrcd(codec, AC97_REG_RECSEL, val); 431 snd_mtxunlock(codec->lock); 432 return 0; 433 } else 434 return -1; 435 } 436 437 static int 438 ac97_setmixer(struct ac97_info *codec, unsigned channel, unsigned left, unsigned right) 439 { 440 struct ac97mixtable_entry *e = &codec->mix[channel]; 441 442 if (e->reg && e->enable && e->bits) { 443 int mask, max, val, reg; 444 445 reg = (e->reg >= 0) ? e->reg : -e->reg; /* AC97 register */ 446 max = (1 << e->bits) - 1; /* actual range */ 447 mask = (max << 8) | max; /* bits of interest */ 448 449 if (!e->stereo) 450 right = left; 451 452 /* 453 * Invert the range if the polarity requires so, 454 * then scale to 0..max-1 to compute the value to 455 * write into the codec, and scale back to 0..100 456 * for the return value. 457 */ 458 if (e->reg > 0) { 459 left = 100 - left; 460 right = 100 - right; 461 } 462 463 left = (left * max) / 100; 464 right = (right * max) / 100; 465 466 val = (left << 8) | right; 467 468 left = (left * 100) / max; 469 right = (right * 100) / max; 470 471 if (e->reg > 0) { 472 left = 100 - left; 473 right = 100 - right; 474 } 475 476 /* 477 * For mono controls, trim val and mask, also taking 478 * care of e->ofs (offset of control field). 479 */ 480 if (e->ofs) { 481 val &= max; 482 val <<= e->ofs; 483 mask = (max << e->ofs); 484 } 485 486 /* 487 * If we have a mute bit, add it to the mask and 488 * update val and set mute if both channels require a 489 * zero volume. 490 */ 491 if (e->mute == 1) { 492 mask |= AC97_MUTE; 493 if (left == 0 && right == 0) 494 val = AC97_MUTE; 495 } 496 497 /* 498 * If the mask bit is set, do not alter the other bits. 499 */ 500 snd_mtxlock(codec->lock); 501 if (e->mask) { 502 int cur = ac97_rdcd(codec, reg); 503 val |= cur & ~(mask); 504 } 505 ac97_wrcd(codec, reg, val); 506 snd_mtxunlock(codec->lock); 507 return left | (right << 8); 508 } else { 509 return -1; 510 } 511 } 512 513 static void 514 ac97_fix_auxout(struct ac97_info *codec) 515 { 516 int keep_ogain; 517 518 /* 519 * By default, The ac97 aux_out register (0x04) corresponds to OSS's 520 * OGAIN setting. 521 * 522 * We first check whether aux_out is a valid register. If not 523 * we may not want to keep ogain. 524 */ 525 keep_ogain = ac97_rdcd(codec, AC97_MIX_AUXOUT) & 0x8000; 526 527 /* 528 * Determine what AUX_OUT really means, it can be: 529 * 530 * 1. Headphone out. 531 * 2. 4-Channel Out 532 * 3. True line level out (effectively master volume). 533 * 534 * See Sections 5.2.1 and 5.27 for AUX_OUT Options in AC97r2.{2,3}. 535 */ 536 if (codec->extcaps & AC97_EXTCAP_SDAC && 537 ac97_rdcd(codec, AC97_MIXEXT_SURROUND) == 0x8080) { 538 codec->mix[SOUND_MIXER_OGAIN].reg = AC97_MIXEXT_SURROUND; 539 keep_ogain = 1; 540 } 541 542 if (keep_ogain == 0) { 543 bzero(&codec->mix[SOUND_MIXER_OGAIN], 544 sizeof(codec->mix[SOUND_MIXER_OGAIN])); 545 } 546 } 547 548 static void 549 ac97_fix_tone(struct ac97_info *codec) 550 { 551 /* 552 * YMF chips does not indicate tone and 3D enhancement capability 553 * in the AC97_REG_RESET register. 554 */ 555 switch (codec->id) { 556 case 0x594d4800: /* YMF743 */ 557 case 0x594d4803: /* YMF753 */ 558 codec->caps |= AC97_CAP_TONE; 559 codec->se |= 0x04; 560 break; 561 case 0x594d4802: /* YMF752 */ 562 codec->se |= 0x04; 563 break; 564 default: 565 break; 566 } 567 568 /* Hide treble and bass if they don't exist */ 569 if ((codec->caps & AC97_CAP_TONE) == 0) { 570 bzero(&codec->mix[SOUND_MIXER_BASS], 571 sizeof(codec->mix[SOUND_MIXER_BASS])); 572 bzero(&codec->mix[SOUND_MIXER_TREBLE], 573 sizeof(codec->mix[SOUND_MIXER_TREBLE])); 574 } 575 } 576 577 static const char* 578 ac97_hw_desc(u_int32_t id, const char* vname, const char* cname, char* buf) 579 { 580 if (cname == NULL) { 581 sprintf(buf, "Unknown AC97 Codec (id = 0x%08x)", id); 582 return buf; 583 } 584 585 if (vname == NULL) vname = "Unknown"; 586 587 if (bootverbose) { 588 sprintf(buf, "%s %s AC97 Codec (id = 0x%08x)", vname, cname, id); 589 } else { 590 sprintf(buf, "%s %s AC97 Codec", vname, cname); 591 } 592 return buf; 593 } 594 595 static unsigned 596 ac97_initmixer(struct ac97_info *codec) 597 { 598 ac97_patch codec_patch; 599 const char *cname, *vname; 600 char desc[80]; 601 device_t pdev; 602 unsigned i, j, k, bit, old; 603 u_int32_t id; 604 int reg; 605 606 snd_mtxlock(codec->lock); 607 codec->count = AC97_INIT(codec->methods, codec->devinfo); 608 if (codec->count == 0) { 609 device_printf(codec->dev, "ac97 codec init failed\n"); 610 snd_mtxunlock(codec->lock); 611 return ENODEV; 612 } 613 614 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); 615 ac97_reset(codec); 616 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); 617 618 i = ac97_rdcd(codec, AC97_REG_RESET); 619 j = ac97_rdcd(codec, AC97_REG_RESET); 620 k = ac97_rdcd(codec, AC97_REG_RESET); 621 /* 622 * Let see if this codec can return consistent value. 623 * If not, turn on aggressive read workaround 624 * (STAC9704 comes in mind). 625 */ 626 if (i != j || j != k) { 627 codec->flags |= AC97_F_RDCD_BUG; 628 i = ac97_rdcd(codec, AC97_REG_RESET); 629 } 630 codec->caps = i & 0x03ff; 631 codec->se = (i & 0x7c00) >> 10; 632 633 id = (ac97_rdcd(codec, AC97_REG_ID1) << 16) | ac97_rdcd(codec, AC97_REG_ID2); 634 if (id == 0 || id == 0xffffffff) { 635 device_printf(codec->dev, "ac97 codec invalid or not present (id == %x)\n", id); 636 snd_mtxunlock(codec->lock); 637 return ENODEV; 638 } 639 640 pdev = codec->dev; 641 while (strcmp(device_get_name(device_get_parent(pdev)), "pci") != 0) { 642 /* find the top-level PCI device handler */ 643 pdev = device_get_parent(pdev); 644 } 645 codec->id = id; 646 codec->subvendor = (u_int32_t)pci_get_subdevice(pdev) << 16; 647 codec->subvendor |= (u_int32_t)pci_get_subvendor(pdev) & 648 0x0000ffff; 649 codec->noext = 0; 650 codec_patch = NULL; 651 652 cname = NULL; 653 for (i = 0; ac97codecid[i].id; i++) { 654 u_int32_t modelmask = 0xffffffff ^ ac97codecid[i].stepmask; 655 if ((ac97codecid[i].id & modelmask) == (id & modelmask)) { 656 codec->noext = ac97codecid[i].noext; 657 codec_patch = ac97codecid[i].patch; 658 cname = ac97codecid[i].name; 659 break; 660 } 661 } 662 663 vname = NULL; 664 for (i = 0; ac97vendorid[i].id; i++) { 665 if (ac97vendorid[i].id == (id & 0xffffff00)) { 666 vname = ac97vendorid[i].name; 667 break; 668 } 669 } 670 671 codec->extcaps = 0; 672 codec->extid = 0; 673 codec->extstat = 0; 674 if (!codec->noext) { 675 i = ac97_rdcd(codec, AC97_REGEXT_ID); 676 if (i != 0xffff) { 677 codec->extcaps = i & 0x3fff; 678 codec->extid = (i & 0xc000) >> 14; 679 codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS; 680 } 681 } 682 683 for (i = 0; i < AC97_MIXER_SIZE; i++) { 684 codec->mix[i] = ac97mixtable_default[i]; 685 } 686 ac97_fix_auxout(codec); 687 ac97_fix_tone(codec); 688 if (codec_patch) 689 codec_patch(codec); 690 691 for (i = 0; i < AC97_MIXER_SIZE; i++) { 692 k = codec->noext? codec->mix[i].enable : 1; 693 reg = codec->mix[i].reg; 694 if (reg < 0) 695 reg = -reg; 696 if (k && reg) { 697 j = old = ac97_rdcd(codec, reg); 698 /* 699 * Test for mute bit (except for AC97_MIX_TONE, 700 * where we simply assume it as available). 701 */ 702 if (codec->mix[i].mute) { 703 ac97_wrcd(codec, reg, j | 0x8000); 704 j = ac97_rdcd(codec, reg); 705 } else 706 j |= 0x8000; 707 if ((j & 0x8000)) { 708 /* 709 * Test whether the control width should be 710 * 4, 5 or 6 bit. For 5bit register, we should 711 * test it whether it's really 5 or 6bit. Leave 712 * 4bit register alone, because sometimes an 713 * attempt to write past 4th bit may cause 714 * incorrect result especially for AC97_MIX_BEEP 715 * (ac97 2.3). 716 */ 717 bit = codec->mix[i].bits; 718 if (bit == 5) 719 bit++; 720 j = ((1 << bit) - 1) << codec->mix[i].ofs; 721 ac97_wrcd(codec, reg, 722 j | (codec->mix[i].mute ? 0x8000 : 0)); 723 k = ac97_rdcd(codec, reg) & j; 724 k >>= codec->mix[i].ofs; 725 if (reg == AC97_MIX_TONE && 726 ((k & 0x0001) == 0x0000)) 727 k >>= 1; 728 for (j = 0; k >> j; j++) 729 ; 730 if (j != 0) { 731 codec->mix[i].enable = 1; 732 codec->mix[i].bits = j; 733 } else if (reg == AC97_MIX_BEEP) { 734 /* 735 * Few codec such as CX20468-21 does 736 * have this control register, although 737 * the only usable part is the mute bit. 738 */ 739 codec->mix[i].enable = 1; 740 } else 741 codec->mix[i].enable = 0; 742 } else 743 codec->mix[i].enable = 0; 744 ac97_wrcd(codec, reg, old); 745 } 746 } 747 748 device_printf(codec->dev, "<%s>\n", 749 ac97_hw_desc(codec->id, vname, cname, desc)); 750 751 if (bootverbose) { 752 if (codec->flags & AC97_F_RDCD_BUG) 753 device_printf(codec->dev, "Buggy AC97 Codec: aggressive ac97_rdcd() workaround enabled\n"); 754 device_printf(codec->dev, "Codec features "); 755 for (i = j = 0; i < 10; i++) 756 if (codec->caps & (1 << i)) 757 printf("%s%s", j++? ", " : "", ac97feature[i]); 758 printf("%s%d bit master volume", j++? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits); 759 printf("%s%s\n", j? ", " : "", ac97enhancement[codec->se]); 760 761 if (codec->extcaps != 0 || codec->extid) { 762 device_printf(codec->dev, "%s codec", 763 codec->extid? "Secondary" : "Primary"); 764 if (codec->extcaps) 765 printf(" extended features "); 766 for (i = j = 0; i < 14; i++) 767 if (codec->extcaps & (1 << i)) 768 printf("%s%s", j++? ", " : "", ac97extfeature[i]); 769 printf("\n"); 770 } 771 } 772 773 i = 0; 774 while ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) { 775 if (++i == 100) { 776 device_printf(codec->dev, "ac97 codec reports dac not ready\n"); 777 break; 778 } 779 DELAY(1000); 780 } 781 if (bootverbose) 782 device_printf(codec->dev, "ac97 codec dac ready count: %d\n", i); 783 snd_mtxunlock(codec->lock); 784 return 0; 785 } 786 787 static unsigned 788 ac97_reinitmixer(struct ac97_info *codec) 789 { 790 snd_mtxlock(codec->lock); 791 codec->count = AC97_INIT(codec->methods, codec->devinfo); 792 if (codec->count == 0) { 793 device_printf(codec->dev, "ac97 codec init failed\n"); 794 snd_mtxunlock(codec->lock); 795 return ENODEV; 796 } 797 798 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); 799 ac97_reset(codec); 800 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); 801 802 if (!codec->noext) { 803 ac97_wrcd(codec, AC97_REGEXT_STAT, codec->extstat); 804 if ((ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS) 805 != codec->extstat) 806 device_printf(codec->dev, "ac97 codec failed to reset extended mode (%x, got %x)\n", 807 codec->extstat, 808 ac97_rdcd(codec, AC97_REGEXT_STAT) & 809 AC97_EXTCAPS); 810 } 811 812 if ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) 813 device_printf(codec->dev, "ac97 codec reports dac not ready\n"); 814 snd_mtxunlock(codec->lock); 815 return 0; 816 } 817 818 struct ac97_info * 819 ac97_create(device_t dev, void *devinfo, kobj_class_t cls) 820 { 821 struct ac97_info *codec; 822 int i; 823 824 codec = malloc(sizeof(*codec), M_AC97, M_WAITOK | M_ZERO); 825 snprintf(codec->name, sizeof(codec->name), "%s:ac97", 826 device_get_nameunit(dev)); 827 codec->lock = snd_mtxcreate(codec->name, "ac97 codec"); 828 codec->methods = kobj_create(cls, M_AC97, M_WAITOK | M_ZERO); 829 codec->dev = dev; 830 codec->devinfo = devinfo; 831 codec->flags = 0; 832 833 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 834 "eapdinv", &i) == 0 && i != 0) 835 codec->flags |= AC97_F_EAPD_INV; 836 837 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 838 "softpcmvol", &i) == 0 && i != 0) 839 pcm_setflags(dev, pcm_getflags(dev) | SD_F_SOFTPCMVOL); 840 841 return codec; 842 } 843 844 void 845 ac97_destroy(struct ac97_info *codec) 846 { 847 snd_mtxlock(codec->lock); 848 if (codec->methods != NULL) 849 kobj_delete(codec->methods, M_AC97); 850 snd_mtxfree(codec->lock); 851 free(codec, M_AC97); 852 } 853 854 void 855 ac97_setflags(struct ac97_info *codec, u_int32_t val) 856 { 857 codec->flags = val; 858 } 859 860 u_int32_t 861 ac97_getflags(struct ac97_info *codec) 862 { 863 return codec->flags; 864 } 865 866 static void 867 ad1886_patch(struct ac97_info *codec) 868 { 869 #define AC97_AD_JACK_SPDIF 0x72 870 /* 871 * Presario700 workaround 872 * for Jack Sense/SPDIF Register misetting causing 873 * no audible output 874 * by Santiago Nullo 04/05/2002 875 */ 876 ac97_wrcd(codec, AC97_AD_JACK_SPDIF, 0x0010); 877 } 878 879 static void 880 ad198x_patch(struct ac97_info *codec) 881 { 882 switch (ac97_getsubvendor(codec)) { 883 case 0x11931043: /* Not for ASUS A9T (probably else too). */ 884 break; 885 default: 886 ac97_wrcd(codec, 0x76, ac97_rdcd(codec, 0x76) | 0x0420); 887 break; 888 } 889 } 890 891 static void 892 ad1981b_patch(struct ac97_info *codec) 893 { 894 /* 895 * Enable headphone jack sensing. 896 */ 897 switch (ac97_getsubvendor(codec)) { 898 case 0x02d91014: /* IBM Thinkcentre */ 899 case 0x099c103c: /* HP nx6110 */ 900 ac97_wrcd(codec, AC97_AD_JACK_SPDIF, 901 ac97_rdcd(codec, AC97_AD_JACK_SPDIF) | 0x0800); 902 break; 903 default: 904 break; 905 } 906 } 907 908 static void 909 cmi9739_patch(struct ac97_info *codec) 910 { 911 /* 912 * Few laptops need extra register initialization 913 * to power up the internal speakers. 914 */ 915 switch (ac97_getsubvendor(codec)) { 916 case 0x18431043: /* ASUS W1000N */ 917 ac97_wrcd(codec, AC97_REG_POWER, 0x000f); 918 ac97_wrcd(codec, AC97_MIXEXT_CLFE, 0x0000); 919 ac97_wrcd(codec, 0x64, 0x7110); 920 break; 921 default: 922 break; 923 } 924 } 925 926 static void 927 alc655_patch(struct ac97_info *codec) 928 { 929 /* 930 * MSI (Micro-Star International) specific EAPD quirk. 931 */ 932 switch (ac97_getsubvendor(codec)) { 933 case 0x00611462: /* MSI S250 */ 934 case 0x01311462: /* MSI S270 */ 935 case 0x01611462: /* LG K1 Express */ 936 case 0x03511462: /* MSI L725 */ 937 ac97_wrcd(codec, 0x7a, ac97_rdcd(codec, 0x7a) & 0xfffd); 938 break; 939 case 0x10ca1734: 940 /* 941 * Amilo Pro V2055 with ALC655 has phone out by default 942 * disabled (surround on), leaving us only with internal 943 * speakers. This should really go to mixer. We write the 944 * Data Flow Control reg. 945 */ 946 ac97_wrcd(codec, 0x6a, ac97_rdcd(codec, 0x6a) | 0x0001); 947 break; 948 default: 949 break; 950 } 951 } 952 953 /* -------------------------------------------------------------------- */ 954 955 static int 956 sysctl_hw_snd_ac97_eapd(SYSCTL_HANDLER_ARGS) 957 { 958 struct ac97_info *codec; 959 int ea, inv, err = 0; 960 u_int16_t val; 961 962 codec = oidp->oid_arg1; 963 if (codec == NULL || codec->id == 0 || codec->lock == NULL) 964 return EINVAL; 965 snd_mtxlock(codec->lock); 966 val = ac97_rdcd(codec, AC97_REG_POWER); 967 inv = (codec->flags & AC97_F_EAPD_INV) ? 0 : 1; 968 ea = (val >> 15) ^ inv; 969 snd_mtxunlock(codec->lock); 970 err = sysctl_handle_int(oidp, &ea, 0, req); 971 if (err == 0 && req->newptr != NULL) { 972 if (ea != 0 && ea != 1) 973 return EINVAL; 974 if (ea != ((val >> 15) ^ inv)) { 975 snd_mtxlock(codec->lock); 976 ac97_wrcd(codec, AC97_REG_POWER, val ^ 0x8000); 977 snd_mtxunlock(codec->lock); 978 } 979 } 980 return err; 981 } 982 983 static void 984 ac97_init_sysctl(struct ac97_info *codec) 985 { 986 u_int16_t orig, val; 987 988 if (codec == NULL || codec->dev == NULL) 989 return; 990 snd_mtxlock(codec->lock); 991 orig = ac97_rdcd(codec, AC97_REG_POWER); 992 ac97_wrcd(codec, AC97_REG_POWER, orig ^ 0x8000); 993 val = ac97_rdcd(codec, AC97_REG_POWER); 994 ac97_wrcd(codec, AC97_REG_POWER, orig); 995 snd_mtxunlock(codec->lock); 996 if ((val & 0x8000) == (orig & 0x8000)) 997 return; 998 SYSCTL_ADD_PROC(device_get_sysctl_ctx(codec->dev), 999 SYSCTL_CHILDREN(device_get_sysctl_tree(codec->dev)), 1000 OID_AUTO, "eapd", 1001 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, 1002 codec, sizeof(codec), sysctl_hw_snd_ac97_eapd, 1003 "I", "AC97 External Amplifier"); 1004 } 1005 1006 static int 1007 ac97mix_init(struct snd_mixer *m) 1008 { 1009 struct ac97_info *codec = mix_getdevinfo(m); 1010 u_int32_t i, mask; 1011 1012 if (codec == NULL) 1013 return -1; 1014 1015 if (ac97_initmixer(codec)) 1016 return -1; 1017 1018 switch (codec->id) { 1019 case 0x41445374: /* AD1981B */ 1020 switch (codec->subvendor) { 1021 case 0x02d91014: 1022 /* 1023 * IBM Thinkcentre: 1024 * 1025 * Tie "ogain" and "phout" to "vol" since its 1026 * master volume is basically useless and can't 1027 * control anything. 1028 */ 1029 mask = 0; 1030 if (codec->mix[SOUND_MIXER_OGAIN].enable) 1031 mask |= SOUND_MASK_OGAIN; 1032 if (codec->mix[SOUND_MIXER_PHONEOUT].enable) 1033 mask |= SOUND_MASK_PHONEOUT; 1034 if (codec->mix[SOUND_MIXER_VOLUME].enable) 1035 mix_setparentchild(m, SOUND_MIXER_VOLUME, 1036 mask); 1037 else { 1038 mix_setparentchild(m, SOUND_MIXER_VOLUME, 1039 mask); 1040 mix_setrealdev(m, SOUND_MIXER_VOLUME, 1041 SOUND_MIXER_NONE); 1042 } 1043 break; 1044 case 0x099c103c: 1045 /* 1046 * HP nx6110: 1047 * 1048 * By default, "vol" is controlling internal speakers 1049 * (not a master volume!) and "ogain" is controlling 1050 * headphone. Enable dummy "phout" so it can be 1051 * remapped to internal speakers and virtualize 1052 * "vol" to control both. 1053 */ 1054 codec->mix[SOUND_MIXER_OGAIN].enable = 1; 1055 codec->mix[SOUND_MIXER_PHONEOUT].enable = 1; 1056 mix_setrealdev(m, SOUND_MIXER_PHONEOUT, 1057 SOUND_MIXER_VOLUME); 1058 mix_setrealdev(m, SOUND_MIXER_VOLUME, 1059 SOUND_MIXER_NONE); 1060 mix_setparentchild(m, SOUND_MIXER_VOLUME, 1061 SOUND_MASK_OGAIN | SOUND_MASK_PHONEOUT); 1062 break; 1063 default: 1064 break; 1065 } 1066 break; 1067 case 0x434d4941: /* CMI9738 */ 1068 case 0x434d4961: /* CMI9739 */ 1069 case 0x434d4978: /* CMI9761 */ 1070 case 0x434d4982: /* CMI9761 */ 1071 case 0x434d4983: /* CMI9761 */ 1072 bzero(&codec->mix[SOUND_MIXER_PCM], 1073 sizeof(codec->mix[SOUND_MIXER_PCM])); 1074 pcm_setflags(codec->dev, pcm_getflags(codec->dev) | 1075 SD_F_SOFTPCMVOL); 1076 /* XXX How about master volume ? */ 1077 break; 1078 default: 1079 break; 1080 } 1081 1082 if (pcm_getflags(codec->dev) & SD_F_SOFTPCMVOL) 1083 ac97_wrcd(codec, AC97_MIX_PCM, 0); 1084 1085 mask = 0; 1086 for (i = 0; i < AC97_MIXER_SIZE; i++) 1087 mask |= codec->mix[i].enable? 1 << i : 0; 1088 mix_setdevs(m, mask); 1089 1090 mask = 0; 1091 for (i = 0; i < AC97_MIXER_SIZE; i++) 1092 mask |= codec->mix[i].recidx? 1 << i : 0; 1093 mix_setrecdevs(m, mask); 1094 1095 ac97_init_sysctl(codec); 1096 1097 return 0; 1098 } 1099 1100 static int 1101 ac97mix_uninit(struct snd_mixer *m) 1102 { 1103 struct ac97_info *codec = mix_getdevinfo(m); 1104 1105 if (codec == NULL) 1106 return -1; 1107 /* 1108 if (ac97_uninitmixer(codec)) 1109 return -1; 1110 */ 1111 ac97_destroy(codec); 1112 return 0; 1113 } 1114 1115 static int 1116 ac97mix_reinit(struct snd_mixer *m) 1117 { 1118 struct ac97_info *codec = mix_getdevinfo(m); 1119 1120 if (codec == NULL) 1121 return -1; 1122 return ac97_reinitmixer(codec); 1123 } 1124 1125 static int 1126 ac97mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 1127 { 1128 struct ac97_info *codec = mix_getdevinfo(m); 1129 1130 if (codec == NULL || dev >= AC97_MIXER_SIZE) 1131 return -1; 1132 return ac97_setmixer(codec, dev, left, right); 1133 } 1134 1135 static u_int32_t 1136 ac97mix_setrecsrc(struct snd_mixer *m, u_int32_t src) 1137 { 1138 int i; 1139 struct ac97_info *codec = mix_getdevinfo(m); 1140 1141 if (codec == NULL) 1142 return -1; 1143 for (i = 0; i < AC97_MIXER_SIZE; i++) 1144 if ((src & (1 << i)) != 0) 1145 break; 1146 return (ac97_setrecsrc(codec, i) == 0)? 1U << i : 0xffffffffU; 1147 } 1148 1149 static kobj_method_t ac97mixer_methods[] = { 1150 KOBJMETHOD(mixer_init, ac97mix_init), 1151 KOBJMETHOD(mixer_uninit, ac97mix_uninit), 1152 KOBJMETHOD(mixer_reinit, ac97mix_reinit), 1153 KOBJMETHOD(mixer_set, ac97mix_set), 1154 KOBJMETHOD(mixer_setrecsrc, ac97mix_setrecsrc), 1155 KOBJMETHOD_END 1156 }; 1157 MIXER_DECLARE(ac97mixer); 1158 1159 /* -------------------------------------------------------------------- */ 1160 1161 kobj_class_t 1162 ac97_getmixerclass(void) 1163 { 1164 return &ac97mixer_class; 1165 } 1166