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