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