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