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