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 u_int8_t model, step; 601 unsigned i, j, k, bit, old; 602 u_int32_t id; 603 int reg; 604 605 snd_mtxlock(codec->lock); 606 codec->count = AC97_INIT(codec->methods, codec->devinfo); 607 if (codec->count == 0) { 608 device_printf(codec->dev, "ac97 codec init failed\n"); 609 snd_mtxunlock(codec->lock); 610 return ENODEV; 611 } 612 613 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); 614 ac97_reset(codec); 615 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); 616 617 i = ac97_rdcd(codec, AC97_REG_RESET); 618 j = 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) { 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 < 32; 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 < 32; 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 kprintf("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 kprintf("%s%s", j++? ", " : "", ac97feature[i]); 761 kprintf("%s%d bit master volume", j++? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits); 762 kprintf("%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 kprintf(" extended features "); 769 for (i = j = 0; i < 14; i++) 770 if (codec->extcaps & (1 << i)) 771 kprintf("%s%s", j++? ", " : "", ac97extfeature[i]); 772 kprintf("\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 826 codec = (struct ac97_info *)kmalloc(sizeof *codec, M_AC97, M_WAITOK); 827 if (codec == NULL) 828 return NULL; 829 830 ksnprintf(codec->name, AC97_NAMELEN, "%s:ac97", device_get_nameunit(dev)); 831 codec->lock = snd_mtxcreate(codec->name, "ac97 codec"); 832 codec->methods = kobj_create(cls, M_AC97, M_WAITOK); 833 if (codec->methods == NULL) { 834 snd_mtxfree(codec->lock); 835 kfree(codec, M_AC97); 836 return NULL; 837 } 838 839 codec->dev = dev; 840 codec->devinfo = devinfo; 841 codec->flags = 0; 842 return codec; 843 } 844 845 void 846 ac97_destroy(struct ac97_info *codec) 847 { 848 if (codec->methods != NULL) 849 kobj_delete(codec->methods, M_AC97); 850 snd_mtxfree(codec->lock); 851 kfree(codec, M_AC97); 852 } 853 854 void 855 ac97_setflags(struct ac97_info *codec, u_int32_t val) 856 { 857 codec->flags = val; 858 } 859 860 u_int32_t 861 ac97_getflags(struct ac97_info *codec) 862 { 863 return codec->flags; 864 } 865 866 /* -------------------------------------------------------------------- */ 867 868 static int 869 ac97mix_init(struct snd_mixer *m) 870 { 871 struct ac97_info *codec = mix_getdevinfo(m); 872 u_int32_t i, mask; 873 874 if (codec == NULL) 875 return -1; 876 877 if (ac97_initmixer(codec)) 878 return -1; 879 880 switch (codec->id) { 881 case 0x41445374: /* AD1981B */ 882 switch (codec->subvendor) { 883 case 0x02d91014: 884 /* 885 * IBM Thinkcentre: 886 * 887 * Tie "ogain" and "phout" to "vol" since its 888 * master volume is basically useless and can't 889 * control anything. 890 */ 891 mask = 0; 892 if (codec->mix[SOUND_MIXER_OGAIN].enable) 893 mask |= SOUND_MASK_OGAIN; 894 if (codec->mix[SOUND_MIXER_PHONEOUT].enable) 895 mask |= SOUND_MASK_PHONEOUT; 896 if (codec->mix[SOUND_MIXER_VOLUME].enable) 897 mix_setparentchild(m, SOUND_MIXER_VOLUME, 898 mask); 899 else { 900 mix_setparentchild(m, SOUND_MIXER_VOLUME, 901 mask); 902 mix_setrealdev(m, SOUND_MIXER_VOLUME, 903 SOUND_MIXER_NONE); 904 } 905 break; 906 case 0x099c103c: 907 /* 908 * HP nx6110: 909 * 910 * By default, "vol" is controlling internal speakers 911 * (not a master volume!) and "ogain" is controlling 912 * headphone. Enable dummy "phout" so it can be 913 * remapped to internal speakers and virtualize 914 * "vol" to control both. 915 */ 916 codec->mix[SOUND_MIXER_OGAIN].enable = 1; 917 codec->mix[SOUND_MIXER_PHONEOUT].enable = 1; 918 mix_setrealdev(m, SOUND_MIXER_PHONEOUT, 919 SOUND_MIXER_VOLUME); 920 mix_setrealdev(m, SOUND_MIXER_VOLUME, 921 SOUND_MIXER_NONE); 922 mix_setparentchild(m, SOUND_MIXER_VOLUME, 923 SOUND_MASK_OGAIN | SOUND_MASK_PHONEOUT); 924 break; 925 default: 926 break; 927 } 928 break; 929 case 0x434d4941: /* CMI9738 */ 930 case 0x434d4961: /* CMI9739 */ 931 case 0x434d4978: /* CMI9761 */ 932 case 0x434d4982: /* CMI9761 */ 933 case 0x434d4983: /* CMI9761 */ 934 ac97_wrcd(codec, AC97_MIX_PCM, 0); 935 bzero(&codec->mix[SOUND_MIXER_PCM], 936 sizeof(codec->mix[SOUND_MIXER_PCM])); 937 pcm_setflags(codec->dev, pcm_getflags(codec->dev) | 938 SD_F_SOFTPCMVOL); 939 /* XXX How about master volume ? */ 940 break; 941 default: 942 break; 943 } 944 945 #if 0 946 /* XXX For the sake of debugging purposes */ 947 mix_setparentchild(m, SOUND_MIXER_VOLUME, 948 SOUND_MASK_PCM | SOUND_MASK_CD); 949 mix_setrealdev(m, SOUND_MIXER_VOLUME, SOUND_MIXER_NONE); 950 ac97_wrcd(codec, AC97_MIX_MASTER, 0); 951 #endif 952 953 mask = 0; 954 for (i = 0; i < 32; i++) 955 mask |= codec->mix[i].enable? 1 << i : 0; 956 mix_setdevs(m, mask); 957 958 mask = 0; 959 for (i = 0; i < 32; i++) 960 mask |= codec->mix[i].recidx? 1 << i : 0; 961 mix_setrecdevs(m, mask); 962 return 0; 963 } 964 965 static int 966 ac97mix_uninit(struct snd_mixer *m) 967 { 968 struct ac97_info *codec = mix_getdevinfo(m); 969 970 if (codec == NULL) 971 return -1; 972 /* 973 if (ac97_uninitmixer(codec)) 974 return -1; 975 */ 976 ac97_destroy(codec); 977 return 0; 978 } 979 980 static int 981 ac97mix_reinit(struct snd_mixer *m) 982 { 983 struct ac97_info *codec = mix_getdevinfo(m); 984 985 if (codec == NULL) 986 return -1; 987 return ac97_reinitmixer(codec); 988 } 989 990 static int 991 ac97mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 992 { 993 struct ac97_info *codec = mix_getdevinfo(m); 994 995 if (codec == NULL) 996 return -1; 997 return ac97_setmixer(codec, dev, left, right); 998 } 999 1000 static int 1001 ac97mix_setrecsrc(struct snd_mixer *m, u_int32_t src) 1002 { 1003 int i; 1004 struct ac97_info *codec = mix_getdevinfo(m); 1005 1006 if (codec == NULL) 1007 return -1; 1008 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) 1009 if ((src & (1 << i)) != 0) 1010 break; 1011 return (ac97_setrecsrc(codec, i) == 0)? 1 << i : -1; 1012 } 1013 1014 static kobj_method_t ac97mixer_methods[] = { 1015 KOBJMETHOD(mixer_init, ac97mix_init), 1016 KOBJMETHOD(mixer_uninit, ac97mix_uninit), 1017 KOBJMETHOD(mixer_reinit, ac97mix_reinit), 1018 KOBJMETHOD(mixer_set, ac97mix_set), 1019 KOBJMETHOD(mixer_setrecsrc, ac97mix_setrecsrc), 1020 KOBJMETHOD_END 1021 }; 1022 MIXER_DECLARE(ac97mixer); 1023 1024 /* -------------------------------------------------------------------- */ 1025 1026 kobj_class_t 1027 ac97_getmixerclass(void) 1028 { 1029 return &ac97mixer_class; 1030 } 1031