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