1 /* $NetBSD: ac97.c,v 1.95 2012/10/27 17:18:18 chs Exp $ */ 2 /* $OpenBSD: ac97.c,v 1.8 2000/07/19 09:01:35 csapuntz Exp $ */ 3 4 /* 5 * Copyright (c) 1999, 2000 Constantine Sapuntzakis 6 * 7 * Author: Constantine Sapuntzakis <csapuntz@stanford.edu> 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote 18 * products derived from this software without specific prior written 19 * permission. 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS 21 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 27 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 30 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 * DAMAGE 32 */ 33 34 /* Partially inspired by FreeBSD's sys/dev/pcm/ac97.c. It came with 35 the following copyright */ 36 37 /* 38 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 39 * All rights reserved. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 50 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 60 * SUCH DAMAGE. 61 * 62 * $FreeBSD$ 63 */ 64 65 #include <sys/cdefs.h> 66 __KERNEL_RCSID(0, "$NetBSD: ac97.c,v 1.95 2012/10/27 17:18:18 chs Exp $"); 67 68 #include <sys/param.h> 69 #include <sys/systm.h> 70 #include <sys/kernel.h> 71 #include <sys/malloc.h> 72 #include <sys/device.h> 73 #include <sys/sysctl.h> 74 75 #include <sys/audioio.h> 76 #include <dev/audio_if.h> 77 78 #include <dev/ic/ac97reg.h> 79 #include <dev/ic/ac97var.h> 80 81 struct ac97_softc; 82 struct ac97_source_info; 83 static int ac97_mixer_get_port(struct ac97_codec_if *, mixer_ctrl_t *); 84 static int ac97_mixer_set_port(struct ac97_codec_if *, mixer_ctrl_t *); 85 static void ac97_detach(struct ac97_codec_if *); 86 static void ac97_lock(struct ac97_codec_if *); 87 static void ac97_unlock(struct ac97_codec_if *); 88 static int ac97_query_devinfo(struct ac97_codec_if *, mixer_devinfo_t *); 89 static int ac97_get_portnum_by_name(struct ac97_codec_if *, const char *, 90 const char *, const char *); 91 static void ac97_restore_shadow(struct ac97_codec_if *); 92 static int ac97_set_rate(struct ac97_codec_if *, int, u_int *); 93 static void ac97_set_clock(struct ac97_codec_if *, unsigned int); 94 static uint16_t ac97_get_extcaps(struct ac97_codec_if *); 95 static int ac97_add_port(struct ac97_softc *, 96 const struct ac97_source_info *); 97 static int ac97_str_equal(const char *, const char *); 98 static int ac97_check_capability(struct ac97_softc *, int); 99 static void ac97_setup_source_info(struct ac97_softc *); 100 static void ac97_read(struct ac97_softc *, uint8_t, uint16_t *); 101 static void ac97_setup_defaults(struct ac97_softc *); 102 static int ac97_write(struct ac97_softc *, uint8_t, uint16_t); 103 104 static void ac97_ad198x_init(struct ac97_softc *); 105 static void ac97_alc650_init(struct ac97_softc *); 106 static void ac97_ucb1400_init(struct ac97_softc *); 107 static void ac97_vt1616_init(struct ac97_softc *); 108 109 static int ac97_modem_offhook_set(struct ac97_softc *, int, int); 110 static int ac97_sysctl_verify(SYSCTLFN_ARGS); 111 112 #define Ac97Nphone "phone" 113 #define Ac97Nline1 "line1" 114 #define Ac97Nline2 "line2" 115 #define Ac97Nhandset "handset" 116 117 static const struct audio_mixer_enum 118 ac97_on_off = { 2, { { { AudioNoff, 0 } , 0 }, 119 { { AudioNon, 0 } , 1 }, 120 { { "", 0 } , 0 }, 121 { { "", 0 } , 0 }, 122 { { "", 0 } , 0 }, 123 { { "", 0 } , 0 }, 124 { { "", 0 } , 0 }, 125 { { "", 0 } , 0 }, 126 { { "", 0 } , 0 }, 127 { { "", 0 } , 0 }, 128 { { "", 0 } , 0 }, 129 { { "", 0 } , 0 }, 130 { { "", 0 } , 0 }, 131 { { "", 0 } , 0 }, 132 { { "", 0 } , 0 }, 133 { { "", 0 } , 0 }, 134 { { "", 0 } , 0 }, 135 { { "", 0 } , 0 }, 136 { { "", 0 } , 0 }, 137 { { "", 0 } , 0 }, 138 { { "", 0 } , 0 }, 139 { { "", 0 } , 0 }, 140 { { "", 0 } , 0 }, 141 { { "", 0 } , 0 }, 142 { { "", 0 } , 0 }, 143 { { "", 0 } , 0 }, 144 { { "", 0 } , 0 }, 145 { { "", 0 } , 0 }, 146 { { "", 0 } , 0 }, 147 { { "", 0 } , 0 }, 148 { { "", 0 } , 0 }, 149 { { "", 0 } , 0 }, } }; 150 151 static const struct audio_mixer_enum 152 ac97_mic_select = { 2, { { { AudioNmicrophone "0", 0 }, 0 }, 153 { { AudioNmicrophone "1", 0 }, 1 }, 154 { { "", 0 } , 0 }, 155 { { "", 0 } , 0 }, 156 { { "", 0 } , 0 }, 157 { { "", 0 } , 0 }, 158 { { "", 0 } , 0 }, 159 { { "", 0 } , 0 }, 160 { { "", 0 } , 0 }, 161 { { "", 0 } , 0 }, 162 { { "", 0 } , 0 }, 163 { { "", 0 } , 0 }, 164 { { "", 0 } , 0 }, 165 { { "", 0 } , 0 }, 166 { { "", 0 } , 0 }, 167 { { "", 0 } , 0 }, 168 { { "", 0 } , 0 }, 169 { { "", 0 } , 0 }, 170 { { "", 0 } , 0 }, 171 { { "", 0 } , 0 }, 172 { { "", 0 } , 0 }, 173 { { "", 0 } , 0 }, 174 { { "", 0 } , 0 }, 175 { { "", 0 } , 0 }, 176 { { "", 0 } , 0 }, 177 { { "", 0 } , 0 }, 178 { { "", 0 } , 0 }, 179 { { "", 0 } , 0 }, 180 { { "", 0 } , 0 }, 181 { { "", 0 } , 0 }, 182 { { "", 0 } , 0 }, 183 { { "", 0 } , 0 }, } }; 184 185 static const struct audio_mixer_enum 186 ac97_mono_select = { 2, { { { AudioNmixerout, 0 }, 0 }, 187 { { AudioNmicrophone, 0 }, 1 }, 188 { { "", 0 } , 0 }, 189 { { "", 0 } , 0 }, 190 { { "", 0 } , 0 }, 191 { { "", 0 } , 0 }, 192 { { "", 0 } , 0 }, 193 { { "", 0 } , 0 }, 194 { { "", 0 } , 0 }, 195 { { "", 0 } , 0 }, 196 { { "", 0 } , 0 }, 197 { { "", 0 } , 0 }, 198 { { "", 0 } , 0 }, 199 { { "", 0 } , 0 }, 200 { { "", 0 } , 0 }, 201 { { "", 0 } , 0 }, 202 { { "", 0 } , 0 }, 203 { { "", 0 } , 0 }, 204 { { "", 0 } , 0 }, 205 { { "", 0 } , 0 }, 206 { { "", 0 } , 0 }, 207 { { "", 0 } , 0 }, 208 { { "", 0 } , 0 }, 209 { { "", 0 } , 0 }, 210 { { "", 0 } , 0 }, 211 { { "", 0 } , 0 }, 212 { { "", 0 } , 0 }, 213 { { "", 0 } , 0 }, 214 { { "", 0 } , 0 }, 215 { { "", 0 } , 0 }, 216 { { "", 0 } , 0 }, 217 { { "", 0 } , 0 }, } }; 218 219 static const struct audio_mixer_enum 220 ac97_source = { 8, { { { AudioNmicrophone, 0 } , 0 }, 221 { { AudioNcd, 0 }, 1 }, 222 { { AudioNvideo, 0 }, 2 }, 223 { { AudioNaux, 0 }, 3 }, 224 { { AudioNline, 0 }, 4 }, 225 { { AudioNmixerout, 0 }, 5 }, 226 { { AudioNmixerout AudioNmono, 0 }, 6 }, 227 { { Ac97Nphone, 0 }, 7 }, 228 { { "", 0 } , 0 }, 229 { { "", 0 } , 0 }, 230 { { "", 0 } , 0 }, 231 { { "", 0 } , 0 }, 232 { { "", 0 } , 0 }, 233 { { "", 0 } , 0 }, 234 { { "", 0 } , 0 }, 235 { { "", 0 } , 0 }, 236 { { "", 0 } , 0 }, 237 { { "", 0 } , 0 }, 238 { { "", 0 } , 0 }, 239 { { "", 0 } , 0 }, 240 { { "", 0 } , 0 }, 241 { { "", 0 } , 0 }, 242 { { "", 0 } , 0 }, 243 { { "", 0 } , 0 }, 244 { { "", 0 } , 0 }, 245 { { "", 0 } , 0 }, 246 { { "", 0 } , 0 }, 247 { { "", 0 } , 0 }, 248 { { "", 0 } , 0 }, 249 { { "", 0 } , 0 }, 250 { { "", 0 } , 0 }, 251 { { "", 0 } , 0 }, } }; 252 253 /* 254 * Due to different values for each source that uses these structures, 255 * the ac97_query_devinfo function sets delta in mixer_devinfo_t using 256 * ac97_source_info.bits. 257 */ 258 static const struct audio_mixer_value 259 ac97_volume_stereo = { { AudioNvolume, 0 }, 2, 0 }; 260 261 static const struct audio_mixer_value 262 ac97_volume_mono = { { AudioNvolume, 0 }, 1, 0 }; 263 264 #define WRAP(a) &a, sizeof(a) 265 266 struct ac97_source_info { 267 const char *class; 268 const char *device; 269 const char *qualifier; 270 271 int type; 272 const void *info; 273 int info_size; 274 275 uint8_t reg; 276 int32_t default_value; 277 unsigned bits:3; 278 unsigned ofs:4; 279 unsigned mute:1; 280 unsigned polarity:1; /* Does 0 == MAX or MIN */ 281 unsigned checkbits:1; 282 enum { 283 CHECK_NONE = 0, 284 CHECK_SURROUND, 285 CHECK_CENTER, 286 CHECK_LFE, 287 CHECK_HEADPHONES, 288 CHECK_TONE, 289 CHECK_MIC, 290 CHECK_LOUDNESS, 291 CHECK_3D, 292 CHECK_LINE1, 293 CHECK_LINE2, 294 CHECK_HANDSET, 295 CHECK_SPDIF 296 } req_feature; 297 298 int prev; 299 int next; 300 int mixer_class; 301 }; 302 303 static const struct ac97_source_info audio_source_info[] = { 304 { AudioCinputs, NULL, NULL, 305 AUDIO_MIXER_CLASS, NULL, 0, 306 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 307 { AudioCoutputs, NULL, 0, 308 AUDIO_MIXER_CLASS, NULL, 0, 309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 310 { AudioCrecord, NULL, 0, 311 AUDIO_MIXER_CLASS, NULL, 0, 312 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 313 /* Stereo master volume*/ 314 { AudioCoutputs, AudioNmaster, 0, 315 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 316 AC97_REG_MASTER_VOLUME, 0x8000, 5, 0, 1, 0, 1, 0, 0, 0, 0, 317 }, 318 /* Mono volume */ 319 { AudioCoutputs, AudioNmono, NULL, 320 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 321 AC97_REG_MASTER_VOLUME_MONO, 0x8000, 6, 0, 1, 0, 1, 0, 0, 0, 0, 322 }, 323 { AudioCoutputs, AudioNmono, AudioNsource, 324 AUDIO_MIXER_ENUM, WRAP(ac97_mono_select), 325 AC97_REG_GP, 0x0000, 1, 9, 0, 0, 0, 0, 0, 0, 0, 326 }, 327 /* Headphone volume */ 328 { AudioCoutputs, AudioNheadphone, NULL, 329 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 330 AC97_REG_HEADPHONE_VOLUME, 0x8000, 5, 0, 1, 0, 1, CHECK_HEADPHONES, 0, 0, 0, 331 }, 332 /* Surround volume - logic hard coded for mute */ 333 { AudioCoutputs, AudioNsurround, NULL, 334 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 335 AC97_REG_SURR_MASTER, 0x8080, 5, 0, 1, 0, 1, CHECK_SURROUND, 0, 0, 0 336 }, 337 /* Center volume*/ 338 { AudioCoutputs, AudioNcenter, NULL, 339 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 340 AC97_REG_CENTER_LFE_MASTER, 0x8080, 5, 0, 0, 0, 1, CHECK_CENTER, 0, 0, 0 341 }, 342 { AudioCoutputs, AudioNcenter, AudioNmute, 343 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 344 AC97_REG_CENTER_LFE_MASTER, 0x8080, 1, 7, 0, 0, 0, CHECK_CENTER, 0, 0, 0 345 }, 346 /* LFE volume*/ 347 { AudioCoutputs, AudioNlfe, NULL, 348 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 349 AC97_REG_CENTER_LFE_MASTER, 0x8080, 5, 8, 0, 0, 1, CHECK_LFE, 0, 0, 0 350 }, 351 { AudioCoutputs, AudioNlfe, AudioNmute, 352 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 353 AC97_REG_CENTER_LFE_MASTER, 0x8080, 1, 15, 0, 0, 0, CHECK_LFE, 0, 0, 0 354 }, 355 /* Tone - bass */ 356 { AudioCoutputs, AudioNbass, NULL, 357 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 358 AC97_REG_MASTER_TONE, 0x0f0f, 4, 8, 0, 0, 0, CHECK_TONE, 0, 0, 0 359 }, 360 /* Tone - treble */ 361 { AudioCoutputs, AudioNtreble, NULL, 362 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 363 AC97_REG_MASTER_TONE, 0x0f0f, 4, 0, 0, 0, 0, CHECK_TONE, 0, 0, 0 364 }, 365 /* PC Beep Volume */ 366 { AudioCinputs, AudioNspeaker, NULL, 367 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 368 AC97_REG_PCBEEP_VOLUME, 0x0000, 4, 1, 1, 0, 0, 0, 0, 0, 0, 369 }, 370 371 /* Phone */ 372 { AudioCinputs, Ac97Nphone, NULL, 373 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 374 AC97_REG_PHONE_VOLUME, 0x8008, 5, 0, 1, 0, 0, 0, 0, 0, 0, 375 }, 376 /* Mic Volume */ 377 { AudioCinputs, AudioNmicrophone, NULL, 378 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 379 AC97_REG_MIC_VOLUME, 0x8008, 5, 0, 1, 0, 0, 0, 0, 0, 0, 380 }, 381 { AudioCinputs, AudioNmicrophone, AudioNpreamp, 382 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 383 AC97_REG_MIC_VOLUME, 0x8008, 1, 6, 0, 0, 0, 0, 0, 0, 0, 384 }, 385 { AudioCinputs, AudioNmicrophone, AudioNsource, 386 AUDIO_MIXER_ENUM, WRAP(ac97_mic_select), 387 AC97_REG_GP, 0x0000, 1, 8, 0, 0, 0, 0, 0, 0, 0, 388 }, 389 /* Line in Volume */ 390 { AudioCinputs, AudioNline, NULL, 391 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 392 AC97_REG_LINEIN_VOLUME, 0x8808, 5, 0, 1, 0, 0, 0, 0, 0, 0, 393 }, 394 /* CD Volume */ 395 { AudioCinputs, AudioNcd, NULL, 396 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 397 AC97_REG_CD_VOLUME, 0x8808, 5, 0, 1, 0, 0, 0, 0, 0, 0, 398 }, 399 /* Video Volume */ 400 { AudioCinputs, AudioNvideo, NULL, 401 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 402 AC97_REG_VIDEO_VOLUME, 0x8808, 5, 0, 1, 0, 0, 0, 0, 0, 0, 403 }, 404 /* AUX volume */ 405 { AudioCinputs, AudioNaux, NULL, 406 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 407 AC97_REG_AUX_VOLUME, 0x8808, 5, 0, 1, 0, 0, 0, 0, 0, 0, 408 }, 409 /* PCM out volume */ 410 { AudioCinputs, AudioNdac, NULL, 411 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 412 AC97_REG_PCMOUT_VOLUME, 0x8808, 5, 0, 1, 0, 0, 0, 0, 0, 0, 413 }, 414 /* Record Source - some logic for this is hard coded - see below */ 415 { AudioCrecord, AudioNsource, NULL, 416 AUDIO_MIXER_ENUM, WRAP(ac97_source), 417 AC97_REG_RECORD_SELECT, 0x0000, 3, 0, 0, 0, 0, 0, 0, 0, 0, 418 }, 419 /* Record Gain */ 420 { AudioCrecord, AudioNvolume, NULL, 421 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 422 AC97_REG_RECORD_GAIN, 0x8000, 4, 0, 1, 1, 0, 0, 0, 0, 0, 423 }, 424 /* Record Gain mic */ 425 { AudioCrecord, AudioNmicrophone, NULL, 426 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 427 AC97_REG_RECORD_GAIN_MIC, 0x8000, 4, 0, 1, 1, 0, CHECK_MIC, 0, 0, 0 428 }, 429 /* */ 430 { AudioCoutputs, AudioNloudness, NULL, 431 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 432 AC97_REG_GP, 0x0000, 1, 12, 0, 0, 0, CHECK_LOUDNESS, 0, 0, 0 433 }, 434 { AudioCoutputs, AudioNspatial, NULL, 435 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 436 AC97_REG_GP, 0x0000, 1, 13, 0, 1, 0, CHECK_3D, 0, 0, 0 437 }, 438 { AudioCoutputs, AudioNspatial, "center", 439 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 440 AC97_REG_3D_CONTROL, 0x0000, 4, 8, 0, 1, 0, CHECK_3D, 0, 0, 0 441 }, 442 { AudioCoutputs, AudioNspatial, "depth", 443 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 444 AC97_REG_3D_CONTROL, 0x0000, 4, 0, 0, 1, 0, CHECK_3D, 0, 0, 0 445 }, 446 447 /* SPDIF */ 448 { "spdif", NULL, NULL, 449 AUDIO_MIXER_CLASS, NULL, 0, 450 0, 0, 0, 0, 0, 0, 0, CHECK_SPDIF, 0, 0, 0 451 }, 452 { "spdif", "enable", NULL, 453 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 454 AC97_REG_EXT_AUDIO_CTRL, -1, 1, 2, 0, 0, 0, CHECK_SPDIF, 0, 0, 0 455 }, 456 457 /* Missing features: Simulated Stereo, POP, Loopback mode */ 458 }; 459 460 static const struct ac97_source_info modem_source_info[] = { 461 /* Classes */ 462 { AudioCinputs, NULL, NULL, 463 AUDIO_MIXER_CLASS, NULL, 0, 464 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 465 { AudioCoutputs, NULL, NULL, 466 AUDIO_MIXER_CLASS, NULL, 0, 467 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 468 { AudioCinputs, Ac97Nline1, NULL, 469 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 470 AC97_REG_LINE1_LEVEL, 0x8080, 4, 0, 0, 1, 0, CHECK_LINE1, 0, 0, 0 471 }, 472 { AudioCoutputs, Ac97Nline1, NULL, 473 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 474 AC97_REG_LINE1_LEVEL, 0x8080, 4, 8, 0, 1, 0, CHECK_LINE1, 0, 0, 0 475 }, 476 { AudioCinputs, Ac97Nline1, AudioNmute, 477 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 478 AC97_REG_LINE1_LEVEL, 0x8080, 1, 7, 0, 0, 0, CHECK_LINE1, 0, 0, 0 479 }, 480 { AudioCoutputs, Ac97Nline1, AudioNmute, 481 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 482 AC97_REG_LINE1_LEVEL, 0x8080, 1, 15, 0, 0, 0, CHECK_LINE1, 0, 0, 0 483 }, 484 }; 485 486 #define AUDIO_SOURCE_INFO_SIZE \ 487 (sizeof(audio_source_info)/sizeof(audio_source_info[0])) 488 #define MODEM_SOURCE_INFO_SIZE \ 489 (sizeof(modem_source_info)/sizeof(modem_source_info[0])) 490 #define SOURCE_INFO_SIZE(as) ((as)->type == AC97_CODEC_TYPE_MODEM ? \ 491 MODEM_SOURCE_INFO_SIZE : AUDIO_SOURCE_INFO_SIZE) 492 493 /* 494 * Check out http://www.intel.com/support/motherboards/desktop/sb/cs-025406.htm for 495 * AC'97 Component Specification 496 */ 497 498 struct ac97_softc { 499 /* ac97_codec_if must be at the first of ac97_softc. */ 500 struct ac97_codec_if codec_if; 501 502 struct ac97_host_if *host_if; 503 504 kmutex_t *lock; 505 506 #define AUDIO_MAX_SOURCES (2 * AUDIO_SOURCE_INFO_SIZE) 507 #define MODEM_MAX_SOURCES (2 * MODEM_SOURCE_INFO_SIZE) 508 struct ac97_source_info audio_source_info[AUDIO_MAX_SOURCES]; 509 struct ac97_source_info modem_source_info[MODEM_MAX_SOURCES]; 510 struct ac97_source_info *source_info; 511 int num_source_info; 512 513 enum ac97_host_flags host_flags; 514 unsigned int ac97_clock; /* usually 48000 */ 515 #define AC97_STANDARD_CLOCK 48000U 516 uint16_t power_all; 517 uint16_t power_reg; /* -> AC97_REG_POWER */ 518 uint16_t caps; /* -> AC97_REG_RESET */ 519 uint16_t ext_id; /* -> AC97_REG_EXT_AUDIO_ID */ 520 uint16_t ext_mid; /* -> AC97_REG_EXT_MODEM_ID */ 521 uint16_t shadow_reg[128]; 522 523 int lock_counter; 524 int type; 525 526 /* sysctl */ 527 struct sysctllog *log; 528 int offhook_line1_mib; 529 int offhook_line2_mib; 530 int offhook_line1; 531 int offhook_line2; 532 }; 533 534 static struct ac97_codec_if_vtbl ac97civ = { 535 ac97_mixer_get_port, 536 ac97_mixer_set_port, 537 ac97_query_devinfo, 538 ac97_get_portnum_by_name, 539 ac97_restore_shadow, 540 ac97_get_extcaps, 541 ac97_set_rate, 542 ac97_set_clock, 543 ac97_detach, 544 ac97_lock, 545 ac97_unlock, 546 }; 547 548 static const struct ac97_codecid { 549 uint32_t id; 550 uint32_t mask; 551 const char *name; 552 void (*init)(struct ac97_softc *); 553 } ac97codecid[] = { 554 /* 555 * Analog Devices SoundMAX 556 * http://www.soundmax.com/products/information/codecs.html 557 * http://www.analog.com/productSelection/pdf/AD1881A_0.pdf 558 * http://www.analog.com/productSelection/pdf/AD1885_0.pdf 559 * http://www.analog.com/UploadedFiles/Data_Sheets/206585810AD1980_0.pdf 560 * http://www.analog.com/productSelection/pdf/AD1981A_0.pdf 561 * http://www.analog.com/productSelection/pdf/AD1981B_0.pdf 562 * http://www.analog.com/UploadedFiles/Data_Sheets/180644528AD1985_0.pdf 563 */ 564 { AC97_CODEC_ID('A', 'D', 'S', 3), 565 0xffffffff, "Analog Devices AD1819B", NULL, }, 566 { AC97_CODEC_ID('A', 'D', 'S', 0x40), 567 0xffffffff, "Analog Devices AD1881", NULL, }, 568 { AC97_CODEC_ID('A', 'D', 'S', 0x48), 569 0xffffffff, "Analog Devices AD1881A", NULL, }, 570 { AC97_CODEC_ID('A', 'D', 'S', 0x60), 571 0xffffffff, "Analog Devices AD1885", NULL, }, 572 { AC97_CODEC_ID('A', 'D', 'S', 0x61), 573 0xffffffff, "Analog Devices AD1886", NULL, }, 574 { AC97_CODEC_ID('A', 'D', 'S', 0x63), 575 0xffffffff, "Analog Devices AD1886A", NULL, }, 576 { AC97_CODEC_ID('A', 'D', 'S', 0x68), 577 0xffffffff, "Analog Devices AD1888", ac97_ad198x_init }, 578 { AC97_CODEC_ID('A', 'D', 'S', 0x70), 579 0xffffffff, "Analog Devices AD1980", ac97_ad198x_init }, 580 { AC97_CODEC_ID('A', 'D', 'S', 0x72), 581 0xffffffff, "Analog Devices AD1981A", NULL, }, 582 { AC97_CODEC_ID('A', 'D', 'S', 0x74), 583 0xffffffff, "Analog Devices AD1981B", NULL, }, 584 { AC97_CODEC_ID('A', 'D', 'S', 0x75), 585 0xffffffff, "Analog Devices AD1985", ac97_ad198x_init }, 586 { AC97_CODEC_ID('A', 'D', 'S', 0), 587 AC97_VENDOR_ID_MASK, "Analog Devices unknown", NULL, }, 588 589 /* 590 * Datasheets: 591 * http://www.asahi-kasei.co.jp/akm/japanese/product/ak4543/ek4543.pdf 592 * http://www.asahi-kasei.co.jp/akm/japanese/product/ak4544a/ek4544a.pdf 593 * http://www.asahi-kasei.co.jp/akm/japanese/product/ak4545/ak4545_f00e.pdf 594 */ 595 { AC97_CODEC_ID('A', 'K', 'M', 0), 596 0xffffffff, "Asahi Kasei AK4540", NULL, }, 597 { AC97_CODEC_ID('A', 'K', 'M', 1), 598 0xffffffff, "Asahi Kasei AK4542", NULL, }, 599 { AC97_CODEC_ID('A', 'K', 'M', 2), 600 0xffffffff, "Asahi Kasei AK4541/AK4543", NULL, }, 601 { AC97_CODEC_ID('A', 'K', 'M', 5), 602 0xffffffff, "Asahi Kasei AK4544", NULL, }, 603 { AC97_CODEC_ID('A', 'K', 'M', 6), 604 0xffffffff, "Asahi Kasei AK4544A", NULL, }, 605 { AC97_CODEC_ID('A', 'K', 'M', 7), 606 0xffffffff, "Asahi Kasei AK4545", NULL, }, 607 { AC97_CODEC_ID('A', 'K', 'M', 0), 608 AC97_VENDOR_ID_MASK, "Asahi Kasei unknown", NULL, }, 609 610 /* 611 * Realtek & Avance Logic 612 * http://www.realtek.com.tw/downloads/downloads1-3.aspx?lineid=5&famid=All&series=All&Spec=True 613 * 614 * ALC650 and ALC658 support VRA, but it supports only 8000, 11025, 615 * 12000, 16000, 22050, 24000, 32000, 44100, and 48000 Hz. 616 */ 617 { AC97_CODEC_ID('A', 'L', 'C', 0x00), 618 0xfffffff0, "Realtek RL5306", NULL, }, 619 { AC97_CODEC_ID('A', 'L', 'C', 0x10), 620 0xfffffff0, "Realtek RL5382", NULL, }, 621 { AC97_CODEC_ID('A', 'L', 'C', 0x20), 622 0xfffffff0, "Realtek RL5383/RL5522/ALC100", NULL, }, 623 { AC97_CODEC_ID('A', 'L', 'G', 0x10), 624 0xffffffff, "Avance Logic ALC200/ALC201", NULL, }, 625 { AC97_CODEC_ID('A', 'L', 'G', 0x20), 626 0xfffffff0, "Avance Logic ALC650", ac97_alc650_init }, 627 { AC97_CODEC_ID('A', 'L', 'G', 0x30), 628 0xffffffff, "Avance Logic ALC101", NULL, }, 629 { AC97_CODEC_ID('A', 'L', 'G', 0x40), 630 0xffffffff, "Avance Logic ALC202", NULL, }, 631 { AC97_CODEC_ID('A', 'L', 'G', 0x50), 632 0xffffffff, "Avance Logic ALC250", NULL, }, 633 { AC97_CODEC_ID('A', 'L', 'G', 0x60), 634 0xfffffff0, "Avance Logic ALC655", NULL, }, 635 { AC97_CODEC_ID('A', 'L', 'G', 0x70), 636 0xffffffff, "Avance Logic ALC203", NULL, }, 637 { AC97_CODEC_ID('A', 'L', 'G', 0x80), 638 0xfffffff0, "Avance Logic ALC658", NULL, }, 639 { AC97_CODEC_ID('A', 'L', 'G', 0x90), 640 0xfffffff0, "Avance Logic ALC850", NULL, }, 641 { AC97_CODEC_ID('A', 'L', 'C', 0), 642 AC97_VENDOR_ID_MASK, "Realtek unknown", NULL, }, 643 { AC97_CODEC_ID('A', 'L', 'G', 0), 644 AC97_VENDOR_ID_MASK, "Avance Logic unknown", NULL, }, 645 646 /** 647 * C-Media Electronics Inc. 648 * http://www.cmedia.com.tw/doc/CMI9739%206CH%20Audio%20Codec%20SPEC_Ver12.pdf 649 */ 650 { AC97_CODEC_ID('C', 'M', 'I', 0x61), 651 0xffffffff, "C-Media CMI9739", NULL, }, 652 { AC97_CODEC_ID('C', 'M', 'I', 0), 653 AC97_VENDOR_ID_MASK, "C-Media unknown", NULL, }, 654 655 /* Cirrus Logic, Crystal series: 656 * 'C' 'R' 'Y' 0x0[0-7] - CS4297 657 * 0x1[0-7] - CS4297A 658 * 0x2[0-7] - CS4298 659 * 0x2[8-f] - CS4294 660 * 0x3[0-7] - CS4299 661 * 0x4[8-f] - CS4201 662 * 0x5[8-f] - CS4205 663 * 0x6[0-7] - CS4291 664 * 0x7[0-7] - CS4202 665 * Datasheets: 666 * http://www.cirrus.com/pubs/cs4297A-5.pdf?DocumentID=593 667 * http://www.cirrus.com/pubs/cs4294.pdf?DocumentID=32 668 * http://www.cirrus.com/pubs/cs4299-5.pdf?DocumentID=594 669 * http://www.cirrus.com/pubs/cs4201-2.pdf?DocumentID=492 670 * http://www.cirrus.com/pubs/cs4205-2.pdf?DocumentID=492 671 * http://www.cirrus.com/pubs/cs4202-1.pdf?DocumentID=852 672 */ 673 { AC97_CODEC_ID('C', 'R', 'Y', 0x00), 674 0xfffffff8, "Crystal CS4297", NULL, }, 675 { AC97_CODEC_ID('C', 'R', 'Y', 0x10), 676 0xfffffff8, "Crystal CS4297A", NULL, }, 677 { AC97_CODEC_ID('C', 'R', 'Y', 0x20), 678 0xfffffff8, "Crystal CS4298", NULL, }, 679 { AC97_CODEC_ID('C', 'R', 'Y', 0x28), 680 0xfffffff8, "Crystal CS4294", NULL, }, 681 { AC97_CODEC_ID('C', 'R', 'Y', 0x30), 682 0xfffffff8, "Crystal CS4299", NULL, }, 683 { AC97_CODEC_ID('C', 'R', 'Y', 0x48), 684 0xfffffff8, "Crystal CS4201", NULL, }, 685 { AC97_CODEC_ID('C', 'R', 'Y', 0x58), 686 0xfffffff8, "Crystal CS4205", NULL, }, 687 { AC97_CODEC_ID('C', 'R', 'Y', 0x60), 688 0xfffffff8, "Crystal CS4291", NULL, }, 689 { AC97_CODEC_ID('C', 'R', 'Y', 0x70), 690 0xfffffff8, "Crystal CS4202", NULL, }, 691 { AC97_CODEC_ID('C', 'R', 'Y', 0), 692 AC97_VENDOR_ID_MASK, "Cirrus Logic unknown", NULL, }, 693 694 { 0x45838308, 0xffffffff, "ESS Technology ES1921", NULL, }, 695 { 0x45838300, AC97_VENDOR_ID_MASK, "ESS Technology unknown", NULL, }, 696 697 { AC97_CODEC_ID('H', 'R', 'S', 0), 698 0xffffffff, "Intersil HMP9701", NULL, }, 699 { AC97_CODEC_ID('H', 'R', 'S', 0), 700 AC97_VENDOR_ID_MASK, "Intersil unknown", NULL, }, 701 702 /* 703 * IC Ensemble (VIA) 704 * http://www.viatech.com/en/datasheet/DS1616.pdf 705 */ 706 { AC97_CODEC_ID('I', 'C', 'E', 0x01), 707 0xffffffff, "ICEnsemble ICE1230/VT1611", NULL, }, 708 { AC97_CODEC_ID('I', 'C', 'E', 0x11), 709 0xffffffff, "ICEnsemble ICE1232/VT1611A", NULL, }, 710 { AC97_CODEC_ID('I', 'C', 'E', 0x14), 711 0xffffffff, "ICEnsemble ICE1232A", NULL, }, 712 { AC97_CODEC_ID('I', 'C', 'E', 0x51), 713 0xffffffff, "VIA Technologies VT1616", ac97_vt1616_init }, 714 { AC97_CODEC_ID('I', 'C', 'E', 0x52), 715 0xffffffff, "VIA Technologies VT1616i", ac97_vt1616_init }, 716 { AC97_CODEC_ID('I', 'C', 'E', 0), 717 AC97_VENDOR_ID_MASK, "ICEnsemble/VIA unknown", NULL, }, 718 719 { AC97_CODEC_ID('N', 'S', 'C', 0), 720 0xffffffff, "National Semiconductor LM454[03568]", NULL, }, 721 { AC97_CODEC_ID('N', 'S', 'C', 49), 722 0xffffffff, "National Semiconductor LM4549", NULL, }, 723 { AC97_CODEC_ID('N', 'S', 'C', 0), 724 AC97_VENDOR_ID_MASK, "National Semiconductor unknown", NULL, }, 725 726 { AC97_CODEC_ID('P', 'S', 'C', 4), 727 0xffffffff, "Philips Semiconductor UCB1400", ac97_ucb1400_init, }, 728 { AC97_CODEC_ID('P', 'S', 'C', 0), 729 AC97_VENDOR_ID_MASK, "Philips Semiconductor unknown", NULL, }, 730 731 { AC97_CODEC_ID('S', 'I', 'L', 34), 732 0xffffffff, "Silicon Laboratory Si3036", NULL, }, 733 { AC97_CODEC_ID('S', 'I', 'L', 35), 734 0xffffffff, "Silicon Laboratory Si3038", NULL, }, 735 { AC97_CODEC_ID('S', 'I', 'L', 0), 736 AC97_VENDOR_ID_MASK, "Silicon Laboratory unknown", NULL, }, 737 738 { AC97_CODEC_ID('T', 'R', 'A', 2), 739 0xffffffff, "TriTech TR28022", NULL, }, 740 { AC97_CODEC_ID('T', 'R', 'A', 3), 741 0xffffffff, "TriTech TR28023", NULL, }, 742 { AC97_CODEC_ID('T', 'R', 'A', 6), 743 0xffffffff, "TriTech TR28026", NULL, }, 744 { AC97_CODEC_ID('T', 'R', 'A', 8), 745 0xffffffff, "TriTech TR28028", NULL, }, 746 { AC97_CODEC_ID('T', 'R', 'A', 35), 747 0xffffffff, "TriTech TR28602", NULL, }, 748 { AC97_CODEC_ID('T', 'R', 'A', 0), 749 AC97_VENDOR_ID_MASK, "TriTech unknown", NULL, }, 750 751 { AC97_CODEC_ID('T', 'X', 'N', 0x20), 752 0xffffffff, "Texas Instruments TLC320AD9xC", NULL, }, 753 { AC97_CODEC_ID('T', 'X', 'N', 0), 754 AC97_VENDOR_ID_MASK, "Texas Instruments unknown", NULL, }, 755 756 /* 757 * VIA 758 * http://www.viatech.com/en/multimedia/audio.jsp 759 */ 760 { AC97_CODEC_ID('V', 'I', 'A', 0x61), 761 0xffffffff, "VIA Technologies VT1612A", NULL, }, 762 { AC97_CODEC_ID('V', 'I', 'A', 0), 763 AC97_VENDOR_ID_MASK, "VIA Technologies unknown", NULL, }, 764 765 { AC97_CODEC_ID('W', 'E', 'C', 1), 766 0xffffffff, "Winbond W83971D", NULL, }, 767 { AC97_CODEC_ID('W', 'E', 'C', 0), 768 AC97_VENDOR_ID_MASK, "Winbond unknown", NULL, }, 769 770 /* 771 * http://www.wolfsonmicro.com/product_list.asp?cid=64 772 * http://www.wolfsonmicro.com/download.asp/did.56/WM9701A.pdf - 00 773 * http://www.wolfsonmicro.com/download.asp/did.57/WM9703.pdf - 03 774 * http://www.wolfsonmicro.com/download.asp/did.58/WM9704M.pdf - 04 775 * http://www.wolfsonmicro.com/download.asp/did.59/WM9704Q.pdf - 04 776 * http://www.wolfsonmicro.com/download.asp/did.184/WM9705_Rev34.pdf - 05 777 * http://www.wolfsonmicro.com/download.asp/did.60/WM9707.pdf - 03 778 * http://www.wolfsonmicro.com/download.asp/did.136/WM9708.pdf - 03 779 * http://www.wolfsonmicro.com/download.asp/did.243/WM9710.pdf - 05 780 */ 781 { AC97_CODEC_ID('W', 'M', 'L', 0), 782 0xffffffff, "Wolfson WM9701A", NULL, }, 783 { AC97_CODEC_ID('W', 'M', 'L', 3), 784 0xffffffff, "Wolfson WM9703/WM9707/WM9708", NULL, }, 785 { AC97_CODEC_ID('W', 'M', 'L', 4), 786 0xffffffff, "Wolfson WM9704", NULL, }, 787 { AC97_CODEC_ID('W', 'M', 'L', 5), 788 0xffffffff, "Wolfson WM9705/WM9710", NULL, }, 789 { AC97_CODEC_ID('W', 'M', 'L', 0), 790 AC97_VENDOR_ID_MASK, "Wolfson unknown", NULL, }, 791 792 /* 793 * http://www.yamaha.co.jp/english/product/lsi/us/products/pcaudio.html 794 * Datasheets: 795 * http://www.yamaha.co.jp/english/product/lsi/us/products/pdf/4MF743A20.pdf 796 * http://www.yamaha.co.jp/english/product/lsi/us/products/pdf/4MF753A20.pdf 797 */ 798 { AC97_CODEC_ID('Y', 'M', 'H', 0), 799 0xffffffff, "Yamaha YMF743-S", NULL, }, 800 { AC97_CODEC_ID('Y', 'M', 'H', 3), 801 0xffffffff, "Yamaha YMF753-S", NULL, }, 802 { AC97_CODEC_ID('Y', 'M', 'H', 0), 803 AC97_VENDOR_ID_MASK, "Yamaha unknown", NULL, }, 804 805 /* 806 * http://www.sigmatel.com/products/technical_docs.htm 807 * and 808 * http://www.sigmatel.com/documents/c-major-brochure-9-0.pdf 809 */ 810 { 0x83847600, 0xffffffff, "SigmaTel STAC9700", NULL, }, 811 { 0x83847604, 0xffffffff, "SigmaTel STAC9701/3/4/5", NULL, }, 812 { 0x83847605, 0xffffffff, "SigmaTel STAC9704", NULL, }, 813 { 0x83847608, 0xffffffff, "SigmaTel STAC9708", NULL, }, 814 { 0x83847609, 0xffffffff, "SigmaTel STAC9721/23", NULL, }, 815 { 0x83847644, 0xffffffff, "SigmaTel STAC9744/45", NULL, }, 816 { 0x83847650, 0xffffffff, "SigmaTel STAC9750/51", NULL, }, 817 { 0x83847652, 0xffffffff, "SigmaTel STAC9752/53", NULL, }, 818 { 0x83847656, 0xffffffff, "SigmaTel STAC9756/57", NULL, }, 819 { 0x83847658, 0xffffffff, "SigmaTel STAC9758/59", NULL, }, 820 { 0x83847666, 0xffffffff, "SigmaTel STAC9766/67", NULL, }, 821 { 0x83847684, 0xffffffff, "SigmaTel STAC9783/84", NULL, }, 822 { 0x83847600, AC97_VENDOR_ID_MASK, "SigmaTel unknown", NULL, }, 823 824 /* Conexant AC'97 modems -- good luck finding datasheets! */ 825 { AC97_CODEC_ID('C', 'X', 'T', 33), 826 0xffffffff, "Conexant HSD11246", NULL, }, 827 { AC97_CODEC_ID('C', 'X', 'T', 34), 828 0xffffffff, "Conexant D480 MDC V.92 Modem", NULL, }, 829 { AC97_CODEC_ID('C', 'X', 'T', 48), 830 0xffffffff, "Conexant CXT48", NULL, }, 831 { AC97_CODEC_ID('C', 'X', 'T', 0), 832 AC97_VENDOR_ID_MASK, "Conexant unknown", NULL, }, 833 834 { 0, 835 0, NULL, NULL, }, 836 }; 837 838 static const char * const ac97enhancement[] = { 839 "no 3D stereo", 840 "Analog Devices Phat Stereo", 841 "Creative", 842 "National Semi 3D", 843 "Yamaha Ymersion", 844 "BBE 3D", 845 "Crystal Semi 3D", 846 "Qsound QXpander", 847 "Spatializer 3D", 848 "SRS 3D", 849 "Platform Tech 3D", 850 "AKM 3D", 851 "Aureal", 852 "AZTECH 3D", 853 "Binaura 3D", 854 "ESS Technology", 855 "Harman International VMAx", 856 "Nvidea 3D", 857 "Philips Incredible Sound", 858 "Texas Instruments' 3D", 859 "VLSI Technology 3D", 860 "TriTech 3D", 861 "Realtek 3D", 862 "Samsung 3D", 863 "Wolfson Microelectronics 3D", 864 "Delta Integration 3D", 865 "SigmaTel 3D", 866 "KS Waves 3D", 867 "Rockwell 3D", 868 "Unknown 3D", 869 "Unknown 3D", 870 "Unknown 3D", 871 }; 872 873 static const char * const ac97feature[] = { 874 "dedicated mic channel", 875 "reserved", 876 "tone", 877 "simulated stereo", 878 "headphone", 879 "bass boost", 880 "18 bit DAC", 881 "20 bit DAC", 882 "18 bit ADC", 883 "20 bit ADC" 884 }; 885 886 887 /* #define AC97_DEBUG 10 */ 888 /* #define AC97_IO_DEBUG */ 889 890 #ifdef AUDIO_DEBUG 891 #define DPRINTF(x) if (ac97debug) printf x 892 #define DPRINTFN(n,x) if (ac97debug>(n)) printf x 893 #ifdef AC97_DEBUG 894 int ac97debug = AC97_DEBUG; 895 #else 896 int ac97debug = 0; 897 #endif 898 #else 899 #define DPRINTF(x) 900 #define DPRINTFN(n,x) 901 #endif 902 903 #ifdef AC97_IO_DEBUG 904 static const char *ac97_register_names[0x80 / 2] = { 905 "RESET", "MASTER_VOLUME", "HEADPHONE_VOLUME", "MASTER_VOLUME_MONO", 906 "MASTER_TONE", "PCBEEP_VOLUME", "PHONE_VOLUME", "MIC_VOLUME", 907 "LINEIN_VOLUME", "CD_VOLUME", "VIDEO_VOLUME", "AUX_VOLUME", 908 "PCMOUT_VOLUME", "RECORD_SELECT", "RECORD_GATIN", "RECORD_GAIN_MIC", 909 "GP", "3D_CONTROL", "AUDIO_INT", "POWER", 910 "EXT_AUDIO_ID", "EXT_AUDIO_CTRL", "PCM_FRONT_DAC_RATE", "PCM_SURR_DAC_RATE", 911 "PCM_LFE_DAC_RATE", "PCM_LR_ADC_RATE", "PCM_MIC_ADC_RATE", "CENTER_LFE_MASTER", 912 "SURR_MASTER", "SPDIF_CTRL", "EXT_MODEM_ID", "EXT_MODEM_CTRL", 913 "LINE1_RATE", "LINE2_RATE", "HANDSET_RATE", "LINE1_LEVEL", 914 "LINE2_LEVEL", "HANDSET_LEVEL", "GPIO_PIN_CONFIG", "GPIO_PIN_POLARITY", 915 "GPIO_PIN_STICKY", "GPIO_PIN_WAKEUP", "GPIO_PIN_STATUS", "MISC_MODEM_CTRL", 916 "0x58", "VENDOR-5A", "VENDOR-5C", "VENDOR-5E", 917 "0x60", "0x62", "0x64", "0x66", 918 "0x68", "0x6a", "0x6c", "0x6e", 919 "VENDOR-70", "VENDOR-72", "VENDOR-74", "VENDOR-76", 920 "VENDOR-78", "VENDOR-7A", "VENDOR_ID1", "VENDOR_ID2" 921 }; 922 #endif 923 924 /* 925 * XXX Some cards have an inverted AC97_POWER_EAMP bit. 926 * These cards will produce no sound unless AC97_HOST_INVERTED_EAMP is set. 927 */ 928 929 #define POWER_EAMP_ON(as) ((as->host_flags & AC97_HOST_INVERTED_EAMP) \ 930 ? AC97_POWER_EAMP : 0) 931 #define POWER_EAMP_OFF(as) ((as->host_flags & AC97_HOST_INVERTED_EAMP) \ 932 ? 0 : AC97_POWER_EAMP) 933 934 static void 935 ac97_read(struct ac97_softc *as, uint8_t reg, uint16_t *val) 936 { 937 KASSERT(mutex_owned(as->lock)); 938 939 if (as->host_flags & AC97_HOST_DONT_READ && 940 (reg != AC97_REG_VENDOR_ID1 && reg != AC97_REG_VENDOR_ID2 && 941 reg != AC97_REG_RESET)) { 942 *val = as->shadow_reg[reg >> 1]; 943 return; 944 } 945 946 if (as->host_if->read(as->host_if->arg, reg, val)) { 947 *val = as->shadow_reg[reg >> 1]; 948 } 949 } 950 951 static int 952 ac97_write(struct ac97_softc *as, uint8_t reg, uint16_t val) 953 { 954 KASSERT(mutex_owned(as->lock)); 955 956 #ifndef AC97_IO_DEBUG 957 as->shadow_reg[reg >> 1] = val; 958 return as->host_if->write(as->host_if->arg, reg, val); 959 #else 960 int ret; 961 uint16_t actual; 962 963 as->shadow_reg[reg >> 1] = val; 964 ret = as->host_if->write(as->host_if->arg, reg, val); 965 as->host_if->read(as->host_if->arg, reg, &actual); 966 if (val != actual && reg < 0x80) { 967 printf("ac97_write: reg=%s, written=0x%04x, read=0x%04x\n", 968 ac97_register_names[reg / 2], val, actual); 969 } 970 return ret; 971 #endif 972 } 973 974 static void 975 ac97_setup_defaults(struct ac97_softc *as) 976 { 977 int idx; 978 const struct ac97_source_info *si; 979 980 KASSERT(mutex_owned(as->lock)); 981 982 memset(as->shadow_reg, 0, sizeof(as->shadow_reg)); 983 984 for (idx = 0; idx < AUDIO_SOURCE_INFO_SIZE; idx++) { 985 si = &audio_source_info[idx]; 986 if (si->default_value >= 0) 987 ac97_write(as, si->reg, si->default_value); 988 } 989 for (idx = 0; idx < MODEM_SOURCE_INFO_SIZE; idx++) { 990 si = &modem_source_info[idx]; 991 if (si->default_value >= 0) 992 ac97_write(as, si->reg, si->default_value); 993 } 994 } 995 996 static void 997 ac97_restore_shadow(struct ac97_codec_if *codec_if) 998 { 999 struct ac97_softc *as; 1000 const struct ac97_source_info *si; 1001 int idx; 1002 uint16_t val; 1003 1004 as = (struct ac97_softc *)codec_if; 1005 1006 KASSERT(mutex_owned(as->lock)); 1007 1008 if (as->type == AC97_CODEC_TYPE_AUDIO) { 1009 /* restore AC97_REG_POWER */ 1010 ac97_write(as, AC97_REG_POWER, as->power_reg); 1011 /* make sure chip is fully operational */ 1012 for (idx = 50000; idx >= 0; idx--) { 1013 ac97_read(as, AC97_REG_POWER, &val); 1014 if ((val & as->power_all) == as->power_all) 1015 break; 1016 DELAY(10); 1017 } 1018 1019 /* 1020 * actually try changing a value! 1021 * The default value of AC97_REG_MASTER_VOLUME is 0x8000. 1022 */ 1023 for (idx = 50000; idx >= 0; idx--) { 1024 ac97_write(as, AC97_REG_MASTER_VOLUME, 0x1010); 1025 ac97_read(as, AC97_REG_MASTER_VOLUME, &val); 1026 if (val == 0x1010) 1027 break; 1028 DELAY(10); 1029 } 1030 } 1031 1032 for (idx = 0; idx < SOURCE_INFO_SIZE(as); idx++) { 1033 if (as->type == AC97_CODEC_TYPE_MODEM) 1034 si = &modem_source_info[idx]; 1035 else 1036 si = &audio_source_info[idx]; 1037 /* don't "restore" to the reset reg! */ 1038 if (si->reg != AC97_REG_RESET) 1039 ac97_write(as, si->reg, as->shadow_reg[si->reg >> 1]); 1040 } 1041 1042 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA 1043 | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM 1044 | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC 1045 | AC97_EXT_AUDIO_LDAC)) { 1046 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, 1047 as->shadow_reg[AC97_REG_EXT_AUDIO_CTRL >> 1]); 1048 } 1049 if (as->ext_mid & (AC97_EXT_MODEM_LINE1 | AC97_EXT_MODEM_LINE2 1050 | AC97_EXT_MODEM_HANDSET | AC97_EXT_MODEM_CID1 1051 | AC97_EXT_MODEM_CID2 | AC97_EXT_MODEM_ID0 1052 | AC97_EXT_MODEM_ID1)) { 1053 ac97_write(as, AC97_REG_EXT_MODEM_CTRL, 1054 as->shadow_reg[AC97_REG_EXT_MODEM_CTRL >> 1]); 1055 } 1056 } 1057 1058 static int 1059 ac97_str_equal(const char *a, const char *b) 1060 { 1061 return (a == b) || (a && b && (!strcmp(a, b))); 1062 } 1063 1064 static int 1065 ac97_check_capability(struct ac97_softc *as, int check) 1066 { 1067 switch (check) { 1068 case CHECK_NONE: 1069 return 1; 1070 case CHECK_SURROUND: 1071 return as->ext_id & AC97_EXT_AUDIO_SDAC; 1072 case CHECK_CENTER: 1073 return as->ext_id & AC97_EXT_AUDIO_CDAC; 1074 case CHECK_LFE: 1075 return as->ext_id & AC97_EXT_AUDIO_LDAC; 1076 case CHECK_SPDIF: 1077 return as->ext_id & AC97_EXT_AUDIO_SPDIF; 1078 case CHECK_HEADPHONES: 1079 return as->caps & AC97_CAPS_HEADPHONES; 1080 case CHECK_TONE: 1081 return as->caps & AC97_CAPS_TONECTRL; 1082 case CHECK_MIC: 1083 return as->caps & AC97_CAPS_MICIN; 1084 case CHECK_LOUDNESS: 1085 return as->caps & AC97_CAPS_LOUDNESS; 1086 case CHECK_3D: 1087 return AC97_CAPS_ENHANCEMENT(as->caps) != 0; 1088 case CHECK_LINE1: 1089 return as->ext_mid & AC97_EXT_MODEM_LINE1; 1090 case CHECK_LINE2: 1091 return as->ext_mid & AC97_EXT_MODEM_LINE2; 1092 case CHECK_HANDSET: 1093 return as->ext_mid & AC97_EXT_MODEM_HANDSET; 1094 default: 1095 printf("%s: internal error: feature=%d\n", __func__, check); 1096 return 0; 1097 } 1098 } 1099 1100 static void 1101 ac97_setup_source_info(struct ac97_softc *as) 1102 { 1103 int idx, ouridx; 1104 struct ac97_source_info *si, *si2; 1105 uint16_t value1, value2, value3; 1106 1107 KASSERT(mutex_owned(as->lock)); 1108 1109 for (idx = 0, ouridx = 0; idx < SOURCE_INFO_SIZE(as); idx++) { 1110 si = &as->source_info[ouridx]; 1111 if (as->type == AC97_CODEC_TYPE_MODEM) { 1112 memcpy(si, &modem_source_info[idx], sizeof(*si)); 1113 } else { 1114 memcpy(si, &audio_source_info[idx], sizeof(*si)); 1115 } 1116 if (!ac97_check_capability(as, si->req_feature)) 1117 continue; 1118 if (si->checkbits) { 1119 /* read the register value */ 1120 ac97_read(as, si->reg, &value1); 1121 /* write 0b100000 */ 1122 value2 = value1 & 0xffc0; 1123 value2 |= 0x20; 1124 ac97_write(as, si->reg, value2); 1125 /* verify */ 1126 ac97_read(as, si->reg, &value3); 1127 if (value2 == value3) { 1128 si->bits = 6; 1129 } else { 1130 si->bits = 5; 1131 } 1132 DPRINTF(("%s: register=%02x bits=%d\n", 1133 __func__, si->reg, si->bits)); 1134 ac97_write(as, si->reg, value1); 1135 } 1136 1137 switch (si->type) { 1138 case AUDIO_MIXER_CLASS: 1139 si->mixer_class = ouridx; 1140 ouridx++; 1141 break; 1142 case AUDIO_MIXER_VALUE: 1143 /* Todo - Test to see if it works */ 1144 ouridx++; 1145 1146 /* Add an entry for mute, if necessary */ 1147 if (si->mute) { 1148 si = &as->source_info[ouridx]; 1149 if (as->type == AC97_CODEC_TYPE_MODEM) 1150 memcpy(si, &modem_source_info[idx], 1151 sizeof(*si)); 1152 else 1153 memcpy(si, &audio_source_info[idx], 1154 sizeof(*si)); 1155 si->qualifier = AudioNmute; 1156 si->type = AUDIO_MIXER_ENUM; 1157 si->info = &ac97_on_off; 1158 si->info_size = sizeof(ac97_on_off); 1159 si->bits = 1; 1160 si->ofs = 15; 1161 si->mute = 0; 1162 si->polarity = 0; 1163 ouridx++; 1164 } 1165 break; 1166 case AUDIO_MIXER_ENUM: 1167 /* Todo - Test to see if it works */ 1168 ouridx++; 1169 break; 1170 default: 1171 aprint_error ("ac97: shouldn't get here\n"); 1172 break; 1173 } 1174 } 1175 1176 as->num_source_info = ouridx; 1177 1178 for (idx = 0; idx < as->num_source_info; idx++) { 1179 int idx2, previdx; 1180 1181 si = &as->source_info[idx]; 1182 1183 /* Find mixer class */ 1184 for (idx2 = 0; idx2 < as->num_source_info; idx2++) { 1185 si2 = &as->source_info[idx2]; 1186 1187 if (si2->type == AUDIO_MIXER_CLASS && 1188 ac97_str_equal(si->class, 1189 si2->class)) { 1190 si->mixer_class = idx2; 1191 } 1192 } 1193 1194 1195 /* Setup prev and next pointers */ 1196 if (si->prev != 0) 1197 continue; 1198 1199 if (si->qualifier) 1200 continue; 1201 1202 si->prev = AUDIO_MIXER_LAST; 1203 previdx = idx; 1204 1205 for (idx2 = 0; idx2 < as->num_source_info; idx2++) { 1206 if (idx2 == idx) 1207 continue; 1208 1209 si2 = &as->source_info[idx2]; 1210 1211 if (!si2->prev && 1212 ac97_str_equal(si->class, si2->class) && 1213 ac97_str_equal(si->device, si2->device)) { 1214 as->source_info[previdx].next = idx2; 1215 as->source_info[idx2].prev = previdx; 1216 1217 previdx = idx2; 1218 } 1219 } 1220 1221 as->source_info[previdx].next = AUDIO_MIXER_LAST; 1222 } 1223 } 1224 1225 /* backward compatibility */ 1226 int 1227 ac97_attach(struct ac97_host_if *host_if, device_t sc_dev, kmutex_t *lk) 1228 { 1229 return ac97_attach_type(host_if, sc_dev, AC97_CODEC_TYPE_AUDIO, lk); 1230 } 1231 1232 int 1233 ac97_attach_type(struct ac97_host_if *host_if, device_t sc_dev, int type, kmutex_t *lk) 1234 { 1235 struct ac97_softc *as; 1236 int error, i, j; 1237 uint32_t id; 1238 uint16_t id1, id2; 1239 uint16_t extstat, rate; 1240 uint16_t val; 1241 mixer_ctrl_t ctl; 1242 void (*initfunc)(struct ac97_softc *); 1243 #define FLAGBUFLEN 140 1244 char flagbuf[FLAGBUFLEN]; 1245 1246 initfunc = NULL; 1247 as = malloc(sizeof(struct ac97_softc), M_DEVBUF, M_WAITOK|M_ZERO); 1248 1249 if (as == NULL) 1250 return ENOMEM; 1251 1252 as->codec_if.vtbl = &ac97civ; 1253 as->host_if = host_if; 1254 as->type = type; 1255 as->lock = lk; 1256 1257 if ((error = host_if->attach(host_if->arg, &as->codec_if))) { 1258 free(as, M_DEVBUF); 1259 return error; 1260 } 1261 1262 mutex_enter(as->lock); 1263 1264 if (host_if->reset != NULL) { 1265 if ((error = host_if->reset(host_if->arg))) { 1266 mutex_exit(as->lock); 1267 free(as, M_DEVBUF); 1268 return error; 1269 } 1270 } 1271 1272 if (host_if->flags) 1273 as->host_flags = host_if->flags(host_if->arg); 1274 1275 /* 1276 * Assume codec has all four power bits. 1277 * XXXSCW: what to do for modems? 1278 */ 1279 as->power_all = AC97_POWER_REF | AC97_POWER_ANL | AC97_POWER_DAC | 1280 AC97_POWER_ADC; 1281 if (as->type == AC97_CODEC_TYPE_AUDIO) { 1282 host_if->write(host_if->arg, AC97_REG_RESET, 0); 1283 1284 /* 1285 * Power-up everything except the analogue mixer. 1286 * If this codec doesn't support analogue mixer power-down, 1287 * AC97_POWER_MIXER will read back as zero. 1288 */ 1289 host_if->write(host_if->arg, AC97_REG_POWER, AC97_POWER_MIXER); 1290 ac97_read(as, AC97_REG_POWER, &val); 1291 if ((val & AC97_POWER_MIXER) == 0) { 1292 /* Codec doesn't support analogue mixer power-down */ 1293 as->power_all &= ~AC97_POWER_ANL; 1294 } 1295 host_if->write(host_if->arg, AC97_REG_POWER, POWER_EAMP_ON(as)); 1296 1297 for (i = 500000; i >= 0; i--) { 1298 ac97_read(as, AC97_REG_POWER, &val); 1299 if ((val & as->power_all) == as->power_all) 1300 break; 1301 DELAY(1); 1302 } 1303 1304 /* save AC97_REG_POWER so that we can restore it later */ 1305 ac97_read(as, AC97_REG_POWER, &as->power_reg); 1306 } else if (as->type == AC97_CODEC_TYPE_MODEM) { 1307 host_if->write(host_if->arg, AC97_REG_EXT_MODEM_ID, 0); 1308 } 1309 1310 ac97_setup_defaults(as); 1311 if (as->type == AC97_CODEC_TYPE_AUDIO) 1312 ac97_read(as, AC97_REG_RESET, &as->caps); 1313 ac97_read(as, AC97_REG_VENDOR_ID1, &id1); 1314 ac97_read(as, AC97_REG_VENDOR_ID2, &id2); 1315 1316 mutex_exit(as->lock); 1317 1318 id = (id1 << 16) | id2; 1319 aprint_normal_dev(sc_dev, "ac97: "); 1320 1321 for (i = 0; ; i++) { 1322 if (ac97codecid[i].id == 0) { 1323 char pnp[4]; 1324 1325 AC97_GET_CODEC_ID(id, pnp); 1326 #define ISASCII(c) ((c) >= ' ' && (c) < 0x7f) 1327 if (ISASCII(pnp[0]) && ISASCII(pnp[1]) && 1328 ISASCII(pnp[2])) 1329 aprint_normal("%c%c%c%d", 1330 pnp[0], pnp[1], pnp[2], pnp[3]); 1331 else 1332 aprint_normal("unknown (0x%08x)", id); 1333 break; 1334 } 1335 if (ac97codecid[i].id == (id & ac97codecid[i].mask)) { 1336 aprint_normal("%s", ac97codecid[i].name); 1337 if (ac97codecid[i].mask == AC97_VENDOR_ID_MASK) { 1338 aprint_normal(" (0x%08x)", id); 1339 } 1340 initfunc = ac97codecid[i].init; 1341 break; 1342 } 1343 } 1344 aprint_normal(" codec; "); 1345 for (i = j = 0; i < 10; i++) { 1346 if (as->caps & (1 << i)) { 1347 aprint_normal("%s%s", j ? ", " : "", ac97feature[i]); 1348 j++; 1349 } 1350 } 1351 aprint_normal("%s%s\n", j ? ", " : "", 1352 ac97enhancement[AC97_CAPS_ENHANCEMENT(as->caps)]); 1353 1354 as->ac97_clock = AC97_STANDARD_CLOCK; 1355 1356 mutex_enter(as->lock); 1357 1358 if (as->type == AC97_CODEC_TYPE_AUDIO) { 1359 ac97_read(as, AC97_REG_EXT_AUDIO_ID, &as->ext_id); 1360 if (as->ext_id != 0) { 1361 mutex_exit(as->lock); 1362 1363 /* Print capabilities */ 1364 snprintb(flagbuf, sizeof(flagbuf), 1365 "\20\20SECONDARY10\17SECONDARY01" 1366 "\14AC97_23\13AC97_22\12AMAP\11LDAC\10SDAC" 1367 "\7CDAC\4VRM\3SPDIF\2DRA\1VRA", as->ext_id); 1368 aprint_normal_dev(sc_dev, "ac97: ext id %s\n", 1369 flagbuf); 1370 1371 /* Print unusual settings */ 1372 if (as->ext_id & AC97_EXT_AUDIO_DSA_MASK) { 1373 aprint_normal_dev(sc_dev, "ac97: Slot assignment: "); 1374 switch (as->ext_id & AC97_EXT_AUDIO_DSA_MASK) { 1375 case AC97_EXT_AUDIO_DSA01: 1376 aprint_normal("7&8, 6&9, 10&11.\n"); 1377 break; 1378 case AC97_EXT_AUDIO_DSA10: 1379 aprint_normal("6&9, 10&11, 3&4.\n"); 1380 break; 1381 case AC97_EXT_AUDIO_DSA11: 1382 aprint_normal("10&11, 3&4, 7&8.\n"); 1383 break; 1384 } 1385 } 1386 if (as->host_flags & AC97_HOST_INVERTED_EAMP) { 1387 aprint_normal_dev(sc_dev, "ac97: using inverted " 1388 "AC97_POWER_EAMP bit\n"); 1389 } 1390 1391 mutex_enter(as->lock); 1392 1393 /* Enable and disable features */ 1394 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat); 1395 extstat &= ~AC97_EXT_AUDIO_DRA; 1396 if (as->ext_id & AC97_EXT_AUDIO_LDAC) 1397 extstat |= AC97_EXT_AUDIO_LDAC; 1398 if (as->ext_id & AC97_EXT_AUDIO_SDAC) 1399 extstat |= AC97_EXT_AUDIO_SDAC; 1400 if (as->ext_id & AC97_EXT_AUDIO_CDAC) 1401 extstat |= AC97_EXT_AUDIO_CDAC; 1402 if (as->ext_id & AC97_EXT_AUDIO_VRM) 1403 extstat |= AC97_EXT_AUDIO_VRM; 1404 if (as->ext_id & AC97_EXT_AUDIO_SPDIF) { 1405 /* Output the same data as DAC to SPDIF output */ 1406 extstat &= ~AC97_EXT_AUDIO_SPSA_MASK; 1407 extstat |= AC97_EXT_AUDIO_SPSA34; 1408 ac97_read(as, AC97_REG_SPDIF_CTRL, &val); 1409 val = (val & ~AC97_SPDIF_SPSR_MASK) 1410 | AC97_SPDIF_SPSR_48K; 1411 ac97_write(as, AC97_REG_SPDIF_CTRL, val); 1412 } 1413 if (as->ext_id & AC97_EXT_AUDIO_VRA) 1414 extstat |= AC97_EXT_AUDIO_VRA; 1415 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat); 1416 if (as->ext_id & AC97_EXT_AUDIO_VRA) { 1417 /* VRA should be enabled. */ 1418 /* so it claims to do variable rate, let's make sure */ 1419 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE, 1420 44100); 1421 ac97_read(as, AC97_REG_PCM_FRONT_DAC_RATE, 1422 &rate); 1423 if (rate != 44100) { 1424 /* We can't believe ext_id */ 1425 as->ext_id = 0; 1426 aprint_normal_dev(sc_dev, 1427 "Ignore these capabilities.\n"); 1428 } 1429 /* restore the default value */ 1430 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE, 1431 AC97_SINGLE_RATE); 1432 } 1433 } 1434 } else if (as->type == AC97_CODEC_TYPE_MODEM) { 1435 const struct sysctlnode *node; 1436 const struct sysctlnode *node_line1; 1437 const struct sysctlnode *node_line2; 1438 uint16_t xrate = 8000; 1439 uint16_t xval, reg; 1440 int err; 1441 1442 ac97_read(as, AC97_REG_EXT_MODEM_ID, &as->ext_mid); 1443 mutex_exit(as->lock); 1444 1445 if (as->ext_mid == 0 || as->ext_mid == 0xffff) { 1446 aprint_normal_dev(sc_dev, "no modem codec found\n"); 1447 return ENXIO; 1448 } 1449 as->type = AC97_CODEC_TYPE_MODEM; 1450 1451 /* Print capabilities */ 1452 snprintb(flagbuf, sizeof(flagbuf), 1453 "\20\5CID2\4CID1\3HANDSET\2LINE2\1LINE1", as->ext_mid); 1454 aprint_normal_dev(sc_dev, "ac97: ext mid %s", 1455 flagbuf); 1456 aprint_normal(", %s codec\n", 1457 (as->ext_mid & 0xc000) == 0 ? 1458 "primary" : "secondary"); 1459 1460 /* Setup modem and sysctls */ 1461 err = sysctl_createv(&as->log, 0, NULL, NULL, 0, CTLTYPE_NODE, 1462 "hw", NULL, NULL, 0, NULL, 0, CTL_HW, 1463 CTL_EOL); 1464 if (err != 0) 1465 goto setup_modem; 1466 err = sysctl_createv(&as->log, 0, NULL, &node, 0, 1467 CTLTYPE_NODE, device_xname(sc_dev), NULL, 1468 NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, 1469 CTL_EOL); 1470 if (err != 0) 1471 goto setup_modem; 1472 setup_modem: 1473 mutex_enter(as->lock); 1474 1475 /* reset */ 1476 ac97_write(as, AC97_REG_EXT_MODEM_ID, 1); 1477 1478 /* program rates */ 1479 xval = 0xff00 & ~AC97_EXT_MODEM_CTRL_PRA; 1480 if (as->ext_mid & AC97_EXT_MODEM_LINE1) { 1481 ac97_write(as, AC97_REG_LINE1_RATE, xrate); 1482 xval &= ~(AC97_EXT_MODEM_CTRL_PRC | 1483 AC97_EXT_MODEM_CTRL_PRD); 1484 } 1485 if (as->ext_mid & AC97_EXT_MODEM_LINE2) { 1486 ac97_write(as, AC97_REG_LINE2_RATE, xrate); 1487 xval &= ~(AC97_EXT_MODEM_CTRL_PRE | 1488 AC97_EXT_MODEM_CTRL_PRF); 1489 } 1490 if (as->ext_mid & AC97_EXT_MODEM_HANDSET) { 1491 ac97_write(as, AC97_REG_HANDSET_RATE, xrate); 1492 xval &= ~(AC97_EXT_MODEM_CTRL_PRG | 1493 AC97_EXT_MODEM_CTRL_PRH); 1494 } 1495 1496 /* power-up everything */ 1497 ac97_write(as, AC97_REG_EXT_MODEM_CTRL, 0); 1498 for (i = 5000; i >= 0; i--) { 1499 ac97_read(as, AC97_REG_EXT_MODEM_CTRL, ®); 1500 if ((reg & /*XXXval*/0xf) == /*XXXval*/0xf) 1501 break; 1502 DELAY(1); 1503 } 1504 if (i <= 0) { 1505 mutex_exit(as->lock); 1506 printf("%s: codec not responding, status=0x%x\n", 1507 device_xname(sc_dev), reg); 1508 return ENXIO; 1509 } 1510 1511 /* setup sysctls */ 1512 if (as->ext_mid & AC97_EXT_MODEM_LINE1) { 1513 ac97_read(as, AC97_REG_GPIO_CFG, ®); 1514 reg &= ~AC97_GPIO_LINE1_OH; 1515 ac97_write(as, AC97_REG_GPIO_CFG, reg); 1516 ac97_read(as, AC97_REG_GPIO_POLARITY, ®); 1517 reg &= ~AC97_GPIO_LINE1_OH; 1518 ac97_write(as, AC97_REG_GPIO_POLARITY, reg); 1519 1520 mutex_exit(as->lock); 1521 err = sysctl_createv(&as->log, 0, NULL, &node_line1, 1522 CTLFLAG_READWRITE, CTLTYPE_INT, 1523 "line1", 1524 SYSCTL_DESCR("off-hook line1"), 1525 ac97_sysctl_verify, 0, (void *)as, 0, 1526 CTL_HW, node->sysctl_num, 1527 CTL_CREATE, CTL_EOL); 1528 mutex_enter(as->lock); 1529 1530 if (err != 0) 1531 goto sysctl_err; 1532 as->offhook_line1_mib = node_line1->sysctl_num; 1533 } 1534 if (as->ext_mid & AC97_EXT_MODEM_LINE2) { 1535 ac97_read(as, AC97_REG_GPIO_CFG, ®); 1536 reg &= ~AC97_GPIO_LINE2_OH; 1537 ac97_write(as, AC97_REG_GPIO_CFG, reg); 1538 ac97_read(as, AC97_REG_GPIO_POLARITY, ®); 1539 reg &= ~AC97_GPIO_LINE2_OH; 1540 ac97_write(as, AC97_REG_GPIO_POLARITY, reg); 1541 1542 mutex_exit(as->lock); 1543 err = sysctl_createv(&as->log, 0, NULL, &node_line2, 1544 CTLFLAG_READWRITE, CTLTYPE_INT, 1545 "line2", 1546 SYSCTL_DESCR("off-hook line2"), 1547 ac97_sysctl_verify, 0, (void *)as, 0, 1548 CTL_HW, node->sysctl_num, 1549 CTL_CREATE, CTL_EOL); 1550 mutex_enter(as->lock); 1551 1552 if (err != 0) 1553 goto sysctl_err; 1554 as->offhook_line2_mib = node_line2->sysctl_num; 1555 } 1556 sysctl_err: 1557 1558 ac97_write(as, AC97_REG_GPIO_STICKY, 0xffff); 1559 ac97_write(as, AC97_REG_GPIO_WAKEUP, 0x0); 1560 ac97_write(as, AC97_REG_MISC_AFE, 0x0); 1561 } 1562 1563 as->source_info = (as->type == AC97_CODEC_TYPE_MODEM ? 1564 as->modem_source_info : as->audio_source_info); 1565 ac97_setup_source_info(as); 1566 1567 memset(&ctl, 0, sizeof(ctl)); 1568 /* disable mutes */ 1569 for (i = 0; i < 11; i++) { 1570 static struct { 1571 const char *class, *device; 1572 } d[11] = { 1573 { AudioCoutputs, AudioNmaster}, 1574 { AudioCoutputs, AudioNheadphone}, 1575 { AudioCoutputs, AudioNsurround}, 1576 { AudioCoutputs, AudioNcenter}, 1577 { AudioCoutputs, AudioNlfe}, 1578 { AudioCinputs, AudioNdac}, 1579 { AudioCinputs, AudioNcd}, 1580 { AudioCinputs, AudioNline}, 1581 { AudioCinputs, AudioNaux}, 1582 { AudioCinputs, AudioNvideo}, 1583 { AudioCrecord, AudioNvolume}, 1584 }; 1585 1586 ctl.type = AUDIO_MIXER_ENUM; 1587 ctl.un.ord = 0; 1588 1589 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, 1590 d[i].class, d[i].device, AudioNmute); 1591 ac97_mixer_set_port(&as->codec_if, &ctl); 1592 } 1593 ctl.type = AUDIO_MIXER_ENUM; 1594 ctl.un.ord = 0; 1595 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord, 1596 AudioNsource, NULL); 1597 ac97_mixer_set_port(&as->codec_if, &ctl); 1598 1599 /* set a reasonable default volume */ 1600 ctl.type = AUDIO_MIXER_VALUE; 1601 ctl.un.value.num_channels = 2; 1602 ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = \ 1603 ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127; 1604 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs, 1605 AudioNmaster, NULL); 1606 ac97_mixer_set_port(&as->codec_if, &ctl); 1607 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs, 1608 AudioNsurround, NULL); 1609 ac97_mixer_set_port(&as->codec_if, &ctl); 1610 ctl.un.value.num_channels = 1; 1611 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs, 1612 AudioNcenter, NULL); 1613 ac97_mixer_set_port(&as->codec_if, &ctl); 1614 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs, 1615 AudioNlfe, NULL); 1616 ac97_mixer_set_port(&as->codec_if, &ctl); 1617 1618 if (initfunc != NULL) 1619 initfunc(as); 1620 1621 /* restore AC97_REG_POWER */ 1622 if (as->type == AC97_CODEC_TYPE_AUDIO) 1623 ac97_write(as, AC97_REG_POWER, as->power_reg); 1624 1625 mutex_exit(as->lock); 1626 1627 return 0; 1628 } 1629 1630 static void 1631 ac97_detach(struct ac97_codec_if *codec_if) 1632 { 1633 struct ac97_softc *as; 1634 1635 as = (struct ac97_softc *)codec_if; 1636 1637 mutex_enter(as->lock); 1638 ac97_write(as, AC97_REG_POWER, AC97_POWER_IN | AC97_POWER_OUT 1639 | AC97_POWER_MIXER | AC97_POWER_MIXER_VREF 1640 | AC97_POWER_ACLINK | AC97_POWER_CLK | AC97_POWER_AUX 1641 | POWER_EAMP_OFF(as)); 1642 mutex_exit(as->lock); 1643 1644 free(as, M_DEVBUF); 1645 } 1646 1647 static void 1648 ac97_lock(struct ac97_codec_if *codec_if) 1649 { 1650 struct ac97_softc *as; 1651 1652 as = (struct ac97_softc *)codec_if; 1653 1654 KASSERT(mutex_owned(as->lock)); 1655 1656 as->lock_counter++; 1657 } 1658 1659 static void 1660 ac97_unlock(struct ac97_codec_if *codec_if) 1661 { 1662 struct ac97_softc *as; 1663 1664 as = (struct ac97_softc *)codec_if; 1665 1666 KASSERT(mutex_owned(as->lock)); 1667 1668 as->lock_counter--; 1669 } 1670 1671 static int 1672 ac97_query_devinfo(struct ac97_codec_if *codec_if, mixer_devinfo_t *dip) 1673 { 1674 struct ac97_softc *as; 1675 struct ac97_source_info *si; 1676 const char *name; 1677 1678 as = (struct ac97_softc *)codec_if; 1679 if (dip->index < as->num_source_info) { 1680 si = &as->source_info[dip->index]; 1681 dip->type = si->type; 1682 dip->mixer_class = si->mixer_class; 1683 dip->prev = si->prev; 1684 dip->next = si->next; 1685 1686 if (si->qualifier) 1687 name = si->qualifier; 1688 else if (si->device) 1689 name = si->device; 1690 else if (si->class) 1691 name = si->class; 1692 else 1693 name = 0; 1694 1695 if (name) 1696 strcpy(dip->label.name, name); 1697 1698 memcpy(&dip->un, si->info, si->info_size); 1699 1700 /* Set the delta for volume sources */ 1701 if (dip->type == AUDIO_MIXER_VALUE) 1702 dip->un.v.delta = 1 << (8 - si->bits); 1703 1704 return 0; 1705 } 1706 1707 return ENXIO; 1708 } 1709 1710 static int 1711 ac97_mixer_set_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp) 1712 { 1713 struct ac97_softc *as; 1714 struct ac97_source_info *si; 1715 uint16_t mask; 1716 uint16_t val, newval; 1717 int error; 1718 bool spdif; 1719 1720 as = (struct ac97_softc *)codec_if; 1721 1722 KASSERT(mutex_owned(as->lock)); 1723 1724 if (cp->dev < 0 || cp->dev >= as->num_source_info) 1725 return EINVAL; 1726 si = &as->source_info[cp->dev]; 1727 1728 if (cp->type == AUDIO_MIXER_CLASS || cp->type != si->type) 1729 return EINVAL; 1730 spdif = si->req_feature == CHECK_SPDIF && si->reg == AC97_REG_EXT_AUDIO_CTRL; 1731 if (spdif && as->lock_counter >= 0) { 1732 /* When the value of lock_counter is the default 0, 1733 * it is not allowed to change the SPDIF mode. */ 1734 return EBUSY; 1735 } 1736 1737 ac97_read(as, si->reg, &val); 1738 1739 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val)); 1740 1741 mask = (1 << si->bits) - 1; 1742 1743 switch (cp->type) { 1744 case AUDIO_MIXER_ENUM: 1745 if (cp->un.ord > mask || cp->un.ord < 0) 1746 return EINVAL; 1747 1748 newval = (cp->un.ord << si->ofs); 1749 if (si->reg == AC97_REG_RECORD_SELECT) { 1750 newval |= (newval << (8 + si->ofs)); 1751 mask |= (mask << 8); 1752 mask = mask << si->ofs; 1753 } else if (si->reg == AC97_REG_SURR_MASTER) { 1754 newval = cp->un.ord ? 0x8080 : 0x0000; 1755 mask = 0x8080; 1756 } else 1757 mask = mask << si->ofs; 1758 break; 1759 case AUDIO_MIXER_VALUE: 1760 { 1761 const struct audio_mixer_value *value = si->info; 1762 uint16_t l, r, ol, or; 1763 int deltal, deltar; 1764 1765 if ((cp->un.value.num_channels <= 0) || 1766 (cp->un.value.num_channels > value->num_channels)) 1767 return EINVAL; 1768 1769 if (cp->un.value.num_channels == 1) { 1770 l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 1771 } else { 1772 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) { 1773 l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1774 r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1775 } else { /* left/right is reversed here */ 1776 r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1777 l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1778 } 1779 1780 } 1781 1782 if (!si->polarity) { 1783 l = 255 - l; 1784 r = 255 - r; 1785 } 1786 1787 ol = (val >> (8+si->ofs)) & mask; 1788 or = (val >> si->ofs) & mask; 1789 1790 deltal = (ol << (8 - si->bits)) - l; 1791 deltar = (or << (8 - si->bits)) - r; 1792 1793 l = l >> (8 - si->bits); 1794 r = r >> (8 - si->bits); 1795 1796 if (deltal && ol == l) 1797 l += (deltal > 0) ? (l ? -1 : 0) : (l < mask ? 1 : 0); 1798 if (deltar && or == r) 1799 r += (deltar > 0) ? (r ? -1 : 0) : (r < mask ? 1 : 0); 1800 1801 newval = ((r & mask) << si->ofs); 1802 if (value->num_channels == 2) { 1803 newval = newval | ((l & mask) << (si->ofs+8)); 1804 mask |= (mask << 8); 1805 } 1806 mask = mask << si->ofs; 1807 break; 1808 } 1809 default: 1810 return EINVAL; 1811 } 1812 1813 error = ac97_write(as, si->reg, (val & ~mask) | newval); 1814 if (error) 1815 return error; 1816 1817 if (spdif && as->host_if->spdif_event != NULL) { 1818 DPRINTF(("%s: call spdif_event(%d)\n", __func__, cp->un.ord)); 1819 as->host_if->spdif_event(as->host_if->arg, cp->un.ord); 1820 } 1821 return 0; 1822 } 1823 1824 static int 1825 ac97_get_portnum_by_name(struct ac97_codec_if *codec_if, const char *class, 1826 const char *device, const char *qualifier) 1827 { 1828 struct ac97_softc *as; 1829 int idx; 1830 1831 as = (struct ac97_softc *)codec_if; 1832 1833 KASSERT(mutex_owned(as->lock)); 1834 1835 for (idx = 0; idx < as->num_source_info; idx++) { 1836 struct ac97_source_info *si = &as->source_info[idx]; 1837 if (ac97_str_equal(class, si->class) && 1838 ac97_str_equal(device, si->device) && 1839 ac97_str_equal(qualifier, si->qualifier)) 1840 return idx; 1841 } 1842 1843 return -1; 1844 } 1845 1846 static int 1847 ac97_mixer_get_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp) 1848 { 1849 struct ac97_softc *as; 1850 struct ac97_source_info *si; 1851 uint16_t mask; 1852 uint16_t val; 1853 1854 as = (struct ac97_softc *)codec_if; 1855 1856 KASSERT(mutex_owned(as->lock)); 1857 1858 si = &as->source_info[cp->dev]; 1859 if (cp->dev < 0 || cp->dev >= as->num_source_info) 1860 return EINVAL; 1861 1862 if (cp->type != si->type) 1863 return EINVAL; 1864 1865 ac97_read(as, si->reg, &val); 1866 1867 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val)); 1868 1869 mask = (1 << si->bits) - 1; 1870 1871 switch (cp->type) { 1872 case AUDIO_MIXER_ENUM: 1873 cp->un.ord = (val >> si->ofs) & mask; 1874 DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n", 1875 val, si->ofs, mask, cp->un.ord)); 1876 break; 1877 case AUDIO_MIXER_VALUE: 1878 { 1879 const struct audio_mixer_value *value = si->info; 1880 uint16_t l, r; 1881 1882 if ((cp->un.value.num_channels <= 0) || 1883 (cp->un.value.num_channels > value->num_channels)) 1884 return EINVAL; 1885 1886 if (value->num_channels == 1) { 1887 l = r = (val >> si->ofs) & mask; 1888 } else { 1889 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) { 1890 l = (val >> (si->ofs + 8)) & mask; 1891 r = (val >> si->ofs) & mask; 1892 } else { /* host has reversed channels */ 1893 r = (val >> (si->ofs + 8)) & mask; 1894 l = (val >> si->ofs) & mask; 1895 } 1896 } 1897 1898 l = (l << (8 - si->bits)); 1899 r = (r << (8 - si->bits)); 1900 if (!si->polarity) { 1901 l = 255 - l; 1902 r = 255 - r; 1903 } 1904 1905 /* The EAP driver averages l and r for stereo 1906 channels that are requested in MONO mode. Does this 1907 make sense? */ 1908 if (cp->un.value.num_channels == 1) { 1909 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l; 1910 } else if (cp->un.value.num_channels == 2) { 1911 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l; 1912 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r; 1913 } 1914 1915 break; 1916 } 1917 default: 1918 return EINVAL; 1919 } 1920 1921 return 0; 1922 } 1923 1924 1925 static int 1926 ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_int *rate) 1927 { 1928 struct ac97_softc *as; 1929 u_int value; 1930 uint16_t ext_stat; 1931 uint16_t actual; 1932 uint16_t power; 1933 uint16_t power_bit; 1934 1935 as = (struct ac97_softc *)codec_if; 1936 1937 KASSERT(mutex_owned(as->lock)); 1938 1939 if (target == AC97_REG_PCM_MIC_ADC_RATE) { 1940 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) { 1941 *rate = AC97_SINGLE_RATE; 1942 return 0; 1943 } 1944 } else { 1945 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) { 1946 *rate = AC97_SINGLE_RATE; 1947 return 0; 1948 } 1949 } 1950 value = *rate * AC97_STANDARD_CLOCK / as->ac97_clock; 1951 ext_stat = 0; 1952 /* 1953 * PCM_FRONT_DAC_RATE/PCM_SURR_DAC_RATE/PCM_LFE_DAC_RATE 1954 * Check VRA, DRA 1955 * PCM_LR_ADC_RATE 1956 * Check VRA 1957 * PCM_MIC_ADC_RATE 1958 * Check VRM 1959 */ 1960 switch (target) { 1961 case AC97_REG_PCM_FRONT_DAC_RATE: 1962 case AC97_REG_PCM_SURR_DAC_RATE: 1963 case AC97_REG_PCM_LFE_DAC_RATE: 1964 power_bit = AC97_POWER_OUT; 1965 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) { 1966 *rate = AC97_SINGLE_RATE; 1967 return 0; 1968 } 1969 if (as->ext_id & AC97_EXT_AUDIO_DRA) { 1970 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &ext_stat); 1971 if (value > 0x1ffff) { 1972 return EINVAL; 1973 } else if (value > 0xffff) { 1974 /* Enable DRA */ 1975 ext_stat |= AC97_EXT_AUDIO_DRA; 1976 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat); 1977 value /= 2; 1978 } else { 1979 /* Disable DRA */ 1980 ext_stat &= ~AC97_EXT_AUDIO_DRA; 1981 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat); 1982 } 1983 } else { 1984 if (value > 0xffff) 1985 return EINVAL; 1986 } 1987 break; 1988 case AC97_REG_PCM_LR_ADC_RATE: 1989 power_bit = AC97_POWER_IN; 1990 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) { 1991 *rate = AC97_SINGLE_RATE; 1992 return 0; 1993 } 1994 if (value > 0xffff) 1995 return EINVAL; 1996 break; 1997 case AC97_REG_PCM_MIC_ADC_RATE: 1998 power_bit = AC97_POWER_IN; 1999 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) { 2000 *rate = AC97_SINGLE_RATE; 2001 return 0; 2002 } 2003 if (value > 0xffff) 2004 return EINVAL; 2005 break; 2006 default: 2007 printf("%s: Unknown register: 0x%x\n", __func__, target); 2008 return EINVAL; 2009 } 2010 2011 ac97_read(as, AC97_REG_POWER, &power); 2012 ac97_write(as, AC97_REG_POWER, power | power_bit); 2013 2014 ac97_write(as, target, (uint16_t)value); 2015 ac97_read(as, target, &actual); 2016 actual = (uint32_t)actual * as->ac97_clock / AC97_STANDARD_CLOCK; 2017 2018 ac97_write(as, AC97_REG_POWER, power); 2019 if (ext_stat & AC97_EXT_AUDIO_DRA) { 2020 *rate = actual * 2; 2021 } else { 2022 *rate = actual; 2023 } 2024 return 0; 2025 } 2026 2027 static void 2028 ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock) 2029 { 2030 struct ac97_softc *as; 2031 2032 as = (struct ac97_softc *)codec_if; 2033 2034 KASSERT(mutex_owned(as->lock)); 2035 2036 as->ac97_clock = clock; 2037 } 2038 2039 static uint16_t 2040 ac97_get_extcaps(struct ac97_codec_if *codec_if) 2041 { 2042 struct ac97_softc *as; 2043 2044 as = (struct ac97_softc *)codec_if; 2045 2046 KASSERT(mutex_owned(as->lock)); 2047 2048 return as->ext_id; 2049 } 2050 2051 static int 2052 ac97_add_port(struct ac97_softc *as, const struct ac97_source_info *src) 2053 { 2054 struct ac97_source_info *si; 2055 int ouridx, idx; 2056 2057 KASSERT(mutex_owned(as->lock)); 2058 2059 if ((as->type == AC97_CODEC_TYPE_AUDIO && 2060 as->num_source_info >= AUDIO_MAX_SOURCES) || 2061 (as->type == AC97_CODEC_TYPE_MODEM && 2062 as->num_source_info >= MODEM_MAX_SOURCES)) { 2063 printf("%s: internal error: increase MAX_SOURCES in %s\n", 2064 __func__, __FILE__); 2065 return -1; 2066 } 2067 if (!ac97_check_capability(as, src->req_feature)) 2068 return -1; 2069 ouridx = as->num_source_info; 2070 si = &as->source_info[ouridx]; 2071 memcpy(si, src, sizeof(*si)); 2072 2073 switch (si->type) { 2074 case AUDIO_MIXER_CLASS: 2075 case AUDIO_MIXER_VALUE: 2076 printf("%s: adding class/value is not supported yet.\n", 2077 __func__); 2078 return -1; 2079 case AUDIO_MIXER_ENUM: 2080 break; 2081 default: 2082 printf("%s: unknown type: %d\n", __func__, si->type); 2083 return -1; 2084 } 2085 as->num_source_info++; 2086 2087 si->mixer_class = ac97_get_portnum_by_name(&as->codec_if, si->class, 2088 NULL, NULL); 2089 /* Find the root of the device */ 2090 idx = ac97_get_portnum_by_name(&as->codec_if, si->class, 2091 si->device, NULL); 2092 /* Find the last item */ 2093 while (as->source_info[idx].next != AUDIO_MIXER_LAST) 2094 idx = as->source_info[idx].next; 2095 /* Append */ 2096 as->source_info[idx].next = ouridx; 2097 si->prev = idx; 2098 si->next = AUDIO_MIXER_LAST; 2099 2100 return 0; 2101 } 2102 2103 /** 2104 * Codec-dependent initialization 2105 */ 2106 2107 #define AD1980_REG_MISC 0x76 2108 #define AD1980_MISC_MBG0 0x0001 /* 0 1888/1980/1981 /1985 */ 2109 #define AD1980_MISC_MBG1 0x0002 /* 1 1888/1980/1981 /1985 */ 2110 #define AD1980_MISC_VREFD 0x0004 /* 2 1888/1980/1981 /1985 */ 2111 #define AD1980_MISC_VREFH 0x0008 /* 3 1888/1980/1981 /1985 */ 2112 #define AD1980_MISC_SRU 0x0010 /* 4 1888/1980 /1985 */ 2113 #define AD1980_MISC_LOSEL 0x0020 /* 5 1888/1980/1981 /1985 */ 2114 #define AD1980_MISC_2CMIC 0x0040 /* 6 1980/1981B/1985 */ 2115 #define AD1980_MISC_SPRD 0x0080 /* 7 1888/1980 /1985 */ 2116 #define AD1980_MISC_DMIX0 0x0100 /* 8 1888/1980 /1985 */ 2117 #define AD1980_MISC_DMIX1 0x0200 /* 9 1888/1980 /1985 */ 2118 #define AD1980_MISC_HPSEL 0x0400 /*10 1888/1980 /1985 */ 2119 #define AD1980_MISC_CLDIS 0x0800 /*11 1888/1980 /1985 */ 2120 #define AD1980_MISC_LODIS 0x1000 /*12 1888/1980/1981 /1985 */ 2121 #define AD1980_MISC_MSPLT 0x2000 /*13 1888/1980/1981 /1985 */ 2122 #define AD1980_MISC_AC97NC 0x4000 /*14 1888/1980 /1985 */ 2123 #define AD1980_MISC_DACZ 0x8000 /*15 1888/1980/1981 /1985 */ 2124 #define AD1981_REG_MISC 0x76 2125 #define AD1981_MISC_MADST 0x0010 /* 4 */ 2126 #define AD1981A_MISC_MADPD 0x0040 /* 6 */ 2127 #define AD1981B_MISC_MADPD 0x0080 /* 7 */ 2128 #define AD1981_MISC_FMXE 0x0200 /* 9 */ 2129 #define AD1981_MISC_DAM 0x0800 /*11 */ 2130 static void 2131 ac97_ad198x_init(struct ac97_softc *as) 2132 { 2133 int i; 2134 uint16_t misc; 2135 2136 KASSERT(mutex_owned(as->lock)); 2137 2138 ac97_read(as, AD1980_REG_MISC, &misc); 2139 ac97_write(as, AD1980_REG_MISC, 2140 misc | AD1980_MISC_LOSEL | AD1980_MISC_HPSEL); 2141 2142 for (i = 0; i < as->num_source_info; i++) { 2143 if (as->source_info[i].type != AUDIO_MIXER_VALUE) 2144 continue; 2145 2146 if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME) 2147 as->source_info[i].reg = AC97_REG_SURR_MASTER; 2148 else if (as->source_info[i].reg == AC97_REG_SURR_MASTER) 2149 as->source_info[i].reg = AC97_REG_MASTER_VOLUME; 2150 } 2151 } 2152 2153 #define ALC650_REG_MULTI_CHANNEL_CONTROL 0x6a 2154 #define ALC650_MCC_SLOT_MODIFY_MASK 0xc000 2155 #define ALC650_MCC_FRONTDAC_FROM_SPDIFIN 0x2000 /* 13 */ 2156 #define ALC650_MCC_SPDIFOUT_FROM_ADC 0x1000 /* 12 */ 2157 #define ALC650_MCC_PCM_FROM_SPDIFIN 0x0800 /* 11 */ 2158 #define ALC650_MCC_MIC_OR_CENTERLFE 0x0400 /* 10 */ 2159 #define ALC650_MCC_LINEIN_OR_SURROUND 0x0200 /* 9 */ 2160 #define ALC650_MCC_INDEPENDENT_MASTER_L 0x0080 /* 7 */ 2161 #define ALC650_MCC_INDEPENDENT_MASTER_R 0x0040 /* 6 */ 2162 #define ALC650_MCC_ANALOG_TO_CENTERLFE 0x0020 /* 5 */ 2163 #define ALC650_MCC_ANALOG_TO_SURROUND 0x0010 /* 4 */ 2164 #define ALC650_MCC_EXCHANGE_CENTERLFE 0x0008 /* 3 */ 2165 #define ALC650_MCC_CENTERLFE_DOWNMIX 0x0004 /* 2 */ 2166 #define ALC650_MCC_SURROUND_DOWNMIX 0x0002 /* 1 */ 2167 #define ALC650_MCC_LINEOUT_TO_SURROUND 0x0001 /* 0 */ 2168 static void 2169 ac97_alc650_init(struct ac97_softc *as) 2170 { 2171 static const struct ac97_source_info sources[6] = { 2172 { AudioCoutputs, AudioNsurround, "lineinjack", 2173 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 2174 ALC650_REG_MULTI_CHANNEL_CONTROL, 2175 0x0000, 1, 9, 0, 0, 0, CHECK_SURROUND, 0, 0, 0, }, 2176 { AudioCoutputs, AudioNsurround, "mixtofront", 2177 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 2178 ALC650_REG_MULTI_CHANNEL_CONTROL, 2179 0x0000, 1, 1, 0, 0, 0, CHECK_SURROUND, 0, 0, 0, }, 2180 { AudioCoutputs, AudioNcenter, "micjack", 2181 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 2182 ALC650_REG_MULTI_CHANNEL_CONTROL, 2183 0x0000, 1, 10, 0, 0, 0, CHECK_CENTER, 0, 0, 0, }, 2184 { AudioCoutputs, AudioNlfe, "micjack", 2185 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 2186 ALC650_REG_MULTI_CHANNEL_CONTROL, 2187 0x0000, 1, 10, 0, 0, 0, CHECK_LFE, 0, 0, 0, }, 2188 { AudioCoutputs, AudioNcenter, "mixtofront", 2189 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 2190 ALC650_REG_MULTI_CHANNEL_CONTROL, 2191 0x0000, 1, 2, 0, 0, 0, CHECK_CENTER, 0, 0, 0, }, 2192 { AudioCoutputs, AudioNlfe, "mixtofront", 2193 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 2194 ALC650_REG_MULTI_CHANNEL_CONTROL, 2195 0x0000, 1, 2, 0, 0, 0, CHECK_LFE, 0, 0, 0, }, 2196 }; 2197 2198 ac97_add_port(as, &sources[0]); 2199 ac97_add_port(as, &sources[1]); 2200 ac97_add_port(as, &sources[2]); 2201 ac97_add_port(as, &sources[3]); 2202 ac97_add_port(as, &sources[4]); 2203 ac97_add_port(as, &sources[5]); 2204 } 2205 2206 #define UCB1400_REG_FEATURE_CSR1 0x6a 2207 #define UCB1400_BB(bb) (((bb) & 0xf) << 11) 2208 #define UCB1400_TR(tr) (((tr) & 0x3) << 9) 2209 #define UCB1400_M_MAXIMUM (3 << 7) 2210 #define UCB1400_M_MINIMUM (1 << 7) 2211 #define UCB1400_M_FLAT (0 << 7) 2212 #define UCB1400_HPEN (1 << 6) 2213 #define UCB1400_DE (1 << 5) 2214 #define UCB1400_DC (1 << 4) 2215 #define UCB1400_HIPS (1 << 3) 2216 #define UCB1400_GIEN (1 << 2) 2217 #define UCB1400_OVFL (1 << 0) 2218 #define UCB1400_REG_FEATURE_CSR2 0x6c 2219 #define UCB1400_SMT (1 << 15) /* Must be 0 */ 2220 #define UCB1400_SUEV1 (1 << 14) /* Must be 0 */ 2221 #define UCB1400_SUEV0 (1 << 13) /* Must be 0 */ 2222 #define UCB1400_AVE (1 << 12) 2223 #define UCB1400_AVEN1 (1 << 11) /* Must be 0 */ 2224 #define UCB1400_AVEN0 (1 << 10) /* Must be 0 */ 2225 #define UCB1400_SLP_ON \ 2226 (UCB1400_SLP_PLL | UCB1400_SLP_CODEC) 2227 #define UCB1400_SLP_PLL (2 << 4) 2228 #define UCB1400_SLP_CODEC (1 << 4) 2229 #define UCB1400_SLP_NO (0 << 4) 2230 #define UCB1400_EV2 (1 << 2) /* Must be 0 */ 2231 #define UCB1400_EV1 (1 << 1) /* Must be 0 */ 2232 #define UCB1400_EV0 (1 << 0) /* Must be 0 */ 2233 static void 2234 ac97_ucb1400_init(struct ac97_softc *as) 2235 { 2236 2237 ac97_write(as, UCB1400_REG_FEATURE_CSR1, 2238 UCB1400_HPEN | UCB1400_DC | UCB1400_HIPS | UCB1400_OVFL); 2239 ac97_write(as, UCB1400_REG_FEATURE_CSR2, UCB1400_AVE | UCB1400_SLP_ON); 2240 } 2241 2242 #define VT1616_REG_IO_CONTROL 0x5a 2243 #define VT1616_IC_LVL (1 << 15) 2244 #define VT1616_IC_LFECENTER_TO_FRONT (1 << 12) 2245 #define VT1616_IC_SURROUND_TO_FRONT (1 << 11) 2246 #define VT1616_IC_BPDC (1 << 10) 2247 #define VT1616_IC_DC (1 << 9) 2248 #define VT1616_IC_IB_MASK 0x000c 2249 static void 2250 ac97_vt1616_init(struct ac97_softc *as) 2251 { 2252 static const struct ac97_source_info sources[3] = { 2253 { AudioCoutputs, AudioNsurround, "mixtofront", 2254 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 2255 VT1616_REG_IO_CONTROL, 2256 0x0000, 1, 11, 0, 0, 0, CHECK_SURROUND, 0, 0, 0, }, 2257 { AudioCoutputs, AudioNcenter, "mixtofront", 2258 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 2259 VT1616_REG_IO_CONTROL, 2260 0x0000, 1, 12, 0, 0, 0, CHECK_CENTER, 0, 0, 0, }, 2261 { AudioCoutputs, AudioNlfe, "mixtofront", 2262 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 2263 VT1616_REG_IO_CONTROL, 2264 0x0000, 1, 12, 0, 0, 0, CHECK_LFE, 0, 0, 0, }, 2265 }; 2266 2267 KASSERT(mutex_owned(as->lock)); 2268 2269 ac97_add_port(as, &sources[0]); 2270 ac97_add_port(as, &sources[1]); 2271 ac97_add_port(as, &sources[2]); 2272 } 2273 2274 static int 2275 ac97_modem_offhook_set(struct ac97_softc *as, int line, int newval) 2276 { 2277 uint16_t val; 2278 2279 KASSERT(mutex_owned(as->lock)); 2280 2281 val = as->shadow_reg[AC97_REG_GPIO_STATUS >> 1]; 2282 switch (newval) { 2283 case 0: 2284 val &= ~line; 2285 break; 2286 case 1: 2287 val |= line; 2288 break; 2289 } 2290 ac97_write(as, AC97_REG_GPIO_STATUS, val); 2291 2292 return 0; 2293 } 2294 2295 static int 2296 ac97_sysctl_verify(SYSCTLFN_ARGS) 2297 { 2298 int error, tmp; 2299 struct sysctlnode node; 2300 struct ac97_softc *as; 2301 2302 node = *rnode; 2303 as = rnode->sysctl_data; 2304 if (node.sysctl_num == as->offhook_line1_mib) { 2305 tmp = as->offhook_line1; 2306 node.sysctl_data = &tmp; 2307 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 2308 if (error || newp == NULL) 2309 return error; 2310 2311 if (tmp < 0 || tmp > 1) 2312 return EINVAL; 2313 2314 as->offhook_line1 = tmp; 2315 mutex_enter(as->lock); 2316 ac97_modem_offhook_set(as, AC97_GPIO_LINE1_OH, tmp); 2317 mutex_exit(as->lock); 2318 } else if (node.sysctl_num == as->offhook_line2_mib) { 2319 tmp = as->offhook_line2; 2320 node.sysctl_data = &tmp; 2321 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 2322 if (error || newp == NULL) 2323 return error; 2324 2325 if (tmp < 0 || tmp > 1) 2326 return EINVAL; 2327 2328 as->offhook_line2 = tmp; 2329 mutex_enter(as->lock); 2330 ac97_modem_offhook_set(as, AC97_GPIO_LINE2_OH, tmp); 2331 mutex_exit(as->lock); 2332 } 2333 2334 return 0; 2335 } 2336