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