xref: /netbsd-src/sys/dev/ic/ac97.c (revision de1dfb1250df962f1ff3a011772cf58e605aed11)
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@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@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