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