1 /* $NetBSD: ac97.c,v 1.65 2004/11/08 14:24:17 kent 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.65 2004/11/08 14:24:17 kent 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 74 #include <sys/audioio.h> 75 #include <dev/audio_if.h> 76 77 #include <dev/ic/ac97reg.h> 78 #include <dev/ic/ac97var.h> 79 80 struct ac97_softc; 81 struct ac97_source_info; 82 static int ac97_mixer_get_port(struct ac97_codec_if *, mixer_ctrl_t *); 83 static int ac97_mixer_set_port(struct ac97_codec_if *, mixer_ctrl_t *); 84 static void ac97_detach(struct ac97_codec_if *); 85 static int ac97_query_devinfo(struct ac97_codec_if *, mixer_devinfo_t *); 86 static int ac97_get_portnum_by_name(struct ac97_codec_if *, const char *, 87 const char *, const char *); 88 static void ac97_restore_shadow(struct ac97_codec_if *); 89 static int ac97_set_rate(struct ac97_codec_if *, int, u_long *); 90 static void ac97_set_clock(struct ac97_codec_if *, unsigned int); 91 static u_int16_t ac97_get_extcaps(struct ac97_codec_if *); 92 static int ac97_add_port(struct ac97_softc *, 93 const struct ac97_source_info *); 94 static int ac97_str_equal(const char *, const char *); 95 static int ac97_check_capability(struct ac97_softc *, int); 96 static void ac97_setup_source_info(struct ac97_softc *); 97 static void ac97_read(struct ac97_softc *, u_int8_t, u_int16_t *); 98 static void ac97_setup_defaults(struct ac97_softc *); 99 static int ac97_write(struct ac97_softc *, u_int8_t, u_int16_t); 100 101 static void ac97_ad198x_init(struct ac97_softc *); 102 static void ac97_alc650_init(struct ac97_softc *); 103 static void ac97_vt1616_init(struct ac97_softc *); 104 105 #define Ac97Nphone "phone" 106 107 static const struct audio_mixer_enum 108 ac97_on_off = { 2, { { { AudioNoff } , 0 }, 109 { { AudioNon } , 1 } } }; 110 111 static const struct audio_mixer_enum 112 ac97_mic_select = { 2, { { { AudioNmicrophone "0" }, 0 }, 113 { { AudioNmicrophone "1" }, 1 } } }; 114 115 static const struct audio_mixer_enum 116 ac97_mono_select = { 2, { { { AudioNmixerout }, 0 }, 117 { { AudioNmicrophone }, 1 } } }; 118 119 static const struct audio_mixer_enum 120 ac97_source = { 8, { { { AudioNmicrophone } , 0 }, 121 { { AudioNcd }, 1 }, 122 { { AudioNvideo }, 2 }, 123 { { AudioNaux }, 3 }, 124 { { AudioNline }, 4 }, 125 { { AudioNmixerout }, 5 }, 126 { { AudioNmixerout AudioNmono }, 6 }, 127 { { Ac97Nphone }, 7 } } }; 128 129 /* 130 * Due to different values for each source that uses these structures, 131 * the ac97_query_devinfo function sets delta in mixer_devinfo_t using 132 * ac97_source_info.bits. 133 */ 134 static const struct audio_mixer_value 135 ac97_volume_stereo = { { AudioNvolume }, 2 }; 136 137 static const struct audio_mixer_value 138 ac97_volume_mono = { { AudioNvolume }, 1 }; 139 140 #define WRAP(a) &a, sizeof(a) 141 142 static const struct ac97_source_info { 143 const char *class; 144 const char *device; 145 const char *qualifier; 146 147 int type; 148 const void *info; 149 int info_size; 150 151 u_int8_t reg; 152 u_int16_t default_value; 153 u_int8_t bits:3; 154 u_int8_t ofs:4; 155 u_int8_t mute:1; 156 u_int8_t polarity:1; /* Does 0 == MAX or MIN */ 157 enum { 158 CHECK_NONE = 0, 159 CHECK_SURROUND, 160 CHECK_CENTER, 161 CHECK_LFE, 162 CHECK_HEADPHONES, 163 CHECK_TONE, 164 CHECK_MIC, 165 CHECK_LOUDNESS, 166 CHECK_3D 167 } req_feature; 168 169 int prev; 170 int next; 171 int mixer_class; 172 } source_info[] = { 173 { AudioCinputs, NULL, NULL, 174 AUDIO_MIXER_CLASS, }, 175 { AudioCoutputs, NULL, NULL, 176 AUDIO_MIXER_CLASS, }, 177 { AudioCrecord, NULL, NULL, 178 AUDIO_MIXER_CLASS, }, 179 /* Stereo master volume*/ 180 { AudioCoutputs, AudioNmaster, NULL, 181 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 182 AC97_REG_MASTER_VOLUME, 0x8000, 5, 0, 1, 183 }, 184 /* Mono volume */ 185 { AudioCoutputs, AudioNmono, NULL, 186 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 187 AC97_REG_MASTER_VOLUME_MONO, 0x8000, 6, 0, 1, 188 }, 189 { AudioCoutputs, AudioNmono, AudioNsource, 190 AUDIO_MIXER_ENUM, WRAP(ac97_mono_select), 191 AC97_REG_GP, 0x0000, 1, 9, 0, 192 }, 193 /* Headphone volume */ 194 { AudioCoutputs, AudioNheadphone, NULL, 195 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 196 AC97_REG_HEADPHONE_VOLUME, 0x8000, 6, 0, 1, 0, CHECK_HEADPHONES 197 }, 198 /* Surround volume - logic hard coded for mute */ 199 { AudioCoutputs, AudioNsurround, NULL, 200 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 201 AC97_REG_SURR_MASTER, 0x8080, 5, 0, 1, 0, CHECK_SURROUND 202 }, 203 /* Center volume*/ 204 { AudioCoutputs, AudioNcenter, NULL, 205 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 206 AC97_REG_CENTER_LFE_MASTER, 0x8080, 5, 0, 0, 0, CHECK_CENTER 207 }, 208 { AudioCoutputs, AudioNcenter, AudioNmute, 209 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 210 AC97_REG_CENTER_LFE_MASTER, 0x8080, 1, 7, 0, 0, CHECK_CENTER 211 }, 212 /* LFE volume*/ 213 { AudioCoutputs, AudioNlfe, NULL, 214 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 215 AC97_REG_CENTER_LFE_MASTER, 0x8080, 5, 8, 0, 0, CHECK_LFE 216 }, 217 { AudioCoutputs, AudioNlfe, AudioNmute, 218 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 219 AC97_REG_CENTER_LFE_MASTER, 0x8080, 1, 15, 0, 0, CHECK_LFE 220 }, 221 /* Tone - bass */ 222 { AudioCoutputs, AudioNbass, NULL, 223 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 224 AC97_REG_MASTER_TONE, 0x0f0f, 4, 8, 0, 0, CHECK_TONE 225 }, 226 /* Tone - treble */ 227 { AudioCoutputs, AudioNtreble, NULL, 228 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 229 AC97_REG_MASTER_TONE, 0x0f0f, 4, 0, 0, 0, CHECK_TONE 230 }, 231 /* PC Beep Volume */ 232 { AudioCinputs, AudioNspeaker, NULL, 233 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 234 AC97_REG_PCBEEP_VOLUME, 0x0000, 4, 1, 1, 235 }, 236 237 /* Phone */ 238 { AudioCinputs, Ac97Nphone, NULL, 239 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 240 AC97_REG_PHONE_VOLUME, 0x8008, 5, 0, 1, 241 }, 242 /* Mic Volume */ 243 { AudioCinputs, AudioNmicrophone, NULL, 244 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 245 AC97_REG_MIC_VOLUME, 0x8008, 5, 0, 1, 246 }, 247 { AudioCinputs, AudioNmicrophone, AudioNpreamp, 248 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 249 AC97_REG_MIC_VOLUME, 0x8008, 1, 6, 0, 250 }, 251 { AudioCinputs, AudioNmicrophone, AudioNsource, 252 AUDIO_MIXER_ENUM, WRAP(ac97_mic_select), 253 AC97_REG_GP, 0x0000, 1, 8, 0, 254 }, 255 /* Line in Volume */ 256 { AudioCinputs, AudioNline, NULL, 257 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 258 AC97_REG_LINEIN_VOLUME, 0x8808, 5, 0, 1, 259 }, 260 /* CD Volume */ 261 { AudioCinputs, AudioNcd, NULL, 262 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 263 AC97_REG_CD_VOLUME, 0x8808, 5, 0, 1, 264 }, 265 /* Video Volume */ 266 { AudioCinputs, AudioNvideo, NULL, 267 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 268 AC97_REG_VIDEO_VOLUME, 0x8808, 5, 0, 1, 269 }, 270 /* AUX volume */ 271 { AudioCinputs, AudioNaux, NULL, 272 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 273 AC97_REG_AUX_VOLUME, 0x8808, 5, 0, 1, 274 }, 275 /* PCM out volume */ 276 { AudioCinputs, AudioNdac, NULL, 277 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 278 AC97_REG_PCMOUT_VOLUME, 0x8808, 5, 0, 1, 279 }, 280 /* Record Source - some logic for this is hard coded - see below */ 281 { AudioCrecord, AudioNsource, NULL, 282 AUDIO_MIXER_ENUM, WRAP(ac97_source), 283 AC97_REG_RECORD_SELECT, 0x0000, 3, 0, 0, 284 }, 285 /* Record Gain */ 286 { AudioCrecord, AudioNvolume, NULL, 287 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 288 AC97_REG_RECORD_GAIN, 0x8000, 4, 0, 1, 1, 289 }, 290 /* Record Gain mic */ 291 { AudioCrecord, AudioNmicrophone, NULL, 292 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 293 AC97_REG_RECORD_GAIN_MIC, 0x8000, 4, 0, 1, 1, CHECK_MIC 294 }, 295 /* */ 296 { AudioCoutputs, AudioNloudness, NULL, 297 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 298 AC97_REG_GP, 0x0000, 1, 12, 0, 0, CHECK_LOUDNESS 299 }, 300 { AudioCoutputs, AudioNspatial, NULL, 301 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 302 AC97_REG_GP, 0x0000, 1, 13, 0, 1, CHECK_3D 303 }, 304 { AudioCoutputs, AudioNspatial, "center", 305 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 306 AC97_REG_3D_CONTROL, 0x0000, 4, 8, 0, 1, CHECK_3D 307 }, 308 { AudioCoutputs, AudioNspatial, "depth", 309 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 310 AC97_REG_3D_CONTROL, 0x0000, 4, 0, 0, 1, CHECK_3D 311 }, 312 313 /* Missing features: Simulated Stereo, POP, Loopback mode */ 314 }; 315 316 #define SOURCE_INFO_SIZE (sizeof(source_info)/sizeof(source_info[0])) 317 318 /* 319 * Check out http://developer.intel.com/pc-supp/platform/ac97/ for 320 * information on AC-97 321 */ 322 323 struct ac97_softc { 324 /* ac97_codec_if must be at the first of ac97_softc. */ 325 struct ac97_codec_if codec_if; 326 327 struct ac97_host_if *host_if; 328 329 #define MAX_SOURCES (2 * SOURCE_INFO_SIZE) 330 struct ac97_source_info source_info[MAX_SOURCES]; 331 int num_source_info; 332 333 enum ac97_host_flags host_flags; 334 unsigned int ac97_clock; /* usually 48000 */ 335 #define AC97_STANDARD_CLOCK 48000U 336 u_int16_t caps; /* -> AC97_REG_RESET */ 337 u_int16_t ext_id; /* -> AC97_REG_EXT_AUDIO_ID */ 338 u_int16_t shadow_reg[128]; 339 }; 340 341 static struct ac97_codec_if_vtbl ac97civ = { 342 ac97_mixer_get_port, 343 ac97_mixer_set_port, 344 ac97_query_devinfo, 345 ac97_get_portnum_by_name, 346 ac97_restore_shadow, 347 ac97_get_extcaps, 348 ac97_set_rate, 349 ac97_set_clock, 350 ac97_detach, 351 }; 352 353 static const struct ac97_codecid { 354 u_int32_t id; 355 u_int32_t mask; 356 const char *name; 357 void (*init)(struct ac97_softc *); 358 } ac97codecid[] = { 359 /* 360 * Analog Devices SoundMAX 361 * http://www.soundmax.com/products/information/codecs.html 362 * http://www.analog.com/productSelection/pdf/AD1881A_0.pdf 363 * http://www.analog.com/productSelection/pdf/AD1885_0.pdf 364 * http://www.analog.com/UploadedFiles/Data_Sheets/206585810AD1980_0.pdf 365 * http://www.analog.com/productSelection/pdf/AD1981A_0.pdf 366 * http://www.analog.com/productSelection/pdf/AD1981B_0.pdf 367 * http://www.analog.com/UploadedFiles/Data_Sheets/180644528AD1985_0.pdf 368 */ 369 { AC97_CODEC_ID('A', 'D', 'S', 3), 370 0xffffffff, "Analog Devices AD1819B" }, 371 { AC97_CODEC_ID('A', 'D', 'S', 0x40), 372 0xffffffff, "Analog Devices AD1881" }, 373 { AC97_CODEC_ID('A', 'D', 'S', 0x48), 374 0xffffffff, "Analog Devices AD1881A" }, 375 { AC97_CODEC_ID('A', 'D', 'S', 0x60), 376 0xffffffff, "Analog Devices AD1885" }, 377 { AC97_CODEC_ID('A', 'D', 'S', 0x61), 378 0xffffffff, "Analog Devices AD1886" }, 379 { AC97_CODEC_ID('A', 'D', 'S', 0x63), 380 0xffffffff, "Analog Devices AD1886A" }, 381 { AC97_CODEC_ID('A', 'D', 'S', 0x68), 382 0xffffffff, "Analog Devices AD1888", ac97_ad198x_init }, 383 { AC97_CODEC_ID('A', 'D', 'S', 0x70), 384 0xffffffff, "Analog Devices AD1980", ac97_ad198x_init }, 385 { AC97_CODEC_ID('A', 'D', 'S', 0x72), 386 0xffffffff, "Analog Devices AD1981A" }, 387 { AC97_CODEC_ID('A', 'D', 'S', 0x74), 388 0xffffffff, "Analog Devices AD1981B" }, 389 { AC97_CODEC_ID('A', 'D', 'S', 0x75), 390 0xffffffff, "Analog Devices AD1985", ac97_ad198x_init }, 391 { AC97_CODEC_ID('A', 'D', 'S', 0), 392 AC97_VENDOR_ID_MASK, "Analog Devices unknown" }, 393 394 /* 395 * Datasheets: 396 * http://www.asahi-kasei.co.jp/akm/usa/product/ak4541/ek4541.pdf 397 * http://www.asahi-kasei.co.jp/akm/usa/product/ak4543/ek4543.pdf 398 * http://www.asahi-kasei.co.jp/akm/usa/product/ak4544a/ek4544a.pdf 399 * http://www.asahi-kasei.co.jp/akm/usa/product/ak4545/ek4545.pdf 400 */ 401 { AC97_CODEC_ID('A', 'K', 'M', 0), 402 0xffffffff, "Asahi Kasei AK4540" }, 403 { AC97_CODEC_ID('A', 'K', 'M', 1), 404 0xffffffff, "Asahi Kasei AK4542" }, 405 { AC97_CODEC_ID('A', 'K', 'M', 2), 406 0xffffffff, "Asahi Kasei AK4541/AK4543" }, 407 { AC97_CODEC_ID('A', 'K', 'M', 5), 408 0xffffffff, "Asahi Kasei AK4544" }, 409 { AC97_CODEC_ID('A', 'K', 'M', 6), 410 0xffffffff, "Asahi Kasei AK4544A" }, 411 { AC97_CODEC_ID('A', 'K', 'M', 7), 412 0xffffffff, "Asahi Kasei AK4545" }, 413 { AC97_CODEC_ID('A', 'K', 'M', 0), 414 AC97_VENDOR_ID_MASK, "Asahi Kasei unknown" }, 415 416 /* 417 * Realtek & Avance Logic 418 * http://www.realtek.com.tw/downloads/downloads1-3.aspx?lineid=5&famid=All&series=All&Spec=True 419 * 420 * ALC650 and ALC658 support VRA, but it supports only 8000, 11025, 421 * 12000, 16000, 22050, 24000, 32000, 44100, and 48000 Hz. 422 */ 423 { AC97_CODEC_ID('A', 'L', 'C', 0x00), 424 0xfffffff0, "Realtek RL5306" }, 425 { AC97_CODEC_ID('A', 'L', 'C', 0x10), 426 0xfffffff0, "Realtek RL5382" }, 427 { AC97_CODEC_ID('A', 'L', 'C', 0x20), 428 0xfffffff0, "Realtek RL5383/RL5522/ALC100" }, 429 { AC97_CODEC_ID('A', 'L', 'G', 0x10), 430 0xffffffff, "Avance Logic ALC200/ALC201" }, 431 { AC97_CODEC_ID('A', 'L', 'G', 0x20), 432 0xfffffff0, "Avance Logic ALC650", ac97_alc650_init }, 433 { AC97_CODEC_ID('A', 'L', 'G', 0x30), 434 0xffffffff, "Avance Logic ALC101" }, 435 { AC97_CODEC_ID('A', 'L', 'G', 0x40), 436 0xffffffff, "Avance Logic ALC202" }, 437 { AC97_CODEC_ID('A', 'L', 'G', 0x50), 438 0xffffffff, "Avance Logic ALC250" }, 439 { AC97_CODEC_ID('A', 'L', 'G', 0x60), 440 0xfffffff0, "Avance Logic ALC655" }, 441 { AC97_CODEC_ID('A', 'L', 'G', 0x80), 442 0xfffffff0, "Avance Logic ALC658" }, 443 { AC97_CODEC_ID('A', 'L', 'G', 0x90), 444 0xfffffff0, "Avance Logic ALC850" }, 445 { AC97_CODEC_ID('A', 'L', 'C', 0), 446 AC97_VENDOR_ID_MASK, "Realtek unknown" }, 447 { AC97_CODEC_ID('A', 'L', 'G', 0), 448 AC97_VENDOR_ID_MASK, "Avance Logic unknown" }, 449 450 /** 451 * C-Media Electronics Inc. 452 * http://www.cmedia.com.tw/doc/CMI9739%206CH%20Audio%20Codec%20SPEC_Ver12.pdf 453 */ 454 { AC97_CODEC_ID('C', 'M', 'I', 0x61), 455 0xffffffff, "C-Media CMI9739" }, 456 { AC97_CODEC_ID('C', 'M', 'I', 0), 457 AC97_VENDOR_ID_MASK, "C-Media unknown" }, 458 459 /* Cirrus Logic, Crystal series: 460 * 'C' 'R' 'Y' 0x0[0-7] - CS4297 461 * 0x1[0-7] - CS4297A 462 * 0x2[0-7] - CS4298 463 * 0x2[8-f] - CS4294 464 * 0x3[0-7] - CS4299 465 * 0x4[8-f] - CS4201 466 * 0x5[8-f] - CS4205 467 * 0x6[0-7] - CS4291 468 * 0x7[0-7] - CS4202 469 * Datasheets: 470 * http://www.cirrus.com/pubs/cs4297A-5.pdf?DocumentID=593 471 * http://www.cirrus.com/pubs/cs4294.pdf?DocumentID=32 472 * http://www.cirrus.com/pubs/cs4299-5.pdf?DocumentID=594 473 * http://www.cirrus.com/pubs/cs4201-2.pdf?DocumentID=492 474 * http://www.cirrus.com/pubs/cs4205-2.pdf?DocumentID=492 475 * http://www.cirrus.com/pubs/cs4202-1.pdf?DocumentID=852 476 */ 477 { AC97_CODEC_ID('C', 'R', 'Y', 0x00), 478 0xfffffff8, "Crystal CS4297", }, 479 { AC97_CODEC_ID('C', 'R', 'Y', 0x10), 480 0xfffffff8, "Crystal CS4297A", }, 481 { AC97_CODEC_ID('C', 'R', 'Y', 0x20), 482 0xfffffff8, "Crystal CS4298", }, 483 { AC97_CODEC_ID('C', 'R', 'Y', 0x28), 484 0xfffffff8, "Crystal CS4294", }, 485 { AC97_CODEC_ID('C', 'R', 'Y', 0x30), 486 0xfffffff8, "Crystal CS4299", }, 487 { AC97_CODEC_ID('C', 'R', 'Y', 0x48), 488 0xfffffff8, "Crystal CS4201", }, 489 { AC97_CODEC_ID('C', 'R', 'Y', 0x58), 490 0xfffffff8, "Crystal CS4205", }, 491 { AC97_CODEC_ID('C', 'R', 'Y', 0x60), 492 0xfffffff8, "Crystal CS4291", }, 493 { AC97_CODEC_ID('C', 'R', 'Y', 0x70), 494 0xfffffff8, "Crystal CS4202", }, 495 { AC97_CODEC_ID('C', 'R', 'Y', 0), 496 AC97_VENDOR_ID_MASK, "Cirrus Logic unknown", }, 497 498 { 0x45838308, 0xffffffff, "ESS Technology ES1921", }, 499 { 0x45838300, AC97_VENDOR_ID_MASK, "ESS Technology unknown", }, 500 501 { AC97_CODEC_ID('H', 'R', 'S', 0), 502 0xffffffff, "Intersil HMP9701", }, 503 { AC97_CODEC_ID('H', 'R', 'S', 0), 504 AC97_VENDOR_ID_MASK, "Intersil unknown", }, 505 506 /* 507 * IC Ensemble (VIA) 508 * http://www.viatech.com/en/datasheet/DS1616.pdf 509 */ 510 { AC97_CODEC_ID('I', 'C', 'E', 0x01), 511 0xffffffff, "ICEnsemble ICE1230/VT1611", }, 512 { AC97_CODEC_ID('I', 'C', 'E', 0x11), 513 0xffffffff, "ICEnsemble ICE1232/VT1611A", }, 514 { AC97_CODEC_ID('I', 'C', 'E', 0x14), 515 0xffffffff, "ICEnsemble ICE1232A", }, 516 { AC97_CODEC_ID('I', 'C', 'E', 0x51), 517 0xffffffff, "VIA Technologies VT1616", ac97_vt1616_init }, 518 { AC97_CODEC_ID('I', 'C', 'E', 0x52), 519 0xffffffff, "VIA Technologies VT1616i", ac97_vt1616_init }, 520 { AC97_CODEC_ID('I', 'C', 'E', 0), 521 AC97_VENDOR_ID_MASK, "ICEnsemble/VIA unknown", }, 522 523 { AC97_CODEC_ID('N', 'S', 'C', 0), 524 0xffffffff, "National Semiconductor LM454[03568]", }, 525 { AC97_CODEC_ID('N', 'S', 'C', 49), 526 0xffffffff, "National Semiconductor LM4549", }, 527 { AC97_CODEC_ID('N', 'S', 'C', 0), 528 AC97_VENDOR_ID_MASK, "National Semiconductor unknown", }, 529 530 { AC97_CODEC_ID('P', 'S', 'C', 4), 531 0xffffffff, "Philips Semiconductor UCB1400", }, 532 { AC97_CODEC_ID('P', 'S', 'C', 0), 533 AC97_VENDOR_ID_MASK, "Philips Semiconductor unknown", }, 534 535 { AC97_CODEC_ID('S', 'I', 'L', 34), 536 0xffffffff, "Silicon Laboratory Si3036", }, 537 { AC97_CODEC_ID('S', 'I', 'L', 35), 538 0xffffffff, "Silicon Laboratory Si3038", }, 539 { AC97_CODEC_ID('S', 'I', 'L', 0), 540 AC97_VENDOR_ID_MASK, "Silicon Laboratory unknown", }, 541 542 { AC97_CODEC_ID('T', 'R', 'A', 2), 543 0xffffffff, "TriTech TR28022", }, 544 { AC97_CODEC_ID('T', 'R', 'A', 3), 545 0xffffffff, "TriTech TR28023", }, 546 { AC97_CODEC_ID('T', 'R', 'A', 6), 547 0xffffffff, "TriTech TR28026", }, 548 { AC97_CODEC_ID('T', 'R', 'A', 8), 549 0xffffffff, "TriTech TR28028", }, 550 { AC97_CODEC_ID('T', 'R', 'A', 35), 551 0xffffffff, "TriTech TR28602", }, 552 { AC97_CODEC_ID('T', 'R', 'A', 0), 553 AC97_VENDOR_ID_MASK, "TriTech unknown", }, 554 555 { AC97_CODEC_ID('T', 'X', 'N', 0x20), 556 0xffffffff, "Texas Instruments TLC320AD9xC", }, 557 { AC97_CODEC_ID('T', 'X', 'N', 0), 558 AC97_VENDOR_ID_MASK, "Texas Instruments unknown", }, 559 560 /* 561 * VIA 562 * http://www.viatech.com/en/multimedia/audio.jsp 563 */ 564 { AC97_CODEC_ID('V', 'I', 'A', 0x61), 565 0xffffffff, "VIA Technologies VT1612A", }, 566 { AC97_CODEC_ID('V', 'I', 'A', 0), 567 AC97_VENDOR_ID_MASK, "VIA Technologies unknown", }, 568 569 { AC97_CODEC_ID('W', 'E', 'C', 1), 570 0xffffffff, "Winbond W83971D", }, 571 { AC97_CODEC_ID('W', 'E', 'C', 0), 572 AC97_VENDOR_ID_MASK, "Winbond unknown", }, 573 574 /* 575 * http://www.wolfsonmicro.com/product_list.asp?cid=64 576 * http://www.wolfsonmicro.com/download.asp/did.56/WM9701A.pdf - 00 577 * http://www.wolfsonmicro.com/download.asp/did.57/WM9703.pdf - 03 578 * http://www.wolfsonmicro.com/download.asp/did.58/WM9704M.pdf - 04 579 * http://www.wolfsonmicro.com/download.asp/did.59/WM9704Q.pdf - 04 580 * http://www.wolfsonmicro.com/download.asp/did.184/WM9705_Rev34.pdf - 05 581 * http://www.wolfsonmicro.com/download.asp/did.60/WM9707.pdf - 03 582 * http://www.wolfsonmicro.com/download.asp/did.136/WM9708.pdf - 03 583 * http://www.wolfsonmicro.com/download.asp/did.243/WM9710.pdf - 05 584 */ 585 { AC97_CODEC_ID('W', 'M', 'L', 0), 586 0xffffffff, "Wolfson WM9701A", }, 587 { AC97_CODEC_ID('W', 'M', 'L', 3), 588 0xffffffff, "Wolfson WM9703/WM9707/WM9708", }, 589 { AC97_CODEC_ID('W', 'M', 'L', 4), 590 0xffffffff, "Wolfson WM9704", }, 591 { AC97_CODEC_ID('W', 'M', 'L', 5), 592 0xffffffff, "Wolfson WM9705/WM9710", }, 593 { AC97_CODEC_ID('W', 'M', 'L', 0), 594 AC97_VENDOR_ID_MASK, "Wolfson unknown", }, 595 596 /* 597 * http://www.yamaha.co.jp/english/product/lsi/us/products/pcaudio.html 598 * Datasheets: 599 * http://www.yamaha.co.jp/english/product/lsi/us/products/pdf/4MF743A20.pdf 600 * http://www.yamaha.co.jp/english/product/lsi/us/products/pdf/4MF753A20.pdf 601 */ 602 { AC97_CODEC_ID('Y', 'M', 'H', 0), 603 0xffffffff, "Yamaha YMF743-S", }, 604 { AC97_CODEC_ID('Y', 'M', 'H', 3), 605 0xffffffff, "Yamaha YMF753-S", }, 606 { AC97_CODEC_ID('Y', 'M', 'H', 0), 607 AC97_VENDOR_ID_MASK, "Yamaha unknown", }, 608 609 /* 610 * http://www.sigmatel.com/products/technical_docs.htm 611 * and 612 * http://www.sigmatel.com/documents/c-major-brochure-9-0.pdf 613 */ 614 { 0x83847600, 0xffffffff, "SigmaTel STAC9700", }, 615 { 0x83847604, 0xffffffff, "SigmaTel STAC9701/3/4/5", }, 616 { 0x83847605, 0xffffffff, "SigmaTel STAC9704", }, 617 { 0x83847608, 0xffffffff, "SigmaTel STAC9708", }, 618 { 0x83847609, 0xffffffff, "SigmaTel STAC9721/23", }, 619 { 0x83847644, 0xffffffff, "SigmaTel STAC9744/45", }, 620 { 0x83847650, 0xffffffff, "SigmaTel STAC9750/51", }, 621 { 0x83847656, 0xffffffff, "SigmaTel STAC9756/57", }, 622 { 0x83847658, 0xffffffff, "SigmaTel STAC9758/59", }, 623 { 0x83847666, 0xffffffff, "SigmaTel STAC9766/67", }, 624 { 0x83847684, 0xffffffff, "SigmaTel STAC9783/84", }, 625 { 0x83847600, AC97_VENDOR_ID_MASK, "SigmaTel unknown", }, 626 627 { 0, 628 0, NULL, } 629 }; 630 631 static const char * const ac97enhancement[] = { 632 "no 3D stereo", 633 "Analog Devices Phat Stereo", 634 "Creative", 635 "National Semi 3D", 636 "Yamaha Ymersion", 637 "BBE 3D", 638 "Crystal Semi 3D", 639 "Qsound QXpander", 640 "Spatializer 3D", 641 "SRS 3D", 642 "Platform Tech 3D", 643 "AKM 3D", 644 "Aureal", 645 "AZTECH 3D", 646 "Binaura 3D", 647 "ESS Technology", 648 "Harman International VMAx", 649 "Nvidea 3D", 650 "Philips Incredible Sound", 651 "Texas Instruments' 3D", 652 "VLSI Technology 3D", 653 "TriTech 3D", 654 "Realtek 3D", 655 "Samsung 3D", 656 "Wolfson Microelectronics 3D", 657 "Delta Integration 3D", 658 "SigmaTel 3D", 659 "KS Waves 3D", 660 "Rockwell 3D", 661 "Unknown 3D", 662 "Unknown 3D", 663 "Unknown 3D", 664 }; 665 666 static const char * const ac97feature[] = { 667 "dedicated mic channel", 668 "reserved", 669 "tone", 670 "simulated stereo", 671 "headphone", 672 "bass boost", 673 "18 bit DAC", 674 "20 bit DAC", 675 "18 bit ADC", 676 "20 bit ADC" 677 }; 678 679 680 /* #define AC97_DEBUG 10 */ 681 /* #define AC97_IO_DEBUG */ 682 683 #ifdef AUDIO_DEBUG 684 #define DPRINTF(x) if (ac97debug) printf x 685 #define DPRINTFN(n,x) if (ac97debug>(n)) printf x 686 #ifdef AC97_DEBUG 687 int ac97debug = AC97_DEBUG; 688 #else 689 int ac97debug = 0; 690 #endif 691 #else 692 #define DPRINTF(x) 693 #define DPRINTFN(n,x) 694 #endif 695 696 #ifdef AC97_IO_DEBUG 697 static const char *ac97_register_names[0x80 / 2] = { 698 "RESET", "MASTER_VOLUME", "HEADPHONE_VOLUME", "MASTER_VOLUME_MONO", 699 "MASTER_TONE", "PCBEEP_VOLUME", "PHONE_VOLUME", "MIC_VOLUME", 700 "LINEIN_VOLUME", "CD_VOLUME", "VIDEO_VOLUME", "AUX_VOLUME", 701 "PCMOUT_VOLUME", "RECORD_SELECT", "RECORD_GATIN", "RECORD_GAIN_MIC", 702 "GP", "3D_CONTROL", "AUDIO_INT", "POWER", 703 "EXT_AUDIO_ID", "EXT_AUDIO_CTRL", "PCM_FRONT_DAC_RATE", "PCM_SURR_DAC_RATE", 704 "PCM_LFE_DAC_RATE", "PCM_LR_ADC_RATE", "PCM_MIC_ADC_RATE", "CENTER_LFE_MASTER", 705 "SURR_MASTER", "SPDIF_CTRL", "EXT_MODEM_ID", "EXT_MODEM_CTRL", 706 "LINE1_RATE", "LINE2_RATE", "HANDSET_RATE", "LINE1_LEVEL", 707 "LINE2_LEVEL", "HANDSET_LEVEL", "GPIO_PIN_CONFIG", "GPIO_PIN_POLARITY", 708 "GPIO_PIN_STICKY", "GPIO_PIN_WAKEUP", "GPIO_PIN_STATUS", "MISC_MODEM_CTRL", 709 "0x58", "VENDOR-5A", "VENDOR-5C", "VENDOR-5E", 710 "0x60", "0x62", "0x64", "0x66", 711 "0x68", "0x6a", "0x6c", "0x6e", 712 "VENDOR-70", "VENDOR-72", "VENDOR-74", "VENDOR-76", 713 "VENDOR-78", "VENDOR-7A", "VENDOR_ID1", "VENDOR_ID2" 714 }; 715 #endif 716 717 static void 718 ac97_read(struct ac97_softc *as, u_int8_t reg, u_int16_t *val) 719 { 720 if (as->host_flags & AC97_HOST_DONT_READ && 721 (reg != AC97_REG_VENDOR_ID1 && reg != AC97_REG_VENDOR_ID2 && 722 reg != AC97_REG_RESET)) { 723 *val = as->shadow_reg[reg >> 1]; 724 return; 725 } 726 727 if (as->host_if->read(as->host_if->arg, reg, val)) { 728 *val = as->shadow_reg[reg >> 1]; 729 } 730 } 731 732 static int 733 ac97_write(struct ac97_softc *as, u_int8_t reg, u_int16_t val) 734 { 735 #ifndef AC97_IO_DEBUG 736 as->shadow_reg[reg >> 1] = val; 737 return as->host_if->write(as->host_if->arg, reg, val); 738 #else 739 int ret; 740 uint16_t actual; 741 742 as->shadow_reg[reg >> 1] = val; 743 ret = as->host_if->write(as->host_if->arg, reg, val); 744 as->host_if->read(as->host_if->arg, reg, &actual); 745 if (val != actual && reg < 0x80) { 746 printf("ac97_write: reg=%s, written=0x%04x, read=0x%04x\n", 747 ac97_register_names[reg / 2], val, actual); 748 } 749 return ret; 750 #endif 751 } 752 753 static void 754 ac97_setup_defaults(struct ac97_softc *as) 755 { 756 int idx; 757 const struct ac97_source_info *si; 758 759 memset(as->shadow_reg, 0, sizeof(as->shadow_reg)); 760 761 for (idx = 0; idx < SOURCE_INFO_SIZE; idx++) { 762 si = &source_info[idx]; 763 ac97_write(as, si->reg, si->default_value); 764 } 765 } 766 767 static void 768 ac97_restore_shadow(struct ac97_codec_if *self) 769 { 770 struct ac97_softc *as; 771 const struct ac97_source_info *si; 772 int idx; 773 uint16_t val; 774 775 as = (struct ac97_softc *) self; 776 777 /* make sure chip is fully operational */ 778 #define AC97_POWER_ALL (AC97_POWER_REF | AC97_POWER_ANL | AC97_POWER_DAC \ 779 | AC97_POWER_ADC) 780 for (idx = 50000; idx >= 0; idx--) { 781 ac97_read(as, AC97_REG_POWER, &val); 782 if ((val & AC97_POWER_ALL) == AC97_POWER_ALL) 783 break; 784 DELAY(10); 785 } 786 #undef AC97_POWER_ALL 787 788 /* 789 * actually try changing a value! 790 * The default value of AC97_REG_MASTER_VOLUME is 0x8000. 791 */ 792 for (idx = 50000; idx >= 0; idx--) { 793 ac97_write(as, AC97_REG_MASTER_VOLUME, 0x1010); 794 ac97_read(as, AC97_REG_MASTER_VOLUME, &val); 795 if (val == 0x1010) 796 break; 797 DELAY(10); 798 } 799 800 for (idx = 0; idx < SOURCE_INFO_SIZE; idx++) { 801 si = &source_info[idx]; 802 /* don't "restore" to the reset reg! */ 803 if (si->reg != AC97_REG_RESET) 804 ac97_write(as, si->reg, as->shadow_reg[si->reg >> 1]); 805 } 806 807 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA 808 | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM 809 | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC 810 | AC97_EXT_AUDIO_LDAC)) { 811 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, 812 as->shadow_reg[AC97_REG_EXT_AUDIO_CTRL >> 1]); 813 } 814 } 815 816 static int 817 ac97_str_equal(const char *a, const char *b) 818 { 819 return (a == b) || (a && b && (!strcmp(a, b))); 820 } 821 822 static int 823 ac97_check_capability(struct ac97_softc *as, int check) 824 { 825 switch (check) { 826 case CHECK_NONE: 827 return 1; 828 case CHECK_SURROUND: 829 return as->ext_id & AC97_EXT_AUDIO_SDAC; 830 case CHECK_CENTER: 831 return as->ext_id & AC97_EXT_AUDIO_CDAC; 832 case CHECK_LFE: 833 return as->ext_id & AC97_EXT_AUDIO_LDAC; 834 case CHECK_HEADPHONES: 835 return as->caps & AC97_CAPS_HEADPHONES; 836 case CHECK_TONE: 837 return as->caps & AC97_CAPS_TONECTRL; 838 case CHECK_MIC: 839 return as->caps & AC97_CAPS_MICIN; 840 case CHECK_LOUDNESS: 841 return as->caps & AC97_CAPS_LOUDNESS; 842 case CHECK_3D: 843 return AC97_CAPS_ENHANCEMENT(as->caps) != 0; 844 default: 845 printf("%s: internal error: feature=%d\n", __func__, check); 846 return 0; 847 } 848 } 849 850 static void 851 ac97_setup_source_info(struct ac97_softc *as) 852 { 853 int idx, ouridx; 854 struct ac97_source_info *si, *si2; 855 856 for (idx = 0, ouridx = 0; idx < SOURCE_INFO_SIZE; idx++) { 857 si = &as->source_info[ouridx]; 858 859 if (!ac97_check_capability(as, source_info[idx].req_feature)) 860 continue; 861 862 memcpy(si, &source_info[idx], sizeof(*si)); 863 864 switch (si->type) { 865 case AUDIO_MIXER_CLASS: 866 si->mixer_class = ouridx; 867 ouridx++; 868 break; 869 case AUDIO_MIXER_VALUE: 870 /* Todo - Test to see if it works */ 871 ouridx++; 872 873 /* Add an entry for mute, if necessary */ 874 if (si->mute) { 875 si = &as->source_info[ouridx]; 876 memcpy(si, &source_info[idx], sizeof(*si)); 877 si->qualifier = AudioNmute; 878 si->type = AUDIO_MIXER_ENUM; 879 si->info = &ac97_on_off; 880 si->info_size = sizeof(ac97_on_off); 881 si->bits = 1; 882 si->ofs = 15; 883 si->mute = 0; 884 si->polarity = 0; 885 ouridx++; 886 } 887 break; 888 case AUDIO_MIXER_ENUM: 889 /* Todo - Test to see if it works */ 890 ouridx++; 891 break; 892 default: 893 aprint_error ("ac97: shouldn't get here\n"); 894 break; 895 } 896 } 897 898 as->num_source_info = ouridx; 899 900 for (idx = 0; idx < as->num_source_info; idx++) { 901 int idx2, previdx; 902 903 si = &as->source_info[idx]; 904 905 /* Find mixer class */ 906 for (idx2 = 0; idx2 < as->num_source_info; idx2++) { 907 si2 = &as->source_info[idx2]; 908 909 if (si2->type == AUDIO_MIXER_CLASS && 910 ac97_str_equal(si->class, 911 si2->class)) { 912 si->mixer_class = idx2; 913 } 914 } 915 916 917 /* Setup prev and next pointers */ 918 if (si->prev != 0) 919 continue; 920 921 if (si->qualifier) 922 continue; 923 924 si->prev = AUDIO_MIXER_LAST; 925 previdx = idx; 926 927 for (idx2 = 0; idx2 < as->num_source_info; idx2++) { 928 if (idx2 == idx) 929 continue; 930 931 si2 = &as->source_info[idx2]; 932 933 if (!si2->prev && 934 ac97_str_equal(si->class, si2->class) && 935 ac97_str_equal(si->device, si2->device)) { 936 as->source_info[previdx].next = idx2; 937 as->source_info[idx2].prev = previdx; 938 939 previdx = idx2; 940 } 941 } 942 943 as->source_info[previdx].next = AUDIO_MIXER_LAST; 944 } 945 } 946 947 int 948 ac97_attach(struct ac97_host_if *host_if) 949 { 950 struct ac97_softc *as; 951 struct device *sc_dev; 952 int error, i, j; 953 uint32_t id; 954 uint16_t id1, id2; 955 uint16_t extstat, rate; 956 uint16_t val; 957 mixer_ctrl_t ctl; 958 void (*initfunc)(struct ac97_softc *); 959 #define FLAGBUFLEN 140 960 char flagbuf[FLAGBUFLEN]; 961 962 sc_dev = (struct device *)host_if->arg; 963 initfunc = NULL; 964 as = malloc(sizeof(struct ac97_softc), M_DEVBUF, M_WAITOK|M_ZERO); 965 966 if (as == NULL) 967 return ENOMEM; 968 969 as->codec_if.vtbl = &ac97civ; 970 as->host_if = host_if; 971 972 if ((error = host_if->attach(host_if->arg, &as->codec_if))) { 973 free(as, M_DEVBUF); 974 return error; 975 } 976 977 if ((error = host_if->reset(host_if->arg))) { 978 free(as, M_DEVBUF); 979 return error; 980 } 981 982 host_if->write(host_if->arg, AC97_REG_RESET, 0); 983 host_if->write(host_if->arg, AC97_REG_POWER, 0); 984 985 if (host_if->flags) 986 as->host_flags = host_if->flags(host_if->arg); 987 988 #define AC97_POWER_ALL (AC97_POWER_REF | AC97_POWER_ANL | AC97_POWER_DAC \ 989 | AC97_POWER_ADC) 990 for (i = 500000; i >= 0; i--) { 991 ac97_read(as, AC97_REG_POWER, &val); 992 if ((val & AC97_POWER_ALL) == AC97_POWER_ALL) 993 break; 994 DELAY(1); 995 } 996 #undef AC97_POWER_ALL 997 998 ac97_setup_defaults(as); 999 ac97_read(as, AC97_REG_RESET, &as->caps); 1000 ac97_read(as, AC97_REG_VENDOR_ID1, &id1); 1001 ac97_read(as, AC97_REG_VENDOR_ID2, &id2); 1002 1003 id = (id1 << 16) | id2; 1004 1005 aprint_normal("%s: ac97: ", sc_dev->dv_xname); 1006 1007 for (i = 0; ; i++) { 1008 if (ac97codecid[i].id == 0) { 1009 char pnp[4]; 1010 1011 AC97_GET_CODEC_ID(id, pnp); 1012 #define ISASCII(c) ((c) >= ' ' && (c) < 0x7f) 1013 if (ISASCII(pnp[0]) && ISASCII(pnp[1]) && 1014 ISASCII(pnp[2])) 1015 aprint_normal("%c%c%c%d", 1016 pnp[0], pnp[1], pnp[2], pnp[3]); 1017 else 1018 aprint_normal("unknown (0x%08x)", id); 1019 break; 1020 } 1021 if (ac97codecid[i].id == (id & ac97codecid[i].mask)) { 1022 aprint_normal("%s", ac97codecid[i].name); 1023 if (ac97codecid[i].mask == AC97_VENDOR_ID_MASK) { 1024 aprint_normal(" (0x%08x)", id); 1025 } 1026 initfunc = ac97codecid[i].init; 1027 break; 1028 } 1029 } 1030 aprint_normal(" codec; "); 1031 for (i = j = 0; i < 10; i++) { 1032 if (as->caps & (1 << i)) { 1033 aprint_normal("%s%s", j ? ", " : "", ac97feature[i]); 1034 j++; 1035 } 1036 } 1037 aprint_normal("%s%s\n", j ? ", " : "", 1038 ac97enhancement[AC97_CAPS_ENHANCEMENT(as->caps)]); 1039 1040 as->ac97_clock = AC97_STANDARD_CLOCK; 1041 ac97_read(as, AC97_REG_EXT_AUDIO_ID, &as->ext_id); 1042 if (as->ext_id != 0) { 1043 /* Print capabilities */ 1044 bitmask_snprintf(as->ext_id, "\20\20SECONDARY10\17SECONDARY01" 1045 "\14AC97_23\13AC97_22\12AMAP\11LDAC\10SDAC" 1046 "\7CDAC\4VRM\3SPDIF\2DRA\1VRA", 1047 flagbuf, FLAGBUFLEN); 1048 aprint_normal("%s: ac97: ext id %s\n", sc_dev->dv_xname, flagbuf); 1049 1050 /* Print unusual settings */ 1051 if (as->ext_id & AC97_EXT_AUDIO_DSA_MASK) { 1052 aprint_normal("%s: ac97: Slot assignment: ", 1053 sc_dev->dv_xname); 1054 switch (as->ext_id & AC97_EXT_AUDIO_DSA_MASK) { 1055 case AC97_EXT_AUDIO_DSA01: 1056 aprint_normal("7&8, 6&9, 10&11.\n"); 1057 break; 1058 case AC97_EXT_AUDIO_DSA10: 1059 aprint_normal("6&9, 10&11, 3&4.\n"); 1060 break; 1061 case AC97_EXT_AUDIO_DSA11: 1062 aprint_normal("10&11, 3&4, 7&8.\n"); 1063 break; 1064 } 1065 } 1066 1067 /* Enable and disable features */ 1068 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat); 1069 extstat &= ~AC97_EXT_AUDIO_DRA; 1070 if (as->ext_id & AC97_EXT_AUDIO_LDAC) 1071 extstat |= AC97_EXT_AUDIO_LDAC; 1072 if (as->ext_id & AC97_EXT_AUDIO_SDAC) 1073 extstat |= AC97_EXT_AUDIO_SDAC; 1074 if (as->ext_id & AC97_EXT_AUDIO_CDAC) 1075 extstat |= AC97_EXT_AUDIO_CDAC; 1076 if (as->ext_id & AC97_EXT_AUDIO_VRM) 1077 extstat |= AC97_EXT_AUDIO_VRM; 1078 if (as->ext_id & AC97_EXT_AUDIO_SPDIF) { 1079 /* Output the same data as DAC to SPDIF output */ 1080 extstat &= ~AC97_EXT_AUDIO_SPSA_MASK; 1081 extstat |= AC97_EXT_AUDIO_SPSA34; 1082 } 1083 if (as->ext_id & AC97_EXT_AUDIO_VRA) 1084 extstat |= AC97_EXT_AUDIO_VRA; 1085 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat); 1086 if (as->ext_id & AC97_EXT_AUDIO_VRA) { 1087 /* VRA should be enabled. */ 1088 /* so it claims to do variable rate, let's make sure */ 1089 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE, 44100); 1090 ac97_read(as, AC97_REG_PCM_FRONT_DAC_RATE, &rate); 1091 if (rate != 44100) { 1092 /* We can't believe ext_id */ 1093 as->ext_id = 0; 1094 aprint_normal( 1095 "%s: Ignore these capabilities.\n", 1096 sc_dev->dv_xname); 1097 } 1098 /* restore the default value */ 1099 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE, 1100 AC97_SINGLE_RATE); 1101 } 1102 } 1103 1104 ac97_setup_source_info(as); 1105 1106 memset(&ctl, 0, sizeof(ctl)); 1107 /* disable mutes */ 1108 for (i = 0; i < 11; i++) { 1109 static struct { 1110 char *class, *device; 1111 } d[11] = { 1112 { AudioCoutputs, AudioNmaster}, 1113 { AudioCoutputs, AudioNheadphone}, 1114 { AudioCoutputs, AudioNsurround}, 1115 { AudioCoutputs, AudioNcenter}, 1116 { AudioCoutputs, AudioNlfe}, 1117 { AudioCinputs, AudioNdac}, 1118 { AudioCinputs, AudioNcd}, 1119 { AudioCinputs, AudioNline}, 1120 { AudioCinputs, AudioNaux}, 1121 { AudioCinputs, AudioNvideo}, 1122 { AudioCrecord, AudioNvolume}, 1123 }; 1124 1125 ctl.type = AUDIO_MIXER_ENUM; 1126 ctl.un.ord = 0; 1127 1128 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, 1129 d[i].class, d[i].device, AudioNmute); 1130 ac97_mixer_set_port(&as->codec_if, &ctl); 1131 } 1132 ctl.type = AUDIO_MIXER_ENUM; 1133 ctl.un.ord = 0; 1134 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord, 1135 AudioNsource, NULL); 1136 ac97_mixer_set_port(&as->codec_if, &ctl); 1137 1138 /* set a reasonable default volume */ 1139 ctl.type = AUDIO_MIXER_VALUE; 1140 ctl.un.value.num_channels = 2; 1141 ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = \ 1142 ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127; 1143 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs, 1144 AudioNmaster, NULL); 1145 ac97_mixer_set_port(&as->codec_if, &ctl); 1146 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs, 1147 AudioNsurround, NULL); 1148 ac97_mixer_set_port(&as->codec_if, &ctl); 1149 ctl.un.value.num_channels = 1; 1150 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs, 1151 AudioNcenter, NULL); 1152 ac97_mixer_set_port(&as->codec_if, &ctl); 1153 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs, 1154 AudioNlfe, NULL); 1155 ac97_mixer_set_port(&as->codec_if, &ctl); 1156 1157 if (initfunc != NULL) 1158 initfunc(as); 1159 return 0; 1160 } 1161 1162 static void 1163 ac97_detach(struct ac97_codec_if *codec_if) 1164 { 1165 struct ac97_softc *as; 1166 1167 as = (struct ac97_softc *)codec_if; 1168 ac97_write(as, AC97_REG_POWER, AC97_POWER_IN | AC97_POWER_OUT 1169 | AC97_POWER_MIXER | AC97_POWER_MIXER_VREF 1170 | AC97_POWER_ACLINK | AC97_POWER_CLK | AC97_POWER_AUX 1171 | AC97_POWER_EAMP); 1172 free(as, M_DEVBUF); 1173 } 1174 1175 static int 1176 ac97_query_devinfo(struct ac97_codec_if *codec_if, mixer_devinfo_t *dip) 1177 { 1178 struct ac97_softc *as; 1179 struct ac97_source_info *si; 1180 const char *name; 1181 1182 as = (struct ac97_softc *)codec_if; 1183 if (dip->index < as->num_source_info) { 1184 si = &as->source_info[dip->index]; 1185 dip->type = si->type; 1186 dip->mixer_class = si->mixer_class; 1187 dip->prev = si->prev; 1188 dip->next = si->next; 1189 1190 if (si->qualifier) 1191 name = si->qualifier; 1192 else if (si->device) 1193 name = si->device; 1194 else if (si->class) 1195 name = si->class; 1196 else 1197 name = 0; 1198 1199 if (name) 1200 strcpy(dip->label.name, name); 1201 1202 memcpy(&dip->un, si->info, si->info_size); 1203 1204 /* Set the delta for volume sources */ 1205 if (dip->type == AUDIO_MIXER_VALUE) 1206 dip->un.v.delta = 1 << (8 - si->bits); 1207 1208 return 0; 1209 } 1210 1211 return ENXIO; 1212 } 1213 1214 1215 1216 static int 1217 ac97_mixer_set_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp) 1218 { 1219 struct ac97_softc *as; 1220 struct ac97_source_info *si; 1221 u_int16_t mask; 1222 u_int16_t val, newval; 1223 int error; 1224 1225 as = (struct ac97_softc *)codec_if; 1226 si = &as->source_info[cp->dev]; 1227 if (cp->dev < 0 || cp->dev >= as->num_source_info) 1228 return EINVAL; 1229 1230 if (cp->type != si->type) 1231 return EINVAL; 1232 1233 ac97_read(as, si->reg, &val); 1234 1235 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val)); 1236 1237 mask = (1 << si->bits) - 1; 1238 1239 switch (cp->type) { 1240 case AUDIO_MIXER_ENUM: 1241 if (cp->un.ord > mask || cp->un.ord < 0) 1242 return EINVAL; 1243 1244 newval = (cp->un.ord << si->ofs); 1245 if (si->reg == AC97_REG_RECORD_SELECT) { 1246 newval |= (newval << (8 + si->ofs)); 1247 mask |= (mask << 8); 1248 mask = mask << si->ofs; 1249 } else if (si->reg == AC97_REG_SURR_MASTER) { 1250 newval = cp->un.ord ? 0x8080 : 0x0000; 1251 mask = 0x8080; 1252 } else 1253 mask = mask << si->ofs; 1254 break; 1255 case AUDIO_MIXER_VALUE: 1256 { 1257 const struct audio_mixer_value *value = si->info; 1258 u_int16_t l, r, ol, or; 1259 int deltal, deltar; 1260 1261 if ((cp->un.value.num_channels <= 0) || 1262 (cp->un.value.num_channels > value->num_channels)) 1263 return EINVAL; 1264 1265 if (cp->un.value.num_channels == 1) { 1266 l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 1267 } else { 1268 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) { 1269 l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1270 r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1271 } else { /* left/right is reversed here */ 1272 r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1273 l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1274 } 1275 1276 } 1277 1278 if (!si->polarity) { 1279 l = 255 - l; 1280 r = 255 - r; 1281 } 1282 1283 ol = (val >> (8+si->ofs)) & mask; 1284 or = (val >> si->ofs) & mask; 1285 1286 deltal = (ol << (8 - si->bits)) - l; 1287 deltar = (or << (8 - si->bits)) - r; 1288 1289 l = l >> (8 - si->bits); 1290 r = r >> (8 - si->bits); 1291 1292 if (deltal && ol == l) 1293 l += (deltal > 0) ? (l ? -1 : 0) : (l < mask ? 1 : 0); 1294 if (deltar && or == r) 1295 r += (deltar > 0) ? (r ? -1 : 0) : (r < mask ? 1 : 0); 1296 1297 newval = ((r & mask) << si->ofs); 1298 if (value->num_channels == 2) { 1299 newval = newval | ((l & mask) << (si->ofs+8)); 1300 mask |= (mask << 8); 1301 } 1302 mask = mask << si->ofs; 1303 break; 1304 } 1305 default: 1306 return EINVAL; 1307 } 1308 1309 error = ac97_write(as, si->reg, (val & ~mask) | newval); 1310 if (error) 1311 return error; 1312 1313 return 0; 1314 } 1315 1316 static int 1317 ac97_get_portnum_by_name(struct ac97_codec_if *codec_if, const char *class, 1318 const char *device, const char *qualifier) 1319 { 1320 struct ac97_softc *as; 1321 int idx; 1322 1323 as = (struct ac97_softc *)codec_if; 1324 for (idx = 0; idx < as->num_source_info; idx++) { 1325 struct ac97_source_info *si = &as->source_info[idx]; 1326 if (ac97_str_equal(class, si->class) && 1327 ac97_str_equal(device, si->device) && 1328 ac97_str_equal(qualifier, si->qualifier)) 1329 return idx; 1330 } 1331 1332 return -1; 1333 } 1334 1335 static int 1336 ac97_mixer_get_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp) 1337 { 1338 struct ac97_softc *as; 1339 struct ac97_source_info *si; 1340 u_int16_t mask; 1341 u_int16_t val; 1342 1343 as = (struct ac97_softc *)codec_if; 1344 si = &as->source_info[cp->dev]; 1345 if (cp->dev < 0 || cp->dev >= as->num_source_info) 1346 return EINVAL; 1347 1348 if (cp->type != si->type) 1349 return EINVAL; 1350 1351 ac97_read(as, si->reg, &val); 1352 1353 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val)); 1354 1355 mask = (1 << si->bits) - 1; 1356 1357 switch (cp->type) { 1358 case AUDIO_MIXER_ENUM: 1359 cp->un.ord = (val >> si->ofs) & mask; 1360 DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n", 1361 val, si->ofs, mask, cp->un.ord)); 1362 break; 1363 case AUDIO_MIXER_VALUE: 1364 { 1365 const struct audio_mixer_value *value = si->info; 1366 u_int16_t l, r; 1367 1368 if ((cp->un.value.num_channels <= 0) || 1369 (cp->un.value.num_channels > value->num_channels)) 1370 return EINVAL; 1371 1372 if (value->num_channels == 1) { 1373 l = r = (val >> si->ofs) & mask; 1374 } else { 1375 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) { 1376 l = (val >> (si->ofs + 8)) & mask; 1377 r = (val >> si->ofs) & mask; 1378 } else { /* host has reversed channels */ 1379 r = (val >> (si->ofs + 8)) & mask; 1380 l = (val >> si->ofs) & mask; 1381 } 1382 } 1383 1384 l = (l << (8 - si->bits)); 1385 r = (r << (8 - si->bits)); 1386 if (!si->polarity) { 1387 l = 255 - l; 1388 r = 255 - r; 1389 } 1390 1391 /* The EAP driver averages l and r for stereo 1392 channels that are requested in MONO mode. Does this 1393 make sense? */ 1394 if (cp->un.value.num_channels == 1) { 1395 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l; 1396 } else if (cp->un.value.num_channels == 2) { 1397 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l; 1398 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r; 1399 } 1400 1401 break; 1402 } 1403 default: 1404 return EINVAL; 1405 } 1406 1407 return 0; 1408 } 1409 1410 1411 static int 1412 ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_long *rate) 1413 { 1414 struct ac97_softc *as; 1415 u_long value; 1416 u_int16_t ext_stat; 1417 u_int16_t actual; 1418 u_int16_t power; 1419 u_int16_t power_bit; 1420 1421 as = (struct ac97_softc *)codec_if; 1422 if (target == AC97_REG_PCM_MIC_ADC_RATE) { 1423 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) { 1424 *rate = AC97_SINGLE_RATE; 1425 return 0; 1426 } 1427 } else { 1428 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) { 1429 *rate = AC97_SINGLE_RATE; 1430 return 0; 1431 } 1432 } 1433 value = *rate * AC97_STANDARD_CLOCK / as->ac97_clock; 1434 ext_stat = 0; 1435 /* 1436 * PCM_FRONT_DAC_RATE/PCM_SURR_DAC_RATE/PCM_LFE_DAC_RATE 1437 * Check VRA, DRA 1438 * PCM_LR_ADC_RATE 1439 * Check VRA 1440 * PCM_MIC_ADC_RATE 1441 * Check VRM 1442 */ 1443 switch (target) { 1444 case AC97_REG_PCM_FRONT_DAC_RATE: 1445 case AC97_REG_PCM_SURR_DAC_RATE: 1446 case AC97_REG_PCM_LFE_DAC_RATE: 1447 power_bit = AC97_POWER_OUT; 1448 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) { 1449 *rate = AC97_SINGLE_RATE; 1450 return 0; 1451 } 1452 if (as->ext_id & AC97_EXT_AUDIO_DRA) { 1453 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &ext_stat); 1454 if (value > 0x1ffff) { 1455 return EINVAL; 1456 } else if (value > 0xffff) { 1457 /* Enable DRA */ 1458 ext_stat |= AC97_EXT_AUDIO_DRA; 1459 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat); 1460 value /= 2; 1461 } else { 1462 /* Disable DRA */ 1463 ext_stat &= ~AC97_EXT_AUDIO_DRA; 1464 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat); 1465 } 1466 } else { 1467 if (value > 0xffff) 1468 return EINVAL; 1469 } 1470 break; 1471 case AC97_REG_PCM_LR_ADC_RATE: 1472 power_bit = AC97_POWER_IN; 1473 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) { 1474 *rate = AC97_SINGLE_RATE; 1475 return 0; 1476 } 1477 if (value > 0xffff) 1478 return EINVAL; 1479 break; 1480 case AC97_REG_PCM_MIC_ADC_RATE: 1481 power_bit = AC97_POWER_IN; 1482 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) { 1483 *rate = AC97_SINGLE_RATE; 1484 return 0; 1485 } 1486 if (value > 0xffff) 1487 return EINVAL; 1488 break; 1489 default: 1490 printf("%s: Unknown register: 0x%x\n", __func__, target); 1491 return EINVAL; 1492 } 1493 1494 ac97_read(as, AC97_REG_POWER, &power); 1495 ac97_write(as, AC97_REG_POWER, power | power_bit); 1496 1497 ac97_write(as, target, (u_int16_t)value); 1498 ac97_read(as, target, &actual); 1499 actual = (u_int32_t)actual * as->ac97_clock / AC97_STANDARD_CLOCK; 1500 1501 ac97_write(as, AC97_REG_POWER, power); 1502 if (ext_stat & AC97_EXT_AUDIO_DRA) { 1503 *rate = actual * 2; 1504 } else { 1505 *rate = actual; 1506 } 1507 return 0; 1508 } 1509 1510 static void 1511 ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock) 1512 { 1513 struct ac97_softc *as; 1514 1515 as = (struct ac97_softc *)codec_if; 1516 as->ac97_clock = clock; 1517 } 1518 1519 static u_int16_t 1520 ac97_get_extcaps(struct ac97_codec_if *codec_if) 1521 { 1522 struct ac97_softc *as; 1523 1524 as = (struct ac97_softc *)codec_if; 1525 return as->ext_id; 1526 } 1527 1528 static int 1529 ac97_add_port(struct ac97_softc *as, const struct ac97_source_info *src) 1530 { 1531 struct ac97_source_info *si; 1532 int ouridx, idx; 1533 1534 if (as->num_source_info >= MAX_SOURCES) { 1535 printf("%s: internal error: increase MAX_SOURCES in %s\n", 1536 __func__, __FILE__); 1537 return -1; 1538 } 1539 if (!ac97_check_capability(as, src->req_feature)) 1540 return -1; 1541 ouridx = as->num_source_info; 1542 si = &as->source_info[ouridx]; 1543 memcpy(si, src, sizeof(*si)); 1544 1545 switch (si->type) { 1546 case AUDIO_MIXER_CLASS: 1547 case AUDIO_MIXER_VALUE: 1548 printf("%s: adding class/value is not supported yet.\n", 1549 __func__); 1550 return -1; 1551 case AUDIO_MIXER_ENUM: 1552 break; 1553 default: 1554 printf("%s: unknown type: %d\n", __func__, si->type); 1555 return -1; 1556 } 1557 as->num_source_info++; 1558 1559 si->mixer_class = ac97_get_portnum_by_name(&as->codec_if, si->class, 1560 NULL, NULL); 1561 /* Find the root of the device */ 1562 idx = ac97_get_portnum_by_name(&as->codec_if, si->class, 1563 si->device, NULL); 1564 /* Find the last item */ 1565 while (as->source_info[idx].next != AUDIO_MIXER_LAST) 1566 idx = as->source_info[idx].next; 1567 /* Append */ 1568 as->source_info[idx].next = ouridx; 1569 si->prev = idx; 1570 si->next = AUDIO_MIXER_LAST; 1571 1572 return 0; 1573 } 1574 1575 /** 1576 * Codec-dependent initialization 1577 */ 1578 1579 #define AD1980_REG_MISC 0x76 1580 #define AD1980_MISC_MBG0 0x0001 /* 0 1888/1980/1981 /1985 */ 1581 #define AD1980_MISC_MBG1 0x0002 /* 1 1888/1980/1981 /1985 */ 1582 #define AD1980_MISC_VREFD 0x0004 /* 2 1888/1980/1981 /1985 */ 1583 #define AD1980_MISC_VREFH 0x0008 /* 3 1888/1980/1981 /1985 */ 1584 #define AD1980_MISC_SRU 0x0010 /* 4 1888/1980 /1985 */ 1585 #define AD1980_MISC_LOSEL 0x0020 /* 5 1888/1980/1981 /1985 */ 1586 #define AD1980_MISC_2CMIC 0x0040 /* 6 1980/1981B/1985 */ 1587 #define AD1980_MISC_SPRD 0x0080 /* 7 1888/1980 /1985 */ 1588 #define AD1980_MISC_DMIX0 0x0100 /* 8 1888/1980 /1985 */ 1589 #define AD1980_MISC_DMIX1 0x0200 /* 9 1888/1980 /1985 */ 1590 #define AD1980_MISC_HPSEL 0x0400 /*10 1888/1980 /1985 */ 1591 #define AD1980_MISC_CLDIS 0x0800 /*11 1888/1980 /1985 */ 1592 #define AD1980_MISC_LODIS 0x1000 /*12 1888/1980/1981 /1985 */ 1593 #define AD1980_MISC_MSPLT 0x2000 /*13 1888/1980/1981 /1985 */ 1594 #define AD1980_MISC_AC97NC 0x4000 /*14 1888/1980 /1985 */ 1595 #define AD1980_MISC_DACZ 0x8000 /*15 1888/1980/1981 /1985 */ 1596 #define AD1981_REG_MISC 0x76 1597 #define AD1981_MISC_MADST 0x0010 /* 4 */ 1598 #define AD1981A_MISC_MADPD 0x0040 /* 6 */ 1599 #define AD1981B_MISC_MADPD 0x0080 /* 7 */ 1600 #define AD1981_MISC_FMXE 0x0200 /* 9 */ 1601 #define AD1981_MISC_DAM 0x0800 /*11 */ 1602 static void 1603 ac97_ad198x_init(struct ac97_softc *as) 1604 { 1605 int i; 1606 uint16_t misc; 1607 1608 ac97_read(as, AD1980_REG_MISC, &misc); 1609 ac97_write(as, AD1980_REG_MISC, 1610 misc | AD1980_MISC_LOSEL | AD1980_MISC_HPSEL); 1611 1612 for (i = 0; i < as->num_source_info; i++) { 1613 if (as->source_info[i].type != AUDIO_MIXER_VALUE) 1614 continue; 1615 1616 if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME) 1617 as->source_info[i].reg = AC97_REG_SURR_MASTER; 1618 else if (as->source_info[i].reg == AC97_REG_SURR_MASTER) 1619 as->source_info[i].reg = AC97_REG_MASTER_VOLUME; 1620 } 1621 } 1622 1623 #define ALC650_REG_MULTI_CHANNEL_CONTROL 0x6a 1624 #define ALC650_MCC_SLOT_MODIFY_MASK 0xc000 1625 #define ALC650_MCC_FRONTDAC_FROM_SPDIFIN 0x2000 /* 13 */ 1626 #define ALC650_MCC_SPDIFOUT_FROM_ADC 0x1000 /* 12 */ 1627 #define ALC650_MCC_PCM_FROM_SPDIFIN 0x0800 /* 11 */ 1628 #define ALC650_MCC_MIC_OR_CENTERLFE 0x0400 /* 10 */ 1629 #define ALC650_MCC_LINEIN_OR_SURROUND 0x0200 /* 9 */ 1630 #define ALC650_MCC_INDEPENDENT_MASTER_L 0x0080 /* 7 */ 1631 #define ALC650_MCC_INDEPENDENT_MASTER_R 0x0040 /* 6 */ 1632 #define ALC650_MCC_ANALOG_TO_CENTERLFE 0x0020 /* 5 */ 1633 #define ALC650_MCC_ANALOG_TO_SURROUND 0x0010 /* 4 */ 1634 #define ALC650_MCC_EXCHANGE_CENTERLFE 0x0008 /* 3 */ 1635 #define ALC650_MCC_CENTERLFE_DOWNMIX 0x0004 /* 2 */ 1636 #define ALC650_MCC_SURROUND_DOWNMIX 0x0002 /* 1 */ 1637 #define ALC650_MCC_LINEOUT_TO_SURROUND 0x0001 /* 0 */ 1638 static void 1639 ac97_alc650_init(struct ac97_softc *as) 1640 { 1641 static const struct ac97_source_info sources[6] = { 1642 { AudioCoutputs, AudioNsurround, "lineinjack", 1643 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1644 ALC650_REG_MULTI_CHANNEL_CONTROL, 1645 0x0000, 1, 9, 0, 0, CHECK_SURROUND }, 1646 { AudioCoutputs, AudioNsurround, "mixtofront", 1647 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1648 ALC650_REG_MULTI_CHANNEL_CONTROL, 1649 0x0000, 1, 1, 0, 0, CHECK_SURROUND }, 1650 { AudioCoutputs, AudioNcenter, "micjack", 1651 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1652 ALC650_REG_MULTI_CHANNEL_CONTROL, 1653 0x0000, 1, 10, 0, 0, CHECK_CENTER }, 1654 { AudioCoutputs, AudioNlfe, "micjack", 1655 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1656 ALC650_REG_MULTI_CHANNEL_CONTROL, 1657 0x0000, 1, 10, 0, 0, CHECK_LFE }, 1658 { AudioCoutputs, AudioNcenter, "mixtofront", 1659 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1660 ALC650_REG_MULTI_CHANNEL_CONTROL, 1661 0x0000, 1, 2, 0, 0, CHECK_CENTER }, 1662 { AudioCoutputs, AudioNlfe, "mixtofront", 1663 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1664 ALC650_REG_MULTI_CHANNEL_CONTROL, 1665 0x0000, 1, 2, 0, 0, CHECK_LFE }, 1666 }; 1667 1668 ac97_add_port(as, &sources[0]); 1669 ac97_add_port(as, &sources[1]); 1670 ac97_add_port(as, &sources[2]); 1671 ac97_add_port(as, &sources[3]); 1672 ac97_add_port(as, &sources[4]); 1673 ac97_add_port(as, &sources[5]); 1674 } 1675 1676 #define VT1616_REG_IO_CONTROL 0x5a 1677 #define VT1616_IC_LVL (1 << 15) 1678 #define VT1616_IC_LFECENTER_TO_FRONT (1 << 12) 1679 #define VT1616_IC_SURROUND_TO_FRONT (1 << 11) 1680 #define VT1616_IC_BPDC (1 << 10) 1681 #define VT1616_IC_DC (1 << 9) 1682 #define VT1616_IC_IB_MASK 0x000c 1683 static void 1684 ac97_vt1616_init(struct ac97_softc *as) 1685 { 1686 static const struct ac97_source_info sources[3] = { 1687 { AudioCoutputs, AudioNsurround, "mixtofront", 1688 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1689 VT1616_REG_IO_CONTROL, 1690 0x0000, 1, 11, 0, 0, CHECK_SURROUND }, 1691 { AudioCoutputs, AudioNcenter, "mixtofront", 1692 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1693 VT1616_REG_IO_CONTROL, 1694 0x0000, 1, 12, 0, 0, CHECK_CENTER }, 1695 { AudioCoutputs, AudioNlfe, "mixtofront", 1696 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1697 VT1616_REG_IO_CONTROL, 1698 0x0000, 1, 12, 0, 0, CHECK_LFE }, 1699 }; 1700 1701 ac97_add_port(as, &sources[0]); 1702 ac97_add_port(as, &sources[1]); 1703 ac97_add_port(as, &sources[2]); 1704 } 1705