xref: /netbsd-src/sys/dev/ic/ac97.c (revision 404fbe5fb94ca1e054339640cabb2801ce52dd30)
1 /*      $NetBSD: ac97.c,v 1.89 2008/12/16 22:35:30 christos 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.89 2008/12/16 22:35:30 christos 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 #include <sys/sysctl.h>
74 
75 #include <sys/audioio.h>
76 #include <dev/audio_if.h>
77 
78 #include <dev/ic/ac97reg.h>
79 #include <dev/ic/ac97var.h>
80 
81 struct ac97_softc;
82 struct ac97_source_info;
83 static int	ac97_mixer_get_port(struct ac97_codec_if *, mixer_ctrl_t *);
84 static int	ac97_mixer_set_port(struct ac97_codec_if *, mixer_ctrl_t *);
85 static void	ac97_detach(struct ac97_codec_if *);
86 static void	ac97_lock(struct ac97_codec_if *);
87 static void	ac97_unlock(struct ac97_codec_if *);
88 static int	ac97_query_devinfo(struct ac97_codec_if *, mixer_devinfo_t *);
89 static int	ac97_get_portnum_by_name(struct ac97_codec_if *, const char *,
90 					 const char *, const char *);
91 static void	ac97_restore_shadow(struct ac97_codec_if *);
92 static int	ac97_set_rate(struct ac97_codec_if *, int, u_int *);
93 static void	ac97_set_clock(struct ac97_codec_if *, unsigned int);
94 static uint16_t ac97_get_extcaps(struct ac97_codec_if *);
95 static int	ac97_add_port(struct ac97_softc *,
96 			      const struct ac97_source_info *);
97 static int	ac97_str_equal(const char *, const char *);
98 static int	ac97_check_capability(struct ac97_softc *, int);
99 static void	ac97_setup_source_info(struct ac97_softc *);
100 static void	ac97_read(struct ac97_softc *, uint8_t, uint16_t *);
101 static void	ac97_setup_defaults(struct ac97_softc *);
102 static int	ac97_write(struct ac97_softc *, uint8_t, uint16_t);
103 
104 static void	ac97_ad198x_init(struct ac97_softc *);
105 static void	ac97_alc650_init(struct ac97_softc *);
106 static void	ac97_vt1616_init(struct ac97_softc *);
107 
108 static int	ac97_modem_offhook_set(struct ac97_softc *, int, int);
109 static int	ac97_sysctl_verify(SYSCTLFN_ARGS);
110 
111 #define Ac97Nphone	"phone"
112 #define Ac97Nline1	"line1"
113 #define Ac97Nline2	"line2"
114 #define Ac97Nhandset	"handset"
115 
116 static const struct audio_mixer_enum
117 ac97_on_off = { 2, { { { AudioNoff, 0 } , 0 },
118 		     { { AudioNon, 0 }  , 1 },
119 		     { { "", 0 }	, 0 },
120 		     { { "", 0 }	, 0 },
121 		     { { "", 0 }	, 0 },
122 		     { { "", 0 }	, 0 },
123 		     { { "", 0 }	, 0 },
124 		     { { "", 0 }	, 0 },
125 		     { { "", 0 }	, 0 },
126 		     { { "", 0 }	, 0 },
127 		     { { "", 0 }	, 0 },
128 		     { { "", 0 }	, 0 },
129 		     { { "", 0 }	, 0 },
130 		     { { "", 0 }	, 0 },
131 		     { { "", 0 }	, 0 },
132 		     { { "", 0 }	, 0 },
133 		     { { "", 0 }	, 0 },
134 		     { { "", 0 }	, 0 },
135 		     { { "", 0 }	, 0 },
136 		     { { "", 0 }	, 0 },
137 		     { { "", 0 }	, 0 },
138 		     { { "", 0 }	, 0 },
139 		     { { "", 0 }	, 0 },
140 		     { { "", 0 }	, 0 },
141 		     { { "", 0 }	, 0 },
142 		     { { "", 0 }	, 0 },
143 		     { { "", 0 }	, 0 },
144 		     { { "", 0 }	, 0 },
145 		     { { "", 0 }	, 0 },
146 		     { { "", 0 }	, 0 },
147 		     { { "", 0 }	, 0 },
148 		     { { "", 0 }	, 0 }, } };
149 
150 static const struct audio_mixer_enum
151 ac97_mic_select = { 2, { { { AudioNmicrophone "0", 0  }, 0 },
152 			 { { AudioNmicrophone "1", 0  }, 1 },
153 			 { { "", 0 }	, 0 },
154 			 { { "", 0 }	, 0 },
155 			 { { "", 0 }	, 0 },
156 			 { { "", 0 }	, 0 },
157 			 { { "", 0 }	, 0 },
158 			 { { "", 0 }	, 0 },
159 			 { { "", 0 }	, 0 },
160 			 { { "", 0 }	, 0 },
161 			 { { "", 0 }	, 0 },
162 			 { { "", 0 }	, 0 },
163 			 { { "", 0 }	, 0 },
164 			 { { "", 0 }	, 0 },
165 			 { { "", 0 }	, 0 },
166 			 { { "", 0 }	, 0 },
167 			 { { "", 0 }	, 0 },
168 			 { { "", 0 }	, 0 },
169 			 { { "", 0 }	, 0 },
170 			 { { "", 0 }	, 0 },
171 			 { { "", 0 }	, 0 },
172 			 { { "", 0 }	, 0 },
173 			 { { "", 0 }	, 0 },
174 			 { { "", 0 }	, 0 },
175 			 { { "", 0 }	, 0 },
176 			 { { "", 0 }	, 0 },
177 			 { { "", 0 }	, 0 },
178 			 { { "", 0 }	, 0 },
179 			 { { "", 0 }	, 0 },
180 			 { { "", 0 }	, 0 },
181 			 { { "", 0 }	, 0 },
182 			 { { "", 0 }	, 0 }, } };
183 
184 static const struct audio_mixer_enum
185 ac97_mono_select = { 2, { { { AudioNmixerout, 0  }, 0 },
186 			  { { AudioNmicrophone, 0  }, 1 },
187 			  { { "", 0 }	, 0 },
188 			  { { "", 0 }	, 0 },
189 			  { { "", 0 }	, 0 },
190 			  { { "", 0 }	, 0 },
191 			  { { "", 0 }	, 0 },
192 			  { { "", 0 }	, 0 },
193 			  { { "", 0 }	, 0 },
194 			  { { "", 0 }	, 0 },
195 			  { { "", 0 }	, 0 },
196 			  { { "", 0 }	, 0 },
197 			  { { "", 0 }	, 0 },
198 			  { { "", 0 }	, 0 },
199 			  { { "", 0 }	, 0 },
200 			  { { "", 0 }	, 0 },
201 			  { { "", 0 }	, 0 },
202 			  { { "", 0 }	, 0 },
203 			  { { "", 0 }	, 0 },
204 			  { { "", 0 }	, 0 },
205 			  { { "", 0 }	, 0 },
206 			  { { "", 0 }	, 0 },
207 			  { { "", 0 }	, 0 },
208 			  { { "", 0 }	, 0 },
209 			  { { "", 0 }	, 0 },
210 			  { { "", 0 }	, 0 },
211 			  { { "", 0 }	, 0 },
212 			  { { "", 0 }	, 0 },
213 			  { { "", 0 }	, 0 },
214 			  { { "", 0 }	, 0 },
215 			  { { "", 0 }	, 0 },
216 			  { { "", 0 }	, 0 }, } };
217 
218 static const struct audio_mixer_enum
219 ac97_source = { 8, { { { AudioNmicrophone, 0  } , 0 },
220 		     { { AudioNcd, 0 }, 1 },
221 		     { { AudioNvideo, 0 }, 2 },
222 		     { { AudioNaux, 0 }, 3 },
223 		     { { AudioNline, 0 }, 4 },
224 		     { { AudioNmixerout, 0 }, 5 },
225 		     { { AudioNmixerout AudioNmono, 0 }, 6 },
226 		     { { Ac97Nphone, 0 }, 7 },
227 		     { { "", 0 }	, 0 },
228 		     { { "", 0 }	, 0 },
229 		     { { "", 0 }	, 0 },
230 		     { { "", 0 }	, 0 },
231 		     { { "", 0 }	, 0 },
232 		     { { "", 0 }	, 0 },
233 		     { { "", 0 }	, 0 },
234 		     { { "", 0 }	, 0 },
235 		     { { "", 0 }	, 0 },
236 		     { { "", 0 }	, 0 },
237 		     { { "", 0 }	, 0 },
238 		     { { "", 0 }	, 0 },
239 		     { { "", 0 }	, 0 },
240 		     { { "", 0 }	, 0 },
241 		     { { "", 0 }	, 0 },
242 		     { { "", 0 }	, 0 },
243 		     { { "", 0 }	, 0 },
244 		     { { "", 0 }	, 0 },
245 		     { { "", 0 }	, 0 },
246 		     { { "", 0 }	, 0 },
247 		     { { "", 0 }	, 0 },
248 		     { { "", 0 }	, 0 },
249 		     { { "", 0 }	, 0 },
250 		     { { "", 0 }	, 0 }, } };
251 
252 /*
253  * Due to different values for each source that uses these structures,
254  * the ac97_query_devinfo function sets delta in mixer_devinfo_t using
255  * ac97_source_info.bits.
256  */
257 static const struct audio_mixer_value
258 ac97_volume_stereo = { { AudioNvolume, 0 }, 2, 0 };
259 
260 static const struct audio_mixer_value
261 ac97_volume_mono = { { AudioNvolume, 0 }, 1, 0 };
262 
263 #define WRAP(a)  &a, sizeof(a)
264 
265 struct ac97_source_info {
266 	const char *class;
267 	const char *device;
268 	const char *qualifier;
269 
270 	int  type;
271 	const void *info;
272 	int  info_size;
273 
274 	uint8_t  reg;
275 	int32_t	 default_value;
276 	unsigned bits:3;
277 	unsigned ofs:4;
278 	unsigned mute:1;
279 	unsigned polarity:1;   /* Does 0 == MAX or MIN */
280 	unsigned checkbits:1;
281 	enum {
282 		CHECK_NONE = 0,
283 		CHECK_SURROUND,
284 		CHECK_CENTER,
285 		CHECK_LFE,
286 		CHECK_HEADPHONES,
287 		CHECK_TONE,
288 		CHECK_MIC,
289 		CHECK_LOUDNESS,
290 		CHECK_3D,
291 		CHECK_LINE1,
292 		CHECK_LINE2,
293 		CHECK_HANDSET,
294 		CHECK_SPDIF
295 	} req_feature;
296 
297 	int  prev;
298 	int  next;
299 	int  mixer_class;
300 };
301 
302 static const struct ac97_source_info audio_source_info[] = {
303 	{ AudioCinputs,		NULL,		NULL,
304 	  AUDIO_MIXER_CLASS,    NULL,		0,
305 	  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
306 	{ AudioCoutputs,	NULL,		0,
307 	  AUDIO_MIXER_CLASS,    NULL,		0,
308 	  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
309 	{ AudioCrecord,		NULL,		0,
310 	  AUDIO_MIXER_CLASS,    NULL,		0,
311 	  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
312 	/* Stereo master volume*/
313 	{ AudioCoutputs,	AudioNmaster,	0,
314 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
315 	  AC97_REG_MASTER_VOLUME, 0x8000, 5, 0, 1, 0, 1, 0, 0, 0, 0,
316 	},
317 	/* Mono volume */
318 	{ AudioCoutputs,	AudioNmono,	NULL,
319 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
320 	  AC97_REG_MASTER_VOLUME_MONO, 0x8000, 6, 0, 1, 0, 1, 0, 0, 0, 0,
321 	},
322 	{ AudioCoutputs,	AudioNmono,	AudioNsource,
323 	  AUDIO_MIXER_ENUM, WRAP(ac97_mono_select),
324 	  AC97_REG_GP, 0x0000, 1, 9, 0, 0, 0, 0, 0, 0, 0,
325 	},
326 	/* Headphone volume */
327 	{ AudioCoutputs,	AudioNheadphone, NULL,
328 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
329 	  AC97_REG_HEADPHONE_VOLUME, 0x8000, 5, 0, 1, 0, 1, CHECK_HEADPHONES, 0, 0, 0,
330 	},
331 	/* Surround volume - logic hard coded for mute */
332 	{ AudioCoutputs,	AudioNsurround,	NULL,
333 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
334 	  AC97_REG_SURR_MASTER, 0x8080, 5, 0, 1, 0, 1, CHECK_SURROUND, 0, 0, 0
335 	},
336 	/* Center volume*/
337 	{ AudioCoutputs,	AudioNcenter,	NULL,
338 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
339 	  AC97_REG_CENTER_LFE_MASTER, 0x8080, 5, 0, 0, 0, 1, CHECK_CENTER, 0, 0, 0
340 	},
341 	{ AudioCoutputs,	AudioNcenter,	AudioNmute,
342 	  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
343 	  AC97_REG_CENTER_LFE_MASTER, 0x8080, 1, 7, 0, 0, 0, CHECK_CENTER, 0, 0, 0
344 	},
345 	/* LFE volume*/
346 	{ AudioCoutputs,	AudioNlfe,	NULL,
347 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
348 	  AC97_REG_CENTER_LFE_MASTER, 0x8080, 5, 8, 0, 0, 1, CHECK_LFE, 0, 0, 0
349 	},
350 	{ AudioCoutputs,	AudioNlfe,	AudioNmute,
351 	  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
352 	  AC97_REG_CENTER_LFE_MASTER, 0x8080, 1, 15, 0, 0, 0, CHECK_LFE, 0, 0, 0
353 	},
354 	/* Tone - bass */
355 	{ AudioCoutputs,	AudioNbass,	NULL,
356 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
357 	  AC97_REG_MASTER_TONE, 0x0f0f, 4, 8, 0, 0, 0, CHECK_TONE, 0, 0, 0
358 	},
359 	/* Tone - treble */
360 	{ AudioCoutputs,	AudioNtreble,	NULL,
361 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
362 	  AC97_REG_MASTER_TONE, 0x0f0f, 4, 0, 0, 0, 0, CHECK_TONE, 0, 0, 0
363 	},
364 	/* PC Beep Volume */
365 	{ AudioCinputs,		AudioNspeaker,	NULL,
366 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
367 	  AC97_REG_PCBEEP_VOLUME, 0x0000, 4, 1, 1, 0, 0, 0, 0, 0, 0,
368 	},
369 
370 	/* Phone */
371 	{ AudioCinputs,		Ac97Nphone,	NULL,
372 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
373 	  AC97_REG_PHONE_VOLUME, 0x8008, 5, 0, 1, 0, 0, 0, 0, 0, 0,
374 	},
375 	/* Mic Volume */
376 	{ AudioCinputs,		AudioNmicrophone, NULL,
377 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
378 	  AC97_REG_MIC_VOLUME, 0x8008, 5, 0, 1, 0, 0, 0, 0, 0, 0,
379 	},
380 	{ AudioCinputs,		AudioNmicrophone, AudioNpreamp,
381 	  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
382 	  AC97_REG_MIC_VOLUME, 0x8008, 1, 6, 0, 0, 0, 0, 0, 0, 0,
383 	},
384 	{ AudioCinputs,		AudioNmicrophone, AudioNsource,
385 	  AUDIO_MIXER_ENUM, WRAP(ac97_mic_select),
386 	  AC97_REG_GP, 0x0000, 1, 8, 0, 0, 0, 0, 0, 0, 0,
387 	},
388 	/* Line in Volume */
389 	{ AudioCinputs,		AudioNline,	NULL,
390 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
391 	  AC97_REG_LINEIN_VOLUME, 0x8808, 5, 0, 1, 0, 0, 0, 0, 0, 0,
392 	},
393 	/* CD Volume */
394 	{ AudioCinputs,		AudioNcd,	NULL,
395 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
396 	  AC97_REG_CD_VOLUME, 0x8808, 5, 0, 1, 0, 0, 0, 0, 0, 0,
397 	},
398 	/* Video Volume */
399 	{ AudioCinputs,		AudioNvideo,	NULL,
400 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
401 	  AC97_REG_VIDEO_VOLUME, 0x8808, 5, 0, 1, 0, 0, 0, 0, 0, 0,
402 	},
403 	/* AUX volume */
404 	{ AudioCinputs,		AudioNaux,	NULL,
405 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
406 	  AC97_REG_AUX_VOLUME, 0x8808, 5, 0, 1, 0, 0, 0, 0, 0, 0,
407 	},
408 	/* PCM out volume */
409 	{ AudioCinputs,		AudioNdac,	NULL,
410 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
411 	  AC97_REG_PCMOUT_VOLUME, 0x8808, 5, 0, 1, 0, 0, 0, 0, 0, 0,
412 	},
413 	/* Record Source - some logic for this is hard coded - see below */
414 	{ AudioCrecord,		AudioNsource,	NULL,
415 	  AUDIO_MIXER_ENUM, WRAP(ac97_source),
416 	  AC97_REG_RECORD_SELECT, 0x0000, 3, 0, 0, 0, 0, 0, 0, 0, 0,
417 	},
418 	/* Record Gain */
419 	{ AudioCrecord,		AudioNvolume,	NULL,
420 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
421 	  AC97_REG_RECORD_GAIN, 0x8000, 4, 0, 1, 1, 0, 0, 0, 0, 0,
422 	},
423 	/* Record Gain mic */
424 	{ AudioCrecord,		AudioNmicrophone, NULL,
425 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
426 	  AC97_REG_RECORD_GAIN_MIC, 0x8000, 4, 0, 1, 1, 0, CHECK_MIC, 0, 0, 0
427 	},
428 	/* */
429 	{ AudioCoutputs,	AudioNloudness,	NULL,
430 	  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
431 	  AC97_REG_GP, 0x0000, 1, 12, 0, 0, 0, CHECK_LOUDNESS, 0, 0, 0
432 	},
433 	{ AudioCoutputs,	AudioNspatial,	NULL,
434 	  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
435 	  AC97_REG_GP, 0x0000, 1, 13, 0, 1, 0, CHECK_3D, 0, 0, 0
436 	},
437 	{ AudioCoutputs,	AudioNspatial,	"center",
438 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
439 	  AC97_REG_3D_CONTROL, 0x0000, 4, 8, 0, 1, 0, CHECK_3D, 0, 0, 0
440 	},
441 	{ AudioCoutputs,	AudioNspatial,	"depth",
442 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
443 	  AC97_REG_3D_CONTROL, 0x0000, 4, 0, 0, 1, 0, CHECK_3D, 0, 0, 0
444 	},
445 
446 	/* SPDIF */
447 	{ "spdif", NULL, NULL,
448 	  AUDIO_MIXER_CLASS, NULL, 0,
449 	  0, 0, 0, 0, 0, 0, 0, CHECK_SPDIF, 0, 0, 0
450 	},
451 	{ "spdif", "enable", NULL,
452 	  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
453 	  AC97_REG_EXT_AUDIO_CTRL, -1, 1, 2, 0, 0, 0, CHECK_SPDIF, 0, 0, 0
454 	},
455 
456 	/* Missing features: Simulated Stereo, POP, Loopback mode */
457 };
458 
459 static const struct ac97_source_info modem_source_info[] = {
460 	/* Classes */
461 	{ AudioCinputs,		NULL,		NULL,
462 	  AUDIO_MIXER_CLASS,    NULL,		0,
463 	  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
464 	{ AudioCoutputs,	NULL,		NULL,
465 	  AUDIO_MIXER_CLASS,    NULL,		0,
466 	  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
467 	{ AudioCinputs,		Ac97Nline1,	NULL,
468 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
469 	  AC97_REG_LINE1_LEVEL, 0x8080, 4, 0, 0, 1, 0, CHECK_LINE1, 0, 0, 0
470 	},
471 	{ AudioCoutputs,	Ac97Nline1,	NULL,
472 	  AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
473 	  AC97_REG_LINE1_LEVEL, 0x8080, 4, 8, 0, 1, 0, CHECK_LINE1, 0, 0, 0
474 	},
475 	{ AudioCinputs,		Ac97Nline1,	AudioNmute,
476 	  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
477 	  AC97_REG_LINE1_LEVEL, 0x8080, 1, 7, 0, 0, 0, CHECK_LINE1, 0, 0, 0
478 	},
479 	{ AudioCoutputs,	Ac97Nline1,	AudioNmute,
480 	  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
481 	  AC97_REG_LINE1_LEVEL, 0x8080, 1, 15, 0, 0, 0, CHECK_LINE1, 0, 0, 0
482 	},
483 };
484 
485 #define AUDIO_SOURCE_INFO_SIZE \
486 		(sizeof(audio_source_info)/sizeof(audio_source_info[0]))
487 #define MODEM_SOURCE_INFO_SIZE \
488 		(sizeof(modem_source_info)/sizeof(modem_source_info[0]))
489 #define SOURCE_INFO_SIZE(as) ((as)->type == AC97_CODEC_TYPE_MODEM ? \
490 		MODEM_SOURCE_INFO_SIZE : AUDIO_SOURCE_INFO_SIZE)
491 
492 /*
493  * Check out http://www.intel.com/support/motherboards/desktop/sb/cs-025406.htm for
494  * AC'97 Component Specification
495  */
496 
497 struct ac97_softc {
498 	/* ac97_codec_if must be at the first of ac97_softc. */
499 	struct ac97_codec_if codec_if;
500 
501 	struct ac97_host_if *host_if;
502 
503 #define AUDIO_MAX_SOURCES	(2 * AUDIO_SOURCE_INFO_SIZE)
504 #define MODEM_MAX_SOURCES	(2 * MODEM_SOURCE_INFO_SIZE)
505 	struct ac97_source_info audio_source_info[AUDIO_MAX_SOURCES];
506 	struct ac97_source_info modem_source_info[MODEM_MAX_SOURCES];
507 	struct ac97_source_info *source_info;
508 	int num_source_info;
509 
510 	enum ac97_host_flags host_flags;
511 	unsigned int ac97_clock; /* usually 48000 */
512 #define AC97_STANDARD_CLOCK	48000U
513 	uint16_t power_all;
514 	uint16_t power_reg;	/* -> AC97_REG_POWER */
515 	uint16_t caps;		/* -> AC97_REG_RESET */
516 	uint16_t ext_id;	/* -> AC97_REG_EXT_AUDIO_ID */
517 	uint16_t ext_mid;	/* -> AC97_REG_EXT_MODEM_ID */
518 	uint16_t shadow_reg[128];
519 
520 	int lock_counter;
521 	int type;
522 
523 	/* sysctl */
524 	struct sysctllog *log;
525 	int offhook_line1_mib;
526 	int offhook_line2_mib;
527 	int offhook_line1;
528 	int offhook_line2;
529 };
530 
531 static struct ac97_codec_if_vtbl ac97civ = {
532 	ac97_mixer_get_port,
533 	ac97_mixer_set_port,
534 	ac97_query_devinfo,
535 	ac97_get_portnum_by_name,
536 	ac97_restore_shadow,
537 	ac97_get_extcaps,
538 	ac97_set_rate,
539 	ac97_set_clock,
540 	ac97_detach,
541 	ac97_lock,
542 	ac97_unlock,
543 };
544 
545 static const struct ac97_codecid {
546 	uint32_t id;
547 	uint32_t mask;
548 	const char *name;
549 	void (*init)(struct ac97_softc *);
550 } ac97codecid[] = {
551 	/*
552 	 * Analog Devices SoundMAX
553 	 * http://www.soundmax.com/products/information/codecs.html
554 	 * http://www.analog.com/productSelection/pdf/AD1881A_0.pdf
555 	 * http://www.analog.com/productSelection/pdf/AD1885_0.pdf
556 	 * http://www.analog.com/UploadedFiles/Data_Sheets/206585810AD1980_0.pdf
557 	 * http://www.analog.com/productSelection/pdf/AD1981A_0.pdf
558 	 * http://www.analog.com/productSelection/pdf/AD1981B_0.pdf
559 	 * http://www.analog.com/UploadedFiles/Data_Sheets/180644528AD1985_0.pdf
560 	 */
561 	{ AC97_CODEC_ID('A', 'D', 'S', 3),
562 	  0xffffffff,			"Analog Devices AD1819B", NULL, },
563 	{ AC97_CODEC_ID('A', 'D', 'S', 0x40),
564 	  0xffffffff,			"Analog Devices AD1881", NULL, },
565 	{ AC97_CODEC_ID('A', 'D', 'S', 0x48),
566 	  0xffffffff,			"Analog Devices AD1881A", NULL, },
567 	{ AC97_CODEC_ID('A', 'D', 'S', 0x60),
568 	  0xffffffff,			"Analog Devices AD1885", NULL, },
569 	{ AC97_CODEC_ID('A', 'D', 'S', 0x61),
570 	  0xffffffff,			"Analog Devices AD1886", NULL, },
571 	{ AC97_CODEC_ID('A', 'D', 'S', 0x63),
572 	  0xffffffff,			"Analog Devices AD1886A", NULL, },
573 	{ AC97_CODEC_ID('A', 'D', 'S', 0x68),
574 	  0xffffffff,			"Analog Devices AD1888", ac97_ad198x_init },
575 	{ AC97_CODEC_ID('A', 'D', 'S', 0x70),
576 	  0xffffffff,			"Analog Devices AD1980", ac97_ad198x_init },
577 	{ AC97_CODEC_ID('A', 'D', 'S', 0x72),
578 	  0xffffffff,			"Analog Devices AD1981A", NULL, },
579 	{ AC97_CODEC_ID('A', 'D', 'S', 0x74),
580 	  0xffffffff,			"Analog Devices AD1981B", NULL, },
581 	{ AC97_CODEC_ID('A', 'D', 'S', 0x75),
582 	  0xffffffff,			"Analog Devices AD1985", ac97_ad198x_init },
583 	{ AC97_CODEC_ID('A', 'D', 'S', 0),
584 	  AC97_VENDOR_ID_MASK,		"Analog Devices unknown", NULL, },
585 
586 	/*
587 	 * Datasheets:
588 	 *	http://www.asahi-kasei.co.jp/akm/japanese/product/ak4543/ek4543.pdf
589 	 *	http://www.asahi-kasei.co.jp/akm/japanese/product/ak4544a/ek4544a.pdf
590 	 *	http://www.asahi-kasei.co.jp/akm/japanese/product/ak4545/ak4545_f00e.pdf
591 	 */
592 	{ AC97_CODEC_ID('A', 'K', 'M', 0),
593 	  0xffffffff,			"Asahi Kasei AK4540", NULL,	},
594 	{ AC97_CODEC_ID('A', 'K', 'M', 1),
595 	  0xffffffff,			"Asahi Kasei AK4542", NULL,	},
596 	{ AC97_CODEC_ID('A', 'K', 'M', 2),
597 	  0xffffffff,			"Asahi Kasei AK4541/AK4543", NULL, },
598 	{ AC97_CODEC_ID('A', 'K', 'M', 5),
599 	  0xffffffff,			"Asahi Kasei AK4544", NULL, },
600 	{ AC97_CODEC_ID('A', 'K', 'M', 6),
601 	  0xffffffff,			"Asahi Kasei AK4544A", NULL, },
602 	{ AC97_CODEC_ID('A', 'K', 'M', 7),
603 	  0xffffffff,			"Asahi Kasei AK4545", NULL, },
604 	{ AC97_CODEC_ID('A', 'K', 'M', 0),
605 	  AC97_VENDOR_ID_MASK,		"Asahi Kasei unknown", NULL, },
606 
607 	/*
608 	 * Realtek & Avance Logic
609 	 *	http://www.realtek.com.tw/downloads/downloads1-3.aspx?lineid=5&famid=All&series=All&Spec=True
610 	 *
611 	 * ALC650 and ALC658 support VRA, but it supports only 8000, 11025,
612 	 * 12000, 16000, 22050, 24000, 32000, 44100, and 48000 Hz.
613 	 */
614 	{ AC97_CODEC_ID('A', 'L', 'C', 0x00),
615 	  0xfffffff0,			"Realtek RL5306", NULL,	},
616 	{ AC97_CODEC_ID('A', 'L', 'C', 0x10),
617 	  0xfffffff0,			"Realtek RL5382", NULL,	},
618 	{ AC97_CODEC_ID('A', 'L', 'C', 0x20),
619 	  0xfffffff0,			"Realtek RL5383/RL5522/ALC100", NULL,	},
620 	{ AC97_CODEC_ID('A', 'L', 'G', 0x10),
621 	  0xffffffff,			"Avance Logic ALC200/ALC201", NULL,	},
622 	{ AC97_CODEC_ID('A', 'L', 'G', 0x20),
623 	  0xfffffff0,			"Avance Logic ALC650", ac97_alc650_init },
624 	{ AC97_CODEC_ID('A', 'L', 'G', 0x30),
625 	  0xffffffff,			"Avance Logic ALC101", NULL,	},
626 	{ AC97_CODEC_ID('A', 'L', 'G', 0x40),
627 	  0xffffffff,			"Avance Logic ALC202", NULL,	},
628 	{ AC97_CODEC_ID('A', 'L', 'G', 0x50),
629 	  0xffffffff,			"Avance Logic ALC250", NULL,	},
630 	{ AC97_CODEC_ID('A', 'L', 'G', 0x60),
631 	  0xfffffff0,			"Avance Logic ALC655", NULL,	},
632 	{ AC97_CODEC_ID('A', 'L', 'G', 0x80),
633 	  0xfffffff0,			"Avance Logic ALC658", NULL,	},
634 	{ AC97_CODEC_ID('A', 'L', 'G', 0x90),
635 	  0xfffffff0,			"Avance Logic ALC850", NULL,	},
636 	{ AC97_CODEC_ID('A', 'L', 'C', 0),
637 	  AC97_VENDOR_ID_MASK,		"Realtek unknown", NULL,	},
638 	{ AC97_CODEC_ID('A', 'L', 'G', 0),
639 	  AC97_VENDOR_ID_MASK,		"Avance Logic unknown", NULL,	},
640 
641 	/**
642 	 * C-Media Electronics Inc.
643 	 * http://www.cmedia.com.tw/doc/CMI9739%206CH%20Audio%20Codec%20SPEC_Ver12.pdf
644 	 */
645 	{ AC97_CODEC_ID('C', 'M', 'I', 0x61),
646 	  0xffffffff,			"C-Media CMI9739", NULL,	},
647 	{ AC97_CODEC_ID('C', 'M', 'I', 0),
648 	  AC97_VENDOR_ID_MASK,		"C-Media unknown", NULL,	},
649 
650 	/* Cirrus Logic, Crystal series:
651 	 *  'C' 'R' 'Y' 0x0[0-7]  - CS4297
652 	 *              0x1[0-7]  - CS4297A
653 	 *              0x2[0-7]  - CS4298
654 	 *              0x2[8-f]  - CS4294
655 	 *              0x3[0-7]  - CS4299
656 	 *              0x4[8-f]  - CS4201
657 	 *              0x5[8-f]  - CS4205
658 	 *              0x6[0-7]  - CS4291
659 	 *              0x7[0-7]  - CS4202
660 	 * Datasheets:
661 	 *	http://www.cirrus.com/pubs/cs4297A-5.pdf?DocumentID=593
662 	 *	http://www.cirrus.com/pubs/cs4294.pdf?DocumentID=32
663 	 *	http://www.cirrus.com/pubs/cs4299-5.pdf?DocumentID=594
664 	 *	http://www.cirrus.com/pubs/cs4201-2.pdf?DocumentID=492
665 	 *	http://www.cirrus.com/pubs/cs4205-2.pdf?DocumentID=492
666 	 *	http://www.cirrus.com/pubs/cs4202-1.pdf?DocumentID=852
667 	 */
668 	{ AC97_CODEC_ID('C', 'R', 'Y', 0x00),
669 	  0xfffffff8,			"Crystal CS4297", NULL,	},
670 	{ AC97_CODEC_ID('C', 'R', 'Y', 0x10),
671 	  0xfffffff8,			"Crystal CS4297A", NULL,	},
672 	{ AC97_CODEC_ID('C', 'R', 'Y', 0x20),
673 	  0xfffffff8,			"Crystal CS4298", NULL,	},
674 	{ AC97_CODEC_ID('C', 'R', 'Y', 0x28),
675 	  0xfffffff8,			"Crystal CS4294", NULL,	},
676 	{ AC97_CODEC_ID('C', 'R', 'Y', 0x30),
677 	  0xfffffff8,			"Crystal CS4299", NULL,	},
678 	{ AC97_CODEC_ID('C', 'R', 'Y', 0x48),
679 	  0xfffffff8,			"Crystal CS4201", NULL,	},
680 	{ AC97_CODEC_ID('C', 'R', 'Y', 0x58),
681 	  0xfffffff8,			"Crystal CS4205", NULL,	},
682 	{ AC97_CODEC_ID('C', 'R', 'Y', 0x60),
683 	  0xfffffff8,			"Crystal CS4291", NULL,	},
684 	{ AC97_CODEC_ID('C', 'R', 'Y', 0x70),
685 	  0xfffffff8,			"Crystal CS4202", NULL,	},
686 	{ AC97_CODEC_ID('C', 'R', 'Y', 0),
687 	  AC97_VENDOR_ID_MASK,		"Cirrus Logic unknown", NULL,	},
688 
689 	{ 0x45838308, 0xffffffff,	"ESS Technology ES1921", NULL, },
690 	{ 0x45838300, AC97_VENDOR_ID_MASK, "ESS Technology unknown", NULL, },
691 
692 	{ AC97_CODEC_ID('H', 'R', 'S', 0),
693 	  0xffffffff,			"Intersil HMP9701", NULL,	},
694 	{ AC97_CODEC_ID('H', 'R', 'S', 0),
695 	  AC97_VENDOR_ID_MASK,		"Intersil unknown", NULL,	},
696 
697 	/*
698 	 * IC Ensemble (VIA)
699 	 *	http://www.viatech.com/en/datasheet/DS1616.pdf
700 	 */
701 	{ AC97_CODEC_ID('I', 'C', 'E', 0x01),
702 	  0xffffffff,			"ICEnsemble ICE1230/VT1611", NULL,	},
703 	{ AC97_CODEC_ID('I', 'C', 'E', 0x11),
704 	  0xffffffff,			"ICEnsemble ICE1232/VT1611A", NULL,	},
705 	{ AC97_CODEC_ID('I', 'C', 'E', 0x14),
706 	  0xffffffff,			"ICEnsemble ICE1232A", NULL,	},
707 	{ AC97_CODEC_ID('I', 'C', 'E', 0x51),
708 	  0xffffffff,			"VIA Technologies VT1616", ac97_vt1616_init },
709 	{ AC97_CODEC_ID('I', 'C', 'E', 0x52),
710 	  0xffffffff,			"VIA Technologies VT1616i", ac97_vt1616_init },
711 	{ AC97_CODEC_ID('I', 'C', 'E', 0),
712 	  AC97_VENDOR_ID_MASK,		"ICEnsemble/VIA unknown", NULL,	},
713 
714 	{ AC97_CODEC_ID('N', 'S', 'C', 0),
715 	  0xffffffff,			"National Semiconductor LM454[03568]", NULL, },
716 	{ AC97_CODEC_ID('N', 'S', 'C', 49),
717 	  0xffffffff,			"National Semiconductor LM4549", NULL, },
718 	{ AC97_CODEC_ID('N', 'S', 'C', 0),
719 	  AC97_VENDOR_ID_MASK,		"National Semiconductor unknown", NULL, },
720 
721 	{ AC97_CODEC_ID('P', 'S', 'C', 4),
722 	  0xffffffff,			"Philips Semiconductor UCB1400", NULL, },
723 	{ AC97_CODEC_ID('P', 'S', 'C', 0),
724 	  AC97_VENDOR_ID_MASK,		"Philips Semiconductor unknown", NULL, },
725 
726 	{ AC97_CODEC_ID('S', 'I', 'L', 34),
727 	  0xffffffff,			"Silicon Laboratory Si3036", NULL, },
728 	{ AC97_CODEC_ID('S', 'I', 'L', 35),
729 	  0xffffffff,			"Silicon Laboratory Si3038", NULL, },
730 	{ AC97_CODEC_ID('S', 'I', 'L', 0),
731 	  AC97_VENDOR_ID_MASK,		"Silicon Laboratory unknown", NULL, },
732 
733 	{ AC97_CODEC_ID('T', 'R', 'A', 2),
734 	  0xffffffff,			"TriTech TR28022", NULL,	},
735 	{ AC97_CODEC_ID('T', 'R', 'A', 3),
736 	  0xffffffff,			"TriTech TR28023", NULL,	},
737 	{ AC97_CODEC_ID('T', 'R', 'A', 6),
738 	  0xffffffff,			"TriTech TR28026", NULL,	},
739 	{ AC97_CODEC_ID('T', 'R', 'A', 8),
740 	  0xffffffff,			"TriTech TR28028", NULL,	},
741 	{ AC97_CODEC_ID('T', 'R', 'A', 35),
742 	  0xffffffff,			"TriTech TR28602", NULL,	},
743 	{ AC97_CODEC_ID('T', 'R', 'A', 0),
744 	  AC97_VENDOR_ID_MASK,		"TriTech unknown", NULL,	},
745 
746 	{ AC97_CODEC_ID('T', 'X', 'N', 0x20),
747 	  0xffffffff,			"Texas Instruments TLC320AD9xC", NULL, },
748 	{ AC97_CODEC_ID('T', 'X', 'N', 0),
749 	  AC97_VENDOR_ID_MASK,		"Texas Instruments unknown", NULL, },
750 
751 	/*
752 	 * VIA
753 	 * http://www.viatech.com/en/multimedia/audio.jsp
754 	 */
755 	{ AC97_CODEC_ID('V', 'I', 'A', 0x61),
756 	  0xffffffff,			"VIA Technologies VT1612A", NULL, },
757 	{ AC97_CODEC_ID('V', 'I', 'A', 0),
758 	  AC97_VENDOR_ID_MASK,		"VIA Technologies unknown", NULL, },
759 
760 	{ AC97_CODEC_ID('W', 'E', 'C', 1),
761 	  0xffffffff,			"Winbond W83971D", NULL,	},
762 	{ AC97_CODEC_ID('W', 'E', 'C', 0),
763 	  AC97_VENDOR_ID_MASK,		"Winbond unknown", NULL,	},
764 
765 	/*
766 	 * http://www.wolfsonmicro.com/product_list.asp?cid=64
767 	 *	http://www.wolfsonmicro.com/download.asp/did.56/WM9701A.pdf - 00
768 	 *	http://www.wolfsonmicro.com/download.asp/did.57/WM9703.pdf  - 03
769 	 *	http://www.wolfsonmicro.com/download.asp/did.58/WM9704M.pdf - 04
770 	 *	http://www.wolfsonmicro.com/download.asp/did.59/WM9704Q.pdf - 04
771 	 *	http://www.wolfsonmicro.com/download.asp/did.184/WM9705_Rev34.pdf - 05
772 	 *	http://www.wolfsonmicro.com/download.asp/did.60/WM9707.pdf  - 03
773 	 *	http://www.wolfsonmicro.com/download.asp/did.136/WM9708.pdf - 03
774 	 *	http://www.wolfsonmicro.com/download.asp/did.243/WM9710.pdf - 05
775 	 */
776 	{ AC97_CODEC_ID('W', 'M', 'L', 0),
777 	  0xffffffff,			"Wolfson WM9701A", NULL,	},
778 	{ AC97_CODEC_ID('W', 'M', 'L', 3),
779 	  0xffffffff,			"Wolfson WM9703/WM9707/WM9708", NULL,	},
780 	{ AC97_CODEC_ID('W', 'M', 'L', 4),
781 	  0xffffffff,			"Wolfson WM9704", NULL,	},
782 	{ AC97_CODEC_ID('W', 'M', 'L', 5),
783 	  0xffffffff,			"Wolfson WM9705/WM9710", NULL, },
784 	{ AC97_CODEC_ID('W', 'M', 'L', 0),
785 	  AC97_VENDOR_ID_MASK,		"Wolfson unknown", NULL,	},
786 
787 	/*
788 	 * http://www.yamaha.co.jp/english/product/lsi/us/products/pcaudio.html
789 	 * Datasheets:
790 	 *	http://www.yamaha.co.jp/english/product/lsi/us/products/pdf/4MF743A20.pdf
791 	 *	http://www.yamaha.co.jp/english/product/lsi/us/products/pdf/4MF753A20.pdf
792 	 */
793 	{ AC97_CODEC_ID('Y', 'M', 'H', 0),
794 	  0xffffffff,			"Yamaha YMF743-S", NULL,	},
795 	{ AC97_CODEC_ID('Y', 'M', 'H', 3),
796 	  0xffffffff,			"Yamaha YMF753-S", NULL,	},
797 	{ AC97_CODEC_ID('Y', 'M', 'H', 0),
798 	  AC97_VENDOR_ID_MASK,		"Yamaha unknown", NULL,	},
799 
800 	/*
801 	 * http://www.sigmatel.com/products/technical_docs.htm
802 	 * and
803 	 * http://www.sigmatel.com/documents/c-major-brochure-9-0.pdf
804 	 */
805 	{ 0x83847600, 0xffffffff,	"SigmaTel STAC9700",	NULL, },
806 	{ 0x83847604, 0xffffffff,	"SigmaTel STAC9701/3/4/5", NULL, },
807 	{ 0x83847605, 0xffffffff,	"SigmaTel STAC9704",	NULL, },
808 	{ 0x83847608, 0xffffffff,	"SigmaTel STAC9708",	NULL, },
809 	{ 0x83847609, 0xffffffff,	"SigmaTel STAC9721/23",	NULL, },
810 	{ 0x83847644, 0xffffffff,	"SigmaTel STAC9744/45",	NULL, },
811 	{ 0x83847650, 0xffffffff,	"SigmaTel STAC9750/51",	NULL, },
812 	{ 0x83847652, 0xffffffff,	"SigmaTel STAC9752/53",	NULL, },
813 	{ 0x83847656, 0xffffffff,	"SigmaTel STAC9756/57",	NULL, },
814 	{ 0x83847658, 0xffffffff,	"SigmaTel STAC9758/59",	NULL, },
815 	{ 0x83847666, 0xffffffff,	"SigmaTel STAC9766/67",	NULL, },
816 	{ 0x83847684, 0xffffffff,	"SigmaTel STAC9783/84",	NULL, },
817 	{ 0x83847600, AC97_VENDOR_ID_MASK, "SigmaTel unknown",	NULL, },
818 
819 	/* Conexant AC'97 modems -- good luck finding datasheets! */
820 	{ AC97_CODEC_ID('C', 'X', 'T', 33),
821 	  0xffffffff,			"Conexant HSD11246", NULL, },
822 	{ AC97_CODEC_ID('C', 'X', 'T', 34),
823 	  0xffffffff,			"Conexant D480 MDC V.92 Modem", NULL, },
824 	{ AC97_CODEC_ID('C', 'X', 'T', 48),
825 	  0xffffffff,			"Conexant CXT48", NULL, },
826 	{ AC97_CODEC_ID('C', 'X', 'T', 0),
827 	  AC97_VENDOR_ID_MASK,		"Conexant unknown", NULL, },
828 
829 	{ 0,
830 	  0,			NULL,	NULL, 		},
831 };
832 
833 static const char * const ac97enhancement[] = {
834 	"no 3D stereo",
835 	"Analog Devices Phat Stereo",
836 	"Creative",
837 	"National Semi 3D",
838 	"Yamaha Ymersion",
839 	"BBE 3D",
840 	"Crystal Semi 3D",
841 	"Qsound QXpander",
842 	"Spatializer 3D",
843 	"SRS 3D",
844 	"Platform Tech 3D",
845 	"AKM 3D",
846 	"Aureal",
847 	"AZTECH 3D",
848 	"Binaura 3D",
849 	"ESS Technology",
850 	"Harman International VMAx",
851 	"Nvidea 3D",
852 	"Philips Incredible Sound",
853 	"Texas Instruments' 3D",
854 	"VLSI Technology 3D",
855 	"TriTech 3D",
856 	"Realtek 3D",
857 	"Samsung 3D",
858 	"Wolfson Microelectronics 3D",
859 	"Delta Integration 3D",
860 	"SigmaTel 3D",
861 	"KS Waves 3D",
862 	"Rockwell 3D",
863 	"Unknown 3D",
864 	"Unknown 3D",
865 	"Unknown 3D",
866 };
867 
868 static const char * const ac97feature[] = {
869 	"dedicated mic channel",
870 	"reserved",
871 	"tone",
872 	"simulated stereo",
873 	"headphone",
874 	"bass boost",
875 	"18 bit DAC",
876 	"20 bit DAC",
877 	"18 bit ADC",
878 	"20 bit ADC"
879 };
880 
881 
882 /* #define AC97_DEBUG 10 */
883 /* #define AC97_IO_DEBUG */
884 
885 #ifdef AUDIO_DEBUG
886 #define DPRINTF(x)	if (ac97debug) printf x
887 #define DPRINTFN(n,x)	if (ac97debug>(n)) printf x
888 #ifdef AC97_DEBUG
889 int	ac97debug = AC97_DEBUG;
890 #else
891 int	ac97debug = 0;
892 #endif
893 #else
894 #define DPRINTF(x)
895 #define DPRINTFN(n,x)
896 #endif
897 
898 #ifdef AC97_IO_DEBUG
899 static const char *ac97_register_names[0x80 / 2] = {
900 	"RESET", "MASTER_VOLUME", "HEADPHONE_VOLUME", "MASTER_VOLUME_MONO",
901 	"MASTER_TONE", "PCBEEP_VOLUME", "PHONE_VOLUME", "MIC_VOLUME",
902 	"LINEIN_VOLUME", "CD_VOLUME", "VIDEO_VOLUME", "AUX_VOLUME",
903 	"PCMOUT_VOLUME", "RECORD_SELECT", "RECORD_GATIN", "RECORD_GAIN_MIC",
904 	"GP", "3D_CONTROL", "AUDIO_INT", "POWER",
905 	"EXT_AUDIO_ID", "EXT_AUDIO_CTRL", "PCM_FRONT_DAC_RATE", "PCM_SURR_DAC_RATE",
906 	"PCM_LFE_DAC_RATE", "PCM_LR_ADC_RATE", "PCM_MIC_ADC_RATE", "CENTER_LFE_MASTER",
907 	"SURR_MASTER", "SPDIF_CTRL", "EXT_MODEM_ID", "EXT_MODEM_CTRL",
908 	"LINE1_RATE", "LINE2_RATE", "HANDSET_RATE", "LINE1_LEVEL",
909 	"LINE2_LEVEL", "HANDSET_LEVEL", "GPIO_PIN_CONFIG", "GPIO_PIN_POLARITY",
910 	"GPIO_PIN_STICKY", "GPIO_PIN_WAKEUP", "GPIO_PIN_STATUS", "MISC_MODEM_CTRL",
911 	"0x58", "VENDOR-5A", "VENDOR-5C", "VENDOR-5E",
912 	"0x60", "0x62", "0x64", "0x66",
913 	"0x68", "0x6a", "0x6c", "0x6e",
914 	"VENDOR-70", "VENDOR-72", "VENDOR-74", "VENDOR-76",
915 	"VENDOR-78", "VENDOR-7A", "VENDOR_ID1", "VENDOR_ID2"
916 };
917 #endif
918 
919 /*
920  * XXX Some cards have an inverted AC97_POWER_EAMP bit.
921  * These cards will produce no sound unless AC97_HOST_INVERTED_EAMP is set.
922  */
923 
924 #define POWER_EAMP_ON(as)  ((as->host_flags & AC97_HOST_INVERTED_EAMP) \
925 			    ? AC97_POWER_EAMP : 0)
926 #define POWER_EAMP_OFF(as) ((as->host_flags & AC97_HOST_INVERTED_EAMP) \
927 			    ? 0 : AC97_POWER_EAMP)
928 
929 static void
930 ac97_read(struct ac97_softc *as, uint8_t reg, uint16_t *val)
931 {
932 	if (as->host_flags & AC97_HOST_DONT_READ &&
933 	    (reg != AC97_REG_VENDOR_ID1 && reg != AC97_REG_VENDOR_ID2 &&
934 	     reg != AC97_REG_RESET)) {
935 		*val = as->shadow_reg[reg >> 1];
936 		return;
937 	}
938 
939 	if (as->host_if->read(as->host_if->arg, reg, val)) {
940 		*val = as->shadow_reg[reg >> 1];
941 	}
942 }
943 
944 static int
945 ac97_write(struct ac97_softc *as, uint8_t reg, uint16_t val)
946 {
947 #ifndef AC97_IO_DEBUG
948 	as->shadow_reg[reg >> 1] = val;
949 	return as->host_if->write(as->host_if->arg, reg, val);
950 #else
951 	int ret;
952 	uint16_t actual;
953 
954 	as->shadow_reg[reg >> 1] = val;
955 	ret = as->host_if->write(as->host_if->arg, reg, val);
956 	as->host_if->read(as->host_if->arg, reg, &actual);
957 	if (val != actual && reg < 0x80) {
958 		printf("ac97_write: reg=%s, written=0x%04x, read=0x%04x\n",
959 		       ac97_register_names[reg / 2], val, actual);
960 	}
961 	return ret;
962 #endif
963 }
964 
965 static void
966 ac97_setup_defaults(struct ac97_softc *as)
967 {
968 	int idx;
969 	const struct ac97_source_info *si;
970 
971 	memset(as->shadow_reg, 0, sizeof(as->shadow_reg));
972 
973 	for (idx = 0; idx < AUDIO_SOURCE_INFO_SIZE; idx++) {
974 		si = &audio_source_info[idx];
975 		if (si->default_value >= 0)
976 			ac97_write(as, si->reg, si->default_value);
977 	}
978 	for (idx = 0; idx < MODEM_SOURCE_INFO_SIZE; idx++) {
979 		si = &modem_source_info[idx];
980 		if (si->default_value >= 0)
981 			ac97_write(as, si->reg, si->default_value);
982 	}
983 }
984 
985 static void
986 ac97_restore_shadow(struct ac97_codec_if *self)
987 {
988 	struct ac97_softc *as;
989 	const struct ac97_source_info *si;
990 	int idx;
991 	uint16_t val;
992 
993 	as = (struct ac97_softc *) self;
994 
995 	if (as->type == AC97_CODEC_TYPE_AUDIO) {
996 		/* restore AC97_REG_POWER */
997 		ac97_write(as, AC97_REG_POWER, as->power_reg);
998 		/* make sure chip is fully operational */
999 		for (idx = 50000; idx >= 0; idx--) {
1000 			ac97_read(as, AC97_REG_POWER, &val);
1001 			if ((val & as->power_all) == as->power_all)
1002 				break;
1003 			DELAY(10);
1004 		}
1005 
1006 		/*
1007 		 * actually try changing a value!
1008 		 * The default value of AC97_REG_MASTER_VOLUME is 0x8000.
1009 		 */
1010 		for (idx = 50000; idx >= 0; idx--) {
1011 			ac97_write(as, AC97_REG_MASTER_VOLUME, 0x1010);
1012 			ac97_read(as, AC97_REG_MASTER_VOLUME, &val);
1013 			if (val == 0x1010)
1014 				break;
1015 			DELAY(10);
1016 		}
1017 	}
1018 
1019        for (idx = 0; idx < SOURCE_INFO_SIZE(as); idx++) {
1020 		if (as->type == AC97_CODEC_TYPE_MODEM)
1021 			si = &modem_source_info[idx];
1022 		else
1023 			si = &audio_source_info[idx];
1024 		/* don't "restore" to the reset reg! */
1025 		if (si->reg != AC97_REG_RESET)
1026 			ac97_write(as, si->reg, as->shadow_reg[si->reg >> 1]);
1027 	}
1028 
1029 	if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA
1030 			  | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM
1031 			  | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC
1032 			  | AC97_EXT_AUDIO_LDAC)) {
1033 		ac97_write(as, AC97_REG_EXT_AUDIO_CTRL,
1034 		    as->shadow_reg[AC97_REG_EXT_AUDIO_CTRL >> 1]);
1035 	}
1036 	if (as->ext_mid & (AC97_EXT_MODEM_LINE1 | AC97_EXT_MODEM_LINE2
1037 			  | AC97_EXT_MODEM_HANDSET | AC97_EXT_MODEM_CID1
1038 			  | AC97_EXT_MODEM_CID2 | AC97_EXT_MODEM_ID0
1039 			  | AC97_EXT_MODEM_ID1)) {
1040 		ac97_write(as, AC97_REG_EXT_MODEM_CTRL,
1041 		    as->shadow_reg[AC97_REG_EXT_MODEM_CTRL >> 1]);
1042 	}
1043 }
1044 
1045 static int
1046 ac97_str_equal(const char *a, const char *b)
1047 {
1048 	return (a == b) || (a && b && (!strcmp(a, b)));
1049 }
1050 
1051 static int
1052 ac97_check_capability(struct ac97_softc *as, int check)
1053 {
1054 	switch (check) {
1055 	case CHECK_NONE:
1056 		return 1;
1057 	case CHECK_SURROUND:
1058 		return as->ext_id & AC97_EXT_AUDIO_SDAC;
1059 	case CHECK_CENTER:
1060 		return as->ext_id & AC97_EXT_AUDIO_CDAC;
1061 	case CHECK_LFE:
1062 		return as->ext_id & AC97_EXT_AUDIO_LDAC;
1063 	case CHECK_SPDIF:
1064 		return as->ext_id & AC97_EXT_AUDIO_SPDIF;
1065 	case CHECK_HEADPHONES:
1066 		return as->caps & AC97_CAPS_HEADPHONES;
1067 	case CHECK_TONE:
1068 		return as->caps & AC97_CAPS_TONECTRL;
1069 	case CHECK_MIC:
1070 		return as->caps & AC97_CAPS_MICIN;
1071 	case CHECK_LOUDNESS:
1072 		return as->caps & AC97_CAPS_LOUDNESS;
1073 	case CHECK_3D:
1074 		return AC97_CAPS_ENHANCEMENT(as->caps) != 0;
1075 	case CHECK_LINE1:
1076 		return as->ext_mid & AC97_EXT_MODEM_LINE1;
1077 	case CHECK_LINE2:
1078 		return as->ext_mid & AC97_EXT_MODEM_LINE2;
1079 	case CHECK_HANDSET:
1080 		return as->ext_mid & AC97_EXT_MODEM_HANDSET;
1081 	default:
1082 		printf("%s: internal error: feature=%d\n", __func__, check);
1083 		return 0;
1084 	}
1085 }
1086 
1087 static void
1088 ac97_setup_source_info(struct ac97_softc *as)
1089 {
1090 	int idx, ouridx;
1091 	struct ac97_source_info *si, *si2;
1092 	uint16_t value1, value2, value3;
1093 
1094 	for (idx = 0, ouridx = 0; idx < SOURCE_INFO_SIZE(as); idx++) {
1095 		si = &as->source_info[ouridx];
1096 		if (as->type == AC97_CODEC_TYPE_MODEM) {
1097 			memcpy(si, &modem_source_info[idx], sizeof(*si));
1098 		} else {
1099 			memcpy(si, &audio_source_info[idx], sizeof(*si));
1100 		}
1101 		if (!ac97_check_capability(as, si->req_feature))
1102 			continue;
1103 		if (si->checkbits) {
1104 			/* read the register value */
1105 			ac97_read(as, si->reg, &value1);
1106 			/* write 0b100000 */
1107 			value2 = value1 & 0xffc0;
1108 			value2 |= 0x20;
1109 			ac97_write(as, si->reg, value2);
1110 			/* verify */
1111 			ac97_read(as, si->reg, &value3);
1112 			if (value2 == value3) {
1113 				si->bits = 6;
1114 			} else {
1115 				si->bits = 5;
1116 			}
1117 			DPRINTF(("%s: register=%02x bits=%d\n",
1118 			    __func__, si->reg, si->bits));
1119 			ac97_write(as, si->reg, value1);
1120 		}
1121 
1122 		switch (si->type) {
1123 		case AUDIO_MIXER_CLASS:
1124 			si->mixer_class = ouridx;
1125 			ouridx++;
1126 			break;
1127 		case AUDIO_MIXER_VALUE:
1128 			/* Todo - Test to see if it works */
1129 			ouridx++;
1130 
1131 			/* Add an entry for mute, if necessary */
1132 			if (si->mute) {
1133 				si = &as->source_info[ouridx];
1134 				if (as->type == AC97_CODEC_TYPE_MODEM)
1135 					memcpy(si, &modem_source_info[idx],
1136 					    sizeof(*si));
1137 				else
1138 					memcpy(si, &audio_source_info[idx],
1139 					    sizeof(*si));
1140 				si->qualifier = AudioNmute;
1141 				si->type = AUDIO_MIXER_ENUM;
1142 				si->info = &ac97_on_off;
1143 				si->info_size = sizeof(ac97_on_off);
1144 				si->bits = 1;
1145 				si->ofs = 15;
1146 				si->mute = 0;
1147 				si->polarity = 0;
1148 				ouridx++;
1149 			}
1150 			break;
1151 		case AUDIO_MIXER_ENUM:
1152 			/* Todo - Test to see if it works */
1153 			ouridx++;
1154 			break;
1155 		default:
1156 			aprint_error ("ac97: shouldn't get here\n");
1157 			break;
1158 		}
1159 	}
1160 
1161 	as->num_source_info = ouridx;
1162 
1163 	for (idx = 0; idx < as->num_source_info; idx++) {
1164 		int idx2, previdx;
1165 
1166 		si = &as->source_info[idx];
1167 
1168 		/* Find mixer class */
1169 		for (idx2 = 0; idx2 < as->num_source_info; idx2++) {
1170 			si2 = &as->source_info[idx2];
1171 
1172 			if (si2->type == AUDIO_MIXER_CLASS &&
1173 			    ac97_str_equal(si->class,
1174 					   si2->class)) {
1175 				si->mixer_class = idx2;
1176 			}
1177 		}
1178 
1179 
1180 		/* Setup prev and next pointers */
1181 		if (si->prev != 0)
1182 			continue;
1183 
1184 		if (si->qualifier)
1185 			continue;
1186 
1187 		si->prev = AUDIO_MIXER_LAST;
1188 		previdx = idx;
1189 
1190 		for (idx2 = 0; idx2 < as->num_source_info; idx2++) {
1191 			if (idx2 == idx)
1192 				continue;
1193 
1194 			si2 = &as->source_info[idx2];
1195 
1196 			if (!si2->prev &&
1197 			    ac97_str_equal(si->class, si2->class) &&
1198 			    ac97_str_equal(si->device, si2->device)) {
1199 				as->source_info[previdx].next = idx2;
1200 				as->source_info[idx2].prev = previdx;
1201 
1202 				previdx = idx2;
1203 			}
1204 		}
1205 
1206 		as->source_info[previdx].next = AUDIO_MIXER_LAST;
1207 	}
1208 }
1209 
1210 /* backward compatibility */
1211 int
1212 ac97_attach(struct ac97_host_if *host_if, struct device *sc_dev)
1213 {
1214 	return ac97_attach_type(host_if, sc_dev, AC97_CODEC_TYPE_AUDIO);
1215 }
1216 
1217 int
1218 ac97_attach_type(struct ac97_host_if *host_if, struct device *sc_dev, int type)
1219 {
1220 	struct ac97_softc *as;
1221 	int error, i, j;
1222 	uint32_t id;
1223 	uint16_t id1, id2;
1224 	uint16_t extstat, rate;
1225 	uint16_t val;
1226 	mixer_ctrl_t ctl;
1227 	void (*initfunc)(struct ac97_softc *);
1228 #define FLAGBUFLEN	140
1229 	char flagbuf[FLAGBUFLEN];
1230 
1231 	initfunc = NULL;
1232 	as = malloc(sizeof(struct ac97_softc), M_DEVBUF, M_WAITOK|M_ZERO);
1233 
1234 	if (as == NULL)
1235 		return ENOMEM;
1236 
1237 	as->codec_if.vtbl = &ac97civ;
1238 	as->host_if = host_if;
1239 	as->type = type;
1240 
1241 	if ((error = host_if->attach(host_if->arg, &as->codec_if))) {
1242 		free(as, M_DEVBUF);
1243 		return error;
1244 	}
1245 
1246 	if (host_if->reset != NULL) {
1247 		if ((error = host_if->reset(host_if->arg))) {
1248 			free(as, M_DEVBUF);
1249 			return error;
1250 		}
1251 	}
1252 
1253 	if (host_if->flags)
1254 		as->host_flags = host_if->flags(host_if->arg);
1255 
1256 	/*
1257 	 * Assume codec has all four power bits.
1258 	 * XXXSCW: what to do for modems?
1259 	 */
1260 	as->power_all = AC97_POWER_REF | AC97_POWER_ANL | AC97_POWER_DAC |
1261 	    AC97_POWER_ADC;
1262 	if (as->type == AC97_CODEC_TYPE_AUDIO) {
1263 		host_if->write(host_if->arg, AC97_REG_RESET, 0);
1264 
1265 		/*
1266 		 * Power-up everything except the analogue mixer.
1267 		 * If this codec doesn't support analogue mixer power-down,
1268 		 * AC97_POWER_MIXER will read back as zero.
1269 		 */
1270 		host_if->write(host_if->arg, AC97_REG_POWER, AC97_POWER_MIXER);
1271 		ac97_read(as, AC97_REG_POWER, &val);
1272 		if ((val & AC97_POWER_MIXER) == 0) {
1273 			/* Codec doesn't support analogue mixer power-down */
1274 			as->power_all &= ~AC97_POWER_ANL;
1275 		}
1276 		host_if->write(host_if->arg, AC97_REG_POWER, POWER_EAMP_ON(as));
1277 
1278 		for (i = 500000; i >= 0; i--) {
1279 			ac97_read(as, AC97_REG_POWER, &val);
1280 			if ((val & as->power_all) == as->power_all)
1281 			       break;
1282 			DELAY(1);
1283 		}
1284 
1285 		/* save AC97_REG_POWER so that we can restore it later */
1286 		ac97_read(as, AC97_REG_POWER, &as->power_reg);
1287 	} else if (as->type == AC97_CODEC_TYPE_MODEM) {
1288 		host_if->write(host_if->arg, AC97_REG_EXT_MODEM_ID, 0);
1289 	}
1290 
1291 	ac97_setup_defaults(as);
1292 	if (as->type == AC97_CODEC_TYPE_AUDIO)
1293 		ac97_read(as, AC97_REG_RESET, &as->caps);
1294 	ac97_read(as, AC97_REG_VENDOR_ID1, &id1);
1295 	ac97_read(as, AC97_REG_VENDOR_ID2, &id2);
1296 
1297 	id = (id1 << 16) | id2;
1298 	aprint_normal_dev(sc_dev, "ac97: ");
1299 
1300 	for (i = 0; ; i++) {
1301 		if (ac97codecid[i].id == 0) {
1302 			char pnp[4];
1303 
1304 			AC97_GET_CODEC_ID(id, pnp);
1305 #define ISASCII(c) ((c) >= ' ' && (c) < 0x7f)
1306 			if (ISASCII(pnp[0]) && ISASCII(pnp[1]) &&
1307 			    ISASCII(pnp[2]))
1308 				aprint_normal("%c%c%c%d",
1309 				    pnp[0], pnp[1], pnp[2], pnp[3]);
1310 			else
1311 				aprint_normal("unknown (0x%08x)", id);
1312 			break;
1313 		}
1314 		if (ac97codecid[i].id == (id & ac97codecid[i].mask)) {
1315 			aprint_normal("%s", ac97codecid[i].name);
1316 			if (ac97codecid[i].mask == AC97_VENDOR_ID_MASK) {
1317 				aprint_normal(" (0x%08x)", id);
1318 			}
1319 			initfunc = ac97codecid[i].init;
1320 			break;
1321 		}
1322 	}
1323 	aprint_normal(" codec; ");
1324 	for (i = j = 0; i < 10; i++) {
1325 		if (as->caps & (1 << i)) {
1326 			aprint_normal("%s%s", j ? ", " : "", ac97feature[i]);
1327 			j++;
1328 		}
1329 	}
1330 	aprint_normal("%s%s\n", j ? ", " : "",
1331 	       ac97enhancement[AC97_CAPS_ENHANCEMENT(as->caps)]);
1332 
1333 	as->ac97_clock = AC97_STANDARD_CLOCK;
1334 
1335 	if (as->type == AC97_CODEC_TYPE_AUDIO) {
1336 		ac97_read(as, AC97_REG_EXT_AUDIO_ID, &as->ext_id);
1337 		if (as->ext_id != 0) {
1338 			/* Print capabilities */
1339 			snprintb(flagbuf, sizeof(flagbuf),
1340 			     "\20\20SECONDARY10\17SECONDARY01"
1341 			     "\14AC97_23\13AC97_22\12AMAP\11LDAC\10SDAC"
1342 			     "\7CDAC\4VRM\3SPDIF\2DRA\1VRA", as->ext_id);
1343 			aprint_normal_dev(sc_dev, "ac97: ext id %s\n",
1344 				      flagbuf);
1345 
1346 			/* Print unusual settings */
1347 			if (as->ext_id & AC97_EXT_AUDIO_DSA_MASK) {
1348 				aprint_normal_dev(sc_dev, "ac97: Slot assignment: ");
1349 				switch (as->ext_id & AC97_EXT_AUDIO_DSA_MASK) {
1350 				case AC97_EXT_AUDIO_DSA01:
1351 					aprint_normal("7&8, 6&9, 10&11.\n");
1352 					break;
1353 				case AC97_EXT_AUDIO_DSA10:
1354 					aprint_normal("6&9, 10&11, 3&4.\n");
1355 					break;
1356 				case AC97_EXT_AUDIO_DSA11:
1357 					aprint_normal("10&11, 3&4, 7&8.\n");
1358 					break;
1359 				}
1360 			}
1361 			if (as->host_flags & AC97_HOST_INVERTED_EAMP) {
1362 				aprint_normal_dev(sc_dev, "ac97: using inverted "
1363 					      "AC97_POWER_EAMP bit\n");
1364 			}
1365 
1366 			/* Enable and disable features */
1367 			ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat);
1368 			extstat &= ~AC97_EXT_AUDIO_DRA;
1369 			if (as->ext_id & AC97_EXT_AUDIO_LDAC)
1370 				extstat |= AC97_EXT_AUDIO_LDAC;
1371 			if (as->ext_id & AC97_EXT_AUDIO_SDAC)
1372 				extstat |= AC97_EXT_AUDIO_SDAC;
1373 			if (as->ext_id & AC97_EXT_AUDIO_CDAC)
1374 				extstat |= AC97_EXT_AUDIO_CDAC;
1375 			if (as->ext_id & AC97_EXT_AUDIO_VRM)
1376 				extstat |= AC97_EXT_AUDIO_VRM;
1377 			if (as->ext_id & AC97_EXT_AUDIO_SPDIF) {
1378 				/* Output the same data as DAC to SPDIF output */
1379 				extstat &= ~AC97_EXT_AUDIO_SPSA_MASK;
1380 				extstat |= AC97_EXT_AUDIO_SPSA34;
1381 				ac97_read(as, AC97_REG_SPDIF_CTRL, &val);
1382 				val = (val & ~AC97_SPDIF_SPSR_MASK)
1383 				    | AC97_SPDIF_SPSR_48K;
1384 				ac97_write(as, AC97_REG_SPDIF_CTRL, val);
1385 			}
1386 			if (as->ext_id & AC97_EXT_AUDIO_VRA)
1387 				extstat |= AC97_EXT_AUDIO_VRA;
1388 			ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat);
1389 			if (as->ext_id & AC97_EXT_AUDIO_VRA) {
1390 				/* VRA should be enabled. */
1391 				/* so it claims to do variable rate, let's make sure */
1392 				ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE,
1393 					   44100);
1394 				ac97_read(as, AC97_REG_PCM_FRONT_DAC_RATE,
1395 					  &rate);
1396 				if (rate != 44100) {
1397 					/* We can't believe ext_id */
1398 					as->ext_id = 0;
1399 					aprint_normal_dev(sc_dev,
1400 					    "Ignore these capabilities.\n");
1401 				}
1402 				/* restore the default value */
1403 				ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE,
1404 					   AC97_SINGLE_RATE);
1405 			}
1406 		}
1407 	} else if (as->type == AC97_CODEC_TYPE_MODEM) {
1408 		const struct sysctlnode *node;
1409 		const struct sysctlnode *node_line1;
1410 		const struct sysctlnode *node_line2;
1411 		uint16_t xrate = 8000;
1412 		uint16_t xval, reg;
1413 		int err;
1414 
1415 		ac97_read(as, AC97_REG_EXT_MODEM_ID, &as->ext_mid);
1416 		if (as->ext_mid == 0 || as->ext_mid == 0xffff) {
1417 			aprint_normal_dev(sc_dev, "no modem codec found\n");
1418 			return ENXIO;
1419 		}
1420 		as->type = AC97_CODEC_TYPE_MODEM;
1421 
1422 		/* Print capabilities */
1423 		snprintb(flagbuf, sizeof(flagbuf),
1424 		    "\20\5CID2\4CID1\3HANDSET\2LINE2\1LINE1", as->ext_mid);
1425 		aprint_normal_dev(sc_dev, "ac97: ext mid %s",
1426 			      flagbuf);
1427 		aprint_normal(", %s codec\n",
1428 			      (as->ext_mid & 0xc000) == 0 ?
1429 			      "primary" : "secondary");
1430 
1431 		/* Setup modem and sysctls */
1432 		err = sysctl_createv(&as->log, 0, NULL, NULL, 0, CTLTYPE_NODE,
1433 				     "hw", NULL, NULL, 0, NULL, 0, CTL_HW,
1434 				     CTL_EOL);
1435 		if (err != 0)
1436 			goto setup_modem;
1437 		err = sysctl_createv(&as->log, 0, NULL, &node, 0,
1438 				     CTLTYPE_NODE, device_xname(sc_dev), NULL,
1439 				     NULL, 0, NULL, 0, CTL_HW, CTL_CREATE,
1440 				     CTL_EOL);
1441 		if (err != 0)
1442 			goto setup_modem;
1443 setup_modem:
1444 		/* reset */
1445 		ac97_write(as, AC97_REG_EXT_MODEM_ID, 1);
1446 
1447 		/* program rates */
1448 		xval = 0xff00 & ~AC97_EXT_MODEM_CTRL_PRA;
1449 		if (as->ext_mid & AC97_EXT_MODEM_LINE1) {
1450 			ac97_write(as, AC97_REG_LINE1_RATE, xrate);
1451 			xval &= ~(AC97_EXT_MODEM_CTRL_PRC |
1452 			       AC97_EXT_MODEM_CTRL_PRD);
1453 		}
1454 		if (as->ext_mid & AC97_EXT_MODEM_LINE2) {
1455 			ac97_write(as, AC97_REG_LINE2_RATE, xrate);
1456 			xval &= ~(AC97_EXT_MODEM_CTRL_PRE |
1457 			       AC97_EXT_MODEM_CTRL_PRF);
1458 		}
1459 		if (as->ext_mid & AC97_EXT_MODEM_HANDSET) {
1460 			ac97_write(as, AC97_REG_HANDSET_RATE, xrate);
1461 			xval &= ~(AC97_EXT_MODEM_CTRL_PRG |
1462 			       AC97_EXT_MODEM_CTRL_PRH);
1463 		}
1464 
1465 		/* power-up everything */
1466 		ac97_write(as, AC97_REG_EXT_MODEM_CTRL, 0);
1467 		for (i = 5000; i >= 0; i--) {
1468 			ac97_read(as, AC97_REG_EXT_MODEM_CTRL, &reg);
1469 			if ((reg & /*XXXval*/0xf) == /*XXXval*/0xf)
1470 			       break;
1471 			DELAY(1);
1472 		}
1473 		if (i <= 0) {
1474 			printf("%s: codec not responding, status=0x%x\n",
1475 			    device_xname(sc_dev), reg);
1476 			return ENXIO;
1477 		}
1478 
1479 		/* setup sysctls */
1480 		if (as->ext_mid & AC97_EXT_MODEM_LINE1) {
1481 			ac97_read(as, AC97_REG_GPIO_CFG, &reg);
1482 			reg &= ~AC97_GPIO_LINE1_OH;
1483 			ac97_write(as, AC97_REG_GPIO_CFG, reg);
1484 			ac97_read(as, AC97_REG_GPIO_POLARITY, &reg);
1485 			reg &= ~AC97_GPIO_LINE1_OH;
1486 			ac97_write(as, AC97_REG_GPIO_POLARITY, reg);
1487 
1488 			err = sysctl_createv(&as->log, 0, NULL, &node_line1,
1489 					     CTLFLAG_READWRITE, CTLTYPE_INT,
1490 					     "line1",
1491 					     SYSCTL_DESCR("off-hook line1"),
1492 					     ac97_sysctl_verify, 0, as, 0,
1493 					     CTL_HW, node->sysctl_num,
1494 					     CTL_CREATE, CTL_EOL);
1495 			if (err != 0)
1496 				goto sysctl_err;
1497 			as->offhook_line1_mib = node_line1->sysctl_num;
1498 		}
1499 		if (as->ext_mid & AC97_EXT_MODEM_LINE2) {
1500 			ac97_read(as, AC97_REG_GPIO_CFG, &reg);
1501 			reg &= ~AC97_GPIO_LINE2_OH;
1502 			ac97_write(as, AC97_REG_GPIO_CFG, reg);
1503 			ac97_read(as, AC97_REG_GPIO_POLARITY, &reg);
1504 			reg &= ~AC97_GPIO_LINE2_OH;
1505 			ac97_write(as, AC97_REG_GPIO_POLARITY, reg);
1506 
1507 			err = sysctl_createv(&as->log, 0, NULL, &node_line2,
1508 					     CTLFLAG_READWRITE, CTLTYPE_INT,
1509 					     "line2",
1510 					     SYSCTL_DESCR("off-hook line2"),
1511 					     ac97_sysctl_verify, 0, as, 0,
1512 					     CTL_HW, node->sysctl_num,
1513 					     CTL_CREATE, CTL_EOL);
1514 			if (err != 0)
1515 				goto sysctl_err;
1516 			as->offhook_line2_mib = node_line2->sysctl_num;
1517 		}
1518 sysctl_err:
1519 
1520 		ac97_write(as, AC97_REG_GPIO_STICKY, 0xffff);
1521 		ac97_write(as, AC97_REG_GPIO_WAKEUP, 0x0);
1522 		ac97_write(as, AC97_REG_MISC_AFE, 0x0);
1523 	}
1524 
1525 	as->source_info = (as->type == AC97_CODEC_TYPE_MODEM ?
1526 			   as->modem_source_info : as->audio_source_info);
1527 	ac97_setup_source_info(as);
1528 
1529 	memset(&ctl, 0, sizeof(ctl));
1530 	/* disable mutes */
1531 	for (i = 0; i < 11; i++) {
1532 		static struct {
1533 			const char *class, *device;
1534 		} d[11] = {
1535 			{ AudioCoutputs, AudioNmaster},
1536 			{ AudioCoutputs, AudioNheadphone},
1537 			{ AudioCoutputs, AudioNsurround},
1538 			{ AudioCoutputs, AudioNcenter},
1539 			{ AudioCoutputs, AudioNlfe},
1540 			{ AudioCinputs, AudioNdac},
1541 			{ AudioCinputs, AudioNcd},
1542 			{ AudioCinputs, AudioNline},
1543 			{ AudioCinputs, AudioNaux},
1544 			{ AudioCinputs, AudioNvideo},
1545 			{ AudioCrecord, AudioNvolume},
1546 		};
1547 
1548 		ctl.type = AUDIO_MIXER_ENUM;
1549 		ctl.un.ord = 0;
1550 
1551 		ctl.dev = ac97_get_portnum_by_name(&as->codec_if,
1552 			d[i].class, d[i].device, AudioNmute);
1553 		ac97_mixer_set_port(&as->codec_if, &ctl);
1554 	}
1555 	ctl.type = AUDIO_MIXER_ENUM;
1556 	ctl.un.ord = 0;
1557 	ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
1558 					   AudioNsource, NULL);
1559 	ac97_mixer_set_port(&as->codec_if, &ctl);
1560 
1561 	/* set a reasonable default volume */
1562 	ctl.type = AUDIO_MIXER_VALUE;
1563 	ctl.un.value.num_channels = 2;
1564 	ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = \
1565 	ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127;
1566 	ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1567 					   AudioNmaster, NULL);
1568 	ac97_mixer_set_port(&as->codec_if, &ctl);
1569 	ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1570 					   AudioNsurround, NULL);
1571 	ac97_mixer_set_port(&as->codec_if, &ctl);
1572 	ctl.un.value.num_channels = 1;
1573 	ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1574 					   AudioNcenter, NULL);
1575 	ac97_mixer_set_port(&as->codec_if, &ctl);
1576 	ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1577 					   AudioNlfe, NULL);
1578 	ac97_mixer_set_port(&as->codec_if, &ctl);
1579 
1580 	if (initfunc != NULL)
1581 		initfunc(as);
1582 
1583 	/* restore AC97_REG_POWER */
1584 	if (as->type == AC97_CODEC_TYPE_AUDIO)
1585 		ac97_write(as, AC97_REG_POWER, as->power_reg);
1586 
1587 	return 0;
1588 }
1589 
1590 static void
1591 ac97_detach(struct ac97_codec_if *codec_if)
1592 {
1593 	struct ac97_softc *as;
1594 
1595 	as = (struct ac97_softc *)codec_if;
1596 	ac97_write(as, AC97_REG_POWER, AC97_POWER_IN | AC97_POWER_OUT
1597 		   | AC97_POWER_MIXER | AC97_POWER_MIXER_VREF
1598 		   | AC97_POWER_ACLINK | AC97_POWER_CLK | AC97_POWER_AUX
1599 		   | POWER_EAMP_OFF(as));
1600 	free(as, M_DEVBUF);
1601 }
1602 
1603 static void
1604 ac97_lock(struct ac97_codec_if *codec_if)
1605 {
1606 	struct ac97_softc *as;
1607 
1608 	as = (struct ac97_softc *)codec_if;
1609 	as->lock_counter++;
1610 }
1611 
1612 static void
1613 ac97_unlock(struct ac97_codec_if *codec_if)
1614 {
1615 	struct ac97_softc *as;
1616 
1617 	as = (struct ac97_softc *)codec_if;
1618 	as->lock_counter--;
1619 }
1620 
1621 static int
1622 ac97_query_devinfo(struct ac97_codec_if *codec_if, mixer_devinfo_t *dip)
1623 {
1624 	struct ac97_softc *as;
1625 	struct ac97_source_info *si;
1626 	const char *name;
1627 
1628 	as = (struct ac97_softc *)codec_if;
1629 	if (dip->index < as->num_source_info) {
1630 		si = &as->source_info[dip->index];
1631 		dip->type = si->type;
1632 		dip->mixer_class = si->mixer_class;
1633 		dip->prev = si->prev;
1634 		dip->next = si->next;
1635 
1636 		if (si->qualifier)
1637 			name = si->qualifier;
1638 		else if (si->device)
1639 			name = si->device;
1640 		else if (si->class)
1641 			name = si->class;
1642 		else
1643 			name = 0;
1644 
1645 		if (name)
1646 			strcpy(dip->label.name, name);
1647 
1648 		memcpy(&dip->un, si->info, si->info_size);
1649 
1650 		/* Set the delta for volume sources */
1651 		if (dip->type == AUDIO_MIXER_VALUE)
1652 			dip->un.v.delta = 1 << (8 - si->bits);
1653 
1654 		return 0;
1655 	}
1656 
1657 	return ENXIO;
1658 }
1659 
1660 static int
1661 ac97_mixer_set_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
1662 {
1663 	struct ac97_softc *as;
1664 	struct ac97_source_info *si;
1665 	uint16_t mask;
1666 	uint16_t val, newval;
1667 	int error;
1668 	bool spdif;
1669 
1670 	as = (struct ac97_softc *)codec_if;
1671 	if (cp->dev < 0 || cp->dev >= as->num_source_info)
1672 		return EINVAL;
1673 	si = &as->source_info[cp->dev];
1674 
1675 	if (cp->type == AUDIO_MIXER_CLASS || cp->type != si->type)
1676 		return EINVAL;
1677 	spdif = si->req_feature == CHECK_SPDIF && si->reg == AC97_REG_EXT_AUDIO_CTRL;
1678 	if (spdif && as->lock_counter >= 0) {
1679 		/* When the value of lock_counter is the default 0,
1680 		 * it is not allowed to change the SPDIF mode. */
1681 		return EBUSY;
1682 	}
1683 
1684 	ac97_read(as, si->reg, &val);
1685 
1686 	DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
1687 
1688 	mask = (1 << si->bits) - 1;
1689 
1690 	switch (cp->type) {
1691 	case AUDIO_MIXER_ENUM:
1692 		if (cp->un.ord > mask || cp->un.ord < 0)
1693 			return EINVAL;
1694 
1695 		newval = (cp->un.ord << si->ofs);
1696 		if (si->reg == AC97_REG_RECORD_SELECT) {
1697 			newval |= (newval << (8 + si->ofs));
1698 			mask |= (mask << 8);
1699 			mask = mask << si->ofs;
1700 		} else if (si->reg == AC97_REG_SURR_MASTER) {
1701 			newval = cp->un.ord ? 0x8080 : 0x0000;
1702 			mask = 0x8080;
1703 		} else
1704 			mask = mask << si->ofs;
1705 		break;
1706 	case AUDIO_MIXER_VALUE:
1707 	{
1708 		const struct audio_mixer_value *value = si->info;
1709 		uint16_t  l, r, ol, or;
1710 		int deltal, deltar;
1711 
1712 		if ((cp->un.value.num_channels <= 0) ||
1713 		    (cp->un.value.num_channels > value->num_channels))
1714 			return EINVAL;
1715 
1716 		if (cp->un.value.num_channels == 1) {
1717 			l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
1718 		} else {
1719 			if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
1720 				l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1721 				r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1722 			} else {	/* left/right is reversed here */
1723 				r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1724 				l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1725 			}
1726 
1727 		}
1728 
1729 		if (!si->polarity) {
1730 			l = 255 - l;
1731 			r = 255 - r;
1732 		}
1733 
1734 		ol = (val >> (8+si->ofs)) & mask;
1735 		or = (val >> si->ofs) & mask;
1736 
1737 		deltal = (ol << (8 - si->bits)) - l;
1738 		deltar = (or << (8 - si->bits)) - r;
1739 
1740 		l = l >> (8 - si->bits);
1741 		r = r >> (8 - si->bits);
1742 
1743 		if (deltal && ol == l)
1744 			l += (deltal > 0) ? (l ? -1 : 0) : (l < mask ? 1 : 0);
1745 		if (deltar && or == r)
1746 			r += (deltar > 0) ? (r ? -1 : 0) : (r < mask ? 1 : 0);
1747 
1748 		newval = ((r & mask) << si->ofs);
1749 		if (value->num_channels == 2) {
1750 			newval = newval | ((l & mask) << (si->ofs+8));
1751 			mask |= (mask << 8);
1752 		}
1753 		mask = mask << si->ofs;
1754 		break;
1755 	}
1756 	default:
1757 		return EINVAL;
1758 	}
1759 
1760 	error = ac97_write(as, si->reg, (val & ~mask) | newval);
1761 	if (error)
1762 		return error;
1763 
1764 	if (spdif && as->host_if->spdif_event != NULL) {
1765 		DPRINTF(("%s: call spdif_event(%d)\n", __func__, cp->un.ord));
1766 		as->host_if->spdif_event(as->host_if->arg, cp->un.ord);
1767 	}
1768 	return 0;
1769 }
1770 
1771 static int
1772 ac97_get_portnum_by_name(struct ac97_codec_if *codec_if, const char *class,
1773 			 const char *device, const char *qualifier)
1774 {
1775 	struct ac97_softc *as;
1776 	int idx;
1777 
1778 	as = (struct ac97_softc *)codec_if;
1779 	for (idx = 0; idx < as->num_source_info; idx++) {
1780 		struct ac97_source_info *si = &as->source_info[idx];
1781 		if (ac97_str_equal(class, si->class) &&
1782 		    ac97_str_equal(device, si->device) &&
1783 		    ac97_str_equal(qualifier, si->qualifier))
1784 			return idx;
1785 	}
1786 
1787 	return -1;
1788 }
1789 
1790 static int
1791 ac97_mixer_get_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
1792 {
1793 	struct ac97_softc *as;
1794 	struct ac97_source_info *si;
1795 	uint16_t mask;
1796 	uint16_t val;
1797 
1798 	as = (struct ac97_softc *)codec_if;
1799 	si = &as->source_info[cp->dev];
1800 	if (cp->dev < 0 || cp->dev >= as->num_source_info)
1801 		return EINVAL;
1802 
1803 	if (cp->type != si->type)
1804 		return EINVAL;
1805 
1806 	ac97_read(as, si->reg, &val);
1807 
1808 	DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
1809 
1810 	mask = (1 << si->bits) - 1;
1811 
1812 	switch (cp->type) {
1813 	case AUDIO_MIXER_ENUM:
1814 		cp->un.ord = (val >> si->ofs) & mask;
1815 		DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n",
1816 			     val, si->ofs, mask, cp->un.ord));
1817 		break;
1818 	case AUDIO_MIXER_VALUE:
1819 	{
1820 		const struct audio_mixer_value *value = si->info;
1821 		uint16_t  l, r;
1822 
1823 		if ((cp->un.value.num_channels <= 0) ||
1824 		    (cp->un.value.num_channels > value->num_channels))
1825 			return EINVAL;
1826 
1827 		if (value->num_channels == 1) {
1828 			l = r = (val >> si->ofs) & mask;
1829 		} else {
1830 			if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
1831 				l = (val >> (si->ofs + 8)) & mask;
1832 				r = (val >> si->ofs) & mask;
1833 			} else {	/* host has reversed channels */
1834 				r = (val >> (si->ofs + 8)) & mask;
1835 				l = (val >> si->ofs) & mask;
1836 			}
1837 		}
1838 
1839 		l = (l << (8 - si->bits));
1840 		r = (r << (8 - si->bits));
1841 		if (!si->polarity) {
1842 			l = 255 - l;
1843 			r = 255 - r;
1844 		}
1845 
1846 		/* The EAP driver averages l and r for stereo
1847 		   channels that are requested in MONO mode. Does this
1848 		   make sense? */
1849 		if (cp->un.value.num_channels == 1) {
1850 			cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l;
1851 		} else if (cp->un.value.num_channels == 2) {
1852 			cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
1853 			cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
1854 		}
1855 
1856 		break;
1857 	}
1858 	default:
1859 		return EINVAL;
1860 	}
1861 
1862 	return 0;
1863 }
1864 
1865 
1866 static int
1867 ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_int *rate)
1868 {
1869 	struct ac97_softc *as;
1870 	u_int value;
1871 	uint16_t ext_stat;
1872 	uint16_t actual;
1873 	uint16_t power;
1874 	uint16_t power_bit;
1875 
1876 	as = (struct ac97_softc *)codec_if;
1877 	if (target == AC97_REG_PCM_MIC_ADC_RATE) {
1878 		if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1879 			*rate = AC97_SINGLE_RATE;
1880 			return 0;
1881 		}
1882 	} else {
1883 		if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1884 			*rate = AC97_SINGLE_RATE;
1885 			return 0;
1886 		}
1887 	}
1888 	value = *rate * AC97_STANDARD_CLOCK / as->ac97_clock;
1889 	ext_stat = 0;
1890 	/*
1891 	 * PCM_FRONT_DAC_RATE/PCM_SURR_DAC_RATE/PCM_LFE_DAC_RATE
1892 	 *	Check VRA, DRA
1893 	 * PCM_LR_ADC_RATE
1894 	 *	Check VRA
1895 	 * PCM_MIC_ADC_RATE
1896 	 *	Check VRM
1897 	 */
1898 	switch (target) {
1899 	case AC97_REG_PCM_FRONT_DAC_RATE:
1900 	case AC97_REG_PCM_SURR_DAC_RATE:
1901 	case AC97_REG_PCM_LFE_DAC_RATE:
1902 		power_bit = AC97_POWER_OUT;
1903 		if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1904 			*rate = AC97_SINGLE_RATE;
1905 			return 0;
1906 		}
1907 		if (as->ext_id & AC97_EXT_AUDIO_DRA) {
1908 			ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &ext_stat);
1909 			if (value > 0x1ffff) {
1910 				return EINVAL;
1911 			} else if (value > 0xffff) {
1912 				/* Enable DRA */
1913 				ext_stat |= AC97_EXT_AUDIO_DRA;
1914 				ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1915 				value /= 2;
1916 			} else {
1917 				/* Disable DRA */
1918 				ext_stat &= ~AC97_EXT_AUDIO_DRA;
1919 				ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1920 			}
1921 		} else {
1922 			if (value > 0xffff)
1923 				return EINVAL;
1924 		}
1925 		break;
1926 	case AC97_REG_PCM_LR_ADC_RATE:
1927 		power_bit = AC97_POWER_IN;
1928 		if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1929 			*rate = AC97_SINGLE_RATE;
1930 			return 0;
1931 		}
1932 		if (value > 0xffff)
1933 			return EINVAL;
1934 		break;
1935 	case AC97_REG_PCM_MIC_ADC_RATE:
1936 		power_bit = AC97_POWER_IN;
1937 		if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1938 			*rate = AC97_SINGLE_RATE;
1939 			return 0;
1940 		}
1941 		if (value > 0xffff)
1942 			return EINVAL;
1943 		break;
1944 	default:
1945 		printf("%s: Unknown register: 0x%x\n", __func__, target);
1946 		return EINVAL;
1947 	}
1948 
1949 	ac97_read(as, AC97_REG_POWER, &power);
1950 	ac97_write(as, AC97_REG_POWER, power | power_bit);
1951 
1952 	ac97_write(as, target, (uint16_t)value);
1953 	ac97_read(as, target, &actual);
1954 	actual = (uint32_t)actual * as->ac97_clock / AC97_STANDARD_CLOCK;
1955 
1956 	ac97_write(as, AC97_REG_POWER, power);
1957 	if (ext_stat & AC97_EXT_AUDIO_DRA) {
1958 		*rate = actual * 2;
1959 	} else {
1960 		*rate = actual;
1961 	}
1962 	return 0;
1963 }
1964 
1965 static void
1966 ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock)
1967 {
1968 	struct ac97_softc *as;
1969 
1970 	as = (struct ac97_softc *)codec_if;
1971 	as->ac97_clock = clock;
1972 }
1973 
1974 static uint16_t
1975 ac97_get_extcaps(struct ac97_codec_if *codec_if)
1976 {
1977 	struct ac97_softc *as;
1978 
1979 	as = (struct ac97_softc *)codec_if;
1980 	return as->ext_id;
1981 }
1982 
1983 static int
1984 ac97_add_port(struct ac97_softc *as, const struct ac97_source_info *src)
1985 {
1986 	struct ac97_source_info *si;
1987 	int ouridx, idx;
1988 
1989 	if ((as->type == AC97_CODEC_TYPE_AUDIO &&
1990 	     as->num_source_info >= AUDIO_MAX_SOURCES) ||
1991 	    (as->type == AC97_CODEC_TYPE_MODEM &&
1992 	     as->num_source_info >= MODEM_MAX_SOURCES)) {
1993 		printf("%s: internal error: increase MAX_SOURCES in %s\n",
1994 		       __func__, __FILE__);
1995 		return -1;
1996 	}
1997 	if (!ac97_check_capability(as, src->req_feature))
1998 		return -1;
1999 	ouridx = as->num_source_info;
2000 	si = &as->source_info[ouridx];
2001 	memcpy(si, src, sizeof(*si));
2002 
2003 	switch (si->type) {
2004 	case AUDIO_MIXER_CLASS:
2005 	case AUDIO_MIXER_VALUE:
2006 		printf("%s: adding class/value is not supported yet.\n",
2007 		       __func__);
2008 		return -1;
2009 	case AUDIO_MIXER_ENUM:
2010 		break;
2011 	default:
2012 		printf("%s: unknown type: %d\n", __func__, si->type);
2013 		return -1;
2014 	}
2015 	as->num_source_info++;
2016 
2017 	si->mixer_class = ac97_get_portnum_by_name(&as->codec_if, si->class,
2018 						   NULL, NULL);
2019 	/* Find the root of the device */
2020 	idx = ac97_get_portnum_by_name(&as->codec_if, si->class,
2021 				       si->device, NULL);
2022 	/* Find the last item */
2023 	while (as->source_info[idx].next != AUDIO_MIXER_LAST)
2024 		idx = as->source_info[idx].next;
2025 	/* Append */
2026 	as->source_info[idx].next = ouridx;
2027 	si->prev = idx;
2028 	si->next = AUDIO_MIXER_LAST;
2029 
2030 	return 0;
2031 }
2032 
2033 /**
2034  * Codec-dependent initialization
2035  */
2036 
2037 #define	AD1980_REG_MISC	0x76
2038 #define		AD1980_MISC_MBG0	0x0001	/* 0 1888/1980/1981 /1985 */
2039 #define		AD1980_MISC_MBG1	0x0002	/* 1 1888/1980/1981 /1985 */
2040 #define		AD1980_MISC_VREFD	0x0004	/* 2 1888/1980/1981 /1985 */
2041 #define		AD1980_MISC_VREFH	0x0008	/* 3 1888/1980/1981 /1985 */
2042 #define		AD1980_MISC_SRU		0x0010	/* 4 1888/1980      /1985 */
2043 #define		AD1980_MISC_LOSEL	0x0020	/* 5 1888/1980/1981 /1985 */
2044 #define		AD1980_MISC_2CMIC	0x0040	/* 6      1980/1981B/1985 */
2045 #define		AD1980_MISC_SPRD	0x0080	/* 7 1888/1980      /1985 */
2046 #define		AD1980_MISC_DMIX0	0x0100	/* 8 1888/1980      /1985 */
2047 #define		AD1980_MISC_DMIX1	0x0200	/* 9 1888/1980      /1985 */
2048 #define		AD1980_MISC_HPSEL	0x0400	/*10 1888/1980      /1985 */
2049 #define		AD1980_MISC_CLDIS	0x0800	/*11 1888/1980      /1985 */
2050 #define		AD1980_MISC_LODIS	0x1000	/*12 1888/1980/1981 /1985 */
2051 #define		AD1980_MISC_MSPLT	0x2000	/*13 1888/1980/1981 /1985 */
2052 #define		AD1980_MISC_AC97NC	0x4000	/*14 1888/1980      /1985 */
2053 #define		AD1980_MISC_DACZ	0x8000	/*15 1888/1980/1981 /1985 */
2054 #define	AD1981_REG_MISC	0x76
2055 #define		AD1981_MISC_MADST	0x0010  /* 4 */
2056 #define		AD1981A_MISC_MADPD	0x0040  /* 6 */
2057 #define		AD1981B_MISC_MADPD	0x0080  /* 7 */
2058 #define		AD1981_MISC_FMXE	0x0200  /* 9 */
2059 #define		AD1981_MISC_DAM		0x0800  /*11 */
2060 static void
2061 ac97_ad198x_init(struct ac97_softc *as)
2062 {
2063 	int i;
2064 	uint16_t misc;
2065 
2066 	ac97_read(as, AD1980_REG_MISC, &misc);
2067 	ac97_write(as, AD1980_REG_MISC,
2068 		   misc | AD1980_MISC_LOSEL | AD1980_MISC_HPSEL);
2069 
2070 	for (i = 0; i < as->num_source_info; i++) {
2071 		if (as->source_info[i].type != AUDIO_MIXER_VALUE)
2072 			continue;
2073 
2074 		if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME)
2075 			as->source_info[i].reg = AC97_REG_SURR_MASTER;
2076 		else if (as->source_info[i].reg == AC97_REG_SURR_MASTER)
2077 			as->source_info[i].reg = AC97_REG_MASTER_VOLUME;
2078 	}
2079 }
2080 
2081 #define ALC650_REG_MULTI_CHANNEL_CONTROL	0x6a
2082 #define		ALC650_MCC_SLOT_MODIFY_MASK		0xc000
2083 #define		ALC650_MCC_FRONTDAC_FROM_SPDIFIN	0x2000 /* 13 */
2084 #define		ALC650_MCC_SPDIFOUT_FROM_ADC		0x1000 /* 12 */
2085 #define		ALC650_MCC_PCM_FROM_SPDIFIN		0x0800 /* 11 */
2086 #define		ALC650_MCC_MIC_OR_CENTERLFE		0x0400 /* 10 */
2087 #define		ALC650_MCC_LINEIN_OR_SURROUND		0x0200 /* 9 */
2088 #define		ALC650_MCC_INDEPENDENT_MASTER_L		0x0080 /* 7 */
2089 #define		ALC650_MCC_INDEPENDENT_MASTER_R		0x0040 /* 6 */
2090 #define		ALC650_MCC_ANALOG_TO_CENTERLFE		0x0020 /* 5 */
2091 #define		ALC650_MCC_ANALOG_TO_SURROUND		0x0010 /* 4 */
2092 #define		ALC650_MCC_EXCHANGE_CENTERLFE		0x0008 /* 3 */
2093 #define		ALC650_MCC_CENTERLFE_DOWNMIX		0x0004 /* 2 */
2094 #define		ALC650_MCC_SURROUND_DOWNMIX		0x0002 /* 1 */
2095 #define		ALC650_MCC_LINEOUT_TO_SURROUND		0x0001 /* 0 */
2096 static void
2097 ac97_alc650_init(struct ac97_softc *as)
2098 {
2099 	static const struct ac97_source_info sources[6] = {
2100 		{ AudioCoutputs, AudioNsurround, "lineinjack",
2101 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2102 		  ALC650_REG_MULTI_CHANNEL_CONTROL,
2103 		  0x0000, 1, 9, 0, 0, 0, CHECK_SURROUND, 0, 0, 0, },
2104 		{ AudioCoutputs, AudioNsurround, "mixtofront",
2105 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2106 		  ALC650_REG_MULTI_CHANNEL_CONTROL,
2107 		  0x0000, 1, 1, 0, 0, 0, CHECK_SURROUND, 0, 0, 0, },
2108 		{ AudioCoutputs, AudioNcenter, "micjack",
2109 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2110 		  ALC650_REG_MULTI_CHANNEL_CONTROL,
2111 		  0x0000, 1, 10, 0, 0, 0, CHECK_CENTER, 0, 0, 0, },
2112 		{ AudioCoutputs, AudioNlfe, "micjack",
2113 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2114 		  ALC650_REG_MULTI_CHANNEL_CONTROL,
2115 		  0x0000, 1, 10, 0, 0, 0, CHECK_LFE, 0, 0, 0, },
2116 		{ AudioCoutputs, AudioNcenter, "mixtofront",
2117 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2118 		  ALC650_REG_MULTI_CHANNEL_CONTROL,
2119 		  0x0000, 1, 2, 0, 0, 0, CHECK_CENTER, 0, 0, 0, },
2120 		{ AudioCoutputs, AudioNlfe, "mixtofront",
2121 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2122 		  ALC650_REG_MULTI_CHANNEL_CONTROL,
2123 		  0x0000, 1, 2, 0, 0, 0, CHECK_LFE, 0, 0, 0, },
2124 	};
2125 
2126 	ac97_add_port(as, &sources[0]);
2127 	ac97_add_port(as, &sources[1]);
2128 	ac97_add_port(as, &sources[2]);
2129 	ac97_add_port(as, &sources[3]);
2130 	ac97_add_port(as, &sources[4]);
2131 	ac97_add_port(as, &sources[5]);
2132 }
2133 
2134 #define VT1616_REG_IO_CONTROL	0x5a
2135 #define		VT1616_IC_LVL			(1 << 15)
2136 #define		VT1616_IC_LFECENTER_TO_FRONT	(1 << 12)
2137 #define		VT1616_IC_SURROUND_TO_FRONT	(1 << 11)
2138 #define		VT1616_IC_BPDC			(1 << 10)
2139 #define		VT1616_IC_DC			(1 << 9)
2140 #define		VT1616_IC_IB_MASK		0x000c
2141 static void
2142 ac97_vt1616_init(struct ac97_softc *as)
2143 {
2144 	static const struct ac97_source_info sources[3] = {
2145 		{ AudioCoutputs, AudioNsurround, "mixtofront",
2146 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2147 		  VT1616_REG_IO_CONTROL,
2148 		  0x0000, 1, 11, 0, 0, 0, CHECK_SURROUND, 0, 0, 0, },
2149 		{ AudioCoutputs, AudioNcenter, "mixtofront",
2150 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2151 		  VT1616_REG_IO_CONTROL,
2152 		  0x0000, 1, 12, 0, 0, 0, CHECK_CENTER, 0, 0, 0, },
2153 		{ AudioCoutputs, AudioNlfe, "mixtofront",
2154 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2155 		  VT1616_REG_IO_CONTROL,
2156 		  0x0000, 1, 12, 0, 0, 0, CHECK_LFE, 0, 0, 0, },
2157 	};
2158 
2159 	ac97_add_port(as, &sources[0]);
2160 	ac97_add_port(as, &sources[1]);
2161 	ac97_add_port(as, &sources[2]);
2162 }
2163 
2164 static int
2165 ac97_modem_offhook_set(struct ac97_softc *as, int line, int newval)
2166 {
2167 	uint16_t val;
2168 
2169 	val = as->shadow_reg[AC97_REG_GPIO_STATUS >> 1];
2170 	switch (newval) {
2171 	case 0:
2172 		val &= ~line;
2173 		break;
2174 	case 1:
2175 		val |= line;
2176 		break;
2177 	}
2178 	ac97_write(as, AC97_REG_GPIO_STATUS, val);
2179 
2180 	return 0;
2181 }
2182 
2183 static int
2184 ac97_sysctl_verify(SYSCTLFN_ARGS)
2185 {
2186 	int error, tmp;
2187 	struct sysctlnode node;
2188 	struct ac97_softc *as;
2189 
2190 	node = *rnode;
2191 	as = rnode->sysctl_data;
2192 	if (node.sysctl_num == as->offhook_line1_mib) {
2193 		tmp = as->offhook_line1;
2194 		node.sysctl_data = &tmp;
2195 		error = sysctl_lookup(SYSCTLFN_CALL(&node));
2196 		if (error || newp == NULL)
2197 			return error;
2198 
2199 		if (tmp < 0 || tmp > 1)
2200 			return EINVAL;
2201 
2202 		as->offhook_line1 = tmp;
2203 		ac97_modem_offhook_set(as, AC97_GPIO_LINE1_OH, tmp);
2204 	} else if (node.sysctl_num == as->offhook_line2_mib) {
2205 		tmp = as->offhook_line2;
2206 		node.sysctl_data = &tmp;
2207 		error = sysctl_lookup(SYSCTLFN_CALL(&node));
2208 		if (error || newp == NULL)
2209 			return error;
2210 
2211 		if (tmp < 0 || tmp > 1)
2212 			return EINVAL;
2213 
2214 		as->offhook_line2 = tmp;
2215 		ac97_modem_offhook_set(as, AC97_GPIO_LINE2_OH, tmp);
2216 	}
2217 
2218 	return 0;
2219 }
2220