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 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 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 step = (id & ~modelmask) & 0xff; 654 break; 655 } 656 } 657 658 vname = NULL; 659 for (i = 0; ac97vendorid[i].id; i++) { 660 if (ac97vendorid[i].id == (id & 0xffffff00)) { 661 vname = ac97vendorid[i].name; 662 break; 663 } 664 } 665 666 codec->extcaps = 0; 667 codec->extid = 0; 668 codec->extstat = 0; 669 if (!codec->noext) { 670 i = ac97_rdcd(codec, AC97_REGEXT_ID); 671 if (i != 0xffff) { 672 codec->extcaps = i & 0x3fff; 673 codec->extid = (i & 0xc000) >> 14; 674 codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS; 675 } 676 } 677 678 for (i = 0; i < 32; i++) { 679 codec->mix[i] = ac97mixtable_default[i]; 680 } 681 ac97_fix_auxout(codec); 682 ac97_fix_tone(codec); 683 if (codec_patch) 684 codec_patch(codec); 685 686 for (i = 0; i < 32; i++) { 687 k = codec->noext? codec->mix[i].enable : 1; 688 reg = codec->mix[i].reg; 689 if (reg < 0) 690 reg = -reg; 691 if (k && reg) { 692 j = old = ac97_rdcd(codec, reg); 693 /* 694 * Test for mute bit (except for AC97_MIX_TONE, 695 * where we simply assume it as available). 696 */ 697 if (codec->mix[i].mute) { 698 ac97_wrcd(codec, reg, j | 0x8000); 699 j = ac97_rdcd(codec, reg); 700 } else 701 j |= 0x8000; 702 if ((j & 0x8000)) { 703 /* 704 * Test whether the control width should be 705 * 4, 5 or 6 bit. For 5bit register, we should 706 * test it whether it's really 5 or 6bit. Leave 707 * 4bit register alone, because sometimes an 708 * attempt to write past 4th bit may cause 709 * incorrect result especially for AC97_MIX_BEEP 710 * (ac97 2.3). 711 */ 712 bit = codec->mix[i].bits; 713 if (bit == 5) 714 bit++; 715 j = ((1 << bit) - 1) << codec->mix[i].ofs; 716 ac97_wrcd(codec, reg, 717 j | (codec->mix[i].mute ? 0x8000 : 0)); 718 k = ac97_rdcd(codec, reg) & j; 719 k >>= codec->mix[i].ofs; 720 if (reg == AC97_MIX_TONE && 721 ((k & 0x0001) == 0x0000)) 722 k >>= 1; 723 for (j = 0; k >> j; j++) 724 ; 725 if (j != 0) { 726 #if 0 727 device_printf(codec->dev, "%2d: [ac97_rdcd() = %d] [Testbit = %d] %d -> %d\n", 728 i, k, bit, codec->mix[i].bits, j); 729 #endif 730 codec->mix[i].enable = 1; 731 codec->mix[i].bits = j; 732 } else if (reg == AC97_MIX_BEEP) { 733 /* 734 * Few codec such as CX20468-21 does 735 * have this control register, although 736 * the only usable part is the mute bit. 737 */ 738 codec->mix[i].enable = 1; 739 } else 740 codec->mix[i].enable = 0; 741 } else 742 codec->mix[i].enable = 0; 743 ac97_wrcd(codec, reg, old); 744 } 745 #if 0 746 kprintf("mixch %d, en=%d, b=%d\n", i, codec->mix[i].enable, codec->mix[i].bits); 747 #endif 748 } 749 750 device_printf(codec->dev, "<%s>\n", 751 ac97_hw_desc(codec->id, vname, cname, desc)); 752 753 if (bootverbose) { 754 if (codec->flags & AC97_F_RDCD_BUG) 755 device_printf(codec->dev, "Buggy AC97 Codec: aggressive ac97_rdcd() workaround enabled\n"); 756 device_printf(codec->dev, "Codec features "); 757 for (i = j = 0; i < 10; i++) 758 if (codec->caps & (1 << i)) 759 kprintf("%s%s", j++? ", " : "", ac97feature[i]); 760 kprintf("%s%d bit master volume", j++? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits); 761 kprintf("%s%s\n", j? ", " : "", ac97enhancement[codec->se]); 762 763 if (codec->extcaps != 0 || codec->extid) { 764 device_printf(codec->dev, "%s codec", 765 codec->extid? "Secondary" : "Primary"); 766 if (codec->extcaps) 767 kprintf(" extended features "); 768 for (i = j = 0; i < 14; i++) 769 if (codec->extcaps & (1 << i)) 770 kprintf("%s%s", j++? ", " : "", ac97extfeature[i]); 771 kprintf("\n"); 772 } 773 } 774 775 i = 0; 776 while ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) { 777 if (++i == 100) { 778 device_printf(codec->dev, "ac97 codec reports dac not ready\n"); 779 break; 780 } 781 DELAY(1000); 782 } 783 if (bootverbose) 784 device_printf(codec->dev, "ac97 codec dac ready count: %d\n", i); 785 snd_mtxunlock(codec->lock); 786 return 0; 787 } 788 789 static unsigned 790 ac97_reinitmixer(struct ac97_info *codec) 791 { 792 snd_mtxlock(codec->lock); 793 codec->count = AC97_INIT(codec->methods, codec->devinfo); 794 if (codec->count == 0) { 795 device_printf(codec->dev, "ac97 codec init failed\n"); 796 snd_mtxunlock(codec->lock); 797 return ENODEV; 798 } 799 800 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); 801 ac97_reset(codec); 802 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); 803 804 if (!codec->noext) { 805 ac97_wrcd(codec, AC97_REGEXT_STAT, codec->extstat); 806 if ((ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS) 807 != codec->extstat) 808 device_printf(codec->dev, "ac97 codec failed to reset extended mode (%x, got %x)\n", 809 codec->extstat, 810 ac97_rdcd(codec, AC97_REGEXT_STAT) & 811 AC97_EXTCAPS); 812 } 813 814 if ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) 815 device_printf(codec->dev, "ac97 codec reports dac not ready\n"); 816 snd_mtxunlock(codec->lock); 817 return 0; 818 } 819 820 struct ac97_info * 821 ac97_create(device_t dev, void *devinfo, kobj_class_t cls) 822 { 823 struct ac97_info *codec; 824 825 codec = (struct ac97_info *)kmalloc(sizeof *codec, M_AC97, M_WAITOK); 826 if (codec == NULL) 827 return NULL; 828 829 ksnprintf(codec->name, AC97_NAMELEN, "%s:ac97", device_get_nameunit(dev)); 830 codec->lock = snd_mtxcreate(codec->name, "ac97 codec"); 831 codec->methods = kobj_create(cls, M_AC97, M_WAITOK); 832 if (codec->methods == NULL) { 833 snd_mtxfree(codec->lock); 834 kfree(codec, M_AC97); 835 return NULL; 836 } 837 838 codec->dev = dev; 839 codec->devinfo = devinfo; 840 codec->flags = 0; 841 return codec; 842 } 843 844 void 845 ac97_destroy(struct ac97_info *codec) 846 { 847 if (codec->methods != NULL) 848 kobj_delete(codec->methods, M_AC97); 849 snd_mtxfree(codec->lock); 850 kfree(codec, M_AC97); 851 } 852 853 void 854 ac97_setflags(struct ac97_info *codec, u_int32_t val) 855 { 856 codec->flags = val; 857 } 858 859 u_int32_t 860 ac97_getflags(struct ac97_info *codec) 861 { 862 return codec->flags; 863 } 864 865 /* -------------------------------------------------------------------- */ 866 867 static int 868 ac97mix_init(struct snd_mixer *m) 869 { 870 struct ac97_info *codec = mix_getdevinfo(m); 871 u_int32_t i, mask; 872 873 if (codec == NULL) 874 return -1; 875 876 if (ac97_initmixer(codec)) 877 return -1; 878 879 switch (codec->id) { 880 case 0x41445374: /* AD1981B */ 881 switch (codec->subvendor) { 882 case 0x02d91014: 883 /* 884 * IBM Thinkcentre: 885 * 886 * Tie "ogain" and "phout" to "vol" since its 887 * master volume is basically useless and can't 888 * control anything. 889 */ 890 mask = 0; 891 if (codec->mix[SOUND_MIXER_OGAIN].enable) 892 mask |= SOUND_MASK_OGAIN; 893 if (codec->mix[SOUND_MIXER_PHONEOUT].enable) 894 mask |= SOUND_MASK_PHONEOUT; 895 if (codec->mix[SOUND_MIXER_VOLUME].enable) 896 mix_setparentchild(m, SOUND_MIXER_VOLUME, 897 mask); 898 else { 899 mix_setparentchild(m, SOUND_MIXER_VOLUME, 900 mask); 901 mix_setrealdev(m, SOUND_MIXER_VOLUME, 902 SOUND_MIXER_NONE); 903 } 904 break; 905 case 0x099c103c: 906 /* 907 * HP nx6110: 908 * 909 * By default, "vol" is controlling internal speakers 910 * (not a master volume!) and "ogain" is controlling 911 * headphone. Enable dummy "phout" so it can be 912 * remapped to internal speakers and virtualize 913 * "vol" to control both. 914 */ 915 codec->mix[SOUND_MIXER_OGAIN].enable = 1; 916 codec->mix[SOUND_MIXER_PHONEOUT].enable = 1; 917 mix_setrealdev(m, SOUND_MIXER_PHONEOUT, 918 SOUND_MIXER_VOLUME); 919 mix_setrealdev(m, SOUND_MIXER_VOLUME, 920 SOUND_MIXER_NONE); 921 mix_setparentchild(m, SOUND_MIXER_VOLUME, 922 SOUND_MASK_OGAIN | SOUND_MASK_PHONEOUT); 923 break; 924 default: 925 break; 926 } 927 break; 928 case 0x434d4941: /* CMI9738 */ 929 case 0x434d4961: /* CMI9739 */ 930 case 0x434d4978: /* CMI9761 */ 931 case 0x434d4982: /* CMI9761 */ 932 case 0x434d4983: /* CMI9761 */ 933 ac97_wrcd(codec, AC97_MIX_PCM, 0); 934 bzero(&codec->mix[SOUND_MIXER_PCM], 935 sizeof(codec->mix[SOUND_MIXER_PCM])); 936 pcm_setflags(codec->dev, pcm_getflags(codec->dev) | 937 SD_F_SOFTPCMVOL); 938 /* XXX How about master volume ? */ 939 break; 940 default: 941 break; 942 } 943 944 #if 0 945 /* XXX For the sake of debugging purposes */ 946 mix_setparentchild(m, SOUND_MIXER_VOLUME, 947 SOUND_MASK_PCM | SOUND_MASK_CD); 948 mix_setrealdev(m, SOUND_MIXER_VOLUME, SOUND_MIXER_NONE); 949 ac97_wrcd(codec, AC97_MIX_MASTER, 0); 950 #endif 951 952 mask = 0; 953 for (i = 0; i < 32; i++) 954 mask |= codec->mix[i].enable? 1 << i : 0; 955 mix_setdevs(m, mask); 956 957 mask = 0; 958 for (i = 0; i < 32; i++) 959 mask |= codec->mix[i].recidx? 1 << i : 0; 960 mix_setrecdevs(m, mask); 961 return 0; 962 } 963 964 static int 965 ac97mix_uninit(struct snd_mixer *m) 966 { 967 struct ac97_info *codec = mix_getdevinfo(m); 968 969 if (codec == NULL) 970 return -1; 971 /* 972 if (ac97_uninitmixer(codec)) 973 return -1; 974 */ 975 ac97_destroy(codec); 976 return 0; 977 } 978 979 static int 980 ac97mix_reinit(struct snd_mixer *m) 981 { 982 struct ac97_info *codec = mix_getdevinfo(m); 983 984 if (codec == NULL) 985 return -1; 986 return ac97_reinitmixer(codec); 987 } 988 989 static int 990 ac97mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 991 { 992 struct ac97_info *codec = mix_getdevinfo(m); 993 994 if (codec == NULL) 995 return -1; 996 return ac97_setmixer(codec, dev, left, right); 997 } 998 999 static int 1000 ac97mix_setrecsrc(struct snd_mixer *m, u_int32_t src) 1001 { 1002 int i; 1003 struct ac97_info *codec = mix_getdevinfo(m); 1004 1005 if (codec == NULL) 1006 return -1; 1007 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) 1008 if ((src & (1 << i)) != 0) 1009 break; 1010 return (ac97_setrecsrc(codec, i) == 0)? 1 << i : -1; 1011 } 1012 1013 static kobj_method_t ac97mixer_methods[] = { 1014 KOBJMETHOD(mixer_init, ac97mix_init), 1015 KOBJMETHOD(mixer_uninit, ac97mix_uninit), 1016 KOBJMETHOD(mixer_reinit, ac97mix_reinit), 1017 KOBJMETHOD(mixer_set, ac97mix_set), 1018 KOBJMETHOD(mixer_setrecsrc, ac97mix_setrecsrc), 1019 KOBJMETHOD_END 1020 }; 1021 MIXER_DECLARE(ac97mixer); 1022 1023 /* -------------------------------------------------------------------- */ 1024 1025 kobj_class_t 1026 ac97_getmixerclass(void) 1027 { 1028 return &ac97mixer_class; 1029 } 1030