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 u_int8_t model, step; 606 unsigned i, j, k, bit, old; 607 u_int32_t id; 608 int reg; 609 610 snd_mtxlock(codec->lock); 611 codec->count = AC97_INIT(codec->methods, codec->devinfo); 612 if (codec->count == 0) { 613 device_printf(codec->dev, "ac97 codec init failed\n"); 614 snd_mtxunlock(codec->lock); 615 return ENODEV; 616 } 617 618 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); 619 ac97_reset(codec); 620 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); 621 622 i = ac97_rdcd(codec, AC97_REG_RESET); 623 j = ac97_rdcd(codec, AC97_REG_RESET); 624 k = ac97_rdcd(codec, AC97_REG_RESET); 625 /* 626 * Let see if this codec can return consistent value. 627 * If not, turn on aggressive read workaround 628 * (STAC9704 comes in mind). 629 */ 630 if (i != j || j != k) { 631 codec->flags |= AC97_F_RDCD_BUG; 632 i = ac97_rdcd(codec, AC97_REG_RESET); 633 } 634 codec->caps = i & 0x03ff; 635 codec->se = (i & 0x7c00) >> 10; 636 637 id = (ac97_rdcd(codec, AC97_REG_ID1) << 16) | ac97_rdcd(codec, AC97_REG_ID2); 638 if (id == 0 || id == 0xffffffff) { 639 device_printf(codec->dev, "ac97 codec invalid or not present (id == %x)\n", id); 640 snd_mtxunlock(codec->lock); 641 return ENODEV; 642 } 643 644 codec->id = id; 645 codec->subvendor = (u_int32_t)pci_get_subdevice(codec->dev) << 16; 646 codec->subvendor |= (u_int32_t)pci_get_subvendor(codec->dev) & 647 0x0000ffff; 648 codec->noext = 0; 649 codec_patch = NULL; 650 651 cname = NULL; 652 model = step = 0; 653 for (i = 0; ac97codecid[i].id; i++) { 654 u_int32_t modelmask = 0xffffffff ^ ac97codecid[i].stepmask; 655 if ((ac97codecid[i].id & modelmask) == (id & modelmask)) { 656 codec->noext = ac97codecid[i].noext; 657 codec_patch = ac97codecid[i].patch; 658 cname = ac97codecid[i].name; 659 model = (id & modelmask) & 0xff; 660 step = (id & ~modelmask) & 0xff; 661 break; 662 } 663 } 664 665 vname = NULL; 666 for (i = 0; ac97vendorid[i].id; i++) { 667 if (ac97vendorid[i].id == (id & 0xffffff00)) { 668 vname = ac97vendorid[i].name; 669 break; 670 } 671 } 672 673 codec->extcaps = 0; 674 codec->extid = 0; 675 codec->extstat = 0; 676 if (!codec->noext) { 677 i = ac97_rdcd(codec, AC97_REGEXT_ID); 678 if (i != 0xffff) { 679 codec->extcaps = i & 0x3fff; 680 codec->extid = (i & 0xc000) >> 14; 681 codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS; 682 } 683 } 684 685 for (i = 0; i < AC97_MIXER_SIZE; i++) { 686 codec->mix[i] = ac97mixtable_default[i]; 687 } 688 ac97_fix_auxout(codec); 689 ac97_fix_tone(codec); 690 if (codec_patch) 691 codec_patch(codec); 692 693 for (i = 0; i < AC97_MIXER_SIZE; i++) { 694 k = codec->noext? codec->mix[i].enable : 1; 695 reg = codec->mix[i].reg; 696 if (reg < 0) 697 reg = -reg; 698 if (k && reg) { 699 j = old = ac97_rdcd(codec, reg); 700 /* 701 * Test for mute bit (except for AC97_MIX_TONE, 702 * where we simply assume it as available). 703 */ 704 if (codec->mix[i].mute) { 705 ac97_wrcd(codec, reg, j | 0x8000); 706 j = ac97_rdcd(codec, reg); 707 } else 708 j |= 0x8000; 709 if ((j & 0x8000)) { 710 /* 711 * Test whether the control width should be 712 * 4, 5 or 6 bit. For 5bit register, we should 713 * test it whether it's really 5 or 6bit. Leave 714 * 4bit register alone, because sometimes an 715 * attempt to write past 4th bit may cause 716 * incorrect result especially for AC97_MIX_BEEP 717 * (ac97 2.3). 718 */ 719 bit = codec->mix[i].bits; 720 if (bit == 5) 721 bit++; 722 j = ((1 << bit) - 1) << codec->mix[i].ofs; 723 ac97_wrcd(codec, reg, 724 j | (codec->mix[i].mute ? 0x8000 : 0)); 725 k = ac97_rdcd(codec, reg) & j; 726 k >>= codec->mix[i].ofs; 727 if (reg == AC97_MIX_TONE && 728 ((k & 0x0001) == 0x0000)) 729 k >>= 1; 730 for (j = 0; k >> j; j++) 731 ; 732 if (j != 0) { 733 #if 0 734 device_printf(codec->dev, "%2d: [ac97_rdcd() = %d] [Testbit = %d] %d -> %d\n", 735 i, k, bit, codec->mix[i].bits, j); 736 #endif 737 codec->mix[i].enable = 1; 738 codec->mix[i].bits = j; 739 } else if (reg == AC97_MIX_BEEP) { 740 /* 741 * Few codec such as CX20468-21 does 742 * have this control register, although 743 * the only usable part is the mute bit. 744 */ 745 codec->mix[i].enable = 1; 746 } else 747 codec->mix[i].enable = 0; 748 } else 749 codec->mix[i].enable = 0; 750 ac97_wrcd(codec, reg, old); 751 } 752 #if 0 753 printf("mixch %d, en=%d, b=%d\n", i, codec->mix[i].enable, codec->mix[i].bits); 754 #endif 755 } 756 757 device_printf(codec->dev, "<%s>\n", 758 ac97_hw_desc(codec->id, vname, cname, desc)); 759 760 if (bootverbose) { 761 if (codec->flags & AC97_F_RDCD_BUG) 762 device_printf(codec->dev, "Buggy AC97 Codec: aggressive ac97_rdcd() workaround enabled\n"); 763 device_printf(codec->dev, "Codec features "); 764 for (i = j = 0; i < 10; i++) 765 if (codec->caps & (1 << i)) 766 printf("%s%s", j++? ", " : "", ac97feature[i]); 767 printf("%s%d bit master volume", j++? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits); 768 printf("%s%s\n", j? ", " : "", ac97enhancement[codec->se]); 769 770 if (codec->extcaps != 0 || codec->extid) { 771 device_printf(codec->dev, "%s codec", 772 codec->extid? "Secondary" : "Primary"); 773 if (codec->extcaps) 774 printf(" extended features "); 775 for (i = j = 0; i < 14; i++) 776 if (codec->extcaps & (1 << i)) 777 printf("%s%s", j++? ", " : "", ac97extfeature[i]); 778 printf("\n"); 779 } 780 } 781 782 i = 0; 783 while ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) { 784 if (++i == 100) { 785 device_printf(codec->dev, "ac97 codec reports dac not ready\n"); 786 break; 787 } 788 DELAY(1000); 789 } 790 if (bootverbose) 791 device_printf(codec->dev, "ac97 codec dac ready count: %d\n", i); 792 snd_mtxunlock(codec->lock); 793 return 0; 794 } 795 796 static unsigned 797 ac97_reinitmixer(struct ac97_info *codec) 798 { 799 snd_mtxlock(codec->lock); 800 codec->count = AC97_INIT(codec->methods, codec->devinfo); 801 if (codec->count == 0) { 802 device_printf(codec->dev, "ac97 codec init failed\n"); 803 snd_mtxunlock(codec->lock); 804 return ENODEV; 805 } 806 807 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); 808 ac97_reset(codec); 809 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); 810 811 if (!codec->noext) { 812 ac97_wrcd(codec, AC97_REGEXT_STAT, codec->extstat); 813 if ((ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS) 814 != codec->extstat) 815 device_printf(codec->dev, "ac97 codec failed to reset extended mode (%x, got %x)\n", 816 codec->extstat, 817 ac97_rdcd(codec, AC97_REGEXT_STAT) & 818 AC97_EXTCAPS); 819 } 820 821 if ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) 822 device_printf(codec->dev, "ac97 codec reports dac not ready\n"); 823 snd_mtxunlock(codec->lock); 824 return 0; 825 } 826 827 struct ac97_info * 828 ac97_create(device_t dev, void *devinfo, kobj_class_t cls) 829 { 830 struct ac97_info *codec; 831 int i; 832 833 codec = malloc(sizeof(*codec), M_AC97, M_WAITOK | M_ZERO); 834 snprintf(codec->name, sizeof(codec->name), "%s:ac97", 835 device_get_nameunit(dev)); 836 codec->lock = snd_mtxcreate(codec->name, "ac97 codec"); 837 codec->methods = kobj_create(cls, M_AC97, M_WAITOK | M_ZERO); 838 codec->dev = dev; 839 codec->devinfo = devinfo; 840 codec->flags = 0; 841 842 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 843 "eapdinv", &i) == 0 && i != 0) 844 codec->flags |= AC97_F_EAPD_INV; 845 846 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 847 "softpcmvol", &i) == 0 && i != 0) 848 pcm_setflags(dev, pcm_getflags(dev) | SD_F_SOFTPCMVOL); 849 850 return codec; 851 } 852 853 void 854 ac97_destroy(struct ac97_info *codec) 855 { 856 snd_mtxlock(codec->lock); 857 if (codec->methods != NULL) 858 kobj_delete(codec->methods, M_AC97); 859 snd_mtxfree(codec->lock); 860 free(codec, M_AC97); 861 } 862 863 void 864 ac97_setflags(struct ac97_info *codec, u_int32_t val) 865 { 866 codec->flags = val; 867 } 868 869 u_int32_t 870 ac97_getflags(struct ac97_info *codec) 871 { 872 return codec->flags; 873 } 874 875 /* -------------------------------------------------------------------- */ 876 877 static int 878 sysctl_hw_snd_ac97_eapd(SYSCTL_HANDLER_ARGS) 879 { 880 struct ac97_info *codec; 881 int ea, inv, err = 0; 882 u_int16_t val; 883 884 codec = oidp->oid_arg1; 885 if (codec == NULL || codec->id == 0 || codec->lock == NULL) 886 return EINVAL; 887 snd_mtxlock(codec->lock); 888 val = ac97_rdcd(codec, AC97_REG_POWER); 889 inv = (codec->flags & AC97_F_EAPD_INV) ? 0 : 1; 890 ea = (val >> 15) ^ inv; 891 snd_mtxunlock(codec->lock); 892 err = sysctl_handle_int(oidp, &ea, 0, req); 893 if (err == 0 && req->newptr != NULL) { 894 if (ea != 0 && ea != 1) 895 return EINVAL; 896 if (ea != ((val >> 15) ^ inv)) { 897 snd_mtxlock(codec->lock); 898 ac97_wrcd(codec, AC97_REG_POWER, val ^ 0x8000); 899 snd_mtxunlock(codec->lock); 900 } 901 } 902 return err; 903 } 904 905 static void 906 ac97_init_sysctl(struct ac97_info *codec) 907 { 908 u_int16_t orig, val; 909 910 if (codec == NULL || codec->dev == NULL) 911 return; 912 snd_mtxlock(codec->lock); 913 orig = ac97_rdcd(codec, AC97_REG_POWER); 914 ac97_wrcd(codec, AC97_REG_POWER, orig ^ 0x8000); 915 val = ac97_rdcd(codec, AC97_REG_POWER); 916 ac97_wrcd(codec, AC97_REG_POWER, orig); 917 snd_mtxunlock(codec->lock); 918 if ((val & 0x8000) == (orig & 0x8000)) 919 return; 920 SYSCTL_ADD_PROC(device_get_sysctl_ctx(codec->dev), 921 SYSCTL_CHILDREN(device_get_sysctl_tree(codec->dev)), 922 OID_AUTO, "eapd", CTLTYPE_INT | CTLFLAG_RW, 923 codec, sizeof(codec), sysctl_hw_snd_ac97_eapd, 924 "I", "AC97 External Amplifier"); 925 } 926 927 static int 928 ac97mix_init(struct snd_mixer *m) 929 { 930 struct ac97_info *codec = mix_getdevinfo(m); 931 u_int32_t i, mask; 932 933 if (codec == NULL) 934 return -1; 935 936 if (ac97_initmixer(codec)) 937 return -1; 938 939 switch (codec->id) { 940 case 0x41445374: /* AD1981B */ 941 switch (codec->subvendor) { 942 case 0x02d91014: 943 /* 944 * IBM Thinkcentre: 945 * 946 * Tie "ogain" and "phout" to "vol" since its 947 * master volume is basically useless and can't 948 * control anything. 949 */ 950 mask = 0; 951 if (codec->mix[SOUND_MIXER_OGAIN].enable) 952 mask |= SOUND_MASK_OGAIN; 953 if (codec->mix[SOUND_MIXER_PHONEOUT].enable) 954 mask |= SOUND_MASK_PHONEOUT; 955 if (codec->mix[SOUND_MIXER_VOLUME].enable) 956 mix_setparentchild(m, SOUND_MIXER_VOLUME, 957 mask); 958 else { 959 mix_setparentchild(m, SOUND_MIXER_VOLUME, 960 mask); 961 mix_setrealdev(m, SOUND_MIXER_VOLUME, 962 SOUND_MIXER_NONE); 963 } 964 break; 965 case 0x099c103c: 966 /* 967 * HP nx6110: 968 * 969 * By default, "vol" is controlling internal speakers 970 * (not a master volume!) and "ogain" is controlling 971 * headphone. Enable dummy "phout" so it can be 972 * remapped to internal speakers and virtualize 973 * "vol" to control both. 974 */ 975 codec->mix[SOUND_MIXER_OGAIN].enable = 1; 976 codec->mix[SOUND_MIXER_PHONEOUT].enable = 1; 977 mix_setrealdev(m, SOUND_MIXER_PHONEOUT, 978 SOUND_MIXER_VOLUME); 979 mix_setrealdev(m, SOUND_MIXER_VOLUME, 980 SOUND_MIXER_NONE); 981 mix_setparentchild(m, SOUND_MIXER_VOLUME, 982 SOUND_MASK_OGAIN | SOUND_MASK_PHONEOUT); 983 break; 984 default: 985 break; 986 } 987 break; 988 case 0x434d4941: /* CMI9738 */ 989 case 0x434d4961: /* CMI9739 */ 990 case 0x434d4978: /* CMI9761 */ 991 case 0x434d4982: /* CMI9761 */ 992 case 0x434d4983: /* CMI9761 */ 993 bzero(&codec->mix[SOUND_MIXER_PCM], 994 sizeof(codec->mix[SOUND_MIXER_PCM])); 995 pcm_setflags(codec->dev, pcm_getflags(codec->dev) | 996 SD_F_SOFTPCMVOL); 997 /* XXX How about master volume ? */ 998 break; 999 default: 1000 break; 1001 } 1002 1003 if (pcm_getflags(codec->dev) & SD_F_SOFTPCMVOL) 1004 ac97_wrcd(codec, AC97_MIX_PCM, 0); 1005 #if 0 1006 /* XXX For the sake of debugging purposes */ 1007 mix_setparentchild(m, SOUND_MIXER_VOLUME, 1008 SOUND_MASK_PCM | SOUND_MASK_CD); 1009 mix_setrealdev(m, SOUND_MIXER_VOLUME, SOUND_MIXER_NONE); 1010 ac97_wrcd(codec, AC97_MIX_MASTER, 0); 1011 #endif 1012 1013 mask = 0; 1014 for (i = 0; i < AC97_MIXER_SIZE; i++) 1015 mask |= codec->mix[i].enable? 1 << i : 0; 1016 mix_setdevs(m, mask); 1017 1018 mask = 0; 1019 for (i = 0; i < AC97_MIXER_SIZE; i++) 1020 mask |= codec->mix[i].recidx? 1 << i : 0; 1021 mix_setrecdevs(m, mask); 1022 1023 ac97_init_sysctl(codec); 1024 1025 return 0; 1026 } 1027 1028 static int 1029 ac97mix_uninit(struct snd_mixer *m) 1030 { 1031 struct ac97_info *codec = mix_getdevinfo(m); 1032 1033 if (codec == NULL) 1034 return -1; 1035 /* 1036 if (ac97_uninitmixer(codec)) 1037 return -1; 1038 */ 1039 ac97_destroy(codec); 1040 return 0; 1041 } 1042 1043 static int 1044 ac97mix_reinit(struct snd_mixer *m) 1045 { 1046 struct ac97_info *codec = mix_getdevinfo(m); 1047 1048 if (codec == NULL) 1049 return -1; 1050 return ac97_reinitmixer(codec); 1051 } 1052 1053 static int 1054 ac97mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 1055 { 1056 struct ac97_info *codec = mix_getdevinfo(m); 1057 1058 if (codec == NULL || dev >= AC97_MIXER_SIZE) 1059 return -1; 1060 return ac97_setmixer(codec, dev, left, right); 1061 } 1062 1063 static u_int32_t 1064 ac97mix_setrecsrc(struct snd_mixer *m, u_int32_t src) 1065 { 1066 int i; 1067 struct ac97_info *codec = mix_getdevinfo(m); 1068 1069 if (codec == NULL) 1070 return -1; 1071 for (i = 0; i < AC97_MIXER_SIZE; i++) 1072 if ((src & (1 << i)) != 0) 1073 break; 1074 return (ac97_setrecsrc(codec, i) == 0)? 1U << i : 0xffffffffU; 1075 } 1076 1077 static kobj_method_t ac97mixer_methods[] = { 1078 KOBJMETHOD(mixer_init, ac97mix_init), 1079 KOBJMETHOD(mixer_uninit, ac97mix_uninit), 1080 KOBJMETHOD(mixer_reinit, ac97mix_reinit), 1081 KOBJMETHOD(mixer_set, ac97mix_set), 1082 KOBJMETHOD(mixer_setrecsrc, ac97mix_setrecsrc), 1083 KOBJMETHOD_END 1084 }; 1085 MIXER_DECLARE(ac97mixer); 1086 1087 /* -------------------------------------------------------------------- */ 1088 1089 kobj_class_t 1090 ac97_getmixerclass(void) 1091 { 1092 return &ac97mixer_class; 1093 } 1094