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