ac97.c revision 1.74 1 /* $NetBSD: ac97.c,v 1.74 2005/05/11 13:13:11 scw 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.74 2005/05/11 13:13:11 scw 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 power_all;
381 uint16_t caps; /* -> AC97_REG_RESET */
382 uint16_t ext_id; /* -> AC97_REG_EXT_AUDIO_ID */
383 uint16_t ext_mid; /* -> AC97_REG_EXT_MODEM_ID */
384 uint16_t shadow_reg[128];
385
386 int type;
387
388 /* sysctl */
389 struct sysctllog *log;
390 int offhook_line1_mib;
391 int offhook_line2_mib;
392 int offhook_line1;
393 int offhook_line2;
394 };
395
396 static struct ac97_codec_if_vtbl ac97civ = {
397 ac97_mixer_get_port,
398 ac97_mixer_set_port,
399 ac97_query_devinfo,
400 ac97_get_portnum_by_name,
401 ac97_restore_shadow,
402 ac97_get_extcaps,
403 ac97_set_rate,
404 ac97_set_clock,
405 ac97_detach,
406 };
407
408 static const struct ac97_codecid {
409 uint32_t id;
410 uint32_t mask;
411 const char *name;
412 void (*init)(struct ac97_softc *);
413 } ac97codecid[] = {
414 /*
415 * Analog Devices SoundMAX
416 * http://www.soundmax.com/products/information/codecs.html
417 * http://www.analog.com/productSelection/pdf/AD1881A_0.pdf
418 * http://www.analog.com/productSelection/pdf/AD1885_0.pdf
419 * http://www.analog.com/UploadedFiles/Data_Sheets/206585810AD1980_0.pdf
420 * http://www.analog.com/productSelection/pdf/AD1981A_0.pdf
421 * http://www.analog.com/productSelection/pdf/AD1981B_0.pdf
422 * http://www.analog.com/UploadedFiles/Data_Sheets/180644528AD1985_0.pdf
423 */
424 { AC97_CODEC_ID('A', 'D', 'S', 3),
425 0xffffffff, "Analog Devices AD1819B" },
426 { AC97_CODEC_ID('A', 'D', 'S', 0x40),
427 0xffffffff, "Analog Devices AD1881" },
428 { AC97_CODEC_ID('A', 'D', 'S', 0x48),
429 0xffffffff, "Analog Devices AD1881A" },
430 { AC97_CODEC_ID('A', 'D', 'S', 0x60),
431 0xffffffff, "Analog Devices AD1885" },
432 { AC97_CODEC_ID('A', 'D', 'S', 0x61),
433 0xffffffff, "Analog Devices AD1886" },
434 { AC97_CODEC_ID('A', 'D', 'S', 0x63),
435 0xffffffff, "Analog Devices AD1886A" },
436 { AC97_CODEC_ID('A', 'D', 'S', 0x68),
437 0xffffffff, "Analog Devices AD1888", ac97_ad198x_init },
438 { AC97_CODEC_ID('A', 'D', 'S', 0x70),
439 0xffffffff, "Analog Devices AD1980", ac97_ad198x_init },
440 { AC97_CODEC_ID('A', 'D', 'S', 0x72),
441 0xffffffff, "Analog Devices AD1981A" },
442 { AC97_CODEC_ID('A', 'D', 'S', 0x74),
443 0xffffffff, "Analog Devices AD1981B" },
444 { AC97_CODEC_ID('A', 'D', 'S', 0x75),
445 0xffffffff, "Analog Devices AD1985", ac97_ad198x_init },
446 { AC97_CODEC_ID('A', 'D', 'S', 0),
447 AC97_VENDOR_ID_MASK, "Analog Devices unknown" },
448
449 /*
450 * Datasheets:
451 * http://www.asahi-kasei.co.jp/akm/usa/product/ak4541/ek4541.pdf
452 * http://www.asahi-kasei.co.jp/akm/usa/product/ak4543/ek4543.pdf
453 * http://www.asahi-kasei.co.jp/akm/usa/product/ak4544a/ek4544a.pdf
454 * http://www.asahi-kasei.co.jp/akm/usa/product/ak4545/ek4545.pdf
455 */
456 { AC97_CODEC_ID('A', 'K', 'M', 0),
457 0xffffffff, "Asahi Kasei AK4540" },
458 { AC97_CODEC_ID('A', 'K', 'M', 1),
459 0xffffffff, "Asahi Kasei AK4542" },
460 { AC97_CODEC_ID('A', 'K', 'M', 2),
461 0xffffffff, "Asahi Kasei AK4541/AK4543" },
462 { AC97_CODEC_ID('A', 'K', 'M', 5),
463 0xffffffff, "Asahi Kasei AK4544" },
464 { AC97_CODEC_ID('A', 'K', 'M', 6),
465 0xffffffff, "Asahi Kasei AK4544A" },
466 { AC97_CODEC_ID('A', 'K', 'M', 7),
467 0xffffffff, "Asahi Kasei AK4545" },
468 { AC97_CODEC_ID('A', 'K', 'M', 0),
469 AC97_VENDOR_ID_MASK, "Asahi Kasei unknown" },
470
471 /*
472 * Realtek & Avance Logic
473 * http://www.realtek.com.tw/downloads/downloads1-3.aspx?lineid=5&famid=All&series=All&Spec=True
474 *
475 * ALC650 and ALC658 support VRA, but it supports only 8000, 11025,
476 * 12000, 16000, 22050, 24000, 32000, 44100, and 48000 Hz.
477 */
478 { AC97_CODEC_ID('A', 'L', 'C', 0x00),
479 0xfffffff0, "Realtek RL5306" },
480 { AC97_CODEC_ID('A', 'L', 'C', 0x10),
481 0xfffffff0, "Realtek RL5382" },
482 { AC97_CODEC_ID('A', 'L', 'C', 0x20),
483 0xfffffff0, "Realtek RL5383/RL5522/ALC100" },
484 { AC97_CODEC_ID('A', 'L', 'G', 0x10),
485 0xffffffff, "Avance Logic ALC200/ALC201" },
486 { AC97_CODEC_ID('A', 'L', 'G', 0x20),
487 0xfffffff0, "Avance Logic ALC650", ac97_alc650_init },
488 { AC97_CODEC_ID('A', 'L', 'G', 0x30),
489 0xffffffff, "Avance Logic ALC101" },
490 { AC97_CODEC_ID('A', 'L', 'G', 0x40),
491 0xffffffff, "Avance Logic ALC202" },
492 { AC97_CODEC_ID('A', 'L', 'G', 0x50),
493 0xffffffff, "Avance Logic ALC250" },
494 { AC97_CODEC_ID('A', 'L', 'G', 0x60),
495 0xfffffff0, "Avance Logic ALC655" },
496 { AC97_CODEC_ID('A', 'L', 'G', 0x80),
497 0xfffffff0, "Avance Logic ALC658" },
498 { AC97_CODEC_ID('A', 'L', 'G', 0x90),
499 0xfffffff0, "Avance Logic ALC850" },
500 { AC97_CODEC_ID('A', 'L', 'C', 0),
501 AC97_VENDOR_ID_MASK, "Realtek unknown" },
502 { AC97_CODEC_ID('A', 'L', 'G', 0),
503 AC97_VENDOR_ID_MASK, "Avance Logic unknown" },
504
505 /**
506 * C-Media Electronics Inc.
507 * http://www.cmedia.com.tw/doc/CMI9739%206CH%20Audio%20Codec%20SPEC_Ver12.pdf
508 */
509 { AC97_CODEC_ID('C', 'M', 'I', 0x61),
510 0xffffffff, "C-Media CMI9739" },
511 { AC97_CODEC_ID('C', 'M', 'I', 0),
512 AC97_VENDOR_ID_MASK, "C-Media unknown" },
513
514 /* Cirrus Logic, Crystal series:
515 * 'C' 'R' 'Y' 0x0[0-7] - CS4297
516 * 0x1[0-7] - CS4297A
517 * 0x2[0-7] - CS4298
518 * 0x2[8-f] - CS4294
519 * 0x3[0-7] - CS4299
520 * 0x4[8-f] - CS4201
521 * 0x5[8-f] - CS4205
522 * 0x6[0-7] - CS4291
523 * 0x7[0-7] - CS4202
524 * Datasheets:
525 * http://www.cirrus.com/pubs/cs4297A-5.pdf?DocumentID=593
526 * http://www.cirrus.com/pubs/cs4294.pdf?DocumentID=32
527 * http://www.cirrus.com/pubs/cs4299-5.pdf?DocumentID=594
528 * http://www.cirrus.com/pubs/cs4201-2.pdf?DocumentID=492
529 * http://www.cirrus.com/pubs/cs4205-2.pdf?DocumentID=492
530 * http://www.cirrus.com/pubs/cs4202-1.pdf?DocumentID=852
531 */
532 { AC97_CODEC_ID('C', 'R', 'Y', 0x00),
533 0xfffffff8, "Crystal CS4297", },
534 { AC97_CODEC_ID('C', 'R', 'Y', 0x10),
535 0xfffffff8, "Crystal CS4297A", },
536 { AC97_CODEC_ID('C', 'R', 'Y', 0x20),
537 0xfffffff8, "Crystal CS4298", },
538 { AC97_CODEC_ID('C', 'R', 'Y', 0x28),
539 0xfffffff8, "Crystal CS4294", },
540 { AC97_CODEC_ID('C', 'R', 'Y', 0x30),
541 0xfffffff8, "Crystal CS4299", },
542 { AC97_CODEC_ID('C', 'R', 'Y', 0x48),
543 0xfffffff8, "Crystal CS4201", },
544 { AC97_CODEC_ID('C', 'R', 'Y', 0x58),
545 0xfffffff8, "Crystal CS4205", },
546 { AC97_CODEC_ID('C', 'R', 'Y', 0x60),
547 0xfffffff8, "Crystal CS4291", },
548 { AC97_CODEC_ID('C', 'R', 'Y', 0x70),
549 0xfffffff8, "Crystal CS4202", },
550 { AC97_CODEC_ID('C', 'R', 'Y', 0),
551 AC97_VENDOR_ID_MASK, "Cirrus Logic unknown", },
552
553 { 0x45838308, 0xffffffff, "ESS Technology ES1921", },
554 { 0x45838300, AC97_VENDOR_ID_MASK, "ESS Technology unknown", },
555
556 { AC97_CODEC_ID('H', 'R', 'S', 0),
557 0xffffffff, "Intersil HMP9701", },
558 { AC97_CODEC_ID('H', 'R', 'S', 0),
559 AC97_VENDOR_ID_MASK, "Intersil unknown", },
560
561 /*
562 * IC Ensemble (VIA)
563 * http://www.viatech.com/en/datasheet/DS1616.pdf
564 */
565 { AC97_CODEC_ID('I', 'C', 'E', 0x01),
566 0xffffffff, "ICEnsemble ICE1230/VT1611", },
567 { AC97_CODEC_ID('I', 'C', 'E', 0x11),
568 0xffffffff, "ICEnsemble ICE1232/VT1611A", },
569 { AC97_CODEC_ID('I', 'C', 'E', 0x14),
570 0xffffffff, "ICEnsemble ICE1232A", },
571 { AC97_CODEC_ID('I', 'C', 'E', 0x51),
572 0xffffffff, "VIA Technologies VT1616", ac97_vt1616_init },
573 { AC97_CODEC_ID('I', 'C', 'E', 0x52),
574 0xffffffff, "VIA Technologies VT1616i", ac97_vt1616_init },
575 { AC97_CODEC_ID('I', 'C', 'E', 0),
576 AC97_VENDOR_ID_MASK, "ICEnsemble/VIA unknown", },
577
578 { AC97_CODEC_ID('N', 'S', 'C', 0),
579 0xffffffff, "National Semiconductor LM454[03568]", },
580 { AC97_CODEC_ID('N', 'S', 'C', 49),
581 0xffffffff, "National Semiconductor LM4549", },
582 { AC97_CODEC_ID('N', 'S', 'C', 0),
583 AC97_VENDOR_ID_MASK, "National Semiconductor unknown", },
584
585 { AC97_CODEC_ID('P', 'S', 'C', 4),
586 0xffffffff, "Philips Semiconductor UCB1400", },
587 { AC97_CODEC_ID('P', 'S', 'C', 0),
588 AC97_VENDOR_ID_MASK, "Philips Semiconductor unknown", },
589
590 { AC97_CODEC_ID('S', 'I', 'L', 34),
591 0xffffffff, "Silicon Laboratory Si3036", },
592 { AC97_CODEC_ID('S', 'I', 'L', 35),
593 0xffffffff, "Silicon Laboratory Si3038", },
594 { AC97_CODEC_ID('S', 'I', 'L', 0),
595 AC97_VENDOR_ID_MASK, "Silicon Laboratory unknown", },
596
597 { AC97_CODEC_ID('T', 'R', 'A', 2),
598 0xffffffff, "TriTech TR28022", },
599 { AC97_CODEC_ID('T', 'R', 'A', 3),
600 0xffffffff, "TriTech TR28023", },
601 { AC97_CODEC_ID('T', 'R', 'A', 6),
602 0xffffffff, "TriTech TR28026", },
603 { AC97_CODEC_ID('T', 'R', 'A', 8),
604 0xffffffff, "TriTech TR28028", },
605 { AC97_CODEC_ID('T', 'R', 'A', 35),
606 0xffffffff, "TriTech TR28602", },
607 { AC97_CODEC_ID('T', 'R', 'A', 0),
608 AC97_VENDOR_ID_MASK, "TriTech unknown", },
609
610 { AC97_CODEC_ID('T', 'X', 'N', 0x20),
611 0xffffffff, "Texas Instruments TLC320AD9xC", },
612 { AC97_CODEC_ID('T', 'X', 'N', 0),
613 AC97_VENDOR_ID_MASK, "Texas Instruments unknown", },
614
615 /*
616 * VIA
617 * http://www.viatech.com/en/multimedia/audio.jsp
618 */
619 { AC97_CODEC_ID('V', 'I', 'A', 0x61),
620 0xffffffff, "VIA Technologies VT1612A", },
621 { AC97_CODEC_ID('V', 'I', 'A', 0),
622 AC97_VENDOR_ID_MASK, "VIA Technologies unknown", },
623
624 { AC97_CODEC_ID('W', 'E', 'C', 1),
625 0xffffffff, "Winbond W83971D", },
626 { AC97_CODEC_ID('W', 'E', 'C', 0),
627 AC97_VENDOR_ID_MASK, "Winbond unknown", },
628
629 /*
630 * http://www.wolfsonmicro.com/product_list.asp?cid=64
631 * http://www.wolfsonmicro.com/download.asp/did.56/WM9701A.pdf - 00
632 * http://www.wolfsonmicro.com/download.asp/did.57/WM9703.pdf - 03
633 * http://www.wolfsonmicro.com/download.asp/did.58/WM9704M.pdf - 04
634 * http://www.wolfsonmicro.com/download.asp/did.59/WM9704Q.pdf - 04
635 * http://www.wolfsonmicro.com/download.asp/did.184/WM9705_Rev34.pdf - 05
636 * http://www.wolfsonmicro.com/download.asp/did.60/WM9707.pdf - 03
637 * http://www.wolfsonmicro.com/download.asp/did.136/WM9708.pdf - 03
638 * http://www.wolfsonmicro.com/download.asp/did.243/WM9710.pdf - 05
639 */
640 { AC97_CODEC_ID('W', 'M', 'L', 0),
641 0xffffffff, "Wolfson WM9701A", },
642 { AC97_CODEC_ID('W', 'M', 'L', 3),
643 0xffffffff, "Wolfson WM9703/WM9707/WM9708", },
644 { AC97_CODEC_ID('W', 'M', 'L', 4),
645 0xffffffff, "Wolfson WM9704", },
646 { AC97_CODEC_ID('W', 'M', 'L', 5),
647 0xffffffff, "Wolfson WM9705/WM9710", },
648 { AC97_CODEC_ID('W', 'M', 'L', 0),
649 AC97_VENDOR_ID_MASK, "Wolfson unknown", },
650
651 /*
652 * http://www.yamaha.co.jp/english/product/lsi/us/products/pcaudio.html
653 * Datasheets:
654 * http://www.yamaha.co.jp/english/product/lsi/us/products/pdf/4MF743A20.pdf
655 * http://www.yamaha.co.jp/english/product/lsi/us/products/pdf/4MF753A20.pdf
656 */
657 { AC97_CODEC_ID('Y', 'M', 'H', 0),
658 0xffffffff, "Yamaha YMF743-S", },
659 { AC97_CODEC_ID('Y', 'M', 'H', 3),
660 0xffffffff, "Yamaha YMF753-S", },
661 { AC97_CODEC_ID('Y', 'M', 'H', 0),
662 AC97_VENDOR_ID_MASK, "Yamaha unknown", },
663
664 /*
665 * http://www.sigmatel.com/products/technical_docs.htm
666 * and
667 * http://www.sigmatel.com/documents/c-major-brochure-9-0.pdf
668 */
669 { 0x83847600, 0xffffffff, "SigmaTel STAC9700", },
670 { 0x83847604, 0xffffffff, "SigmaTel STAC9701/3/4/5", },
671 { 0x83847605, 0xffffffff, "SigmaTel STAC9704", },
672 { 0x83847608, 0xffffffff, "SigmaTel STAC9708", },
673 { 0x83847609, 0xffffffff, "SigmaTel STAC9721/23", },
674 { 0x83847644, 0xffffffff, "SigmaTel STAC9744/45", },
675 { 0x83847650, 0xffffffff, "SigmaTel STAC9750/51", },
676 { 0x83847656, 0xffffffff, "SigmaTel STAC9756/57", },
677 { 0x83847658, 0xffffffff, "SigmaTel STAC9758/59", },
678 { 0x83847666, 0xffffffff, "SigmaTel STAC9766/67", },
679 { 0x83847684, 0xffffffff, "SigmaTel STAC9783/84", },
680 { 0x83847600, AC97_VENDOR_ID_MASK, "SigmaTel unknown", },
681
682 /* Conexant AC'97 modems -- good luck finding datasheets! */
683 { AC97_CODEC_ID('C', 'X', 'T', 33),
684 0xffffffff, "Conexant HSD11246", },
685 { AC97_CODEC_ID('C', 'X', 'T', 34),
686 0xffffffff, "Conexant D480 MDC V.92 Modem", },
687 { AC97_CODEC_ID('C', 'X', 'T', 0),
688 AC97_VENDOR_ID_MASK, "Conexant unknown", },
689
690 { 0,
691 0, NULL, }
692 };
693
694 static const char * const ac97enhancement[] = {
695 "no 3D stereo",
696 "Analog Devices Phat Stereo",
697 "Creative",
698 "National Semi 3D",
699 "Yamaha Ymersion",
700 "BBE 3D",
701 "Crystal Semi 3D",
702 "Qsound QXpander",
703 "Spatializer 3D",
704 "SRS 3D",
705 "Platform Tech 3D",
706 "AKM 3D",
707 "Aureal",
708 "AZTECH 3D",
709 "Binaura 3D",
710 "ESS Technology",
711 "Harman International VMAx",
712 "Nvidea 3D",
713 "Philips Incredible Sound",
714 "Texas Instruments' 3D",
715 "VLSI Technology 3D",
716 "TriTech 3D",
717 "Realtek 3D",
718 "Samsung 3D",
719 "Wolfson Microelectronics 3D",
720 "Delta Integration 3D",
721 "SigmaTel 3D",
722 "KS Waves 3D",
723 "Rockwell 3D",
724 "Unknown 3D",
725 "Unknown 3D",
726 "Unknown 3D",
727 };
728
729 static const char * const ac97feature[] = {
730 "dedicated mic channel",
731 "reserved",
732 "tone",
733 "simulated stereo",
734 "headphone",
735 "bass boost",
736 "18 bit DAC",
737 "20 bit DAC",
738 "18 bit ADC",
739 "20 bit ADC"
740 };
741
742
743 /* #define AC97_DEBUG 10 */
744 /* #define AC97_IO_DEBUG */
745
746 #ifdef AUDIO_DEBUG
747 #define DPRINTF(x) if (ac97debug) printf x
748 #define DPRINTFN(n,x) if (ac97debug>(n)) printf x
749 #ifdef AC97_DEBUG
750 int ac97debug = AC97_DEBUG;
751 #else
752 int ac97debug = 0;
753 #endif
754 #else
755 #define DPRINTF(x)
756 #define DPRINTFN(n,x)
757 #endif
758
759 #ifdef AC97_IO_DEBUG
760 static const char *ac97_register_names[0x80 / 2] = {
761 "RESET", "MASTER_VOLUME", "HEADPHONE_VOLUME", "MASTER_VOLUME_MONO",
762 "MASTER_TONE", "PCBEEP_VOLUME", "PHONE_VOLUME", "MIC_VOLUME",
763 "LINEIN_VOLUME", "CD_VOLUME", "VIDEO_VOLUME", "AUX_VOLUME",
764 "PCMOUT_VOLUME", "RECORD_SELECT", "RECORD_GATIN", "RECORD_GAIN_MIC",
765 "GP", "3D_CONTROL", "AUDIO_INT", "POWER",
766 "EXT_AUDIO_ID", "EXT_AUDIO_CTRL", "PCM_FRONT_DAC_RATE", "PCM_SURR_DAC_RATE",
767 "PCM_LFE_DAC_RATE", "PCM_LR_ADC_RATE", "PCM_MIC_ADC_RATE", "CENTER_LFE_MASTER",
768 "SURR_MASTER", "SPDIF_CTRL", "EXT_MODEM_ID", "EXT_MODEM_CTRL",
769 "LINE1_RATE", "LINE2_RATE", "HANDSET_RATE", "LINE1_LEVEL",
770 "LINE2_LEVEL", "HANDSET_LEVEL", "GPIO_PIN_CONFIG", "GPIO_PIN_POLARITY",
771 "GPIO_PIN_STICKY", "GPIO_PIN_WAKEUP", "GPIO_PIN_STATUS", "MISC_MODEM_CTRL",
772 "0x58", "VENDOR-5A", "VENDOR-5C", "VENDOR-5E",
773 "0x60", "0x62", "0x64", "0x66",
774 "0x68", "0x6a", "0x6c", "0x6e",
775 "VENDOR-70", "VENDOR-72", "VENDOR-74", "VENDOR-76",
776 "VENDOR-78", "VENDOR-7A", "VENDOR_ID1", "VENDOR_ID2"
777 };
778 #endif
779
780 static void
781 ac97_read(struct ac97_softc *as, uint8_t reg, uint16_t *val)
782 {
783 if (as->host_flags & AC97_HOST_DONT_READ &&
784 (reg != AC97_REG_VENDOR_ID1 && reg != AC97_REG_VENDOR_ID2 &&
785 reg != AC97_REG_RESET)) {
786 *val = as->shadow_reg[reg >> 1];
787 return;
788 }
789
790 if (as->host_if->read(as->host_if->arg, reg, val)) {
791 *val = as->shadow_reg[reg >> 1];
792 }
793 }
794
795 static int
796 ac97_write(struct ac97_softc *as, uint8_t reg, uint16_t val)
797 {
798 #ifndef AC97_IO_DEBUG
799 as->shadow_reg[reg >> 1] = val;
800 return as->host_if->write(as->host_if->arg, reg, val);
801 #else
802 int ret;
803 uint16_t actual;
804
805 as->shadow_reg[reg >> 1] = val;
806 ret = as->host_if->write(as->host_if->arg, reg, val);
807 as->host_if->read(as->host_if->arg, reg, &actual);
808 if (val != actual && reg < 0x80) {
809 printf("ac97_write: reg=%s, written=0x%04x, read=0x%04x\n",
810 ac97_register_names[reg / 2], val, actual);
811 }
812 return ret;
813 #endif
814 }
815
816 static void
817 ac97_setup_defaults(struct ac97_softc *as)
818 {
819 int idx;
820 const struct ac97_source_info *si;
821
822 memset(as->shadow_reg, 0, sizeof(as->shadow_reg));
823
824 for (idx = 0; idx < AUDIO_SOURCE_INFO_SIZE; idx++) {
825 si = &audio_source_info[idx];
826 ac97_write(as, si->reg, si->default_value);
827 }
828 for (idx = 0; idx < MODEM_SOURCE_INFO_SIZE; idx++) {
829 si = &modem_source_info[idx];
830 ac97_write(as, si->reg, si->default_value);
831 }
832 }
833
834 static void
835 ac97_restore_shadow(struct ac97_codec_if *self)
836 {
837 struct ac97_softc *as;
838 const struct ac97_source_info *si;
839 int idx;
840 uint16_t val;
841
842 as = (struct ac97_softc *) self;
843
844 if (as->type == AC97_CODEC_TYPE_AUDIO) {
845 /* make sure chip is fully operational */
846 for (idx = 50000; idx >= 0; idx--) {
847 ac97_read(as, AC97_REG_POWER, &val);
848 if ((val & as->power_all) == as->power_all)
849 break;
850 DELAY(10);
851 }
852
853 /*
854 * actually try changing a value!
855 * The default value of AC97_REG_MASTER_VOLUME is 0x8000.
856 */
857 for (idx = 50000; idx >= 0; idx--) {
858 ac97_write(as, AC97_REG_MASTER_VOLUME, 0x1010);
859 ac97_read(as, AC97_REG_MASTER_VOLUME, &val);
860 if (val == 0x1010)
861 break;
862 DELAY(10);
863 }
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
1084 /*
1085 * Assume codec has all four power bits.
1086 * XXXSCW: what to do for modems?
1087 */
1088 as->power_all = AC97_POWER_REF | AC97_POWER_ANL | AC97_POWER_DAC |
1089 AC97_POWER_ADC;
1090 if (as->type == AC97_CODEC_TYPE_AUDIO) {
1091 host_if->write(host_if->arg, AC97_REG_RESET, 0);
1092
1093 /*
1094 * Power-up everything except the analogue mixer.
1095 * If this codec doesn't support analogue mixer power-down,
1096 * AC97_POWER_MIXER will read back as zero.
1097 */
1098 host_if->write(host_if->arg, AC97_REG_POWER, AC97_POWER_MIXER);
1099 ac97_read(as, AC97_REG_POWER, &val);
1100 if ((val & AC97_POWER_MIXER) == 0) {
1101 /* Codec doesn't support analogue mixer power-down */
1102 as->power_all &= ~AC97_POWER_ANL;
1103 }
1104 host_if->write(host_if->arg, AC97_REG_POWER, 0);
1105
1106 for (i = 500000; i >= 0; i--) {
1107 ac97_read(as, AC97_REG_POWER, &val);
1108 if ((val & as->power_all) == as->power_all)
1109 break;
1110 DELAY(1);
1111 }
1112 } else if (as->type == AC97_CODEC_TYPE_MODEM) {
1113 host_if->write(host_if->arg, AC97_REG_EXT_MODEM_ID, 0);
1114 }
1115
1116 ac97_setup_defaults(as);
1117 if (as->type == AC97_CODEC_TYPE_AUDIO)
1118 ac97_read(as, AC97_REG_RESET, &as->caps);
1119 ac97_read(as, AC97_REG_VENDOR_ID1, &id1);
1120 ac97_read(as, AC97_REG_VENDOR_ID2, &id2);
1121
1122 id = (id1 << 16) | id2;
1123 aprint_normal("%s: ac97: ", sc_dev->dv_xname);
1124
1125 for (i = 0; ; i++) {
1126 if (ac97codecid[i].id == 0) {
1127 char pnp[4];
1128
1129 AC97_GET_CODEC_ID(id, pnp);
1130 #define ISASCII(c) ((c) >= ' ' && (c) < 0x7f)
1131 if (ISASCII(pnp[0]) && ISASCII(pnp[1]) &&
1132 ISASCII(pnp[2]))
1133 aprint_normal("%c%c%c%d",
1134 pnp[0], pnp[1], pnp[2], pnp[3]);
1135 else
1136 aprint_normal("unknown (0x%08x)", id);
1137 break;
1138 }
1139 if (ac97codecid[i].id == (id & ac97codecid[i].mask)) {
1140 aprint_normal("%s", ac97codecid[i].name);
1141 if (ac97codecid[i].mask == AC97_VENDOR_ID_MASK) {
1142 aprint_normal(" (0x%08x)", id);
1143 }
1144 initfunc = ac97codecid[i].init;
1145 break;
1146 }
1147 }
1148 aprint_normal(" codec; ");
1149 for (i = j = 0; i < 10; i++) {
1150 if (as->caps & (1 << i)) {
1151 aprint_normal("%s%s", j ? ", " : "", ac97feature[i]);
1152 j++;
1153 }
1154 }
1155 aprint_normal("%s%s\n", j ? ", " : "",
1156 ac97enhancement[AC97_CAPS_ENHANCEMENT(as->caps)]);
1157
1158 as->ac97_clock = AC97_STANDARD_CLOCK;
1159
1160 if (as->type == AC97_CODEC_TYPE_AUDIO) {
1161 ac97_read(as, AC97_REG_EXT_AUDIO_ID, &as->ext_id);
1162 if (as->ext_id != 0) {
1163 /* Print capabilities */
1164 bitmask_snprintf(as->ext_id,
1165 "\20\20SECONDARY10\17SECONDARY01"
1166 "\14AC97_23\13AC97_22\12AMAP\11LDAC\10SDAC"
1167 "\7CDAC\4VRM\3SPDIF\2DRA\1VRA",
1168 flagbuf, FLAGBUFLEN);
1169 aprint_normal("%s: ac97: ext id %s\n", sc_dev->dv_xname,
1170 flagbuf);
1171
1172 /* Print unusual settings */
1173 if (as->ext_id & AC97_EXT_AUDIO_DSA_MASK) {
1174 aprint_normal("%s: ac97: Slot assignment: ",
1175 sc_dev->dv_xname);
1176 switch (as->ext_id & AC97_EXT_AUDIO_DSA_MASK) {
1177 case AC97_EXT_AUDIO_DSA01:
1178 aprint_normal("7&8, 6&9, 10&11.\n");
1179 break;
1180 case AC97_EXT_AUDIO_DSA10:
1181 aprint_normal("6&9, 10&11, 3&4.\n");
1182 break;
1183 case AC97_EXT_AUDIO_DSA11:
1184 aprint_normal("10&11, 3&4, 7&8.\n");
1185 break;
1186 }
1187 }
1188
1189 /* Enable and disable features */
1190 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat);
1191 extstat &= ~AC97_EXT_AUDIO_DRA;
1192 if (as->ext_id & AC97_EXT_AUDIO_LDAC)
1193 extstat |= AC97_EXT_AUDIO_LDAC;
1194 if (as->ext_id & AC97_EXT_AUDIO_SDAC)
1195 extstat |= AC97_EXT_AUDIO_SDAC;
1196 if (as->ext_id & AC97_EXT_AUDIO_CDAC)
1197 extstat |= AC97_EXT_AUDIO_CDAC;
1198 if (as->ext_id & AC97_EXT_AUDIO_VRM)
1199 extstat |= AC97_EXT_AUDIO_VRM;
1200 if (as->ext_id & AC97_EXT_AUDIO_SPDIF) {
1201 /* Output the same data as DAC to SPDIF output */
1202 extstat &= ~AC97_EXT_AUDIO_SPSA_MASK;
1203 extstat |= AC97_EXT_AUDIO_SPSA34;
1204 }
1205 if (as->ext_id & AC97_EXT_AUDIO_VRA)
1206 extstat |= AC97_EXT_AUDIO_VRA;
1207 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat);
1208 if (as->ext_id & AC97_EXT_AUDIO_VRA) {
1209 /* VRA should be enabled. */
1210 /* so it claims to do variable rate, let's make sure */
1211 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE,
1212 44100);
1213 ac97_read(as, AC97_REG_PCM_FRONT_DAC_RATE,
1214 &rate);
1215 if (rate != 44100) {
1216 /* We can't believe ext_id */
1217 as->ext_id = 0;
1218 aprint_normal(
1219 "%s: Ignore these capabilities.\n",
1220 sc_dev->dv_xname);
1221 }
1222 /* restore the default value */
1223 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE,
1224 AC97_SINGLE_RATE);
1225 }
1226 }
1227 } else if (as->type == AC97_CODEC_TYPE_MODEM) {
1228 struct sysctlnode *node;
1229 struct sysctlnode *node_line1;
1230 struct sysctlnode *node_line2;
1231 uint16_t rate = 8000;
1232 uint16_t val, reg;
1233 int err;
1234
1235 ac97_read(as, AC97_REG_EXT_MODEM_ID, &as->ext_mid);
1236 if (as->ext_mid == 0 || as->ext_mid == 0xffff) {
1237 aprint_normal("%s: no modem codec found\n",
1238 sc_dev->dv_xname);
1239 return ENXIO;
1240 }
1241 as->type = AC97_CODEC_TYPE_MODEM;
1242
1243 /* Print capabilities */
1244 bitmask_snprintf(as->ext_mid,
1245 "\20\5CID2\4CID1\3HANDSET\2LINE2\1LINE1",
1246 flagbuf, FLAGBUFLEN);
1247 aprint_normal("%s: ac97: ext mid %s", sc_dev->dv_xname,
1248 flagbuf);
1249 aprint_normal(", %s codec\n",
1250 (as->ext_mid & 0xc000) == 0 ?
1251 "primary" : "secondary");
1252
1253 /* Setup modem and sysctls */
1254 err = sysctl_createv(&as->log, 0, NULL, NULL, 0, CTLTYPE_NODE,
1255 "hw", NULL, NULL, 0, NULL, 0, CTL_HW,
1256 CTL_EOL);
1257 if (err != 0)
1258 goto setup_modem;
1259 err = sysctl_createv(&as->log, 0, NULL, &node, 0,
1260 CTLTYPE_NODE, sc_dev->dv_xname, NULL,
1261 NULL, 0, NULL, 0, CTL_HW, CTL_CREATE,
1262 CTL_EOL);
1263 if (err != 0)
1264 goto setup_modem;
1265 setup_modem:
1266 /* reset */
1267 ac97_write(as, AC97_REG_EXT_MODEM_ID, 1);
1268
1269 /* program rates */
1270 val = 0xff00 & ~AC97_EXT_MODEM_CTRL_PRA;
1271 if (as->ext_mid & AC97_EXT_MODEM_LINE1) {
1272 ac97_write(as, AC97_REG_LINE1_RATE, rate);
1273 val &= ~(AC97_EXT_MODEM_CTRL_PRC |
1274 AC97_EXT_MODEM_CTRL_PRD);
1275 }
1276 if (as->ext_mid & AC97_EXT_MODEM_LINE2) {
1277 ac97_write(as, AC97_REG_LINE2_RATE, rate);
1278 val &= ~(AC97_EXT_MODEM_CTRL_PRE |
1279 AC97_EXT_MODEM_CTRL_PRF);
1280 }
1281 if (as->ext_mid & AC97_EXT_MODEM_HANDSET) {
1282 ac97_write(as, AC97_REG_HANDSET_RATE, rate);
1283 val &= ~(AC97_EXT_MODEM_CTRL_PRG |
1284 AC97_EXT_MODEM_CTRL_PRH);
1285 }
1286
1287 /* power-up everything */
1288 ac97_write(as, AC97_REG_EXT_MODEM_CTRL, 0);
1289 for (i = 5000; i >= 0; i--) {
1290 ac97_read(as, AC97_REG_EXT_MODEM_CTRL, ®);
1291 if ((reg & /*XXXval*/0xf) == /*XXXval*/0xf)
1292 break;
1293 DELAY(1);
1294 }
1295 if (i <= 0) {
1296 printf("%s: codec not responding, status=0x%x\n",
1297 sc_dev->dv_xname, reg);
1298 return ENXIO;
1299 }
1300
1301 /* setup sysctls */
1302 if (as->ext_mid & AC97_EXT_MODEM_LINE1) {
1303 ac97_read(as, AC97_REG_GPIO_CFG, ®);
1304 reg &= ~AC97_GPIO_LINE1_OH;
1305 ac97_write(as, AC97_REG_GPIO_CFG, reg);
1306 ac97_read(as, AC97_REG_GPIO_POLARITY, ®);
1307 reg &= ~AC97_GPIO_LINE1_OH;
1308 ac97_write(as, AC97_REG_GPIO_POLARITY, reg);
1309
1310 err = sysctl_createv(&as->log, 0, NULL, &node_line1,
1311 CTLFLAG_READWRITE, CTLTYPE_INT,
1312 "line1",
1313 SYSCTL_DESCR("off-hook line1"),
1314 ac97_sysctl_verify, 0, as, 0,
1315 CTL_HW, node->sysctl_num,
1316 CTL_CREATE, CTL_EOL);
1317 if (err != 0)
1318 goto sysctl_err;
1319 as->offhook_line1_mib = node_line1->sysctl_num;
1320 }
1321 if (as->ext_mid & AC97_EXT_MODEM_LINE2) {
1322 ac97_read(as, AC97_REG_GPIO_CFG, ®);
1323 reg &= ~AC97_GPIO_LINE2_OH;
1324 ac97_write(as, AC97_REG_GPIO_CFG, reg);
1325 ac97_read(as, AC97_REG_GPIO_POLARITY, ®);
1326 reg &= ~AC97_GPIO_LINE2_OH;
1327 ac97_write(as, AC97_REG_GPIO_POLARITY, reg);
1328
1329 err = sysctl_createv(&as->log, 0, NULL, &node_line2,
1330 CTLFLAG_READWRITE, CTLTYPE_INT,
1331 "line2",
1332 SYSCTL_DESCR("off-hook line2"),
1333 ac97_sysctl_verify, 0, as, 0,
1334 CTL_HW, node->sysctl_num,
1335 CTL_CREATE, CTL_EOL);
1336 if (err != 0)
1337 goto sysctl_err;
1338 as->offhook_line2_mib = node_line2->sysctl_num;
1339 }
1340 sysctl_err:
1341
1342 ac97_write(as, AC97_REG_GPIO_STICKY, 0xffff);
1343 ac97_write(as, AC97_REG_GPIO_WAKEUP, 0x0);
1344 ac97_write(as, AC97_REG_MISC_AFE, 0x0);
1345 }
1346
1347 as->source_info = (as->type == AC97_CODEC_TYPE_MODEM ?
1348 as->modem_source_info : as->audio_source_info);
1349 ac97_setup_source_info(as);
1350
1351 memset(&ctl, 0, sizeof(ctl));
1352 /* disable mutes */
1353 for (i = 0; i < 11; i++) {
1354 static struct {
1355 char *class, *device;
1356 } d[11] = {
1357 { AudioCoutputs, AudioNmaster},
1358 { AudioCoutputs, AudioNheadphone},
1359 { AudioCoutputs, AudioNsurround},
1360 { AudioCoutputs, AudioNcenter},
1361 { AudioCoutputs, AudioNlfe},
1362 { AudioCinputs, AudioNdac},
1363 { AudioCinputs, AudioNcd},
1364 { AudioCinputs, AudioNline},
1365 { AudioCinputs, AudioNaux},
1366 { AudioCinputs, AudioNvideo},
1367 { AudioCrecord, AudioNvolume},
1368 };
1369
1370 ctl.type = AUDIO_MIXER_ENUM;
1371 ctl.un.ord = 0;
1372
1373 ctl.dev = ac97_get_portnum_by_name(&as->codec_if,
1374 d[i].class, d[i].device, AudioNmute);
1375 ac97_mixer_set_port(&as->codec_if, &ctl);
1376 }
1377 ctl.type = AUDIO_MIXER_ENUM;
1378 ctl.un.ord = 0;
1379 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
1380 AudioNsource, NULL);
1381 ac97_mixer_set_port(&as->codec_if, &ctl);
1382
1383 /* set a reasonable default volume */
1384 ctl.type = AUDIO_MIXER_VALUE;
1385 ctl.un.value.num_channels = 2;
1386 ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = \
1387 ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127;
1388 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1389 AudioNmaster, NULL);
1390 ac97_mixer_set_port(&as->codec_if, &ctl);
1391 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1392 AudioNsurround, NULL);
1393 ac97_mixer_set_port(&as->codec_if, &ctl);
1394 ctl.un.value.num_channels = 1;
1395 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1396 AudioNcenter, NULL);
1397 ac97_mixer_set_port(&as->codec_if, &ctl);
1398 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1399 AudioNlfe, NULL);
1400 ac97_mixer_set_port(&as->codec_if, &ctl);
1401
1402 if (initfunc != NULL)
1403 initfunc(as);
1404 return 0;
1405 }
1406
1407 static void
1408 ac97_detach(struct ac97_codec_if *codec_if)
1409 {
1410 struct ac97_softc *as;
1411
1412 as = (struct ac97_softc *)codec_if;
1413 ac97_write(as, AC97_REG_POWER, AC97_POWER_IN | AC97_POWER_OUT
1414 | AC97_POWER_MIXER | AC97_POWER_MIXER_VREF
1415 | AC97_POWER_ACLINK | AC97_POWER_CLK | AC97_POWER_AUX
1416 | AC97_POWER_EAMP);
1417 free(as, M_DEVBUF);
1418 }
1419
1420 static int
1421 ac97_query_devinfo(struct ac97_codec_if *codec_if, mixer_devinfo_t *dip)
1422 {
1423 struct ac97_softc *as;
1424 struct ac97_source_info *si;
1425 const char *name;
1426
1427 as = (struct ac97_softc *)codec_if;
1428 if (dip->index < as->num_source_info) {
1429 si = &as->source_info[dip->index];
1430 dip->type = si->type;
1431 dip->mixer_class = si->mixer_class;
1432 dip->prev = si->prev;
1433 dip->next = si->next;
1434
1435 if (si->qualifier)
1436 name = si->qualifier;
1437 else if (si->device)
1438 name = si->device;
1439 else if (si->class)
1440 name = si->class;
1441 else
1442 name = 0;
1443
1444 if (name)
1445 strcpy(dip->label.name, name);
1446
1447 memcpy(&dip->un, si->info, si->info_size);
1448
1449 /* Set the delta for volume sources */
1450 if (dip->type == AUDIO_MIXER_VALUE)
1451 dip->un.v.delta = 1 << (8 - si->bits);
1452
1453 return 0;
1454 }
1455
1456 return ENXIO;
1457 }
1458
1459 static int
1460 ac97_mixer_set_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
1461 {
1462 struct ac97_softc *as;
1463 struct ac97_source_info *si;
1464 uint16_t mask;
1465 uint16_t val, newval;
1466 int error;
1467
1468 as = (struct ac97_softc *)codec_if;
1469 si = &as->source_info[cp->dev];
1470 if (cp->dev < 0 || cp->dev >= as->num_source_info)
1471 return EINVAL;
1472
1473 if (cp->type != si->type)
1474 return EINVAL;
1475
1476 ac97_read(as, si->reg, &val);
1477
1478 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
1479
1480 mask = (1 << si->bits) - 1;
1481
1482 switch (cp->type) {
1483 case AUDIO_MIXER_ENUM:
1484 if (cp->un.ord > mask || cp->un.ord < 0)
1485 return EINVAL;
1486
1487 newval = (cp->un.ord << si->ofs);
1488 if (si->reg == AC97_REG_RECORD_SELECT) {
1489 newval |= (newval << (8 + si->ofs));
1490 mask |= (mask << 8);
1491 mask = mask << si->ofs;
1492 } else if (si->reg == AC97_REG_SURR_MASTER) {
1493 newval = cp->un.ord ? 0x8080 : 0x0000;
1494 mask = 0x8080;
1495 } else
1496 mask = mask << si->ofs;
1497 break;
1498 case AUDIO_MIXER_VALUE:
1499 {
1500 const struct audio_mixer_value *value = si->info;
1501 uint16_t l, r, ol, or;
1502 int deltal, deltar;
1503
1504 if ((cp->un.value.num_channels <= 0) ||
1505 (cp->un.value.num_channels > value->num_channels))
1506 return EINVAL;
1507
1508 if (cp->un.value.num_channels == 1) {
1509 l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
1510 } else {
1511 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
1512 l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1513 r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1514 } else { /* left/right is reversed here */
1515 r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1516 l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1517 }
1518
1519 }
1520
1521 if (!si->polarity) {
1522 l = 255 - l;
1523 r = 255 - r;
1524 }
1525
1526 ol = (val >> (8+si->ofs)) & mask;
1527 or = (val >> si->ofs) & mask;
1528
1529 deltal = (ol << (8 - si->bits)) - l;
1530 deltar = (or << (8 - si->bits)) - r;
1531
1532 l = l >> (8 - si->bits);
1533 r = r >> (8 - si->bits);
1534
1535 if (deltal && ol == l)
1536 l += (deltal > 0) ? (l ? -1 : 0) : (l < mask ? 1 : 0);
1537 if (deltar && or == r)
1538 r += (deltar > 0) ? (r ? -1 : 0) : (r < mask ? 1 : 0);
1539
1540 newval = ((r & mask) << si->ofs);
1541 if (value->num_channels == 2) {
1542 newval = newval | ((l & mask) << (si->ofs+8));
1543 mask |= (mask << 8);
1544 }
1545 mask = mask << si->ofs;
1546 break;
1547 }
1548 default:
1549 return EINVAL;
1550 }
1551
1552 error = ac97_write(as, si->reg, (val & ~mask) | newval);
1553 if (error)
1554 return error;
1555
1556 return 0;
1557 }
1558
1559 static int
1560 ac97_get_portnum_by_name(struct ac97_codec_if *codec_if, const char *class,
1561 const char *device, const char *qualifier)
1562 {
1563 struct ac97_softc *as;
1564 int idx;
1565
1566 as = (struct ac97_softc *)codec_if;
1567 for (idx = 0; idx < as->num_source_info; idx++) {
1568 struct ac97_source_info *si = &as->source_info[idx];
1569 if (ac97_str_equal(class, si->class) &&
1570 ac97_str_equal(device, si->device) &&
1571 ac97_str_equal(qualifier, si->qualifier))
1572 return idx;
1573 }
1574
1575 return -1;
1576 }
1577
1578 static int
1579 ac97_mixer_get_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
1580 {
1581 struct ac97_softc *as;
1582 struct ac97_source_info *si;
1583 uint16_t mask;
1584 uint16_t val;
1585
1586 as = (struct ac97_softc *)codec_if;
1587 si = &as->source_info[cp->dev];
1588 if (cp->dev < 0 || cp->dev >= as->num_source_info)
1589 return EINVAL;
1590
1591 if (cp->type != si->type)
1592 return EINVAL;
1593
1594 ac97_read(as, si->reg, &val);
1595
1596 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
1597
1598 mask = (1 << si->bits) - 1;
1599
1600 switch (cp->type) {
1601 case AUDIO_MIXER_ENUM:
1602 cp->un.ord = (val >> si->ofs) & mask;
1603 DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n",
1604 val, si->ofs, mask, cp->un.ord));
1605 break;
1606 case AUDIO_MIXER_VALUE:
1607 {
1608 const struct audio_mixer_value *value = si->info;
1609 uint16_t l, r;
1610
1611 if ((cp->un.value.num_channels <= 0) ||
1612 (cp->un.value.num_channels > value->num_channels))
1613 return EINVAL;
1614
1615 if (value->num_channels == 1) {
1616 l = r = (val >> si->ofs) & mask;
1617 } else {
1618 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
1619 l = (val >> (si->ofs + 8)) & mask;
1620 r = (val >> si->ofs) & mask;
1621 } else { /* host has reversed channels */
1622 r = (val >> (si->ofs + 8)) & mask;
1623 l = (val >> si->ofs) & mask;
1624 }
1625 }
1626
1627 l = (l << (8 - si->bits));
1628 r = (r << (8 - si->bits));
1629 if (!si->polarity) {
1630 l = 255 - l;
1631 r = 255 - r;
1632 }
1633
1634 /* The EAP driver averages l and r for stereo
1635 channels that are requested in MONO mode. Does this
1636 make sense? */
1637 if (cp->un.value.num_channels == 1) {
1638 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l;
1639 } else if (cp->un.value.num_channels == 2) {
1640 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
1641 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
1642 }
1643
1644 break;
1645 }
1646 default:
1647 return EINVAL;
1648 }
1649
1650 return 0;
1651 }
1652
1653
1654 static int
1655 ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_int *rate)
1656 {
1657 struct ac97_softc *as;
1658 u_int value;
1659 uint16_t ext_stat;
1660 uint16_t actual;
1661 uint16_t power;
1662 uint16_t power_bit;
1663
1664 as = (struct ac97_softc *)codec_if;
1665 if (target == AC97_REG_PCM_MIC_ADC_RATE) {
1666 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1667 *rate = AC97_SINGLE_RATE;
1668 return 0;
1669 }
1670 } else {
1671 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1672 *rate = AC97_SINGLE_RATE;
1673 return 0;
1674 }
1675 }
1676 value = *rate * AC97_STANDARD_CLOCK / as->ac97_clock;
1677 ext_stat = 0;
1678 /*
1679 * PCM_FRONT_DAC_RATE/PCM_SURR_DAC_RATE/PCM_LFE_DAC_RATE
1680 * Check VRA, DRA
1681 * PCM_LR_ADC_RATE
1682 * Check VRA
1683 * PCM_MIC_ADC_RATE
1684 * Check VRM
1685 */
1686 switch (target) {
1687 case AC97_REG_PCM_FRONT_DAC_RATE:
1688 case AC97_REG_PCM_SURR_DAC_RATE:
1689 case AC97_REG_PCM_LFE_DAC_RATE:
1690 power_bit = AC97_POWER_OUT;
1691 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1692 *rate = AC97_SINGLE_RATE;
1693 return 0;
1694 }
1695 if (as->ext_id & AC97_EXT_AUDIO_DRA) {
1696 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &ext_stat);
1697 if (value > 0x1ffff) {
1698 return EINVAL;
1699 } else if (value > 0xffff) {
1700 /* Enable DRA */
1701 ext_stat |= AC97_EXT_AUDIO_DRA;
1702 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1703 value /= 2;
1704 } else {
1705 /* Disable DRA */
1706 ext_stat &= ~AC97_EXT_AUDIO_DRA;
1707 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1708 }
1709 } else {
1710 if (value > 0xffff)
1711 return EINVAL;
1712 }
1713 break;
1714 case AC97_REG_PCM_LR_ADC_RATE:
1715 power_bit = AC97_POWER_IN;
1716 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1717 *rate = AC97_SINGLE_RATE;
1718 return 0;
1719 }
1720 if (value > 0xffff)
1721 return EINVAL;
1722 break;
1723 case AC97_REG_PCM_MIC_ADC_RATE:
1724 power_bit = AC97_POWER_IN;
1725 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1726 *rate = AC97_SINGLE_RATE;
1727 return 0;
1728 }
1729 if (value > 0xffff)
1730 return EINVAL;
1731 break;
1732 default:
1733 printf("%s: Unknown register: 0x%x\n", __func__, target);
1734 return EINVAL;
1735 }
1736
1737 ac97_read(as, AC97_REG_POWER, &power);
1738 ac97_write(as, AC97_REG_POWER, power | power_bit);
1739
1740 ac97_write(as, target, (uint16_t)value);
1741 ac97_read(as, target, &actual);
1742 actual = (uint32_t)actual * as->ac97_clock / AC97_STANDARD_CLOCK;
1743
1744 ac97_write(as, AC97_REG_POWER, power);
1745 if (ext_stat & AC97_EXT_AUDIO_DRA) {
1746 *rate = actual * 2;
1747 } else {
1748 *rate = actual;
1749 }
1750 return 0;
1751 }
1752
1753 static void
1754 ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock)
1755 {
1756 struct ac97_softc *as;
1757
1758 as = (struct ac97_softc *)codec_if;
1759 as->ac97_clock = clock;
1760 }
1761
1762 static uint16_t
1763 ac97_get_extcaps(struct ac97_codec_if *codec_if)
1764 {
1765 struct ac97_softc *as;
1766
1767 as = (struct ac97_softc *)codec_if;
1768 return as->ext_id;
1769 }
1770
1771 static int
1772 ac97_add_port(struct ac97_softc *as, const struct ac97_source_info *src)
1773 {
1774 struct ac97_source_info *si;
1775 int ouridx, idx;
1776
1777 if ((as->type == AC97_CODEC_TYPE_AUDIO &&
1778 as->num_source_info >= AUDIO_MAX_SOURCES) ||
1779 (as->type == AC97_CODEC_TYPE_MODEM &&
1780 as->num_source_info >= MODEM_MAX_SOURCES)) {
1781 printf("%s: internal error: increase MAX_SOURCES in %s\n",
1782 __func__, __FILE__);
1783 return -1;
1784 }
1785 if (!ac97_check_capability(as, src->req_feature))
1786 return -1;
1787 ouridx = as->num_source_info;
1788 si = &as->source_info[ouridx];
1789 memcpy(si, src, sizeof(*si));
1790
1791 switch (si->type) {
1792 case AUDIO_MIXER_CLASS:
1793 case AUDIO_MIXER_VALUE:
1794 printf("%s: adding class/value is not supported yet.\n",
1795 __func__);
1796 return -1;
1797 case AUDIO_MIXER_ENUM:
1798 break;
1799 default:
1800 printf("%s: unknown type: %d\n", __func__, si->type);
1801 return -1;
1802 }
1803 as->num_source_info++;
1804
1805 si->mixer_class = ac97_get_portnum_by_name(&as->codec_if, si->class,
1806 NULL, NULL);
1807 /* Find the root of the device */
1808 idx = ac97_get_portnum_by_name(&as->codec_if, si->class,
1809 si->device, NULL);
1810 /* Find the last item */
1811 while (as->source_info[idx].next != AUDIO_MIXER_LAST)
1812 idx = as->source_info[idx].next;
1813 /* Append */
1814 as->source_info[idx].next = ouridx;
1815 si->prev = idx;
1816 si->next = AUDIO_MIXER_LAST;
1817
1818 return 0;
1819 }
1820
1821 /**
1822 * Codec-dependent initialization
1823 */
1824
1825 #define AD1980_REG_MISC 0x76
1826 #define AD1980_MISC_MBG0 0x0001 /* 0 1888/1980/1981 /1985 */
1827 #define AD1980_MISC_MBG1 0x0002 /* 1 1888/1980/1981 /1985 */
1828 #define AD1980_MISC_VREFD 0x0004 /* 2 1888/1980/1981 /1985 */
1829 #define AD1980_MISC_VREFH 0x0008 /* 3 1888/1980/1981 /1985 */
1830 #define AD1980_MISC_SRU 0x0010 /* 4 1888/1980 /1985 */
1831 #define AD1980_MISC_LOSEL 0x0020 /* 5 1888/1980/1981 /1985 */
1832 #define AD1980_MISC_2CMIC 0x0040 /* 6 1980/1981B/1985 */
1833 #define AD1980_MISC_SPRD 0x0080 /* 7 1888/1980 /1985 */
1834 #define AD1980_MISC_DMIX0 0x0100 /* 8 1888/1980 /1985 */
1835 #define AD1980_MISC_DMIX1 0x0200 /* 9 1888/1980 /1985 */
1836 #define AD1980_MISC_HPSEL 0x0400 /*10 1888/1980 /1985 */
1837 #define AD1980_MISC_CLDIS 0x0800 /*11 1888/1980 /1985 */
1838 #define AD1980_MISC_LODIS 0x1000 /*12 1888/1980/1981 /1985 */
1839 #define AD1980_MISC_MSPLT 0x2000 /*13 1888/1980/1981 /1985 */
1840 #define AD1980_MISC_AC97NC 0x4000 /*14 1888/1980 /1985 */
1841 #define AD1980_MISC_DACZ 0x8000 /*15 1888/1980/1981 /1985 */
1842 #define AD1981_REG_MISC 0x76
1843 #define AD1981_MISC_MADST 0x0010 /* 4 */
1844 #define AD1981A_MISC_MADPD 0x0040 /* 6 */
1845 #define AD1981B_MISC_MADPD 0x0080 /* 7 */
1846 #define AD1981_MISC_FMXE 0x0200 /* 9 */
1847 #define AD1981_MISC_DAM 0x0800 /*11 */
1848 static void
1849 ac97_ad198x_init(struct ac97_softc *as)
1850 {
1851 int i;
1852 uint16_t misc;
1853
1854 ac97_read(as, AD1980_REG_MISC, &misc);
1855 ac97_write(as, AD1980_REG_MISC,
1856 misc | AD1980_MISC_LOSEL | AD1980_MISC_HPSEL);
1857
1858 for (i = 0; i < as->num_source_info; i++) {
1859 if (as->source_info[i].type != AUDIO_MIXER_VALUE)
1860 continue;
1861
1862 if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME)
1863 as->source_info[i].reg = AC97_REG_SURR_MASTER;
1864 else if (as->source_info[i].reg == AC97_REG_SURR_MASTER)
1865 as->source_info[i].reg = AC97_REG_MASTER_VOLUME;
1866 }
1867 }
1868
1869 #define ALC650_REG_MULTI_CHANNEL_CONTROL 0x6a
1870 #define ALC650_MCC_SLOT_MODIFY_MASK 0xc000
1871 #define ALC650_MCC_FRONTDAC_FROM_SPDIFIN 0x2000 /* 13 */
1872 #define ALC650_MCC_SPDIFOUT_FROM_ADC 0x1000 /* 12 */
1873 #define ALC650_MCC_PCM_FROM_SPDIFIN 0x0800 /* 11 */
1874 #define ALC650_MCC_MIC_OR_CENTERLFE 0x0400 /* 10 */
1875 #define ALC650_MCC_LINEIN_OR_SURROUND 0x0200 /* 9 */
1876 #define ALC650_MCC_INDEPENDENT_MASTER_L 0x0080 /* 7 */
1877 #define ALC650_MCC_INDEPENDENT_MASTER_R 0x0040 /* 6 */
1878 #define ALC650_MCC_ANALOG_TO_CENTERLFE 0x0020 /* 5 */
1879 #define ALC650_MCC_ANALOG_TO_SURROUND 0x0010 /* 4 */
1880 #define ALC650_MCC_EXCHANGE_CENTERLFE 0x0008 /* 3 */
1881 #define ALC650_MCC_CENTERLFE_DOWNMIX 0x0004 /* 2 */
1882 #define ALC650_MCC_SURROUND_DOWNMIX 0x0002 /* 1 */
1883 #define ALC650_MCC_LINEOUT_TO_SURROUND 0x0001 /* 0 */
1884 static void
1885 ac97_alc650_init(struct ac97_softc *as)
1886 {
1887 static const struct ac97_source_info sources[6] = {
1888 { AudioCoutputs, AudioNsurround, "lineinjack",
1889 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1890 ALC650_REG_MULTI_CHANNEL_CONTROL,
1891 0x0000, 1, 9, 0, 0, CHECK_SURROUND },
1892 { AudioCoutputs, AudioNsurround, "mixtofront",
1893 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1894 ALC650_REG_MULTI_CHANNEL_CONTROL,
1895 0x0000, 1, 1, 0, 0, CHECK_SURROUND },
1896 { AudioCoutputs, AudioNcenter, "micjack",
1897 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1898 ALC650_REG_MULTI_CHANNEL_CONTROL,
1899 0x0000, 1, 10, 0, 0, CHECK_CENTER },
1900 { AudioCoutputs, AudioNlfe, "micjack",
1901 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1902 ALC650_REG_MULTI_CHANNEL_CONTROL,
1903 0x0000, 1, 10, 0, 0, CHECK_LFE },
1904 { AudioCoutputs, AudioNcenter, "mixtofront",
1905 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1906 ALC650_REG_MULTI_CHANNEL_CONTROL,
1907 0x0000, 1, 2, 0, 0, CHECK_CENTER },
1908 { AudioCoutputs, AudioNlfe, "mixtofront",
1909 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1910 ALC650_REG_MULTI_CHANNEL_CONTROL,
1911 0x0000, 1, 2, 0, 0, CHECK_LFE },
1912 };
1913
1914 ac97_add_port(as, &sources[0]);
1915 ac97_add_port(as, &sources[1]);
1916 ac97_add_port(as, &sources[2]);
1917 ac97_add_port(as, &sources[3]);
1918 ac97_add_port(as, &sources[4]);
1919 ac97_add_port(as, &sources[5]);
1920 }
1921
1922 #define VT1616_REG_IO_CONTROL 0x5a
1923 #define VT1616_IC_LVL (1 << 15)
1924 #define VT1616_IC_LFECENTER_TO_FRONT (1 << 12)
1925 #define VT1616_IC_SURROUND_TO_FRONT (1 << 11)
1926 #define VT1616_IC_BPDC (1 << 10)
1927 #define VT1616_IC_DC (1 << 9)
1928 #define VT1616_IC_IB_MASK 0x000c
1929 static void
1930 ac97_vt1616_init(struct ac97_softc *as)
1931 {
1932 static const struct ac97_source_info sources[3] = {
1933 { AudioCoutputs, AudioNsurround, "mixtofront",
1934 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1935 VT1616_REG_IO_CONTROL,
1936 0x0000, 1, 11, 0, 0, CHECK_SURROUND },
1937 { AudioCoutputs, AudioNcenter, "mixtofront",
1938 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1939 VT1616_REG_IO_CONTROL,
1940 0x0000, 1, 12, 0, 0, CHECK_CENTER },
1941 { AudioCoutputs, AudioNlfe, "mixtofront",
1942 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1943 VT1616_REG_IO_CONTROL,
1944 0x0000, 1, 12, 0, 0, CHECK_LFE },
1945 };
1946
1947 ac97_add_port(as, &sources[0]);
1948 ac97_add_port(as, &sources[1]);
1949 ac97_add_port(as, &sources[2]);
1950 }
1951
1952 static int
1953 ac97_modem_offhook_set(struct ac97_softc *as, int line, int newval)
1954 {
1955 uint16_t val;
1956
1957 val = as->shadow_reg[AC97_REG_GPIO_STATUS >> 1];
1958 switch (newval) {
1959 case 0:
1960 val &= ~line;
1961 break;
1962 case 1:
1963 val |= line;
1964 break;
1965 }
1966 ac97_write(as, AC97_REG_GPIO_STATUS, val);
1967
1968 return 0;
1969 }
1970
1971 static int
1972 ac97_sysctl_verify(SYSCTLFN_ARGS)
1973 {
1974 int error, tmp;
1975 struct sysctlnode node;
1976 struct ac97_softc *as;
1977
1978 node = *rnode;
1979 as = rnode->sysctl_data;
1980 if (node.sysctl_num == as->offhook_line1_mib) {
1981 tmp = as->offhook_line1;
1982 node.sysctl_data = &tmp;
1983 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1984 if (error || newp == NULL)
1985 return error;
1986
1987 if (tmp < 0 || tmp > 1)
1988 return EINVAL;
1989
1990 as->offhook_line1 = tmp;
1991 ac97_modem_offhook_set(as, AC97_GPIO_LINE1_OH, tmp);
1992 } else if (node.sysctl_num == as->offhook_line2_mib) {
1993 tmp = as->offhook_line2;
1994 node.sysctl_data = &tmp;
1995 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1996 if (error || newp == NULL)
1997 return error;
1998
1999 if (tmp < 0 || tmp > 1)
2000 return EINVAL;
2001
2002 as->offhook_line2 = tmp;
2003 ac97_modem_offhook_set(as, AC97_GPIO_LINE2_OH, tmp);
2004 }
2005
2006 return 0;
2007 }
2008