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