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