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