1 /* $OpenBSD: ac97.c,v 1.77 2011/01/03 15:28:46 fgsch Exp $ */ 2 3 /* 4 * Copyright (c) 1999, 2000 Constantine Sapuntzakis 5 * 6 * Author: Constantine Sapuntzakis <csapuntz@stanford.edu> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote 17 * products derived from this software without specific prior written 18 * permission. 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS 20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 25 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 26 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 29 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 * DAMAGE. */ 31 32 /* Partially inspired by FreeBSD's sys/dev/pcm/ac97.c. It came with 33 the following copyright */ 34 35 /* 36 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 37 * All rights reserved. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * $FreeBSD$ 61 */ 62 63 #include <sys/param.h> 64 #include <sys/systm.h> 65 #include <sys/kernel.h> 66 #include <sys/malloc.h> 67 #include <sys/device.h> 68 69 #include <sys/audioio.h> 70 #include <dev/audio_if.h> 71 #include <dev/ic/ac97.h> 72 73 74 /* default parameters; supported by all ac97 codecs */ 75 const struct audio_params ac97_audio_default = { 76 48000, /* sample_rate */ 77 AUDIO_ENCODING_SLINEAR_LE, /* encoding */ 78 16, /* precision */ 79 2, /* bps */ 80 1, /* msb */ 81 2, /* channels */ 82 NULL, /* sw_code */ 83 1 /* factor */ 84 }; 85 86 const struct audio_mixer_enum ac97_on_off = { 87 2, 88 { { { AudioNoff } , 0 }, 89 { { AudioNon } , 1 } } 90 }; 91 92 const struct audio_mixer_enum ac97_mic_select = { 93 2, 94 { { { AudioNmicrophone "0" }, 0 }, 95 { { AudioNmicrophone "1" }, 1 } } 96 }; 97 98 const struct audio_mixer_enum ac97_mono_select = { 99 2, 100 { { { AudioNmixerout }, 0 }, 101 { { AudioNmicrophone }, 1 } } 102 }; 103 104 const struct audio_mixer_enum ac97_source = { 105 8, 106 { { { AudioNmicrophone } , 0 }, 107 { { AudioNcd }, 1 }, 108 { { "video" }, 2 }, 109 { { AudioNaux }, 3 }, 110 { { AudioNline }, 4 }, 111 { { AudioNmixerout }, 5 }, 112 { { AudioNmixerout AudioNmono }, 6 }, 113 { { "phone" }, 7 }} 114 }; 115 116 /* 117 * Due to different values for each source that uses these structures, 118 * the ac97_query_devinfo function sets delta in mixer_devinfo_t using 119 * ac97_source_info.bits. 120 */ 121 const struct audio_mixer_value ac97_volume_stereo = { 122 { AudioNvolume }, 123 2 124 }; 125 126 const struct audio_mixer_value ac97_volume_mono = { 127 { AudioNvolume }, 128 1 129 }; 130 131 #define AudioNspdif "spdif" 132 133 #define WRAP(a) &a, sizeof(a) 134 135 const struct ac97_source_info { 136 char *class; 137 char *device; 138 char *qualifier; 139 int type; 140 141 const void *info; 142 int16_t info_size; 143 144 u_int8_t reg; 145 u_int16_t default_value; 146 u_int8_t bits:3; 147 u_int8_t ofs:4; 148 u_int8_t mute:1; 149 u_int8_t polarity:1; /* Does 0 == MAX or MIN */ 150 enum { 151 CHECK_NONE = 0, 152 CHECK_SURROUND, 153 CHECK_CENTER, 154 CHECK_LFE, 155 CHECK_HEADPHONES, 156 CHECK_TONE, 157 CHECK_MIC, 158 CHECK_LOUDNESS, 159 CHECK_3D, 160 CHECK_SPDIF 161 } req_feature; 162 163 int16_t prev; 164 int16_t next; 165 int16_t mixer_class; 166 } source_info[] = { 167 { AudioCinputs, NULL, NULL, 168 AUDIO_MIXER_CLASS, }, 169 { AudioCoutputs, NULL, NULL, 170 AUDIO_MIXER_CLASS, }, 171 { AudioCrecord, NULL, NULL, 172 AUDIO_MIXER_CLASS, }, 173 /* Stereo master volume*/ 174 { AudioCoutputs, AudioNmaster, NULL, 175 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 176 AC97_REG_MASTER_VOLUME, 0x8000, 5, 0, 1, 177 }, 178 /* Mono volume */ 179 { AudioCoutputs, AudioNmono, NULL, 180 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 181 AC97_REG_MASTER_VOLUME_MONO, 0x8000, 6, 0, 1, 182 }, 183 { AudioCoutputs, AudioNmono, AudioNsource, 184 AUDIO_MIXER_ENUM, WRAP(ac97_mono_select), 185 AC97_REG_GP, 0x0000, 1, 9, 0, 186 }, 187 /* Headphone volume */ 188 { AudioCoutputs, AudioNheadphone, NULL, 189 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 190 AC97_REG_HEADPHONE_VOLUME, 0x8000, 6, 0, 1, 0, CHECK_HEADPHONES 191 }, 192 /* Surround volume - logic hard coded for mute */ 193 { AudioCoutputs, AudioNsurround, NULL, 194 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 195 AC97_REG_SURR_MASTER, 0x8080, 5, 0, 1, 0, CHECK_SURROUND 196 }, 197 /* Center volume*/ 198 { AudioCoutputs, AudioNcenter, NULL, 199 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 200 AC97_REG_CENTER_LFE_MASTER, 0x8080, 5, 0, 0, 0, CHECK_CENTER 201 }, 202 { AudioCoutputs, AudioNcenter, AudioNmute, 203 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 204 AC97_REG_CENTER_LFE_MASTER, 0x8080, 1, 7, 0, 0, CHECK_CENTER 205 }, 206 /* LFE volume*/ 207 { AudioCoutputs, AudioNlfe, NULL, 208 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 209 AC97_REG_CENTER_LFE_MASTER, 0x8080, 5, 8, 0, 0, CHECK_LFE 210 }, 211 { AudioCoutputs, AudioNlfe, AudioNmute, 212 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 213 AC97_REG_CENTER_LFE_MASTER, 0x8080, 1, 15, 0, 0, CHECK_LFE 214 }, 215 /* Tone */ 216 { AudioCoutputs, "tone", NULL, 217 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 218 AC97_REG_MASTER_TONE, 0x0f0f, 4, 0, 0, 0, CHECK_TONE 219 }, 220 /* PC Beep Volume */ 221 { AudioCinputs, AudioNspeaker, NULL, 222 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 223 AC97_REG_PCBEEP_VOLUME, 0x0000, 4, 1, 1, 224 }, 225 226 /* Phone */ 227 { AudioCinputs, "phone", NULL, 228 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 229 AC97_REG_PHONE_VOLUME, 0x8008, 5, 0, 1, 230 }, 231 /* Mic Volume */ 232 { AudioCinputs, AudioNmicrophone, NULL, 233 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 234 AC97_REG_MIC_VOLUME, 0x8008, 5, 0, 1, 235 }, 236 { AudioCinputs, AudioNmicrophone, AudioNpreamp, 237 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 238 AC97_REG_MIC_VOLUME, 0x8008, 1, 6, 0, 239 }, 240 { AudioCinputs, AudioNmicrophone, AudioNsource, 241 AUDIO_MIXER_ENUM, WRAP(ac97_mic_select), 242 AC97_REG_GP, 0x0000, 1, 8, 0, 243 }, 244 /* Line in Volume */ 245 { AudioCinputs, AudioNline, NULL, 246 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 247 AC97_REG_LINEIN_VOLUME, 0x8808, 5, 0, 1, 248 }, 249 /* CD Volume */ 250 { AudioCinputs, AudioNcd, NULL, 251 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 252 AC97_REG_CD_VOLUME, 0x8808, 5, 0, 1, 253 }, 254 /* Video Volume */ 255 { AudioCinputs, AudioNvideo, NULL, 256 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 257 AC97_REG_VIDEO_VOLUME, 0x8808, 5, 0, 1, 258 }, 259 /* AUX volume */ 260 { AudioCinputs, AudioNaux, NULL, 261 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 262 AC97_REG_AUX_VOLUME, 0x8808, 5, 0, 1, 263 }, 264 /* PCM out volume */ 265 { AudioCinputs, AudioNdac, NULL, 266 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 267 AC97_REG_PCMOUT_VOLUME, 0x8808, 5, 0, 1, 268 }, 269 /* Record Source - some logic for this is hard coded - see below */ 270 { AudioCrecord, AudioNsource, NULL, 271 AUDIO_MIXER_ENUM, WRAP(ac97_source), 272 AC97_REG_RECORD_SELECT, 0x0000, 3, 0, 0, 273 }, 274 /* Record Gain */ 275 { AudioCrecord, AudioNvolume, NULL, 276 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo), 277 AC97_REG_RECORD_GAIN, 0x8000, 4, 0, 1, 278 }, 279 /* Record Gain mic */ 280 { AudioCrecord, AudioNmicrophone, NULL, 281 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 282 AC97_REG_RECORD_GAIN_MIC, 0x8000, 4, 0, 1, 1, CHECK_MIC 283 }, 284 /* */ 285 { AudioCoutputs, AudioNloudness, NULL, 286 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 287 AC97_REG_GP, 0x0000, 1, 12, 0, 0, CHECK_LOUDNESS 288 }, 289 { AudioCoutputs, AudioNspatial, NULL, 290 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 291 AC97_REG_GP, 0x0000, 1, 13, 0, 1, CHECK_3D 292 }, 293 { AudioCoutputs, AudioNspatial, "center", 294 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 295 AC97_REG_3D_CONTROL, 0x0000, 4, 8, 0, 1, CHECK_3D 296 }, 297 { AudioCoutputs, AudioNspatial, "depth", 298 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), 299 AC97_REG_3D_CONTROL, 0x0000, 4, 0, 0, 1, CHECK_3D 300 }, 301 /* External Amp */ 302 { AudioCoutputs, AudioNextamp, NULL, 303 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 304 AC97_REG_POWER, 0x0000, 1, 15, 0, 0 305 }, 306 /* S/PDIF output enable */ 307 { AudioCoutputs, AudioNspdif, NULL, 308 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 309 AC97_REG_EXT_AUDIO_CTRL, 0x0000, 1, 2, 0, 0, CHECK_SPDIF 310 } 311 312 /* Missing features: Simulated Stereo, POP, Loopback mode */ 313 }; 314 315 /* 316 * Check out http://www.intel.com/technology/computing/audio/index.htm 317 * for information on AC-97 318 */ 319 320 struct ac97_softc { 321 /* ac97_codec_if must be at the first of ac97_softc. */ 322 struct ac97_codec_if codec_if; 323 struct ac97_host_if *host_if; 324 #define MAX_SOURCES (2 * nitems(source_info)) 325 struct ac97_source_info source_info[MAX_SOURCES]; 326 int num_source_info; 327 enum ac97_host_flags host_flags; 328 unsigned int ac97_clock; /* usually 48000 */ 329 #define AC97_STANDARD_CLOCK 48000U 330 u_int16_t caps; /* -> AC97_REG_RESET */ 331 u_int16_t ext_id; /* -> AC97_REG_EXT_AUDIO_ID */ 332 u_int16_t shadow_reg[128]; 333 int lock_counter; 334 }; 335 336 int ac97_mixer_get_port(struct ac97_codec_if *, mixer_ctrl_t *); 337 int ac97_mixer_set_port(struct ac97_codec_if *, mixer_ctrl_t *); 338 void ac97_lock(struct ac97_codec_if *); 339 void ac97_unlock(struct ac97_codec_if *); 340 int ac97_query_devinfo(struct ac97_codec_if *, mixer_devinfo_t *); 341 int ac97_get_portnum_by_name(struct ac97_codec_if *, char *, char *, 342 char *); 343 void ac97_restore_shadow(struct ac97_codec_if *); 344 int ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_long *rate); 345 void ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock); 346 u_int16_t ac97_get_extcaps(struct ac97_codec_if *codec_if); 347 int ac97_add_port(struct ac97_softc *as, struct ac97_source_info *src); 348 349 void ac97_ad1885_init(struct ac97_softc *, int); 350 void ac97_ad1886_init(struct ac97_softc *, int); 351 void ac97_ad198x_init(struct ac97_softc *, int); 352 void ac97_alc650_init(struct ac97_softc *, int); 353 void ac97_cx20468_init(struct ac97_softc *, int); 354 void ac97_vt1616_init(struct ac97_softc *, int); 355 356 struct ac97_codec_if_vtbl ac97civ = { 357 ac97_mixer_get_port, 358 ac97_mixer_set_port, 359 ac97_query_devinfo, 360 ac97_get_portnum_by_name, 361 ac97_restore_shadow, 362 ac97_get_extcaps, 363 ac97_set_rate, 364 ac97_set_clock, 365 ac97_lock, 366 ac97_unlock 367 }; 368 369 const struct ac97_codecid { 370 u_int8_t id; 371 u_int8_t mask; 372 u_int8_t rev; 373 u_int8_t shift; /* no use yet */ 374 char * const name; 375 void (*init)(struct ac97_softc *, int); 376 } ac97_ad[] = { 377 { 0x03, 0xff, 0, 0, "AD1819" }, 378 { 0x40, 0xff, 0, 0, "AD1881" }, 379 { 0x48, 0xff, 0, 0, "AD1881A" }, 380 { 0x60, 0xff, 0, 0, "AD1885", ac97_ad1885_init }, 381 { 0x61, 0xff, 0, 0, "AD1886", ac97_ad1886_init }, 382 { 0x63, 0xff, 0, 0, "AD1886A" }, 383 { 0x68, 0xff, 0, 0, "AD1888", ac97_ad198x_init }, 384 { 0x70, 0xff, 0, 0, "AD1980", ac97_ad198x_init }, 385 { 0x72, 0xff, 0, 0, "AD1981A" }, 386 { 0x74, 0xff, 0, 0, "AD1981B" }, 387 { 0x75, 0xff, 0, 0, "AD1985", ac97_ad198x_init }, 388 }, ac97_ak[] = { 389 { 0x00, 0xfe, 1, 0, "AK4540" }, 390 { 0x01, 0xfe, 1, 0, "AK4540" }, 391 { 0x02, 0xff, 0, 0, "AK4543" }, 392 { 0x05, 0xff, 0, 0, "AK4544" }, 393 { 0x06, 0xff, 0, 0, "AK4544A" }, 394 { 0x07, 0xff, 0, 0, "AK4545" }, 395 }, ac97_av[] = { 396 { 0x10, 0xff, 0, 0, "ALC200" }, 397 { 0x20, 0xff, 0, 0, "ALC650" }, 398 { 0x21, 0xff, 0, 0, "ALC650D" }, 399 { 0x22, 0xff, 0, 0, "ALC650E" }, 400 { 0x23, 0xff, 0, 0, "ALC650F" }, 401 { 0x30, 0xff, 0, 0, "ALC101" }, 402 { 0x40, 0xff, 0, 0, "ALC202" }, 403 { 0x50, 0xff, 0, 0, "ALC250" }, 404 { 0x52, 0xff, 0, 0, "ALC250A?" }, 405 { 0x60, 0xf0, 0xf, 0, "ALC655", ac97_alc650_init }, 406 { 0x70, 0xf0, 0xf, 0, "ALC203" }, 407 { 0x80, 0xf0, 0xf, 0, "ALC658", ac97_alc650_init }, 408 { 0x90, 0xf0, 0xf, 0, "ALC850" }, 409 }, ac97_rl[] = { 410 { 0x00, 0xf0, 0xf, 0, "RL5306" }, 411 { 0x10, 0xf0, 0xf, 0, "RL5382" }, 412 { 0x20, 0xf0, 0xf, 0, "RL5383" }, 413 }, ac97_cm[] = { 414 { 0x41, 0xff, 0, 0, "CMI9738" }, 415 { 0x61, 0xff, 0, 0, "CMI9739" }, 416 { 0x78, 0xff, 0, 0, "CMI9761A" }, 417 { 0x82, 0xff, 0, 0, "CMI9761B" }, 418 { 0x83, 0xff, 0, 0, "CMI9761A+" }, 419 }, ac97_cr[] = { 420 { 0x84, 0xff, 0, 0, "EV1938" }, 421 }, ac97_cs[] = { 422 { 0x00, 0xf8, 7, 0, "CS4297" }, 423 { 0x10, 0xf8, 7, 0, "CS4297A" }, 424 { 0x20, 0xf8, 7, 0, "CS4298" }, 425 { 0x28, 0xf8, 7, 0, "CS4294" }, 426 { 0x30, 0xf8, 7, 0, "CS4299" }, 427 { 0x48, 0xf8, 7, 0, "CS4201" }, 428 { 0x58, 0xf8, 7, 0, "CS4205" }, 429 { 0x60, 0xf8, 7, 0, "CS4291" }, 430 { 0x70, 0xf8, 7, 0, "CS4202" }, 431 }, ac97_cx[] = { 432 { 0x21, 0xff, 0, 0, "HSD11246" }, 433 { 0x28, 0xf8, 7, 0, "CX20468", ac97_cx20468_init }, 434 { 0x30, 0xff, 0, 0, "CXT48", }, 435 { 0x42, 0xff, 0, 0, "CXT66", }, 436 }, ac97_dt[] = { 437 { 0x00, 0xff, 0, 0, "DT0398" }, 438 }, ac97_em[] = { 439 { 0x23, 0xff, 0, 0, "EM28023" }, 440 { 0x28, 0xff, 0, 0, "EM28028" }, 441 }, ac97_es[] = { 442 { 0x08, 0xff, 0, 0, "ES1921" }, 443 }, ac97_is[] = { 444 { 0x00, 0xff, 0, 0, "HMP9701" }, 445 }, ac97_ic[] = { 446 { 0x01, 0xff, 0, 0, "ICE1230" }, 447 { 0x11, 0xff, 0, 0, "ICE1232" }, 448 { 0x14, 0xff, 0, 0, "ICE1232A" }, 449 { 0x51, 0xff, 0, 0, "VIA VT1616" }, 450 { 0x52, 0xff, 0, 0, "VIA VT1616i", ac97_vt1616_init }, 451 }, ac97_it[] = { 452 { 0x20, 0xff, 0, 0, "ITE2226E" }, 453 { 0x60, 0xff, 0, 0, "ITE2646E" }, 454 }, ac97_ns[] = { 455 { 0x00, 0xff, 0, 0, "LM454[03568]" }, 456 { 0x31, 0xff, 0, 0, "LM4549" }, 457 { 0x40, 0xff, 0, 0, "LM4540" }, 458 { 0x43, 0xff, 0, 0, "LM4543" }, 459 { 0x46, 0xff, 0, 0, "LM4546A" }, 460 { 0x48, 0xff, 0, 0, "LM4548A" }, 461 { 0x49, 0xff, 0, 0, "LM4549A" }, 462 { 0x50, 0xff, 0, 0, "LM4550" }, 463 }, ac97_ps[] = { 464 { 0x01, 0xff, 0, 0, "UCB1510" }, 465 { 0x04, 0xff, 0, 0, "UCB1400" }, 466 }, ac97_sl[] = { 467 { 0x20, 0xe0, 0, 0, "Si3036/38" }, 468 }, ac97_st[] = { 469 { 0x00, 0xff, 0, 0, "STAC9700" }, 470 { 0x04, 0xff, 0, 0, "STAC970[135]" }, 471 { 0x05, 0xff, 0, 0, "STAC9704" }, 472 { 0x08, 0xff, 0, 0, "STAC9708/11" }, 473 { 0x09, 0xff, 0, 0, "STAC9721/23" }, 474 { 0x44, 0xff, 0, 0, "STAC9744/45" }, 475 { 0x50, 0xff, 0, 0, "STAC9750/51" }, 476 { 0x52, 0xff, 0, 0, "STAC9752/53" }, 477 { 0x56, 0xff, 0, 0, "STAC9756/57" }, 478 { 0x58, 0xff, 0, 0, "STAC9758/59" }, 479 { 0x60, 0xff, 0, 0, "STAC9760/61" }, 480 { 0x62, 0xff, 0, 0, "STAC9762/63" }, 481 { 0x66, 0xff, 0, 0, "STAC9766/67" }, 482 { 0x84, 0xff, 0, 0, "STAC9784/85" }, 483 }, ac97_vi[] = { 484 { 0x61, 0xff, 0, 0, "VT1612A" }, 485 { 0x70, 0xff, 0, 0, "VT1617" }, 486 }, ac97_tt[] = { 487 { 0x02, 0xff, 0, 0, "TR28022" }, 488 { 0x03, 0xff, 0, 0, "TR28023" }, 489 { 0x06, 0xff, 0, 0, "TR28026" }, 490 { 0x08, 0xff, 0, 0, "TR28028" }, 491 { 0x23, 0xff, 0, 0, "TR28602" }, 492 }, ac97_ti[] = { 493 { 0x20, 0xff, 0, 0, "TLC320AD9xC" }, 494 }, ac97_wb[] = { 495 { 0x01, 0xff, 0, 0, "W83971D" }, 496 }, ac97_wo[] = { 497 { 0x00, 0xff, 0, 0, "WM9701A" }, 498 { 0x03, 0xff, 0, 0, "WM9704M/Q-0" }, /* & WM9703 */ 499 { 0x04, 0xff, 0, 0, "WM9704M/Q-1" }, 500 { 0x05, 0xff, 0, 0, "WM9705/10" }, 501 { 0x09, 0xff, 0, 0, "WM9709" }, 502 { 0x12, 0xff, 0, 0, "WM9711/12" }, 503 }, ac97_ym[] = { 504 { 0x00, 0xff, 0, 0, "YMF743-S" }, 505 { 0x02, 0xff, 0, 0, "YMF752-S" }, 506 { 0x03, 0xff, 0, 0, "YMF753-S" }, 507 }; 508 509 #define cl(n) n, nitems(n) 510 const struct ac97_vendorid { 511 u_int32_t id; 512 char * const name; 513 const struct ac97_codecid * const codecs; 514 u_int8_t num; 515 } ac97_vendors[] = { 516 { 0x01408300, "Creative", cl(ac97_cr) }, 517 { 0x41445300, "Analog Devices", cl(ac97_ad) }, 518 { 0x414b4D00, "Asahi Kasei", cl(ac97_ak) }, 519 { 0x414c4300, "Realtek", cl(ac97_rl) }, 520 { 0x414c4700, "Avance Logic", cl(ac97_av) }, 521 { 0x434d4900, "C-Media Electronics", cl(ac97_cm) }, 522 { 0x43525900, "Cirrus Logic", cl(ac97_cs) }, 523 { 0x43585400, "Conexant", cl(ac97_cx) }, 524 { 0x44543000, "Diamond Technology", cl(ac97_dt) }, 525 { 0x454d4300, "eMicro", cl(ac97_em) }, 526 { 0x45838300, "ESS Technology", cl(ac97_es) }, 527 { 0x48525300, "Intersil", cl(ac97_is) }, 528 { 0x49434500, "ICEnsemble", cl(ac97_ic) }, 529 { 0x49544500, "ITE, Inc.", cl(ac97_it) }, 530 { 0x4e534300, "National Semiconductor", cl(ac97_ns) }, 531 { 0x50534300, "Philips Semiconductor", cl(ac97_ps) }, 532 { 0x53494c00, "Silicon Laboratory", cl(ac97_sl) }, 533 { 0x54524100, "TriTech Microelectronics", cl(ac97_tt) }, 534 { 0x54584e00, "Texas Instruments", cl(ac97_ti) }, 535 { 0x56494100, "VIA Technologies", cl(ac97_vi) }, 536 { 0x57454300, "Winbond", cl(ac97_wb) }, 537 { 0x574d4c00, "Wolfson", cl(ac97_wo) }, 538 { 0x594d4800, "Yamaha", cl(ac97_ym) }, 539 { 0x83847600, "SigmaTel", cl(ac97_st) }, 540 }; 541 #undef cl 542 543 const char * const ac97enhancement[] = { 544 "No 3D Stereo", 545 "Analog Devices Phat Stereo", 546 "Creative", 547 "National Semi 3D", 548 "Yamaha Ymersion", 549 "BBE 3D", 550 "Crystal Semi 3D", 551 "Qsound QXpander", 552 "Spatializer 3D", 553 "SRS 3D", 554 "Platform Tech 3D", 555 "AKM 3D", 556 "Aureal", 557 "AZTECH 3D", 558 "Binaura 3D", 559 "ESS Technology", 560 "Harman International VMAx", 561 "Nvidea 3D", 562 "Philips Incredible Sound", 563 "Texas Instruments 3D", 564 "VLSI Technology 3D", 565 "TriTech 3D", 566 "Realtek 3D", 567 "Samsung 3D", 568 "Wolfson Microelectronics 3D", 569 "Delta Integration 3D", 570 "SigmaTel 3D", 571 "KS Waves 3D", 572 "Rockwell 3D", 573 "Unknown 3D", 574 "Unknown 3D", 575 "Unknown 3D" 576 }; 577 578 const char * const ac97feature[] = { 579 "mic channel", 580 "reserved", 581 "tone", 582 "simulated stereo", 583 "headphone", 584 "bass boost", 585 "18 bit DAC", 586 "20 bit DAC", 587 "18 bit ADC", 588 "20 bit ADC" 589 }; 590 591 592 int ac97_str_equal(const char *, const char *); 593 int ac97_check_capability(struct ac97_softc *, int); 594 void ac97_setup_source_info(struct ac97_softc *); 595 void ac97_setup_defaults(struct ac97_softc *); 596 int ac97_read(struct ac97_softc *, u_int8_t, u_int16_t *); 597 int ac97_write(struct ac97_softc *, u_int8_t, u_int16_t); 598 599 600 #ifdef AUDIO_DEBUG 601 #define DPRINTF(x) if (ac97debug) printf x 602 #define DPRINTFN(n,x) if (ac97debug>(n)) printf x 603 #ifdef AC97_DEBUG 604 int ac97debug = 1; 605 #else 606 int ac97debug = 0; 607 #endif 608 #else 609 #define DPRINTF(x) 610 #define DPRINTFN(n,x) 611 #endif 612 613 void 614 ac97_get_default_params(struct audio_params *params) 615 { 616 *params = ac97_audio_default; 617 } 618 619 int 620 ac97_read(struct ac97_softc *as, u_int8_t reg, u_int16_t *val) 621 { 622 int error; 623 624 if (((as->host_flags & AC97_HOST_DONT_READ) && 625 (reg != AC97_REG_VENDOR_ID1 && reg != AC97_REG_VENDOR_ID2 && 626 reg != AC97_REG_RESET)) || 627 (as->host_flags & AC97_HOST_DONT_READANY)) { 628 *val = as->shadow_reg[reg >> 1]; 629 return (0); 630 } 631 632 if ((error = as->host_if->read(as->host_if->arg, reg, val))) 633 *val = as->shadow_reg[reg >> 1]; 634 return (error); 635 } 636 637 int 638 ac97_write(struct ac97_softc *as, u_int8_t reg, u_int16_t val) 639 { 640 as->shadow_reg[reg >> 1] = val; 641 return (as->host_if->write(as->host_if->arg, reg, val)); 642 } 643 644 void 645 ac97_setup_defaults(struct ac97_softc *as) 646 { 647 int idx; 648 649 bzero(as->shadow_reg, sizeof(as->shadow_reg)); 650 651 for (idx = 0; idx < nitems(source_info); idx++) { 652 const struct ac97_source_info *si = &source_info[idx]; 653 654 ac97_write(as, si->reg, si->default_value); 655 } 656 } 657 658 void 659 ac97_restore_shadow(struct ac97_codec_if *self) 660 { 661 struct ac97_softc *as = (struct ac97_softc *)self; 662 int idx; 663 664 for (idx = 0; idx < nitems(source_info); idx++) { 665 const struct ac97_source_info *si = &source_info[idx]; 666 667 ac97_write(as, si->reg, as->shadow_reg[si->reg >> 1]); 668 } 669 } 670 671 int 672 ac97_str_equal(const char *a, const char *b) 673 { 674 return ((a == b) || (a && b && (!strcmp(a, b)))); 675 } 676 677 int 678 ac97_check_capability(struct ac97_softc *as, int check) 679 { 680 switch (check) { 681 case CHECK_NONE: 682 return 1; 683 case CHECK_SURROUND: 684 return as->ext_id & AC97_EXT_AUDIO_SDAC; 685 case CHECK_CENTER: 686 return as->ext_id & AC97_EXT_AUDIO_CDAC; 687 case CHECK_LFE: 688 return as->ext_id & AC97_EXT_AUDIO_LDAC; 689 case CHECK_SPDIF: 690 return as->ext_id & AC97_EXT_AUDIO_SPDIF; 691 case CHECK_HEADPHONES: 692 return as->caps & AC97_CAPS_HEADPHONES; 693 case CHECK_TONE: 694 return as->caps & AC97_CAPS_TONECTRL; 695 case CHECK_MIC: 696 return as->caps & AC97_CAPS_MICIN; 697 case CHECK_LOUDNESS: 698 return as->caps & AC97_CAPS_LOUDNESS; 699 case CHECK_3D: 700 return AC97_CAPS_ENHANCEMENT(as->caps) != 0; 701 default: 702 printf("%s: internal error: feature=%d\n", __func__, check); 703 return 0; 704 } 705 } 706 707 void 708 ac97_setup_source_info(struct ac97_softc *as) 709 { 710 struct ac97_source_info *si, *si2; 711 int idx, ouridx; 712 713 for (idx = 0, ouridx = 0; idx < nitems(source_info); idx++) { 714 si = &as->source_info[ouridx]; 715 716 if (!ac97_check_capability(as, source_info[idx].req_feature)) 717 continue; 718 719 bcopy(&source_info[idx], si, sizeof(*si)); 720 721 switch (si->type) { 722 case AUDIO_MIXER_CLASS: 723 si->mixer_class = ouridx; 724 ouridx++; 725 break; 726 case AUDIO_MIXER_VALUE: 727 /* Todo - Test to see if it works */ 728 ouridx++; 729 730 /* Add an entry for mute, if necessary */ 731 if (si->mute) { 732 si = &as->source_info[ouridx]; 733 bcopy(&source_info[idx], si, sizeof(*si)); 734 si->qualifier = AudioNmute; 735 si->type = AUDIO_MIXER_ENUM; 736 si->info = &ac97_on_off; 737 si->info_size = sizeof(ac97_on_off); 738 si->bits = 1; 739 si->ofs = 15; 740 si->mute = 0; 741 si->polarity = 0; 742 ouridx++; 743 } 744 break; 745 case AUDIO_MIXER_ENUM: 746 /* Todo - Test to see if it works */ 747 ouridx++; 748 break; 749 default: 750 printf ("ac97: shouldn't get here\n"); 751 break; 752 } 753 } 754 755 as->num_source_info = ouridx; 756 757 for (idx = 0; idx < as->num_source_info; idx++) { 758 int idx2, previdx; 759 760 si = &as->source_info[idx]; 761 762 /* Find mixer class */ 763 for (idx2 = 0; idx2 < as->num_source_info; idx2++) { 764 si2 = &as->source_info[idx2]; 765 766 if (si2->type == AUDIO_MIXER_CLASS && 767 ac97_str_equal(si->class, si2->class)) { 768 si->mixer_class = idx2; 769 } 770 } 771 772 773 /* Setup prev and next pointers */ 774 if (si->prev != 0 || si->qualifier) 775 continue; 776 777 si->prev = AUDIO_MIXER_LAST; 778 previdx = idx; 779 780 for (idx2 = 0; idx2 < as->num_source_info; idx2++) { 781 if (idx2 == idx) 782 continue; 783 784 si2 = &as->source_info[idx2]; 785 786 if (!si2->prev && 787 ac97_str_equal(si->class, si2->class) && 788 ac97_str_equal(si->device, si2->device)) { 789 as->source_info[previdx].next = idx2; 790 as->source_info[idx2].prev = previdx; 791 792 previdx = idx2; 793 } 794 } 795 796 as->source_info[previdx].next = AUDIO_MIXER_LAST; 797 } 798 } 799 800 int 801 ac97_attach(struct ac97_host_if *host_if) 802 { 803 struct ac97_softc *as; 804 u_int16_t id1, id2, val; 805 u_int32_t id; 806 u_int16_t extstat, rate; 807 mixer_ctrl_t ctl; 808 int error, i; 809 void (*initfunc)(struct ac97_softc *, int); 810 811 initfunc = NULL; 812 813 if (!(as = malloc(sizeof(*as), M_DEVBUF, M_NOWAIT | M_ZERO))) 814 return (ENOMEM); 815 816 as->codec_if.as = as; 817 as->codec_if.vtbl = &ac97civ; 818 as->host_if = host_if; 819 820 if ((error = host_if->attach(host_if->arg, &as->codec_if))) { 821 free(as, M_DEVBUF); 822 return (error); 823 } 824 825 host_if->reset(host_if->arg); 826 DELAY(1000); 827 828 host_if->write(host_if->arg, AC97_REG_POWER, 0); 829 host_if->write(host_if->arg, AC97_REG_RESET, 0); 830 DELAY(10000); 831 832 if (host_if->flags) 833 as->host_flags = host_if->flags(host_if->arg); 834 835 ac97_setup_defaults(as); 836 ac97_read(as, AC97_REG_VENDOR_ID1, &id1); 837 ac97_read(as, AC97_REG_VENDOR_ID2, &id2); 838 ac97_read(as, AC97_REG_RESET, &as->caps); 839 840 id = (id1 << 16) | id2; 841 if (id) { 842 register const struct ac97_vendorid *vendor; 843 register const struct ac97_codecid *codec; 844 845 printf("ac97: codec id 0x%08x", id); 846 for (vendor = &ac97_vendors[sizeof(ac97_vendors) / 847 sizeof(ac97_vendors[0]) - 1]; 848 vendor >= ac97_vendors; vendor--) { 849 if (vendor->id == (id & AC97_VENDOR_ID_MASK)) { 850 printf(" (%s", vendor->name); 851 for (codec = &vendor->codecs[vendor->num-1]; 852 codec >= vendor->codecs; codec--) { 853 if (codec->id == (id & codec->mask)) 854 break; 855 } 856 if (codec >= vendor->codecs && codec->mask) { 857 printf(" %s", codec->name); 858 initfunc = codec->init; 859 } else 860 printf(" <%02x>", id & 0xff); 861 if (codec >= vendor->codecs && codec->rev) 862 printf(" rev %d", id & codec->rev); 863 printf(")"); 864 break; 865 } 866 } 867 printf("\n"); 868 } else 869 printf("ac97: codec id not read\n"); 870 871 if (as->caps) { 872 printf("ac97: codec features "); 873 for (i = 0; i < 10; i++) { 874 if (as->caps & (1 << i)) 875 printf("%s, ", ac97feature[i]); 876 } 877 printf("%s\n", 878 ac97enhancement[AC97_CAPS_ENHANCEMENT(as->caps)]); 879 } 880 881 882 as->ac97_clock = AC97_STANDARD_CLOCK; 883 ac97_read(as, AC97_REG_EXT_AUDIO_ID, &as->ext_id); 884 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA 885 | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM 886 | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC 887 | AC97_EXT_AUDIO_LDAC)) { 888 889 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat); 890 extstat &= ~AC97_EXT_AUDIO_DRA; 891 892 if (as->ext_id & AC97_EXT_AUDIO_VRM) 893 extstat |= AC97_EXT_AUDIO_VRM; 894 895 if (as->ext_id & AC97_EXT_AUDIO_LDAC) 896 extstat |= AC97_EXT_AUDIO_LDAC; 897 if (as->ext_id & AC97_EXT_AUDIO_SDAC) 898 extstat |= AC97_EXT_AUDIO_SDAC; 899 if (as->ext_id & AC97_EXT_AUDIO_CDAC) 900 extstat |= AC97_EXT_AUDIO_CDAC; 901 if (as->ext_id & AC97_EXT_AUDIO_SPDIF) { 902 /* XXX S/PDIF gets same data as DAC? 903 * maybe this should be settable? 904 * default is SPSAAB (10/11) on AD1980 and ALC codecs. 905 */ 906 extstat &= ~AC97_EXT_AUDIO_SPSA_MASK; 907 extstat |= AC97_EXT_AUDIO_SPSA34; 908 ac97_read(as, AC97_REG_SPDIF_CTRL, &val); 909 val = (val & ~AC97_SPDIF_SPSR_MASK) | 910 AC97_SPDIF_SPSR_48K; 911 ac97_write(as, AC97_REG_SPDIF_CTRL, val); 912 } 913 if (as->ext_id & AC97_EXT_AUDIO_VRA) 914 extstat |= AC97_EXT_AUDIO_VRA; 915 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat); 916 if (as->ext_id & AC97_EXT_AUDIO_VRA) { 917 /* VRA should be enabled. */ 918 /* so it claims to do variable rate, let's make sure */ 919 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE, 44100); 920 ac97_read(as, AC97_REG_PCM_FRONT_DAC_RATE, &rate); 921 if (rate != 44100) { 922 /* We can't believe ext_id */ 923 as->ext_id = 0; 924 } 925 /* restore the default value */ 926 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE, 927 AC97_SINGLE_RATE); 928 } 929 } 930 931 ac97_setup_source_info(as); 932 933 DELAY(900 * 1000); 934 935 /* use initfunc for specific device */ 936 as->codec_if.initfunc = initfunc; 937 if (initfunc != NULL) 938 initfunc(as, 0); 939 940 /* Just enable the DAC and master volumes by default */ 941 bzero(&ctl, sizeof(ctl)); 942 943 ctl.type = AUDIO_MIXER_ENUM; 944 ctl.un.ord = 0; /* off */ 945 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs, 946 AudioNmaster, AudioNmute); 947 ac97_mixer_set_port(&as->codec_if, &ctl); 948 949 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCinputs, 950 AudioNdac, AudioNmute); 951 ac97_mixer_set_port(&as->codec_if, &ctl); 952 953 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord, 954 AudioNvolume, AudioNmute); 955 ac97_mixer_set_port(&as->codec_if, &ctl); 956 957 ctl.type = AUDIO_MIXER_ENUM; 958 ctl.un.ord = 0; 959 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord, 960 AudioNsource, NULL); 961 ac97_mixer_set_port(&as->codec_if, &ctl); 962 963 return (0); 964 } 965 966 int 967 ac97_resume(struct ac97_host_if *host_if, struct ac97_codec_if *codec_if) 968 { 969 struct ac97_softc *as = codec_if->as; 970 u_int16_t val, extstat; 971 972 host_if->reset(host_if->arg); 973 DELAY(1000); 974 975 host_if->write(host_if->arg, AC97_REG_POWER, 0); 976 host_if->write(host_if->arg, AC97_REG_RESET, 0); 977 DELAY(10000); 978 979 codec_if->vtbl->restore_ports(codec_if); 980 981 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA 982 | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM 983 | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC 984 | AC97_EXT_AUDIO_LDAC)) { 985 986 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat); 987 extstat &= ~AC97_EXT_AUDIO_DRA; 988 989 if (as->ext_id & AC97_EXT_AUDIO_VRM) 990 extstat |= AC97_EXT_AUDIO_VRM; 991 992 if (as->ext_id & AC97_EXT_AUDIO_LDAC) 993 extstat |= AC97_EXT_AUDIO_LDAC; 994 if (as->ext_id & AC97_EXT_AUDIO_SDAC) 995 extstat |= AC97_EXT_AUDIO_SDAC; 996 if (as->ext_id & AC97_EXT_AUDIO_CDAC) 997 extstat |= AC97_EXT_AUDIO_CDAC; 998 999 if (as->ext_id & AC97_EXT_AUDIO_SPDIF) { 1000 extstat &= ~AC97_EXT_AUDIO_SPSA_MASK; 1001 extstat |= AC97_EXT_AUDIO_SPSA34; 1002 ac97_read(as, AC97_REG_SPDIF_CTRL, &val); 1003 val = (val & ~AC97_SPDIF_SPSR_MASK) | 1004 AC97_SPDIF_SPSR_48K; 1005 ac97_write(as, AC97_REG_SPDIF_CTRL, val); 1006 } 1007 if (as->ext_id & AC97_EXT_AUDIO_VRA) 1008 extstat |= AC97_EXT_AUDIO_VRA; 1009 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat); 1010 } 1011 1012 /* use initfunc for specific device */ 1013 if (as->codec_if.initfunc != NULL) 1014 as->codec_if.initfunc(as, 1); 1015 1016 return (0); 1017 } 1018 1019 void 1020 ac97_lock(struct ac97_codec_if *codec_if) 1021 { 1022 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1023 as->lock_counter++; 1024 } 1025 1026 void 1027 ac97_unlock(struct ac97_codec_if *codec_if) 1028 { 1029 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1030 as->lock_counter--; 1031 } 1032 1033 int 1034 ac97_query_devinfo(struct ac97_codec_if *codec_if, mixer_devinfo_t *dip) 1035 { 1036 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1037 1038 if (dip->index < as->num_source_info && dip->index >= 0) { 1039 struct ac97_source_info *si = &as->source_info[dip->index]; 1040 const char *name; 1041 1042 dip->type = si->type; 1043 dip->mixer_class = si->mixer_class; 1044 dip->prev = si->prev; 1045 dip->next = si->next; 1046 1047 if (si->qualifier) 1048 name = si->qualifier; 1049 else if (si->device) 1050 name = si->device; 1051 else if (si->class) 1052 name = si->class; 1053 else 1054 name = NULL; 1055 1056 if (name) 1057 strlcpy(dip->label.name, name, sizeof dip->label.name); 1058 1059 bcopy(si->info, &dip->un, si->info_size); 1060 1061 /* Set the delta for volume sources */ 1062 if (dip->type == AUDIO_MIXER_VALUE) 1063 dip->un.v.delta = 1 << (8 - si->bits); 1064 1065 return (0); 1066 } 1067 1068 return (ENXIO); 1069 } 1070 1071 int 1072 ac97_mixer_set_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp) 1073 { 1074 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1075 struct ac97_source_info *si = &as->source_info[cp->dev]; 1076 u_int16_t mask; 1077 u_int16_t val, newval; 1078 int error, spdif; 1079 1080 if (cp->dev < 0 || cp->dev >= as->num_source_info || 1081 cp->type == AUDIO_MIXER_CLASS || cp->type != si->type) 1082 return (EINVAL); 1083 1084 spdif = si->req_feature == CHECK_SPDIF && 1085 si->reg == AC97_REG_EXT_AUDIO_CTRL; 1086 if (spdif && as->lock_counter >= 0) 1087 return EBUSY; 1088 1089 ac97_read(as, si->reg, &val); 1090 1091 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val)); 1092 1093 mask = (1 << si->bits) - 1; 1094 1095 switch (cp->type) { 1096 case AUDIO_MIXER_ENUM: 1097 if (cp->un.ord > mask || cp->un.ord < 0) 1098 return (EINVAL); 1099 1100 newval = (cp->un.ord << si->ofs); 1101 if (si->reg == AC97_REG_RECORD_SELECT) { 1102 newval |= (newval << (8 + si->ofs)); 1103 mask |= (mask << 8); 1104 mask = mask << si->ofs; 1105 } else if (si->reg == AC97_REG_SURR_MASTER) { 1106 newval = cp->un.ord ? 0x8080 : 0x0000; 1107 mask = 0x8080; 1108 } else 1109 mask = mask << si->ofs; 1110 1111 if (si->mute) { 1112 newval |= newval << 8; 1113 mask |= mask << 8; 1114 } 1115 1116 break; 1117 case AUDIO_MIXER_VALUE: 1118 { 1119 const struct audio_mixer_value *value = si->info; 1120 u_int16_t l, r; 1121 1122 if (cp->un.value.num_channels <= 0 || 1123 cp->un.value.num_channels > value->num_channels) 1124 return (EINVAL); 1125 1126 if (cp->un.value.num_channels == 1) { 1127 l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 1128 } else { 1129 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) { 1130 l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1131 r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1132 } else { 1133 r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1134 l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1135 } 1136 } 1137 1138 if (!si->polarity) { 1139 l = 255 - l; 1140 r = 255 - r; 1141 } 1142 1143 l >>= 8 - si->bits; 1144 r >>= 8 - si->bits; 1145 1146 newval = ((l & mask) << si->ofs); 1147 if (value->num_channels == 2) { 1148 newval |= ((r & mask) << (si->ofs + 8)); 1149 mask |= (mask << 8); 1150 } 1151 mask = mask << si->ofs; 1152 break; 1153 } 1154 default: 1155 return (EINVAL); 1156 } 1157 1158 error = ac97_write(as, si->reg, (val & ~mask) | newval); 1159 if (error) 1160 return (error); 1161 1162 if (spdif && as->host_if->spdif_event != NULL) 1163 as->host_if->spdif_event(as->host_if->arg, cp->un.ord); 1164 1165 return (0); 1166 } 1167 1168 1169 int 1170 ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_long *rate) 1171 { 1172 struct ac97_softc *as; 1173 u_long value; 1174 u_int16_t ext_stat; 1175 u_int16_t actual; 1176 u_int16_t power; 1177 u_int16_t power_bit; 1178 1179 as = (struct ac97_softc *)codec_if; 1180 1181 if ((target == AC97_REG_PCM_SURR_DAC_RATE) && 1182 !(as->ext_id & AC97_EXT_AUDIO_SDAC)) 1183 return 0; 1184 if ((target == AC97_REG_PCM_LFE_DAC_RATE) && 1185 !(as->ext_id & AC97_EXT_AUDIO_LDAC)) 1186 return 0; 1187 if (target == AC97_REG_PCM_MIC_ADC_RATE) { 1188 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) { 1189 *rate = AC97_SINGLE_RATE; 1190 return 0; 1191 } 1192 } else { 1193 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) { 1194 *rate = AC97_SINGLE_RATE; 1195 return 0; 1196 } 1197 } 1198 if (as->ac97_clock == 0) 1199 as->ac97_clock = AC97_STANDARD_CLOCK; 1200 value = *rate * AC97_STANDARD_CLOCK / as->ac97_clock; 1201 ext_stat = 0; 1202 /* 1203 * PCM_FRONT_DAC_RATE/PCM_SURR_DAC_RATE/PCM_LFE_DAC_RATE 1204 * Check VRA, DRA 1205 * PCM_LR_ADC_RATE 1206 * Check VRA 1207 * PCM_MIC_ADC_RATE 1208 * Check VRM 1209 */ 1210 switch (target) { 1211 case AC97_REG_PCM_FRONT_DAC_RATE: 1212 case AC97_REG_PCM_SURR_DAC_RATE: 1213 case AC97_REG_PCM_LFE_DAC_RATE: 1214 power_bit = AC97_POWER_OUT; 1215 if (as->ext_id & AC97_EXT_AUDIO_DRA) { 1216 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &ext_stat); 1217 if (value > 0x1ffff) { 1218 return EINVAL; 1219 } else if (value > 0xffff) { 1220 /* Enable DRA */ 1221 ext_stat |= AC97_EXT_AUDIO_DRA; 1222 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat); 1223 value /= 2; 1224 } else { 1225 /* Disable DRA */ 1226 ext_stat &= ~AC97_EXT_AUDIO_DRA; 1227 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat); 1228 } 1229 } else { 1230 if (value > 0xffff) 1231 return EINVAL; 1232 } 1233 break; 1234 case AC97_REG_PCM_LR_ADC_RATE: 1235 power_bit = AC97_POWER_IN; 1236 if (value > 0xffff) 1237 return EINVAL; 1238 break; 1239 case AC97_REG_PCM_MIC_ADC_RATE: 1240 power_bit = AC97_POWER_IN; 1241 if (value > 0xffff) 1242 return EINVAL; 1243 break; 1244 default: 1245 printf("%s: Unknown register: 0x%x\n", __func__, target); 1246 return EINVAL; 1247 } 1248 1249 ac97_read(as, AC97_REG_POWER, &power); 1250 ac97_write(as, AC97_REG_POWER, power | power_bit); 1251 1252 ac97_write(as, target, (u_int16_t)value); 1253 ac97_read(as, target, &actual); 1254 actual = (u_int32_t)actual * as->ac97_clock / AC97_STANDARD_CLOCK; 1255 1256 ac97_write(as, AC97_REG_POWER, power); 1257 if (ext_stat & AC97_EXT_AUDIO_DRA) { 1258 *rate = actual * 2; 1259 } else { 1260 *rate = actual; 1261 } 1262 return 0; 1263 } 1264 1265 void 1266 ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock) 1267 { 1268 struct ac97_softc *as; 1269 1270 as = (struct ac97_softc *)codec_if; 1271 as->ac97_clock = clock; 1272 } 1273 1274 u_int16_t 1275 ac97_get_extcaps(struct ac97_codec_if *codec_if) 1276 { 1277 struct ac97_softc *as; 1278 1279 as = (struct ac97_softc *)codec_if; 1280 return as->ext_id; 1281 } 1282 1283 int 1284 ac97_add_port(struct ac97_softc *as, struct ac97_source_info *src) 1285 { 1286 struct ac97_source_info *si; 1287 int ouridx, idx; 1288 1289 if (as->num_source_info >= MAX_SOURCES) { 1290 printf("%s: internal error: increase MAX_SOURCES in %s\n", 1291 __func__, __FILE__); 1292 return -1; 1293 } 1294 if (!ac97_check_capability(as, src->req_feature)) 1295 return -1; 1296 ouridx = as->num_source_info; 1297 si = &as->source_info[ouridx]; 1298 memcpy(si, src, sizeof(*si)); 1299 1300 switch (si->type) { 1301 case AUDIO_MIXER_CLASS: 1302 case AUDIO_MIXER_VALUE: 1303 printf("%s: adding class/value is not supported yet.\n", 1304 __func__); 1305 return -1; 1306 case AUDIO_MIXER_ENUM: 1307 break; 1308 default: 1309 printf("%s: unknown type: %d\n", __func__, si->type); 1310 return -1; 1311 } 1312 as->num_source_info++; 1313 1314 si->mixer_class = ac97_get_portnum_by_name(&as->codec_if, si->class, 1315 NULL, NULL); 1316 /* Find the root of the device */ 1317 idx = ac97_get_portnum_by_name(&as->codec_if, si->class, 1318 si->device, NULL); 1319 /* Find the last item */ 1320 while (as->source_info[idx].next != AUDIO_MIXER_LAST) 1321 idx = as->source_info[idx].next; 1322 /* Append */ 1323 as->source_info[idx].next = ouridx; 1324 si->prev = idx; 1325 si->next = AUDIO_MIXER_LAST; 1326 1327 return 0; 1328 } 1329 1330 int 1331 ac97_get_portnum_by_name(struct ac97_codec_if *codec_if, char *class, 1332 char *device, char *qualifier) 1333 { 1334 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1335 int idx; 1336 1337 for (idx = 0; idx < as->num_source_info; idx++) { 1338 struct ac97_source_info *si = &as->source_info[idx]; 1339 if (ac97_str_equal(class, si->class) && 1340 ac97_str_equal(device, si->device) && 1341 ac97_str_equal(qualifier, si->qualifier)) 1342 return (idx); 1343 } 1344 1345 return (-1); 1346 } 1347 1348 int 1349 ac97_mixer_get_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp) 1350 { 1351 struct ac97_softc *as = (struct ac97_softc *)codec_if; 1352 struct ac97_source_info *si = &as->source_info[cp->dev]; 1353 u_int16_t mask; 1354 u_int16_t val; 1355 1356 if (cp->dev < 0 || cp->dev >= as->num_source_info || 1357 cp->type != si->type) 1358 return (EINVAL); 1359 1360 ac97_read(as, si->reg, &val); 1361 1362 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val)); 1363 1364 mask = (1 << si->bits) - 1; 1365 1366 switch (cp->type) { 1367 case AUDIO_MIXER_ENUM: 1368 cp->un.ord = (val >> si->ofs) & mask; 1369 DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n", val, si->ofs, 1370 mask, cp->un.ord)); 1371 break; 1372 case AUDIO_MIXER_VALUE: 1373 { 1374 const struct audio_mixer_value *value = si->info; 1375 u_int16_t l, r; 1376 1377 if ((cp->un.value.num_channels <= 0) || 1378 (cp->un.value.num_channels > value->num_channels)) 1379 return (EINVAL); 1380 1381 if (value->num_channels == 1) 1382 l = r = (val >> si->ofs) & mask; 1383 else { 1384 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) { 1385 l = (val >> si->ofs) & mask; 1386 r = (val >> (si->ofs + 8)) & mask; 1387 } else { 1388 r = (val >> si->ofs) & mask; 1389 l = (val >> (si->ofs + 8)) & mask; 1390 } 1391 } 1392 1393 l <<= 8 - si->bits; 1394 r <<= 8 - si->bits; 1395 if (!si->polarity) { 1396 l = 255 - l; 1397 r = 255 - r; 1398 } 1399 1400 /* 1401 * The EAP driver averages l and r for stereo 1402 * channels that are requested in MONO mode. Does this 1403 * make sense? 1404 */ 1405 if (cp->un.value.num_channels == 1) { 1406 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l; 1407 } else if (cp->un.value.num_channels == 2) { 1408 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l; 1409 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r; 1410 } 1411 1412 break; 1413 } 1414 default: 1415 return (EINVAL); 1416 } 1417 1418 return (0); 1419 } 1420 1421 1422 /* 1423 * Codec-dependent initialization 1424 */ 1425 1426 void 1427 ac97_ad1885_init(struct ac97_softc *as, int resuming) 1428 { 1429 int i; 1430 1431 if (resuming) 1432 return; 1433 1434 for (i = 0; i < as->num_source_info; i++) { 1435 if (as->source_info[i].reg == AC97_REG_HEADPHONE_VOLUME) 1436 as->source_info[i].reg = AC97_REG_MASTER_VOLUME; 1437 else if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME) 1438 as->source_info[i].reg = AC97_REG_HEADPHONE_VOLUME; 1439 } 1440 } 1441 1442 #define AC97_AD1886_JACK_SENSE 0x72 1443 1444 void 1445 ac97_ad1886_init(struct ac97_softc *as, int resuming) 1446 { 1447 ac97_write(as, AC97_AD1886_JACK_SENSE, 0x0010); 1448 } 1449 1450 void 1451 ac97_ad198x_init(struct ac97_softc *as, int resuming) 1452 { 1453 int i; 1454 u_int16_t misc; 1455 1456 ac97_read(as, AC97_AD_REG_MISC, &misc); 1457 ac97_write(as, AC97_AD_REG_MISC, 1458 misc|AC97_AD_MISC_HPSEL|AC97_AD_MISC_LOSEL); 1459 1460 if (resuming) 1461 return; 1462 1463 for (i = 0; i < as->num_source_info; i++) { 1464 if (as->source_info[i].reg == AC97_REG_SURR_MASTER) 1465 as->source_info[i].reg = AC97_REG_MASTER_VOLUME; 1466 else if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME) 1467 as->source_info[i].reg = AC97_REG_SURR_MASTER; 1468 } 1469 } 1470 1471 void 1472 ac97_alc650_init(struct ac97_softc *as, int resuming) 1473 { 1474 u_int16_t misc; 1475 1476 ac97_read(as, AC97_ALC650_REG_MISC, &misc); 1477 if (as->host_flags & AC97_HOST_ALC650_PIN47_IS_EAPD) 1478 misc &= ~AC97_ALC650_MISC_PIN47; 1479 misc &= ~AC97_ALC650_MISC_VREFDIS; 1480 ac97_write(as, AC97_ALC650_REG_MISC, misc); 1481 1482 if (resuming) 1483 return; 1484 1485 struct ac97_source_info sources[3] = { 1486 { AudioCoutputs, AudioNsurround, "lineinjack", 1487 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1488 AC97_ALC650_REG_MULTI_CHANNEL_CONTROL, 1489 0x0000, 1, 9, 0, 0, CHECK_SURROUND }, 1490 { AudioCoutputs, AudioNcenter, "micjack", 1491 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1492 AC97_ALC650_REG_MULTI_CHANNEL_CONTROL, 1493 0x0000, 1, 10, 0, 0, CHECK_CENTER }, 1494 { AudioCoutputs, AudioNlfe, "micjack", 1495 AUDIO_MIXER_ENUM, WRAP(ac97_on_off), 1496 AC97_ALC650_REG_MULTI_CHANNEL_CONTROL, 1497 0x0000, 1, 10, 0, 0, CHECK_LFE }}; 1498 1499 ac97_add_port(as, &sources[0]); 1500 ac97_add_port(as, &sources[1]); 1501 ac97_add_port(as, &sources[2]); 1502 } 1503 1504 void 1505 ac97_cx20468_init(struct ac97_softc *as, int resuming) 1506 { 1507 u_int16_t misc; 1508 1509 ac97_read(as, AC97_CX_REG_MISC, &misc); 1510 ac97_write(as, AC97_CX_REG_MISC, misc & 1511 ~(AC97_CX_SPDIFEN | AC97_CX_COPYRIGHT | AC97_CX_MASK)); 1512 } 1513 1514 void 1515 ac97_vt1616_init(struct ac97_softc *as, int resuming) 1516 { 1517 u_int16_t reg; 1518 1519 if (as->host_flags & AC97_HOST_VT1616_DYNEX) { 1520 ac97_read(as, AC97_VT_REG_TEST, ®); 1521 1522 /* disable 'hp' mixer controls controlling the surround pins */ 1523 reg &= ~(AC97_VT_LVL); 1524 1525 /* disable downmixing */ 1526 reg &= ~(AC97_VT_LCTF | AC97_VT_STF); 1527 1528 /* enable DC offset removal */ 1529 reg |= AC97_VT_BPDC; 1530 1531 ac97_write(as, AC97_VT_REG_TEST, reg); 1532 } 1533 } 1534