xref: /netbsd-src/sys/dev/ic/ac97.c (revision 2980e352a13e8f0b545a366830c411e7a542ada8)
1 /*      $NetBSD: ac97.c,v 1.88 2008/06/24 10:57:45 gmcgarry 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.88 2008/06/24 10:57:45 gmcgarry 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 			bitmask_snprintf(as->ext_id,
1340 				 "\20\20SECONDARY10\17SECONDARY01"
1341 				 "\14AC97_23\13AC97_22\12AMAP\11LDAC\10SDAC"
1342 				 "\7CDAC\4VRM\3SPDIF\2DRA\1VRA",
1343 				 flagbuf, FLAGBUFLEN);
1344 			aprint_normal_dev(sc_dev, "ac97: ext id %s\n",
1345 				      flagbuf);
1346 
1347 			/* Print unusual settings */
1348 			if (as->ext_id & AC97_EXT_AUDIO_DSA_MASK) {
1349 				aprint_normal_dev(sc_dev, "ac97: Slot assignment: ");
1350 				switch (as->ext_id & AC97_EXT_AUDIO_DSA_MASK) {
1351 				case AC97_EXT_AUDIO_DSA01:
1352 					aprint_normal("7&8, 6&9, 10&11.\n");
1353 					break;
1354 				case AC97_EXT_AUDIO_DSA10:
1355 					aprint_normal("6&9, 10&11, 3&4.\n");
1356 					break;
1357 				case AC97_EXT_AUDIO_DSA11:
1358 					aprint_normal("10&11, 3&4, 7&8.\n");
1359 					break;
1360 				}
1361 			}
1362 			if (as->host_flags & AC97_HOST_INVERTED_EAMP) {
1363 				aprint_normal_dev(sc_dev, "ac97: using inverted "
1364 					      "AC97_POWER_EAMP bit\n");
1365 			}
1366 
1367 			/* Enable and disable features */
1368 			ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat);
1369 			extstat &= ~AC97_EXT_AUDIO_DRA;
1370 			if (as->ext_id & AC97_EXT_AUDIO_LDAC)
1371 				extstat |= AC97_EXT_AUDIO_LDAC;
1372 			if (as->ext_id & AC97_EXT_AUDIO_SDAC)
1373 				extstat |= AC97_EXT_AUDIO_SDAC;
1374 			if (as->ext_id & AC97_EXT_AUDIO_CDAC)
1375 				extstat |= AC97_EXT_AUDIO_CDAC;
1376 			if (as->ext_id & AC97_EXT_AUDIO_VRM)
1377 				extstat |= AC97_EXT_AUDIO_VRM;
1378 			if (as->ext_id & AC97_EXT_AUDIO_SPDIF) {
1379 				/* Output the same data as DAC to SPDIF output */
1380 				extstat &= ~AC97_EXT_AUDIO_SPSA_MASK;
1381 				extstat |= AC97_EXT_AUDIO_SPSA34;
1382 				ac97_read(as, AC97_REG_SPDIF_CTRL, &val);
1383 				val = (val & ~AC97_SPDIF_SPSR_MASK)
1384 				    | AC97_SPDIF_SPSR_48K;
1385 				ac97_write(as, AC97_REG_SPDIF_CTRL, val);
1386 			}
1387 			if (as->ext_id & AC97_EXT_AUDIO_VRA)
1388 				extstat |= AC97_EXT_AUDIO_VRA;
1389 			ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat);
1390 			if (as->ext_id & AC97_EXT_AUDIO_VRA) {
1391 				/* VRA should be enabled. */
1392 				/* so it claims to do variable rate, let's make sure */
1393 				ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE,
1394 					   44100);
1395 				ac97_read(as, AC97_REG_PCM_FRONT_DAC_RATE,
1396 					  &rate);
1397 				if (rate != 44100) {
1398 					/* We can't believe ext_id */
1399 					as->ext_id = 0;
1400 					aprint_normal_dev(sc_dev,
1401 					    "Ignore these capabilities.\n");
1402 				}
1403 				/* restore the default value */
1404 				ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE,
1405 					   AC97_SINGLE_RATE);
1406 			}
1407 		}
1408 	} else if (as->type == AC97_CODEC_TYPE_MODEM) {
1409 		const struct sysctlnode *node;
1410 		const struct sysctlnode *node_line1;
1411 		const struct sysctlnode *node_line2;
1412 		uint16_t xrate = 8000;
1413 		uint16_t xval, reg;
1414 		int err;
1415 
1416 		ac97_read(as, AC97_REG_EXT_MODEM_ID, &as->ext_mid);
1417 		if (as->ext_mid == 0 || as->ext_mid == 0xffff) {
1418 			aprint_normal_dev(sc_dev, "no modem codec found\n");
1419 			return ENXIO;
1420 		}
1421 		as->type = AC97_CODEC_TYPE_MODEM;
1422 
1423 		/* Print capabilities */
1424 		bitmask_snprintf(as->ext_mid,
1425 				 "\20\5CID2\4CID1\3HANDSET\2LINE2\1LINE1",
1426 				 flagbuf, FLAGBUFLEN);
1427 		aprint_normal_dev(sc_dev, "ac97: ext mid %s",
1428 			      flagbuf);
1429 		aprint_normal(", %s codec\n",
1430 			      (as->ext_mid & 0xc000) == 0 ?
1431 			      "primary" : "secondary");
1432 
1433 		/* Setup modem and sysctls */
1434 		err = sysctl_createv(&as->log, 0, NULL, NULL, 0, CTLTYPE_NODE,
1435 				     "hw", NULL, NULL, 0, NULL, 0, CTL_HW,
1436 				     CTL_EOL);
1437 		if (err != 0)
1438 			goto setup_modem;
1439 		err = sysctl_createv(&as->log, 0, NULL, &node, 0,
1440 				     CTLTYPE_NODE, device_xname(sc_dev), NULL,
1441 				     NULL, 0, NULL, 0, CTL_HW, CTL_CREATE,
1442 				     CTL_EOL);
1443 		if (err != 0)
1444 			goto setup_modem;
1445 setup_modem:
1446 		/* reset */
1447 		ac97_write(as, AC97_REG_EXT_MODEM_ID, 1);
1448 
1449 		/* program rates */
1450 		xval = 0xff00 & ~AC97_EXT_MODEM_CTRL_PRA;
1451 		if (as->ext_mid & AC97_EXT_MODEM_LINE1) {
1452 			ac97_write(as, AC97_REG_LINE1_RATE, xrate);
1453 			xval &= ~(AC97_EXT_MODEM_CTRL_PRC |
1454 			       AC97_EXT_MODEM_CTRL_PRD);
1455 		}
1456 		if (as->ext_mid & AC97_EXT_MODEM_LINE2) {
1457 			ac97_write(as, AC97_REG_LINE2_RATE, xrate);
1458 			xval &= ~(AC97_EXT_MODEM_CTRL_PRE |
1459 			       AC97_EXT_MODEM_CTRL_PRF);
1460 		}
1461 		if (as->ext_mid & AC97_EXT_MODEM_HANDSET) {
1462 			ac97_write(as, AC97_REG_HANDSET_RATE, xrate);
1463 			xval &= ~(AC97_EXT_MODEM_CTRL_PRG |
1464 			       AC97_EXT_MODEM_CTRL_PRH);
1465 		}
1466 
1467 		/* power-up everything */
1468 		ac97_write(as, AC97_REG_EXT_MODEM_CTRL, 0);
1469 		for (i = 5000; i >= 0; i--) {
1470 			ac97_read(as, AC97_REG_EXT_MODEM_CTRL, &reg);
1471 			if ((reg & /*XXXval*/0xf) == /*XXXval*/0xf)
1472 			       break;
1473 			DELAY(1);
1474 		}
1475 		if (i <= 0) {
1476 			printf("%s: codec not responding, status=0x%x\n",
1477 			    device_xname(sc_dev), reg);
1478 			return ENXIO;
1479 		}
1480 
1481 		/* setup sysctls */
1482 		if (as->ext_mid & AC97_EXT_MODEM_LINE1) {
1483 			ac97_read(as, AC97_REG_GPIO_CFG, &reg);
1484 			reg &= ~AC97_GPIO_LINE1_OH;
1485 			ac97_write(as, AC97_REG_GPIO_CFG, reg);
1486 			ac97_read(as, AC97_REG_GPIO_POLARITY, &reg);
1487 			reg &= ~AC97_GPIO_LINE1_OH;
1488 			ac97_write(as, AC97_REG_GPIO_POLARITY, reg);
1489 
1490 			err = sysctl_createv(&as->log, 0, NULL, &node_line1,
1491 					     CTLFLAG_READWRITE, CTLTYPE_INT,
1492 					     "line1",
1493 					     SYSCTL_DESCR("off-hook line1"),
1494 					     ac97_sysctl_verify, 0, as, 0,
1495 					     CTL_HW, node->sysctl_num,
1496 					     CTL_CREATE, CTL_EOL);
1497 			if (err != 0)
1498 				goto sysctl_err;
1499 			as->offhook_line1_mib = node_line1->sysctl_num;
1500 		}
1501 		if (as->ext_mid & AC97_EXT_MODEM_LINE2) {
1502 			ac97_read(as, AC97_REG_GPIO_CFG, &reg);
1503 			reg &= ~AC97_GPIO_LINE2_OH;
1504 			ac97_write(as, AC97_REG_GPIO_CFG, reg);
1505 			ac97_read(as, AC97_REG_GPIO_POLARITY, &reg);
1506 			reg &= ~AC97_GPIO_LINE2_OH;
1507 			ac97_write(as, AC97_REG_GPIO_POLARITY, reg);
1508 
1509 			err = sysctl_createv(&as->log, 0, NULL, &node_line2,
1510 					     CTLFLAG_READWRITE, CTLTYPE_INT,
1511 					     "line2",
1512 					     SYSCTL_DESCR("off-hook line2"),
1513 					     ac97_sysctl_verify, 0, as, 0,
1514 					     CTL_HW, node->sysctl_num,
1515 					     CTL_CREATE, CTL_EOL);
1516 			if (err != 0)
1517 				goto sysctl_err;
1518 			as->offhook_line2_mib = node_line2->sysctl_num;
1519 		}
1520 sysctl_err:
1521 
1522 		ac97_write(as, AC97_REG_GPIO_STICKY, 0xffff);
1523 		ac97_write(as, AC97_REG_GPIO_WAKEUP, 0x0);
1524 		ac97_write(as, AC97_REG_MISC_AFE, 0x0);
1525 	}
1526 
1527 	as->source_info = (as->type == AC97_CODEC_TYPE_MODEM ?
1528 			   as->modem_source_info : as->audio_source_info);
1529 	ac97_setup_source_info(as);
1530 
1531 	memset(&ctl, 0, sizeof(ctl));
1532 	/* disable mutes */
1533 	for (i = 0; i < 11; i++) {
1534 		static struct {
1535 			const char *class, *device;
1536 		} d[11] = {
1537 			{ AudioCoutputs, AudioNmaster},
1538 			{ AudioCoutputs, AudioNheadphone},
1539 			{ AudioCoutputs, AudioNsurround},
1540 			{ AudioCoutputs, AudioNcenter},
1541 			{ AudioCoutputs, AudioNlfe},
1542 			{ AudioCinputs, AudioNdac},
1543 			{ AudioCinputs, AudioNcd},
1544 			{ AudioCinputs, AudioNline},
1545 			{ AudioCinputs, AudioNaux},
1546 			{ AudioCinputs, AudioNvideo},
1547 			{ AudioCrecord, AudioNvolume},
1548 		};
1549 
1550 		ctl.type = AUDIO_MIXER_ENUM;
1551 		ctl.un.ord = 0;
1552 
1553 		ctl.dev = ac97_get_portnum_by_name(&as->codec_if,
1554 			d[i].class, d[i].device, AudioNmute);
1555 		ac97_mixer_set_port(&as->codec_if, &ctl);
1556 	}
1557 	ctl.type = AUDIO_MIXER_ENUM;
1558 	ctl.un.ord = 0;
1559 	ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
1560 					   AudioNsource, NULL);
1561 	ac97_mixer_set_port(&as->codec_if, &ctl);
1562 
1563 	/* set a reasonable default volume */
1564 	ctl.type = AUDIO_MIXER_VALUE;
1565 	ctl.un.value.num_channels = 2;
1566 	ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = \
1567 	ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127;
1568 	ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1569 					   AudioNmaster, NULL);
1570 	ac97_mixer_set_port(&as->codec_if, &ctl);
1571 	ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1572 					   AudioNsurround, NULL);
1573 	ac97_mixer_set_port(&as->codec_if, &ctl);
1574 	ctl.un.value.num_channels = 1;
1575 	ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1576 					   AudioNcenter, NULL);
1577 	ac97_mixer_set_port(&as->codec_if, &ctl);
1578 	ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1579 					   AudioNlfe, NULL);
1580 	ac97_mixer_set_port(&as->codec_if, &ctl);
1581 
1582 	if (initfunc != NULL)
1583 		initfunc(as);
1584 
1585 	/* restore AC97_REG_POWER */
1586 	if (as->type == AC97_CODEC_TYPE_AUDIO)
1587 		ac97_write(as, AC97_REG_POWER, as->power_reg);
1588 
1589 	return 0;
1590 }
1591 
1592 static void
1593 ac97_detach(struct ac97_codec_if *codec_if)
1594 {
1595 	struct ac97_softc *as;
1596 
1597 	as = (struct ac97_softc *)codec_if;
1598 	ac97_write(as, AC97_REG_POWER, AC97_POWER_IN | AC97_POWER_OUT
1599 		   | AC97_POWER_MIXER | AC97_POWER_MIXER_VREF
1600 		   | AC97_POWER_ACLINK | AC97_POWER_CLK | AC97_POWER_AUX
1601 		   | POWER_EAMP_OFF(as));
1602 	free(as, M_DEVBUF);
1603 }
1604 
1605 static void
1606 ac97_lock(struct ac97_codec_if *codec_if)
1607 {
1608 	struct ac97_softc *as;
1609 
1610 	as = (struct ac97_softc *)codec_if;
1611 	as->lock_counter++;
1612 }
1613 
1614 static void
1615 ac97_unlock(struct ac97_codec_if *codec_if)
1616 {
1617 	struct ac97_softc *as;
1618 
1619 	as = (struct ac97_softc *)codec_if;
1620 	as->lock_counter--;
1621 }
1622 
1623 static int
1624 ac97_query_devinfo(struct ac97_codec_if *codec_if, mixer_devinfo_t *dip)
1625 {
1626 	struct ac97_softc *as;
1627 	struct ac97_source_info *si;
1628 	const char *name;
1629 
1630 	as = (struct ac97_softc *)codec_if;
1631 	if (dip->index < as->num_source_info) {
1632 		si = &as->source_info[dip->index];
1633 		dip->type = si->type;
1634 		dip->mixer_class = si->mixer_class;
1635 		dip->prev = si->prev;
1636 		dip->next = si->next;
1637 
1638 		if (si->qualifier)
1639 			name = si->qualifier;
1640 		else if (si->device)
1641 			name = si->device;
1642 		else if (si->class)
1643 			name = si->class;
1644 		else
1645 			name = 0;
1646 
1647 		if (name)
1648 			strcpy(dip->label.name, name);
1649 
1650 		memcpy(&dip->un, si->info, si->info_size);
1651 
1652 		/* Set the delta for volume sources */
1653 		if (dip->type == AUDIO_MIXER_VALUE)
1654 			dip->un.v.delta = 1 << (8 - si->bits);
1655 
1656 		return 0;
1657 	}
1658 
1659 	return ENXIO;
1660 }
1661 
1662 static int
1663 ac97_mixer_set_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
1664 {
1665 	struct ac97_softc *as;
1666 	struct ac97_source_info *si;
1667 	uint16_t mask;
1668 	uint16_t val, newval;
1669 	int error;
1670 	bool spdif;
1671 
1672 	as = (struct ac97_softc *)codec_if;
1673 	if (cp->dev < 0 || cp->dev >= as->num_source_info)
1674 		return EINVAL;
1675 	si = &as->source_info[cp->dev];
1676 
1677 	if (cp->type == AUDIO_MIXER_CLASS || cp->type != si->type)
1678 		return EINVAL;
1679 	spdif = si->req_feature == CHECK_SPDIF && si->reg == AC97_REG_EXT_AUDIO_CTRL;
1680 	if (spdif && as->lock_counter >= 0) {
1681 		/* When the value of lock_counter is the default 0,
1682 		 * it is not allowed to change the SPDIF mode. */
1683 		return EBUSY;
1684 	}
1685 
1686 	ac97_read(as, si->reg, &val);
1687 
1688 	DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
1689 
1690 	mask = (1 << si->bits) - 1;
1691 
1692 	switch (cp->type) {
1693 	case AUDIO_MIXER_ENUM:
1694 		if (cp->un.ord > mask || cp->un.ord < 0)
1695 			return EINVAL;
1696 
1697 		newval = (cp->un.ord << si->ofs);
1698 		if (si->reg == AC97_REG_RECORD_SELECT) {
1699 			newval |= (newval << (8 + si->ofs));
1700 			mask |= (mask << 8);
1701 			mask = mask << si->ofs;
1702 		} else if (si->reg == AC97_REG_SURR_MASTER) {
1703 			newval = cp->un.ord ? 0x8080 : 0x0000;
1704 			mask = 0x8080;
1705 		} else
1706 			mask = mask << si->ofs;
1707 		break;
1708 	case AUDIO_MIXER_VALUE:
1709 	{
1710 		const struct audio_mixer_value *value = si->info;
1711 		uint16_t  l, r, ol, or;
1712 		int deltal, deltar;
1713 
1714 		if ((cp->un.value.num_channels <= 0) ||
1715 		    (cp->un.value.num_channels > value->num_channels))
1716 			return EINVAL;
1717 
1718 		if (cp->un.value.num_channels == 1) {
1719 			l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
1720 		} else {
1721 			if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
1722 				l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1723 				r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1724 			} else {	/* left/right is reversed here */
1725 				r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1726 				l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1727 			}
1728 
1729 		}
1730 
1731 		if (!si->polarity) {
1732 			l = 255 - l;
1733 			r = 255 - r;
1734 		}
1735 
1736 		ol = (val >> (8+si->ofs)) & mask;
1737 		or = (val >> si->ofs) & mask;
1738 
1739 		deltal = (ol << (8 - si->bits)) - l;
1740 		deltar = (or << (8 - si->bits)) - r;
1741 
1742 		l = l >> (8 - si->bits);
1743 		r = r >> (8 - si->bits);
1744 
1745 		if (deltal && ol == l)
1746 			l += (deltal > 0) ? (l ? -1 : 0) : (l < mask ? 1 : 0);
1747 		if (deltar && or == r)
1748 			r += (deltar > 0) ? (r ? -1 : 0) : (r < mask ? 1 : 0);
1749 
1750 		newval = ((r & mask) << si->ofs);
1751 		if (value->num_channels == 2) {
1752 			newval = newval | ((l & mask) << (si->ofs+8));
1753 			mask |= (mask << 8);
1754 		}
1755 		mask = mask << si->ofs;
1756 		break;
1757 	}
1758 	default:
1759 		return EINVAL;
1760 	}
1761 
1762 	error = ac97_write(as, si->reg, (val & ~mask) | newval);
1763 	if (error)
1764 		return error;
1765 
1766 	if (spdif && as->host_if->spdif_event != NULL) {
1767 		DPRINTF(("%s: call spdif_event(%d)\n", __func__, cp->un.ord));
1768 		as->host_if->spdif_event(as->host_if->arg, cp->un.ord);
1769 	}
1770 	return 0;
1771 }
1772 
1773 static int
1774 ac97_get_portnum_by_name(struct ac97_codec_if *codec_if, const char *class,
1775 			 const char *device, const char *qualifier)
1776 {
1777 	struct ac97_softc *as;
1778 	int idx;
1779 
1780 	as = (struct ac97_softc *)codec_if;
1781 	for (idx = 0; idx < as->num_source_info; idx++) {
1782 		struct ac97_source_info *si = &as->source_info[idx];
1783 		if (ac97_str_equal(class, si->class) &&
1784 		    ac97_str_equal(device, si->device) &&
1785 		    ac97_str_equal(qualifier, si->qualifier))
1786 			return idx;
1787 	}
1788 
1789 	return -1;
1790 }
1791 
1792 static int
1793 ac97_mixer_get_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
1794 {
1795 	struct ac97_softc *as;
1796 	struct ac97_source_info *si;
1797 	uint16_t mask;
1798 	uint16_t val;
1799 
1800 	as = (struct ac97_softc *)codec_if;
1801 	si = &as->source_info[cp->dev];
1802 	if (cp->dev < 0 || cp->dev >= as->num_source_info)
1803 		return EINVAL;
1804 
1805 	if (cp->type != si->type)
1806 		return EINVAL;
1807 
1808 	ac97_read(as, si->reg, &val);
1809 
1810 	DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
1811 
1812 	mask = (1 << si->bits) - 1;
1813 
1814 	switch (cp->type) {
1815 	case AUDIO_MIXER_ENUM:
1816 		cp->un.ord = (val >> si->ofs) & mask;
1817 		DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n",
1818 			     val, si->ofs, mask, cp->un.ord));
1819 		break;
1820 	case AUDIO_MIXER_VALUE:
1821 	{
1822 		const struct audio_mixer_value *value = si->info;
1823 		uint16_t  l, r;
1824 
1825 		if ((cp->un.value.num_channels <= 0) ||
1826 		    (cp->un.value.num_channels > value->num_channels))
1827 			return EINVAL;
1828 
1829 		if (value->num_channels == 1) {
1830 			l = r = (val >> si->ofs) & mask;
1831 		} else {
1832 			if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
1833 				l = (val >> (si->ofs + 8)) & mask;
1834 				r = (val >> si->ofs) & mask;
1835 			} else {	/* host has reversed channels */
1836 				r = (val >> (si->ofs + 8)) & mask;
1837 				l = (val >> si->ofs) & mask;
1838 			}
1839 		}
1840 
1841 		l = (l << (8 - si->bits));
1842 		r = (r << (8 - si->bits));
1843 		if (!si->polarity) {
1844 			l = 255 - l;
1845 			r = 255 - r;
1846 		}
1847 
1848 		/* The EAP driver averages l and r for stereo
1849 		   channels that are requested in MONO mode. Does this
1850 		   make sense? */
1851 		if (cp->un.value.num_channels == 1) {
1852 			cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l;
1853 		} else if (cp->un.value.num_channels == 2) {
1854 			cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
1855 			cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
1856 		}
1857 
1858 		break;
1859 	}
1860 	default:
1861 		return EINVAL;
1862 	}
1863 
1864 	return 0;
1865 }
1866 
1867 
1868 static int
1869 ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_int *rate)
1870 {
1871 	struct ac97_softc *as;
1872 	u_int value;
1873 	uint16_t ext_stat;
1874 	uint16_t actual;
1875 	uint16_t power;
1876 	uint16_t power_bit;
1877 
1878 	as = (struct ac97_softc *)codec_if;
1879 	if (target == AC97_REG_PCM_MIC_ADC_RATE) {
1880 		if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1881 			*rate = AC97_SINGLE_RATE;
1882 			return 0;
1883 		}
1884 	} else {
1885 		if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1886 			*rate = AC97_SINGLE_RATE;
1887 			return 0;
1888 		}
1889 	}
1890 	value = *rate * AC97_STANDARD_CLOCK / as->ac97_clock;
1891 	ext_stat = 0;
1892 	/*
1893 	 * PCM_FRONT_DAC_RATE/PCM_SURR_DAC_RATE/PCM_LFE_DAC_RATE
1894 	 *	Check VRA, DRA
1895 	 * PCM_LR_ADC_RATE
1896 	 *	Check VRA
1897 	 * PCM_MIC_ADC_RATE
1898 	 *	Check VRM
1899 	 */
1900 	switch (target) {
1901 	case AC97_REG_PCM_FRONT_DAC_RATE:
1902 	case AC97_REG_PCM_SURR_DAC_RATE:
1903 	case AC97_REG_PCM_LFE_DAC_RATE:
1904 		power_bit = AC97_POWER_OUT;
1905 		if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1906 			*rate = AC97_SINGLE_RATE;
1907 			return 0;
1908 		}
1909 		if (as->ext_id & AC97_EXT_AUDIO_DRA) {
1910 			ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &ext_stat);
1911 			if (value > 0x1ffff) {
1912 				return EINVAL;
1913 			} else if (value > 0xffff) {
1914 				/* Enable DRA */
1915 				ext_stat |= AC97_EXT_AUDIO_DRA;
1916 				ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1917 				value /= 2;
1918 			} else {
1919 				/* Disable DRA */
1920 				ext_stat &= ~AC97_EXT_AUDIO_DRA;
1921 				ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1922 			}
1923 		} else {
1924 			if (value > 0xffff)
1925 				return EINVAL;
1926 		}
1927 		break;
1928 	case AC97_REG_PCM_LR_ADC_RATE:
1929 		power_bit = AC97_POWER_IN;
1930 		if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1931 			*rate = AC97_SINGLE_RATE;
1932 			return 0;
1933 		}
1934 		if (value > 0xffff)
1935 			return EINVAL;
1936 		break;
1937 	case AC97_REG_PCM_MIC_ADC_RATE:
1938 		power_bit = AC97_POWER_IN;
1939 		if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1940 			*rate = AC97_SINGLE_RATE;
1941 			return 0;
1942 		}
1943 		if (value > 0xffff)
1944 			return EINVAL;
1945 		break;
1946 	default:
1947 		printf("%s: Unknown register: 0x%x\n", __func__, target);
1948 		return EINVAL;
1949 	}
1950 
1951 	ac97_read(as, AC97_REG_POWER, &power);
1952 	ac97_write(as, AC97_REG_POWER, power | power_bit);
1953 
1954 	ac97_write(as, target, (uint16_t)value);
1955 	ac97_read(as, target, &actual);
1956 	actual = (uint32_t)actual * as->ac97_clock / AC97_STANDARD_CLOCK;
1957 
1958 	ac97_write(as, AC97_REG_POWER, power);
1959 	if (ext_stat & AC97_EXT_AUDIO_DRA) {
1960 		*rate = actual * 2;
1961 	} else {
1962 		*rate = actual;
1963 	}
1964 	return 0;
1965 }
1966 
1967 static void
1968 ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock)
1969 {
1970 	struct ac97_softc *as;
1971 
1972 	as = (struct ac97_softc *)codec_if;
1973 	as->ac97_clock = clock;
1974 }
1975 
1976 static uint16_t
1977 ac97_get_extcaps(struct ac97_codec_if *codec_if)
1978 {
1979 	struct ac97_softc *as;
1980 
1981 	as = (struct ac97_softc *)codec_if;
1982 	return as->ext_id;
1983 }
1984 
1985 static int
1986 ac97_add_port(struct ac97_softc *as, const struct ac97_source_info *src)
1987 {
1988 	struct ac97_source_info *si;
1989 	int ouridx, idx;
1990 
1991 	if ((as->type == AC97_CODEC_TYPE_AUDIO &&
1992 	     as->num_source_info >= AUDIO_MAX_SOURCES) ||
1993 	    (as->type == AC97_CODEC_TYPE_MODEM &&
1994 	     as->num_source_info >= MODEM_MAX_SOURCES)) {
1995 		printf("%s: internal error: increase MAX_SOURCES in %s\n",
1996 		       __func__, __FILE__);
1997 		return -1;
1998 	}
1999 	if (!ac97_check_capability(as, src->req_feature))
2000 		return -1;
2001 	ouridx = as->num_source_info;
2002 	si = &as->source_info[ouridx];
2003 	memcpy(si, src, sizeof(*si));
2004 
2005 	switch (si->type) {
2006 	case AUDIO_MIXER_CLASS:
2007 	case AUDIO_MIXER_VALUE:
2008 		printf("%s: adding class/value is not supported yet.\n",
2009 		       __func__);
2010 		return -1;
2011 	case AUDIO_MIXER_ENUM:
2012 		break;
2013 	default:
2014 		printf("%s: unknown type: %d\n", __func__, si->type);
2015 		return -1;
2016 	}
2017 	as->num_source_info++;
2018 
2019 	si->mixer_class = ac97_get_portnum_by_name(&as->codec_if, si->class,
2020 						   NULL, NULL);
2021 	/* Find the root of the device */
2022 	idx = ac97_get_portnum_by_name(&as->codec_if, si->class,
2023 				       si->device, NULL);
2024 	/* Find the last item */
2025 	while (as->source_info[idx].next != AUDIO_MIXER_LAST)
2026 		idx = as->source_info[idx].next;
2027 	/* Append */
2028 	as->source_info[idx].next = ouridx;
2029 	si->prev = idx;
2030 	si->next = AUDIO_MIXER_LAST;
2031 
2032 	return 0;
2033 }
2034 
2035 /**
2036  * Codec-dependent initialization
2037  */
2038 
2039 #define	AD1980_REG_MISC	0x76
2040 #define		AD1980_MISC_MBG0	0x0001	/* 0 1888/1980/1981 /1985 */
2041 #define		AD1980_MISC_MBG1	0x0002	/* 1 1888/1980/1981 /1985 */
2042 #define		AD1980_MISC_VREFD	0x0004	/* 2 1888/1980/1981 /1985 */
2043 #define		AD1980_MISC_VREFH	0x0008	/* 3 1888/1980/1981 /1985 */
2044 #define		AD1980_MISC_SRU		0x0010	/* 4 1888/1980      /1985 */
2045 #define		AD1980_MISC_LOSEL	0x0020	/* 5 1888/1980/1981 /1985 */
2046 #define		AD1980_MISC_2CMIC	0x0040	/* 6      1980/1981B/1985 */
2047 #define		AD1980_MISC_SPRD	0x0080	/* 7 1888/1980      /1985 */
2048 #define		AD1980_MISC_DMIX0	0x0100	/* 8 1888/1980      /1985 */
2049 #define		AD1980_MISC_DMIX1	0x0200	/* 9 1888/1980      /1985 */
2050 #define		AD1980_MISC_HPSEL	0x0400	/*10 1888/1980      /1985 */
2051 #define		AD1980_MISC_CLDIS	0x0800	/*11 1888/1980      /1985 */
2052 #define		AD1980_MISC_LODIS	0x1000	/*12 1888/1980/1981 /1985 */
2053 #define		AD1980_MISC_MSPLT	0x2000	/*13 1888/1980/1981 /1985 */
2054 #define		AD1980_MISC_AC97NC	0x4000	/*14 1888/1980      /1985 */
2055 #define		AD1980_MISC_DACZ	0x8000	/*15 1888/1980/1981 /1985 */
2056 #define	AD1981_REG_MISC	0x76
2057 #define		AD1981_MISC_MADST	0x0010  /* 4 */
2058 #define		AD1981A_MISC_MADPD	0x0040  /* 6 */
2059 #define		AD1981B_MISC_MADPD	0x0080  /* 7 */
2060 #define		AD1981_MISC_FMXE	0x0200  /* 9 */
2061 #define		AD1981_MISC_DAM		0x0800  /*11 */
2062 static void
2063 ac97_ad198x_init(struct ac97_softc *as)
2064 {
2065 	int i;
2066 	uint16_t misc;
2067 
2068 	ac97_read(as, AD1980_REG_MISC, &misc);
2069 	ac97_write(as, AD1980_REG_MISC,
2070 		   misc | AD1980_MISC_LOSEL | AD1980_MISC_HPSEL);
2071 
2072 	for (i = 0; i < as->num_source_info; i++) {
2073 		if (as->source_info[i].type != AUDIO_MIXER_VALUE)
2074 			continue;
2075 
2076 		if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME)
2077 			as->source_info[i].reg = AC97_REG_SURR_MASTER;
2078 		else if (as->source_info[i].reg == AC97_REG_SURR_MASTER)
2079 			as->source_info[i].reg = AC97_REG_MASTER_VOLUME;
2080 	}
2081 }
2082 
2083 #define ALC650_REG_MULTI_CHANNEL_CONTROL	0x6a
2084 #define		ALC650_MCC_SLOT_MODIFY_MASK		0xc000
2085 #define		ALC650_MCC_FRONTDAC_FROM_SPDIFIN	0x2000 /* 13 */
2086 #define		ALC650_MCC_SPDIFOUT_FROM_ADC		0x1000 /* 12 */
2087 #define		ALC650_MCC_PCM_FROM_SPDIFIN		0x0800 /* 11 */
2088 #define		ALC650_MCC_MIC_OR_CENTERLFE		0x0400 /* 10 */
2089 #define		ALC650_MCC_LINEIN_OR_SURROUND		0x0200 /* 9 */
2090 #define		ALC650_MCC_INDEPENDENT_MASTER_L		0x0080 /* 7 */
2091 #define		ALC650_MCC_INDEPENDENT_MASTER_R		0x0040 /* 6 */
2092 #define		ALC650_MCC_ANALOG_TO_CENTERLFE		0x0020 /* 5 */
2093 #define		ALC650_MCC_ANALOG_TO_SURROUND		0x0010 /* 4 */
2094 #define		ALC650_MCC_EXCHANGE_CENTERLFE		0x0008 /* 3 */
2095 #define		ALC650_MCC_CENTERLFE_DOWNMIX		0x0004 /* 2 */
2096 #define		ALC650_MCC_SURROUND_DOWNMIX		0x0002 /* 1 */
2097 #define		ALC650_MCC_LINEOUT_TO_SURROUND		0x0001 /* 0 */
2098 static void
2099 ac97_alc650_init(struct ac97_softc *as)
2100 {
2101 	static const struct ac97_source_info sources[6] = {
2102 		{ AudioCoutputs, AudioNsurround, "lineinjack",
2103 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2104 		  ALC650_REG_MULTI_CHANNEL_CONTROL,
2105 		  0x0000, 1, 9, 0, 0, 0, CHECK_SURROUND, 0, 0, 0, },
2106 		{ AudioCoutputs, AudioNsurround, "mixtofront",
2107 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2108 		  ALC650_REG_MULTI_CHANNEL_CONTROL,
2109 		  0x0000, 1, 1, 0, 0, 0, CHECK_SURROUND, 0, 0, 0, },
2110 		{ AudioCoutputs, AudioNcenter, "micjack",
2111 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2112 		  ALC650_REG_MULTI_CHANNEL_CONTROL,
2113 		  0x0000, 1, 10, 0, 0, 0, CHECK_CENTER, 0, 0, 0, },
2114 		{ AudioCoutputs, AudioNlfe, "micjack",
2115 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2116 		  ALC650_REG_MULTI_CHANNEL_CONTROL,
2117 		  0x0000, 1, 10, 0, 0, 0, CHECK_LFE, 0, 0, 0, },
2118 		{ AudioCoutputs, AudioNcenter, "mixtofront",
2119 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2120 		  ALC650_REG_MULTI_CHANNEL_CONTROL,
2121 		  0x0000, 1, 2, 0, 0, 0, CHECK_CENTER, 0, 0, 0, },
2122 		{ AudioCoutputs, AudioNlfe, "mixtofront",
2123 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2124 		  ALC650_REG_MULTI_CHANNEL_CONTROL,
2125 		  0x0000, 1, 2, 0, 0, 0, CHECK_LFE, 0, 0, 0, },
2126 	};
2127 
2128 	ac97_add_port(as, &sources[0]);
2129 	ac97_add_port(as, &sources[1]);
2130 	ac97_add_port(as, &sources[2]);
2131 	ac97_add_port(as, &sources[3]);
2132 	ac97_add_port(as, &sources[4]);
2133 	ac97_add_port(as, &sources[5]);
2134 }
2135 
2136 #define VT1616_REG_IO_CONTROL	0x5a
2137 #define		VT1616_IC_LVL			(1 << 15)
2138 #define		VT1616_IC_LFECENTER_TO_FRONT	(1 << 12)
2139 #define		VT1616_IC_SURROUND_TO_FRONT	(1 << 11)
2140 #define		VT1616_IC_BPDC			(1 << 10)
2141 #define		VT1616_IC_DC			(1 << 9)
2142 #define		VT1616_IC_IB_MASK		0x000c
2143 static void
2144 ac97_vt1616_init(struct ac97_softc *as)
2145 {
2146 	static const struct ac97_source_info sources[3] = {
2147 		{ AudioCoutputs, AudioNsurround, "mixtofront",
2148 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2149 		  VT1616_REG_IO_CONTROL,
2150 		  0x0000, 1, 11, 0, 0, 0, CHECK_SURROUND, 0, 0, 0, },
2151 		{ AudioCoutputs, AudioNcenter, "mixtofront",
2152 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2153 		  VT1616_REG_IO_CONTROL,
2154 		  0x0000, 1, 12, 0, 0, 0, CHECK_CENTER, 0, 0, 0, },
2155 		{ AudioCoutputs, AudioNlfe, "mixtofront",
2156 		  AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
2157 		  VT1616_REG_IO_CONTROL,
2158 		  0x0000, 1, 12, 0, 0, 0, CHECK_LFE, 0, 0, 0, },
2159 	};
2160 
2161 	ac97_add_port(as, &sources[0]);
2162 	ac97_add_port(as, &sources[1]);
2163 	ac97_add_port(as, &sources[2]);
2164 }
2165 
2166 static int
2167 ac97_modem_offhook_set(struct ac97_softc *as, int line, int newval)
2168 {
2169 	uint16_t val;
2170 
2171 	val = as->shadow_reg[AC97_REG_GPIO_STATUS >> 1];
2172 	switch (newval) {
2173 	case 0:
2174 		val &= ~line;
2175 		break;
2176 	case 1:
2177 		val |= line;
2178 		break;
2179 	}
2180 	ac97_write(as, AC97_REG_GPIO_STATUS, val);
2181 
2182 	return 0;
2183 }
2184 
2185 static int
2186 ac97_sysctl_verify(SYSCTLFN_ARGS)
2187 {
2188 	int error, tmp;
2189 	struct sysctlnode node;
2190 	struct ac97_softc *as;
2191 
2192 	node = *rnode;
2193 	as = rnode->sysctl_data;
2194 	if (node.sysctl_num == as->offhook_line1_mib) {
2195 		tmp = as->offhook_line1;
2196 		node.sysctl_data = &tmp;
2197 		error = sysctl_lookup(SYSCTLFN_CALL(&node));
2198 		if (error || newp == NULL)
2199 			return error;
2200 
2201 		if (tmp < 0 || tmp > 1)
2202 			return EINVAL;
2203 
2204 		as->offhook_line1 = tmp;
2205 		ac97_modem_offhook_set(as, AC97_GPIO_LINE1_OH, tmp);
2206 	} else if (node.sysctl_num == as->offhook_line2_mib) {
2207 		tmp = as->offhook_line2;
2208 		node.sysctl_data = &tmp;
2209 		error = sysctl_lookup(SYSCTLFN_CALL(&node));
2210 		if (error || newp == NULL)
2211 			return error;
2212 
2213 		if (tmp < 0 || tmp > 1)
2214 			return EINVAL;
2215 
2216 		as->offhook_line2 = tmp;
2217 		ac97_modem_offhook_set(as, AC97_GPIO_LINE2_OH, tmp);
2218 	}
2219 
2220 	return 0;
2221 }
2222