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