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