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