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