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