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