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