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