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