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