ac97.c revision 1.73 1 /* $NetBSD: ac97.c,v 1.73 2005/04/12 21:11:43 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.73 2005/04/12 21:11:43 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 = 5000; 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: codec not responding, status=0x%x\n",
1281 sc_dev->dv_xname, reg);
1282 return ENXIO;
1283 }
1284
1285 /* setup sysctls */
1286 if (as->ext_mid & AC97_EXT_MODEM_LINE1) {
1287 ac97_read(as, AC97_REG_GPIO_CFG, ®);
1288 reg &= ~AC97_GPIO_LINE1_OH;
1289 ac97_write(as, AC97_REG_GPIO_CFG, reg);
1290 ac97_read(as, AC97_REG_GPIO_POLARITY, ®);
1291 reg &= ~AC97_GPIO_LINE1_OH;
1292 ac97_write(as, AC97_REG_GPIO_POLARITY, reg);
1293
1294 err = sysctl_createv(&as->log, 0, NULL, &node_line1,
1295 CTLFLAG_READWRITE, CTLTYPE_INT,
1296 "line1",
1297 SYSCTL_DESCR("off-hook line1"),
1298 ac97_sysctl_verify, 0, as, 0,
1299 CTL_HW, node->sysctl_num,
1300 CTL_CREATE, CTL_EOL);
1301 if (err != 0)
1302 goto sysctl_err;
1303 as->offhook_line1_mib = node_line1->sysctl_num;
1304 }
1305 if (as->ext_mid & AC97_EXT_MODEM_LINE2) {
1306 ac97_read(as, AC97_REG_GPIO_CFG, ®);
1307 reg &= ~AC97_GPIO_LINE2_OH;
1308 ac97_write(as, AC97_REG_GPIO_CFG, reg);
1309 ac97_read(as, AC97_REG_GPIO_POLARITY, ®);
1310 reg &= ~AC97_GPIO_LINE2_OH;
1311 ac97_write(as, AC97_REG_GPIO_POLARITY, reg);
1312
1313 err = sysctl_createv(&as->log, 0, NULL, &node_line2,
1314 CTLFLAG_READWRITE, CTLTYPE_INT,
1315 "line2",
1316 SYSCTL_DESCR("off-hook line2"),
1317 ac97_sysctl_verify, 0, as, 0,
1318 CTL_HW, node->sysctl_num,
1319 CTL_CREATE, CTL_EOL);
1320 if (err != 0)
1321 goto sysctl_err;
1322 as->offhook_line2_mib = node_line2->sysctl_num;
1323 }
1324 sysctl_err:
1325
1326 ac97_write(as, AC97_REG_GPIO_STICKY, 0xffff);
1327 ac97_write(as, AC97_REG_GPIO_WAKEUP, 0x0);
1328 ac97_write(as, AC97_REG_MISC_AFE, 0x0);
1329 }
1330
1331 as->source_info = (as->type == AC97_CODEC_TYPE_MODEM ?
1332 as->modem_source_info : as->audio_source_info);
1333 ac97_setup_source_info(as);
1334
1335 memset(&ctl, 0, sizeof(ctl));
1336 /* disable mutes */
1337 for (i = 0; i < 11; i++) {
1338 static struct {
1339 char *class, *device;
1340 } d[11] = {
1341 { AudioCoutputs, AudioNmaster},
1342 { AudioCoutputs, AudioNheadphone},
1343 { AudioCoutputs, AudioNsurround},
1344 { AudioCoutputs, AudioNcenter},
1345 { AudioCoutputs, AudioNlfe},
1346 { AudioCinputs, AudioNdac},
1347 { AudioCinputs, AudioNcd},
1348 { AudioCinputs, AudioNline},
1349 { AudioCinputs, AudioNaux},
1350 { AudioCinputs, AudioNvideo},
1351 { AudioCrecord, AudioNvolume},
1352 };
1353
1354 ctl.type = AUDIO_MIXER_ENUM;
1355 ctl.un.ord = 0;
1356
1357 ctl.dev = ac97_get_portnum_by_name(&as->codec_if,
1358 d[i].class, d[i].device, AudioNmute);
1359 ac97_mixer_set_port(&as->codec_if, &ctl);
1360 }
1361 ctl.type = AUDIO_MIXER_ENUM;
1362 ctl.un.ord = 0;
1363 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
1364 AudioNsource, NULL);
1365 ac97_mixer_set_port(&as->codec_if, &ctl);
1366
1367 /* set a reasonable default volume */
1368 ctl.type = AUDIO_MIXER_VALUE;
1369 ctl.un.value.num_channels = 2;
1370 ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = \
1371 ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127;
1372 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1373 AudioNmaster, NULL);
1374 ac97_mixer_set_port(&as->codec_if, &ctl);
1375 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1376 AudioNsurround, NULL);
1377 ac97_mixer_set_port(&as->codec_if, &ctl);
1378 ctl.un.value.num_channels = 1;
1379 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1380 AudioNcenter, NULL);
1381 ac97_mixer_set_port(&as->codec_if, &ctl);
1382 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1383 AudioNlfe, NULL);
1384 ac97_mixer_set_port(&as->codec_if, &ctl);
1385
1386 if (initfunc != NULL)
1387 initfunc(as);
1388 return 0;
1389 }
1390
1391 static void
1392 ac97_detach(struct ac97_codec_if *codec_if)
1393 {
1394 struct ac97_softc *as;
1395
1396 as = (struct ac97_softc *)codec_if;
1397 ac97_write(as, AC97_REG_POWER, AC97_POWER_IN | AC97_POWER_OUT
1398 | AC97_POWER_MIXER | AC97_POWER_MIXER_VREF
1399 | AC97_POWER_ACLINK | AC97_POWER_CLK | AC97_POWER_AUX
1400 | AC97_POWER_EAMP);
1401 free(as, M_DEVBUF);
1402 }
1403
1404 static int
1405 ac97_query_devinfo(struct ac97_codec_if *codec_if, mixer_devinfo_t *dip)
1406 {
1407 struct ac97_softc *as;
1408 struct ac97_source_info *si;
1409 const char *name;
1410
1411 as = (struct ac97_softc *)codec_if;
1412 if (dip->index < as->num_source_info) {
1413 si = &as->source_info[dip->index];
1414 dip->type = si->type;
1415 dip->mixer_class = si->mixer_class;
1416 dip->prev = si->prev;
1417 dip->next = si->next;
1418
1419 if (si->qualifier)
1420 name = si->qualifier;
1421 else if (si->device)
1422 name = si->device;
1423 else if (si->class)
1424 name = si->class;
1425 else
1426 name = 0;
1427
1428 if (name)
1429 strcpy(dip->label.name, name);
1430
1431 memcpy(&dip->un, si->info, si->info_size);
1432
1433 /* Set the delta for volume sources */
1434 if (dip->type == AUDIO_MIXER_VALUE)
1435 dip->un.v.delta = 1 << (8 - si->bits);
1436
1437 return 0;
1438 }
1439
1440 return ENXIO;
1441 }
1442
1443 static int
1444 ac97_mixer_set_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
1445 {
1446 struct ac97_softc *as;
1447 struct ac97_source_info *si;
1448 uint16_t mask;
1449 uint16_t val, newval;
1450 int error;
1451
1452 as = (struct ac97_softc *)codec_if;
1453 si = &as->source_info[cp->dev];
1454 if (cp->dev < 0 || cp->dev >= as->num_source_info)
1455 return EINVAL;
1456
1457 if (cp->type != si->type)
1458 return EINVAL;
1459
1460 ac97_read(as, si->reg, &val);
1461
1462 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
1463
1464 mask = (1 << si->bits) - 1;
1465
1466 switch (cp->type) {
1467 case AUDIO_MIXER_ENUM:
1468 if (cp->un.ord > mask || cp->un.ord < 0)
1469 return EINVAL;
1470
1471 newval = (cp->un.ord << si->ofs);
1472 if (si->reg == AC97_REG_RECORD_SELECT) {
1473 newval |= (newval << (8 + si->ofs));
1474 mask |= (mask << 8);
1475 mask = mask << si->ofs;
1476 } else if (si->reg == AC97_REG_SURR_MASTER) {
1477 newval = cp->un.ord ? 0x8080 : 0x0000;
1478 mask = 0x8080;
1479 } else
1480 mask = mask << si->ofs;
1481 break;
1482 case AUDIO_MIXER_VALUE:
1483 {
1484 const struct audio_mixer_value *value = si->info;
1485 uint16_t l, r, ol, or;
1486 int deltal, deltar;
1487
1488 if ((cp->un.value.num_channels <= 0) ||
1489 (cp->un.value.num_channels > value->num_channels))
1490 return EINVAL;
1491
1492 if (cp->un.value.num_channels == 1) {
1493 l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
1494 } else {
1495 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
1496 l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1497 r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1498 } else { /* left/right is reversed here */
1499 r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1500 l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1501 }
1502
1503 }
1504
1505 if (!si->polarity) {
1506 l = 255 - l;
1507 r = 255 - r;
1508 }
1509
1510 ol = (val >> (8+si->ofs)) & mask;
1511 or = (val >> si->ofs) & mask;
1512
1513 deltal = (ol << (8 - si->bits)) - l;
1514 deltar = (or << (8 - si->bits)) - r;
1515
1516 l = l >> (8 - si->bits);
1517 r = r >> (8 - si->bits);
1518
1519 if (deltal && ol == l)
1520 l += (deltal > 0) ? (l ? -1 : 0) : (l < mask ? 1 : 0);
1521 if (deltar && or == r)
1522 r += (deltar > 0) ? (r ? -1 : 0) : (r < mask ? 1 : 0);
1523
1524 newval = ((r & mask) << si->ofs);
1525 if (value->num_channels == 2) {
1526 newval = newval | ((l & mask) << (si->ofs+8));
1527 mask |= (mask << 8);
1528 }
1529 mask = mask << si->ofs;
1530 break;
1531 }
1532 default:
1533 return EINVAL;
1534 }
1535
1536 error = ac97_write(as, si->reg, (val & ~mask) | newval);
1537 if (error)
1538 return error;
1539
1540 return 0;
1541 }
1542
1543 static int
1544 ac97_get_portnum_by_name(struct ac97_codec_if *codec_if, const char *class,
1545 const char *device, const char *qualifier)
1546 {
1547 struct ac97_softc *as;
1548 int idx;
1549
1550 as = (struct ac97_softc *)codec_if;
1551 for (idx = 0; idx < as->num_source_info; idx++) {
1552 struct ac97_source_info *si = &as->source_info[idx];
1553 if (ac97_str_equal(class, si->class) &&
1554 ac97_str_equal(device, si->device) &&
1555 ac97_str_equal(qualifier, si->qualifier))
1556 return idx;
1557 }
1558
1559 return -1;
1560 }
1561
1562 static int
1563 ac97_mixer_get_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
1564 {
1565 struct ac97_softc *as;
1566 struct ac97_source_info *si;
1567 uint16_t mask;
1568 uint16_t val;
1569
1570 as = (struct ac97_softc *)codec_if;
1571 si = &as->source_info[cp->dev];
1572 if (cp->dev < 0 || cp->dev >= as->num_source_info)
1573 return EINVAL;
1574
1575 if (cp->type != si->type)
1576 return EINVAL;
1577
1578 ac97_read(as, si->reg, &val);
1579
1580 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
1581
1582 mask = (1 << si->bits) - 1;
1583
1584 switch (cp->type) {
1585 case AUDIO_MIXER_ENUM:
1586 cp->un.ord = (val >> si->ofs) & mask;
1587 DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n",
1588 val, si->ofs, mask, cp->un.ord));
1589 break;
1590 case AUDIO_MIXER_VALUE:
1591 {
1592 const struct audio_mixer_value *value = si->info;
1593 uint16_t l, r;
1594
1595 if ((cp->un.value.num_channels <= 0) ||
1596 (cp->un.value.num_channels > value->num_channels))
1597 return EINVAL;
1598
1599 if (value->num_channels == 1) {
1600 l = r = (val >> si->ofs) & mask;
1601 } else {
1602 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
1603 l = (val >> (si->ofs + 8)) & mask;
1604 r = (val >> si->ofs) & mask;
1605 } else { /* host has reversed channels */
1606 r = (val >> (si->ofs + 8)) & mask;
1607 l = (val >> si->ofs) & mask;
1608 }
1609 }
1610
1611 l = (l << (8 - si->bits));
1612 r = (r << (8 - si->bits));
1613 if (!si->polarity) {
1614 l = 255 - l;
1615 r = 255 - r;
1616 }
1617
1618 /* The EAP driver averages l and r for stereo
1619 channels that are requested in MONO mode. Does this
1620 make sense? */
1621 if (cp->un.value.num_channels == 1) {
1622 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l;
1623 } else if (cp->un.value.num_channels == 2) {
1624 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
1625 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
1626 }
1627
1628 break;
1629 }
1630 default:
1631 return EINVAL;
1632 }
1633
1634 return 0;
1635 }
1636
1637
1638 static int
1639 ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_int *rate)
1640 {
1641 struct ac97_softc *as;
1642 u_int value;
1643 uint16_t ext_stat;
1644 uint16_t actual;
1645 uint16_t power;
1646 uint16_t power_bit;
1647
1648 as = (struct ac97_softc *)codec_if;
1649 if (target == AC97_REG_PCM_MIC_ADC_RATE) {
1650 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1651 *rate = AC97_SINGLE_RATE;
1652 return 0;
1653 }
1654 } else {
1655 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1656 *rate = AC97_SINGLE_RATE;
1657 return 0;
1658 }
1659 }
1660 value = *rate * AC97_STANDARD_CLOCK / as->ac97_clock;
1661 ext_stat = 0;
1662 /*
1663 * PCM_FRONT_DAC_RATE/PCM_SURR_DAC_RATE/PCM_LFE_DAC_RATE
1664 * Check VRA, DRA
1665 * PCM_LR_ADC_RATE
1666 * Check VRA
1667 * PCM_MIC_ADC_RATE
1668 * Check VRM
1669 */
1670 switch (target) {
1671 case AC97_REG_PCM_FRONT_DAC_RATE:
1672 case AC97_REG_PCM_SURR_DAC_RATE:
1673 case AC97_REG_PCM_LFE_DAC_RATE:
1674 power_bit = AC97_POWER_OUT;
1675 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1676 *rate = AC97_SINGLE_RATE;
1677 return 0;
1678 }
1679 if (as->ext_id & AC97_EXT_AUDIO_DRA) {
1680 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &ext_stat);
1681 if (value > 0x1ffff) {
1682 return EINVAL;
1683 } else if (value > 0xffff) {
1684 /* Enable DRA */
1685 ext_stat |= AC97_EXT_AUDIO_DRA;
1686 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1687 value /= 2;
1688 } else {
1689 /* Disable DRA */
1690 ext_stat &= ~AC97_EXT_AUDIO_DRA;
1691 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1692 }
1693 } else {
1694 if (value > 0xffff)
1695 return EINVAL;
1696 }
1697 break;
1698 case AC97_REG_PCM_LR_ADC_RATE:
1699 power_bit = AC97_POWER_IN;
1700 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1701 *rate = AC97_SINGLE_RATE;
1702 return 0;
1703 }
1704 if (value > 0xffff)
1705 return EINVAL;
1706 break;
1707 case AC97_REG_PCM_MIC_ADC_RATE:
1708 power_bit = AC97_POWER_IN;
1709 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1710 *rate = AC97_SINGLE_RATE;
1711 return 0;
1712 }
1713 if (value > 0xffff)
1714 return EINVAL;
1715 break;
1716 default:
1717 printf("%s: Unknown register: 0x%x\n", __func__, target);
1718 return EINVAL;
1719 }
1720
1721 ac97_read(as, AC97_REG_POWER, &power);
1722 ac97_write(as, AC97_REG_POWER, power | power_bit);
1723
1724 ac97_write(as, target, (uint16_t)value);
1725 ac97_read(as, target, &actual);
1726 actual = (uint32_t)actual * as->ac97_clock / AC97_STANDARD_CLOCK;
1727
1728 ac97_write(as, AC97_REG_POWER, power);
1729 if (ext_stat & AC97_EXT_AUDIO_DRA) {
1730 *rate = actual * 2;
1731 } else {
1732 *rate = actual;
1733 }
1734 return 0;
1735 }
1736
1737 static void
1738 ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock)
1739 {
1740 struct ac97_softc *as;
1741
1742 as = (struct ac97_softc *)codec_if;
1743 as->ac97_clock = clock;
1744 }
1745
1746 static uint16_t
1747 ac97_get_extcaps(struct ac97_codec_if *codec_if)
1748 {
1749 struct ac97_softc *as;
1750
1751 as = (struct ac97_softc *)codec_if;
1752 return as->ext_id;
1753 }
1754
1755 static int
1756 ac97_add_port(struct ac97_softc *as, const struct ac97_source_info *src)
1757 {
1758 struct ac97_source_info *si;
1759 int ouridx, idx;
1760
1761 if ((as->type == AC97_CODEC_TYPE_AUDIO &&
1762 as->num_source_info >= AUDIO_MAX_SOURCES) ||
1763 (as->type == AC97_CODEC_TYPE_MODEM &&
1764 as->num_source_info >= MODEM_MAX_SOURCES)) {
1765 printf("%s: internal error: increase MAX_SOURCES in %s\n",
1766 __func__, __FILE__);
1767 return -1;
1768 }
1769 if (!ac97_check_capability(as, src->req_feature))
1770 return -1;
1771 ouridx = as->num_source_info;
1772 si = &as->source_info[ouridx];
1773 memcpy(si, src, sizeof(*si));
1774
1775 switch (si->type) {
1776 case AUDIO_MIXER_CLASS:
1777 case AUDIO_MIXER_VALUE:
1778 printf("%s: adding class/value is not supported yet.\n",
1779 __func__);
1780 return -1;
1781 case AUDIO_MIXER_ENUM:
1782 break;
1783 default:
1784 printf("%s: unknown type: %d\n", __func__, si->type);
1785 return -1;
1786 }
1787 as->num_source_info++;
1788
1789 si->mixer_class = ac97_get_portnum_by_name(&as->codec_if, si->class,
1790 NULL, NULL);
1791 /* Find the root of the device */
1792 idx = ac97_get_portnum_by_name(&as->codec_if, si->class,
1793 si->device, NULL);
1794 /* Find the last item */
1795 while (as->source_info[idx].next != AUDIO_MIXER_LAST)
1796 idx = as->source_info[idx].next;
1797 /* Append */
1798 as->source_info[idx].next = ouridx;
1799 si->prev = idx;
1800 si->next = AUDIO_MIXER_LAST;
1801
1802 return 0;
1803 }
1804
1805 /**
1806 * Codec-dependent initialization
1807 */
1808
1809 #define AD1980_REG_MISC 0x76
1810 #define AD1980_MISC_MBG0 0x0001 /* 0 1888/1980/1981 /1985 */
1811 #define AD1980_MISC_MBG1 0x0002 /* 1 1888/1980/1981 /1985 */
1812 #define AD1980_MISC_VREFD 0x0004 /* 2 1888/1980/1981 /1985 */
1813 #define AD1980_MISC_VREFH 0x0008 /* 3 1888/1980/1981 /1985 */
1814 #define AD1980_MISC_SRU 0x0010 /* 4 1888/1980 /1985 */
1815 #define AD1980_MISC_LOSEL 0x0020 /* 5 1888/1980/1981 /1985 */
1816 #define AD1980_MISC_2CMIC 0x0040 /* 6 1980/1981B/1985 */
1817 #define AD1980_MISC_SPRD 0x0080 /* 7 1888/1980 /1985 */
1818 #define AD1980_MISC_DMIX0 0x0100 /* 8 1888/1980 /1985 */
1819 #define AD1980_MISC_DMIX1 0x0200 /* 9 1888/1980 /1985 */
1820 #define AD1980_MISC_HPSEL 0x0400 /*10 1888/1980 /1985 */
1821 #define AD1980_MISC_CLDIS 0x0800 /*11 1888/1980 /1985 */
1822 #define AD1980_MISC_LODIS 0x1000 /*12 1888/1980/1981 /1985 */
1823 #define AD1980_MISC_MSPLT 0x2000 /*13 1888/1980/1981 /1985 */
1824 #define AD1980_MISC_AC97NC 0x4000 /*14 1888/1980 /1985 */
1825 #define AD1980_MISC_DACZ 0x8000 /*15 1888/1980/1981 /1985 */
1826 #define AD1981_REG_MISC 0x76
1827 #define AD1981_MISC_MADST 0x0010 /* 4 */
1828 #define AD1981A_MISC_MADPD 0x0040 /* 6 */
1829 #define AD1981B_MISC_MADPD 0x0080 /* 7 */
1830 #define AD1981_MISC_FMXE 0x0200 /* 9 */
1831 #define AD1981_MISC_DAM 0x0800 /*11 */
1832 static void
1833 ac97_ad198x_init(struct ac97_softc *as)
1834 {
1835 int i;
1836 uint16_t misc;
1837
1838 ac97_read(as, AD1980_REG_MISC, &misc);
1839 ac97_write(as, AD1980_REG_MISC,
1840 misc | AD1980_MISC_LOSEL | AD1980_MISC_HPSEL);
1841
1842 for (i = 0; i < as->num_source_info; i++) {
1843 if (as->source_info[i].type != AUDIO_MIXER_VALUE)
1844 continue;
1845
1846 if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME)
1847 as->source_info[i].reg = AC97_REG_SURR_MASTER;
1848 else if (as->source_info[i].reg == AC97_REG_SURR_MASTER)
1849 as->source_info[i].reg = AC97_REG_MASTER_VOLUME;
1850 }
1851 }
1852
1853 #define ALC650_REG_MULTI_CHANNEL_CONTROL 0x6a
1854 #define ALC650_MCC_SLOT_MODIFY_MASK 0xc000
1855 #define ALC650_MCC_FRONTDAC_FROM_SPDIFIN 0x2000 /* 13 */
1856 #define ALC650_MCC_SPDIFOUT_FROM_ADC 0x1000 /* 12 */
1857 #define ALC650_MCC_PCM_FROM_SPDIFIN 0x0800 /* 11 */
1858 #define ALC650_MCC_MIC_OR_CENTERLFE 0x0400 /* 10 */
1859 #define ALC650_MCC_LINEIN_OR_SURROUND 0x0200 /* 9 */
1860 #define ALC650_MCC_INDEPENDENT_MASTER_L 0x0080 /* 7 */
1861 #define ALC650_MCC_INDEPENDENT_MASTER_R 0x0040 /* 6 */
1862 #define ALC650_MCC_ANALOG_TO_CENTERLFE 0x0020 /* 5 */
1863 #define ALC650_MCC_ANALOG_TO_SURROUND 0x0010 /* 4 */
1864 #define ALC650_MCC_EXCHANGE_CENTERLFE 0x0008 /* 3 */
1865 #define ALC650_MCC_CENTERLFE_DOWNMIX 0x0004 /* 2 */
1866 #define ALC650_MCC_SURROUND_DOWNMIX 0x0002 /* 1 */
1867 #define ALC650_MCC_LINEOUT_TO_SURROUND 0x0001 /* 0 */
1868 static void
1869 ac97_alc650_init(struct ac97_softc *as)
1870 {
1871 static const struct ac97_source_info sources[6] = {
1872 { AudioCoutputs, AudioNsurround, "lineinjack",
1873 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1874 ALC650_REG_MULTI_CHANNEL_CONTROL,
1875 0x0000, 1, 9, 0, 0, CHECK_SURROUND },
1876 { AudioCoutputs, AudioNsurround, "mixtofront",
1877 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1878 ALC650_REG_MULTI_CHANNEL_CONTROL,
1879 0x0000, 1, 1, 0, 0, CHECK_SURROUND },
1880 { AudioCoutputs, AudioNcenter, "micjack",
1881 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1882 ALC650_REG_MULTI_CHANNEL_CONTROL,
1883 0x0000, 1, 10, 0, 0, CHECK_CENTER },
1884 { AudioCoutputs, AudioNlfe, "micjack",
1885 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1886 ALC650_REG_MULTI_CHANNEL_CONTROL,
1887 0x0000, 1, 10, 0, 0, CHECK_LFE },
1888 { AudioCoutputs, AudioNcenter, "mixtofront",
1889 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1890 ALC650_REG_MULTI_CHANNEL_CONTROL,
1891 0x0000, 1, 2, 0, 0, CHECK_CENTER },
1892 { AudioCoutputs, AudioNlfe, "mixtofront",
1893 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1894 ALC650_REG_MULTI_CHANNEL_CONTROL,
1895 0x0000, 1, 2, 0, 0, CHECK_LFE },
1896 };
1897
1898 ac97_add_port(as, &sources[0]);
1899 ac97_add_port(as, &sources[1]);
1900 ac97_add_port(as, &sources[2]);
1901 ac97_add_port(as, &sources[3]);
1902 ac97_add_port(as, &sources[4]);
1903 ac97_add_port(as, &sources[5]);
1904 }
1905
1906 #define VT1616_REG_IO_CONTROL 0x5a
1907 #define VT1616_IC_LVL (1 << 15)
1908 #define VT1616_IC_LFECENTER_TO_FRONT (1 << 12)
1909 #define VT1616_IC_SURROUND_TO_FRONT (1 << 11)
1910 #define VT1616_IC_BPDC (1 << 10)
1911 #define VT1616_IC_DC (1 << 9)
1912 #define VT1616_IC_IB_MASK 0x000c
1913 static void
1914 ac97_vt1616_init(struct ac97_softc *as)
1915 {
1916 static const struct ac97_source_info sources[3] = {
1917 { AudioCoutputs, AudioNsurround, "mixtofront",
1918 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1919 VT1616_REG_IO_CONTROL,
1920 0x0000, 1, 11, 0, 0, CHECK_SURROUND },
1921 { AudioCoutputs, AudioNcenter, "mixtofront",
1922 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1923 VT1616_REG_IO_CONTROL,
1924 0x0000, 1, 12, 0, 0, CHECK_CENTER },
1925 { AudioCoutputs, AudioNlfe, "mixtofront",
1926 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1927 VT1616_REG_IO_CONTROL,
1928 0x0000, 1, 12, 0, 0, CHECK_LFE },
1929 };
1930
1931 ac97_add_port(as, &sources[0]);
1932 ac97_add_port(as, &sources[1]);
1933 ac97_add_port(as, &sources[2]);
1934 }
1935
1936 static int
1937 ac97_modem_offhook_set(struct ac97_softc *as, int line, int newval)
1938 {
1939 uint16_t val;
1940
1941 val = as->shadow_reg[AC97_REG_GPIO_STATUS >> 1];
1942 switch (newval) {
1943 case 0:
1944 val &= ~line;
1945 break;
1946 case 1:
1947 val |= line;
1948 break;
1949 }
1950 ac97_write(as, AC97_REG_GPIO_STATUS, val);
1951
1952 return 0;
1953 }
1954
1955 static int
1956 ac97_sysctl_verify(SYSCTLFN_ARGS)
1957 {
1958 int error, tmp;
1959 struct sysctlnode node;
1960 struct ac97_softc *as;
1961
1962 node = *rnode;
1963 as = rnode->sysctl_data;
1964 if (node.sysctl_num == as->offhook_line1_mib) {
1965 tmp = as->offhook_line1;
1966 node.sysctl_data = &tmp;
1967 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1968 if (error || newp == NULL)
1969 return error;
1970
1971 if (tmp < 0 || tmp > 1)
1972 return EINVAL;
1973
1974 as->offhook_line1 = tmp;
1975 ac97_modem_offhook_set(as, AC97_GPIO_LINE1_OH, tmp);
1976 } else if (node.sysctl_num == as->offhook_line2_mib) {
1977 tmp = as->offhook_line2;
1978 node.sysctl_data = &tmp;
1979 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1980 if (error || newp == NULL)
1981 return error;
1982
1983 if (tmp < 0 || tmp > 1)
1984 return EINVAL;
1985
1986 as->offhook_line2 = tmp;
1987 ac97_modem_offhook_set(as, AC97_GPIO_LINE2_OH, tmp);
1988 }
1989
1990 return 0;
1991 }
1992