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