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