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