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