ac97.c revision 1.78 1 /* $NetBSD: ac97.c,v 1.78 2005/11/06 10:08:24 rpaulo 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.78 2005/11/06 10:08:24 rpaulo 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 { 0x83847652, 0xffffffff, "SigmaTel STAC9752/53", },
677 { 0x83847656, 0xffffffff, "SigmaTel STAC9756/57", },
678 { 0x83847658, 0xffffffff, "SigmaTel STAC9758/59", },
679 { 0x83847666, 0xffffffff, "SigmaTel STAC9766/67", },
680 { 0x83847684, 0xffffffff, "SigmaTel STAC9783/84", },
681 { 0x83847600, AC97_VENDOR_ID_MASK, "SigmaTel unknown", },
682
683 /* Conexant AC'97 modems -- good luck finding datasheets! */
684 { AC97_CODEC_ID('C', 'X', 'T', 33),
685 0xffffffff, "Conexant HSD11246", },
686 { AC97_CODEC_ID('C', 'X', 'T', 34),
687 0xffffffff, "Conexant D480 MDC V.92 Modem", },
688 { AC97_CODEC_ID('C', 'X', 'T', 48),
689 0xffffffff, "Conexant CXT48", },
690 { AC97_CODEC_ID('C', 'X', 'T', 0),
691 AC97_VENDOR_ID_MASK, "Conexant unknown", },
692
693 { 0,
694 0, NULL, }
695 };
696
697 static const char * const ac97enhancement[] = {
698 "no 3D stereo",
699 "Analog Devices Phat Stereo",
700 "Creative",
701 "National Semi 3D",
702 "Yamaha Ymersion",
703 "BBE 3D",
704 "Crystal Semi 3D",
705 "Qsound QXpander",
706 "Spatializer 3D",
707 "SRS 3D",
708 "Platform Tech 3D",
709 "AKM 3D",
710 "Aureal",
711 "AZTECH 3D",
712 "Binaura 3D",
713 "ESS Technology",
714 "Harman International VMAx",
715 "Nvidea 3D",
716 "Philips Incredible Sound",
717 "Texas Instruments' 3D",
718 "VLSI Technology 3D",
719 "TriTech 3D",
720 "Realtek 3D",
721 "Samsung 3D",
722 "Wolfson Microelectronics 3D",
723 "Delta Integration 3D",
724 "SigmaTel 3D",
725 "KS Waves 3D",
726 "Rockwell 3D",
727 "Unknown 3D",
728 "Unknown 3D",
729 "Unknown 3D",
730 };
731
732 static const char * const ac97feature[] = {
733 "dedicated mic channel",
734 "reserved",
735 "tone",
736 "simulated stereo",
737 "headphone",
738 "bass boost",
739 "18 bit DAC",
740 "20 bit DAC",
741 "18 bit ADC",
742 "20 bit ADC"
743 };
744
745
746 /* #define AC97_DEBUG 10 */
747 /* #define AC97_IO_DEBUG */
748
749 #ifdef AUDIO_DEBUG
750 #define DPRINTF(x) if (ac97debug) printf x
751 #define DPRINTFN(n,x) if (ac97debug>(n)) printf x
752 #ifdef AC97_DEBUG
753 int ac97debug = AC97_DEBUG;
754 #else
755 int ac97debug = 0;
756 #endif
757 #else
758 #define DPRINTF(x)
759 #define DPRINTFN(n,x)
760 #endif
761
762 #ifdef AC97_IO_DEBUG
763 static const char *ac97_register_names[0x80 / 2] = {
764 "RESET", "MASTER_VOLUME", "HEADPHONE_VOLUME", "MASTER_VOLUME_MONO",
765 "MASTER_TONE", "PCBEEP_VOLUME", "PHONE_VOLUME", "MIC_VOLUME",
766 "LINEIN_VOLUME", "CD_VOLUME", "VIDEO_VOLUME", "AUX_VOLUME",
767 "PCMOUT_VOLUME", "RECORD_SELECT", "RECORD_GATIN", "RECORD_GAIN_MIC",
768 "GP", "3D_CONTROL", "AUDIO_INT", "POWER",
769 "EXT_AUDIO_ID", "EXT_AUDIO_CTRL", "PCM_FRONT_DAC_RATE", "PCM_SURR_DAC_RATE",
770 "PCM_LFE_DAC_RATE", "PCM_LR_ADC_RATE", "PCM_MIC_ADC_RATE", "CENTER_LFE_MASTER",
771 "SURR_MASTER", "SPDIF_CTRL", "EXT_MODEM_ID", "EXT_MODEM_CTRL",
772 "LINE1_RATE", "LINE2_RATE", "HANDSET_RATE", "LINE1_LEVEL",
773 "LINE2_LEVEL", "HANDSET_LEVEL", "GPIO_PIN_CONFIG", "GPIO_PIN_POLARITY",
774 "GPIO_PIN_STICKY", "GPIO_PIN_WAKEUP", "GPIO_PIN_STATUS", "MISC_MODEM_CTRL",
775 "0x58", "VENDOR-5A", "VENDOR-5C", "VENDOR-5E",
776 "0x60", "0x62", "0x64", "0x66",
777 "0x68", "0x6a", "0x6c", "0x6e",
778 "VENDOR-70", "VENDOR-72", "VENDOR-74", "VENDOR-76",
779 "VENDOR-78", "VENDOR-7A", "VENDOR_ID1", "VENDOR_ID2"
780 };
781 #endif
782
783 static void
784 ac97_read(struct ac97_softc *as, uint8_t reg, uint16_t *val)
785 {
786 if (as->host_flags & AC97_HOST_DONT_READ &&
787 (reg != AC97_REG_VENDOR_ID1 && reg != AC97_REG_VENDOR_ID2 &&
788 reg != AC97_REG_RESET)) {
789 *val = as->shadow_reg[reg >> 1];
790 return;
791 }
792
793 if (as->host_if->read(as->host_if->arg, reg, val)) {
794 *val = as->shadow_reg[reg >> 1];
795 }
796 }
797
798 static int
799 ac97_write(struct ac97_softc *as, uint8_t reg, uint16_t val)
800 {
801 #ifndef AC97_IO_DEBUG
802 as->shadow_reg[reg >> 1] = val;
803 return as->host_if->write(as->host_if->arg, reg, val);
804 #else
805 int ret;
806 uint16_t actual;
807
808 as->shadow_reg[reg >> 1] = val;
809 ret = as->host_if->write(as->host_if->arg, reg, val);
810 as->host_if->read(as->host_if->arg, reg, &actual);
811 if (val != actual && reg < 0x80) {
812 printf("ac97_write: reg=%s, written=0x%04x, read=0x%04x\n",
813 ac97_register_names[reg / 2], val, actual);
814 }
815 return ret;
816 #endif
817 }
818
819 static void
820 ac97_setup_defaults(struct ac97_softc *as)
821 {
822 int idx;
823 const struct ac97_source_info *si;
824
825 memset(as->shadow_reg, 0, sizeof(as->shadow_reg));
826
827 for (idx = 0; idx < AUDIO_SOURCE_INFO_SIZE; idx++) {
828 si = &audio_source_info[idx];
829 ac97_write(as, si->reg, si->default_value);
830 }
831 for (idx = 0; idx < MODEM_SOURCE_INFO_SIZE; idx++) {
832 si = &modem_source_info[idx];
833 ac97_write(as, si->reg, si->default_value);
834 }
835 }
836
837 static void
838 ac97_restore_shadow(struct ac97_codec_if *self)
839 {
840 struct ac97_softc *as;
841 const struct ac97_source_info *si;
842 int idx;
843 uint16_t val;
844
845 as = (struct ac97_softc *) self;
846
847 if (as->type == AC97_CODEC_TYPE_AUDIO) {
848 /* make sure chip is fully operational */
849 for (idx = 50000; idx >= 0; idx--) {
850 ac97_read(as, AC97_REG_POWER, &val);
851 if ((val & as->power_all) == as->power_all)
852 break;
853 DELAY(10);
854 }
855
856 /*
857 * actually try changing a value!
858 * The default value of AC97_REG_MASTER_VOLUME is 0x8000.
859 */
860 for (idx = 50000; idx >= 0; idx--) {
861 ac97_write(as, AC97_REG_MASTER_VOLUME, 0x1010);
862 ac97_read(as, AC97_REG_MASTER_VOLUME, &val);
863 if (val == 0x1010)
864 break;
865 DELAY(10);
866 }
867 }
868
869 for (idx = 0; idx < SOURCE_INFO_SIZE(as); idx++) {
870 if (as->type == AC97_CODEC_TYPE_MODEM)
871 si = &modem_source_info[idx];
872 else
873 si = &audio_source_info[idx];
874 /* don't "restore" to the reset reg! */
875 if (si->reg != AC97_REG_RESET)
876 ac97_write(as, si->reg, as->shadow_reg[si->reg >> 1]);
877 }
878
879 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA
880 | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM
881 | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC
882 | AC97_EXT_AUDIO_LDAC)) {
883 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL,
884 as->shadow_reg[AC97_REG_EXT_AUDIO_CTRL >> 1]);
885 }
886 if (as->ext_mid & (AC97_EXT_MODEM_LINE1 | AC97_EXT_MODEM_LINE2
887 | AC97_EXT_MODEM_HANDSET | AC97_EXT_MODEM_CID1
888 | AC97_EXT_MODEM_CID2 | AC97_EXT_MODEM_ID0
889 | AC97_EXT_MODEM_ID1)) {
890 ac97_write(as, AC97_REG_EXT_MODEM_CTRL,
891 as->shadow_reg[AC97_REG_EXT_MODEM_CTRL >> 1]);
892 }
893 }
894
895 static int
896 ac97_str_equal(const char *a, const char *b)
897 {
898 return (a == b) || (a && b && (!strcmp(a, b)));
899 }
900
901 static int
902 ac97_check_capability(struct ac97_softc *as, int check)
903 {
904 switch (check) {
905 case CHECK_NONE:
906 return 1;
907 case CHECK_SURROUND:
908 return as->ext_id & AC97_EXT_AUDIO_SDAC;
909 case CHECK_CENTER:
910 return as->ext_id & AC97_EXT_AUDIO_CDAC;
911 case CHECK_LFE:
912 return as->ext_id & AC97_EXT_AUDIO_LDAC;
913 case CHECK_HEADPHONES:
914 return as->caps & AC97_CAPS_HEADPHONES;
915 case CHECK_TONE:
916 return as->caps & AC97_CAPS_TONECTRL;
917 case CHECK_MIC:
918 return as->caps & AC97_CAPS_MICIN;
919 case CHECK_LOUDNESS:
920 return as->caps & AC97_CAPS_LOUDNESS;
921 case CHECK_3D:
922 return AC97_CAPS_ENHANCEMENT(as->caps) != 0;
923 case CHECK_LINE1:
924 return as->ext_mid & AC97_EXT_MODEM_LINE1;
925 case CHECK_LINE2:
926 return as->ext_mid & AC97_EXT_MODEM_LINE2;
927 case CHECK_HANDSET:
928 return as->ext_mid & AC97_EXT_MODEM_HANDSET;
929 default:
930 printf("%s: internal error: feature=%d\n", __func__, check);
931 return 0;
932 }
933 }
934
935 static void
936 ac97_setup_source_info(struct ac97_softc *as)
937 {
938 int idx, ouridx;
939 struct ac97_source_info *si, *si2;
940
941 for (idx = 0, ouridx = 0; idx < SOURCE_INFO_SIZE(as); idx++) {
942 si = &as->source_info[ouridx];
943 if (as->type == AC97_CODEC_TYPE_MODEM) {
944 if (!ac97_check_capability(as,
945 modem_source_info[idx].req_feature))
946 continue;
947 memcpy(si, &modem_source_info[idx], sizeof(*si));
948 } else {
949 if (!ac97_check_capability(as,
950 audio_source_info[idx].req_feature))
951 continue;
952 memcpy(si, &audio_source_info[idx], sizeof(*si));
953 }
954
955 switch (si->type) {
956 case AUDIO_MIXER_CLASS:
957 si->mixer_class = ouridx;
958 ouridx++;
959 break;
960 case AUDIO_MIXER_VALUE:
961 /* Todo - Test to see if it works */
962 ouridx++;
963
964 /* Add an entry for mute, if necessary */
965 if (si->mute) {
966 si = &as->source_info[ouridx];
967 if (as->type == AC97_CODEC_TYPE_MODEM)
968 memcpy(si, &modem_source_info[idx],
969 sizeof(*si));
970 else
971 memcpy(si, &audio_source_info[idx],
972 sizeof(*si));
973 si->qualifier = AudioNmute;
974 si->type = AUDIO_MIXER_ENUM;
975 si->info = &ac97_on_off;
976 si->info_size = sizeof(ac97_on_off);
977 si->bits = 1;
978 si->ofs = 15;
979 si->mute = 0;
980 si->polarity = 0;
981 ouridx++;
982 }
983 break;
984 case AUDIO_MIXER_ENUM:
985 /* Todo - Test to see if it works */
986 ouridx++;
987 break;
988 default:
989 aprint_error ("ac97: shouldn't get here\n");
990 break;
991 }
992 }
993
994 as->num_source_info = ouridx;
995
996 for (idx = 0; idx < as->num_source_info; idx++) {
997 int idx2, previdx;
998
999 si = &as->source_info[idx];
1000
1001 /* Find mixer class */
1002 for (idx2 = 0; idx2 < as->num_source_info; idx2++) {
1003 si2 = &as->source_info[idx2];
1004
1005 if (si2->type == AUDIO_MIXER_CLASS &&
1006 ac97_str_equal(si->class,
1007 si2->class)) {
1008 si->mixer_class = idx2;
1009 }
1010 }
1011
1012
1013 /* Setup prev and next pointers */
1014 if (si->prev != 0)
1015 continue;
1016
1017 if (si->qualifier)
1018 continue;
1019
1020 si->prev = AUDIO_MIXER_LAST;
1021 previdx = idx;
1022
1023 for (idx2 = 0; idx2 < as->num_source_info; idx2++) {
1024 if (idx2 == idx)
1025 continue;
1026
1027 si2 = &as->source_info[idx2];
1028
1029 if (!si2->prev &&
1030 ac97_str_equal(si->class, si2->class) &&
1031 ac97_str_equal(si->device, si2->device)) {
1032 as->source_info[previdx].next = idx2;
1033 as->source_info[idx2].prev = previdx;
1034
1035 previdx = idx2;
1036 }
1037 }
1038
1039 as->source_info[previdx].next = AUDIO_MIXER_LAST;
1040 }
1041 }
1042
1043 /* backwords compatibility */
1044 int
1045 ac97_attach(struct ac97_host_if *host_if, struct device *sc_dev)
1046 {
1047 return ac97_attach_type(host_if, sc_dev, AC97_CODEC_TYPE_AUDIO);
1048 }
1049
1050 int
1051 ac97_attach_type(struct ac97_host_if *host_if, struct device *sc_dev, int type)
1052 {
1053 struct ac97_softc *as;
1054 int error, i, j;
1055 uint32_t id;
1056 uint16_t id1, id2;
1057 uint16_t extstat, rate;
1058 uint16_t val;
1059 mixer_ctrl_t ctl;
1060 void (*initfunc)(struct ac97_softc *);
1061 #define FLAGBUFLEN 140
1062 char flagbuf[FLAGBUFLEN];
1063
1064 initfunc = NULL;
1065 as = malloc(sizeof(struct ac97_softc), M_DEVBUF, M_WAITOK|M_ZERO);
1066
1067 if (as == NULL)
1068 return ENOMEM;
1069
1070 as->codec_if.vtbl = &ac97civ;
1071 as->host_if = host_if;
1072 as->type = type;
1073
1074 if ((error = host_if->attach(host_if->arg, &as->codec_if))) {
1075 free(as, M_DEVBUF);
1076 return error;
1077 }
1078
1079 if ((error = host_if->reset(host_if->arg))) {
1080 free(as, M_DEVBUF);
1081 return error;
1082 }
1083
1084 if (host_if->flags)
1085 as->host_flags = host_if->flags(host_if->arg);
1086
1087 /*
1088 * Assume codec has all four power bits.
1089 * XXXSCW: what to do for modems?
1090 */
1091 as->power_all = AC97_POWER_REF | AC97_POWER_ANL | AC97_POWER_DAC |
1092 AC97_POWER_ADC;
1093 if (as->type == AC97_CODEC_TYPE_AUDIO) {
1094 host_if->write(host_if->arg, AC97_REG_RESET, 0);
1095
1096 /*
1097 * Power-up everything except the analogue mixer.
1098 * If this codec doesn't support analogue mixer power-down,
1099 * AC97_POWER_MIXER will read back as zero.
1100 */
1101 host_if->write(host_if->arg, AC97_REG_POWER, AC97_POWER_MIXER);
1102 ac97_read(as, AC97_REG_POWER, &val);
1103 if ((val & AC97_POWER_MIXER) == 0) {
1104 /* Codec doesn't support analogue mixer power-down */
1105 as->power_all &= ~AC97_POWER_ANL;
1106 }
1107 host_if->write(host_if->arg, AC97_REG_POWER, 0);
1108
1109 for (i = 500000; i >= 0; i--) {
1110 ac97_read(as, AC97_REG_POWER, &val);
1111 if ((val & as->power_all) == as->power_all)
1112 break;
1113 DELAY(1);
1114 }
1115 } else if (as->type == AC97_CODEC_TYPE_MODEM) {
1116 host_if->write(host_if->arg, AC97_REG_EXT_MODEM_ID, 0);
1117 }
1118
1119 ac97_setup_defaults(as);
1120 if (as->type == AC97_CODEC_TYPE_AUDIO)
1121 ac97_read(as, AC97_REG_RESET, &as->caps);
1122 ac97_read(as, AC97_REG_VENDOR_ID1, &id1);
1123 ac97_read(as, AC97_REG_VENDOR_ID2, &id2);
1124
1125 id = (id1 << 16) | id2;
1126 aprint_normal("%s: ac97: ", sc_dev->dv_xname);
1127
1128 for (i = 0; ; i++) {
1129 if (ac97codecid[i].id == 0) {
1130 char pnp[4];
1131
1132 AC97_GET_CODEC_ID(id, pnp);
1133 #define ISASCII(c) ((c) >= ' ' && (c) < 0x7f)
1134 if (ISASCII(pnp[0]) && ISASCII(pnp[1]) &&
1135 ISASCII(pnp[2]))
1136 aprint_normal("%c%c%c%d",
1137 pnp[0], pnp[1], pnp[2], pnp[3]);
1138 else
1139 aprint_normal("unknown (0x%08x)", id);
1140 break;
1141 }
1142 if (ac97codecid[i].id == (id & ac97codecid[i].mask)) {
1143 aprint_normal("%s", ac97codecid[i].name);
1144 if (ac97codecid[i].mask == AC97_VENDOR_ID_MASK) {
1145 aprint_normal(" (0x%08x)", id);
1146 }
1147 initfunc = ac97codecid[i].init;
1148 break;
1149 }
1150 }
1151 aprint_normal(" codec; ");
1152 for (i = j = 0; i < 10; i++) {
1153 if (as->caps & (1 << i)) {
1154 aprint_normal("%s%s", j ? ", " : "", ac97feature[i]);
1155 j++;
1156 }
1157 }
1158 aprint_normal("%s%s\n", j ? ", " : "",
1159 ac97enhancement[AC97_CAPS_ENHANCEMENT(as->caps)]);
1160
1161 as->ac97_clock = AC97_STANDARD_CLOCK;
1162
1163 if (as->type == AC97_CODEC_TYPE_AUDIO) {
1164 ac97_read(as, AC97_REG_EXT_AUDIO_ID, &as->ext_id);
1165 if (as->ext_id != 0) {
1166 /* Print capabilities */
1167 bitmask_snprintf(as->ext_id,
1168 "\20\20SECONDARY10\17SECONDARY01"
1169 "\14AC97_23\13AC97_22\12AMAP\11LDAC\10SDAC"
1170 "\7CDAC\4VRM\3SPDIF\2DRA\1VRA",
1171 flagbuf, FLAGBUFLEN);
1172 aprint_normal("%s: ac97: ext id %s\n", sc_dev->dv_xname,
1173 flagbuf);
1174
1175 /* Print unusual settings */
1176 if (as->ext_id & AC97_EXT_AUDIO_DSA_MASK) {
1177 aprint_normal("%s: ac97: Slot assignment: ",
1178 sc_dev->dv_xname);
1179 switch (as->ext_id & AC97_EXT_AUDIO_DSA_MASK) {
1180 case AC97_EXT_AUDIO_DSA01:
1181 aprint_normal("7&8, 6&9, 10&11.\n");
1182 break;
1183 case AC97_EXT_AUDIO_DSA10:
1184 aprint_normal("6&9, 10&11, 3&4.\n");
1185 break;
1186 case AC97_EXT_AUDIO_DSA11:
1187 aprint_normal("10&11, 3&4, 7&8.\n");
1188 break;
1189 }
1190 }
1191
1192 /* Enable and disable features */
1193 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat);
1194 extstat &= ~AC97_EXT_AUDIO_DRA;
1195 if (as->ext_id & AC97_EXT_AUDIO_LDAC)
1196 extstat |= AC97_EXT_AUDIO_LDAC;
1197 if (as->ext_id & AC97_EXT_AUDIO_SDAC)
1198 extstat |= AC97_EXT_AUDIO_SDAC;
1199 if (as->ext_id & AC97_EXT_AUDIO_CDAC)
1200 extstat |= AC97_EXT_AUDIO_CDAC;
1201 if (as->ext_id & AC97_EXT_AUDIO_VRM)
1202 extstat |= AC97_EXT_AUDIO_VRM;
1203 if (as->ext_id & AC97_EXT_AUDIO_SPDIF) {
1204 /* Output the same data as DAC to SPDIF output */
1205 extstat &= ~AC97_EXT_AUDIO_SPSA_MASK;
1206 extstat |= AC97_EXT_AUDIO_SPSA34;
1207 }
1208 if (as->ext_id & AC97_EXT_AUDIO_VRA)
1209 extstat |= AC97_EXT_AUDIO_VRA;
1210 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat);
1211 if (as->ext_id & AC97_EXT_AUDIO_VRA) {
1212 /* VRA should be enabled. */
1213 /* so it claims to do variable rate, let's make sure */
1214 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE,
1215 44100);
1216 ac97_read(as, AC97_REG_PCM_FRONT_DAC_RATE,
1217 &rate);
1218 if (rate != 44100) {
1219 /* We can't believe ext_id */
1220 as->ext_id = 0;
1221 aprint_normal(
1222 "%s: Ignore these capabilities.\n",
1223 sc_dev->dv_xname);
1224 }
1225 /* restore the default value */
1226 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE,
1227 AC97_SINGLE_RATE);
1228 }
1229 }
1230 } else if (as->type == AC97_CODEC_TYPE_MODEM) {
1231 const struct sysctlnode *node;
1232 const struct sysctlnode *node_line1;
1233 const struct sysctlnode *node_line2;
1234 uint16_t xrate = 8000;
1235 uint16_t xval, reg;
1236 int err;
1237
1238 ac97_read(as, AC97_REG_EXT_MODEM_ID, &as->ext_mid);
1239 if (as->ext_mid == 0 || as->ext_mid == 0xffff) {
1240 aprint_normal("%s: no modem codec found\n",
1241 sc_dev->dv_xname);
1242 return ENXIO;
1243 }
1244 as->type = AC97_CODEC_TYPE_MODEM;
1245
1246 /* Print capabilities */
1247 bitmask_snprintf(as->ext_mid,
1248 "\20\5CID2\4CID1\3HANDSET\2LINE2\1LINE1",
1249 flagbuf, FLAGBUFLEN);
1250 aprint_normal("%s: ac97: ext mid %s", sc_dev->dv_xname,
1251 flagbuf);
1252 aprint_normal(", %s codec\n",
1253 (as->ext_mid & 0xc000) == 0 ?
1254 "primary" : "secondary");
1255
1256 /* Setup modem and sysctls */
1257 err = sysctl_createv(&as->log, 0, NULL, NULL, 0, CTLTYPE_NODE,
1258 "hw", NULL, NULL, 0, NULL, 0, CTL_HW,
1259 CTL_EOL);
1260 if (err != 0)
1261 goto setup_modem;
1262 err = sysctl_createv(&as->log, 0, NULL, &node, 0,
1263 CTLTYPE_NODE, sc_dev->dv_xname, NULL,
1264 NULL, 0, NULL, 0, CTL_HW, CTL_CREATE,
1265 CTL_EOL);
1266 if (err != 0)
1267 goto setup_modem;
1268 setup_modem:
1269 /* reset */
1270 ac97_write(as, AC97_REG_EXT_MODEM_ID, 1);
1271
1272 /* program rates */
1273 xval = 0xff00 & ~AC97_EXT_MODEM_CTRL_PRA;
1274 if (as->ext_mid & AC97_EXT_MODEM_LINE1) {
1275 ac97_write(as, AC97_REG_LINE1_RATE, xrate);
1276 xval &= ~(AC97_EXT_MODEM_CTRL_PRC |
1277 AC97_EXT_MODEM_CTRL_PRD);
1278 }
1279 if (as->ext_mid & AC97_EXT_MODEM_LINE2) {
1280 ac97_write(as, AC97_REG_LINE2_RATE, xrate);
1281 xval &= ~(AC97_EXT_MODEM_CTRL_PRE |
1282 AC97_EXT_MODEM_CTRL_PRF);
1283 }
1284 if (as->ext_mid & AC97_EXT_MODEM_HANDSET) {
1285 ac97_write(as, AC97_REG_HANDSET_RATE, xrate);
1286 xval &= ~(AC97_EXT_MODEM_CTRL_PRG |
1287 AC97_EXT_MODEM_CTRL_PRH);
1288 }
1289
1290 /* power-up everything */
1291 ac97_write(as, AC97_REG_EXT_MODEM_CTRL, 0);
1292 for (i = 5000; i >= 0; i--) {
1293 ac97_read(as, AC97_REG_EXT_MODEM_CTRL, ®);
1294 if ((reg & /*XXXval*/0xf) == /*XXXval*/0xf)
1295 break;
1296 DELAY(1);
1297 }
1298 if (i <= 0) {
1299 printf("%s: codec not responding, status=0x%x\n",
1300 sc_dev->dv_xname, reg);
1301 return ENXIO;
1302 }
1303
1304 /* setup sysctls */
1305 if (as->ext_mid & AC97_EXT_MODEM_LINE1) {
1306 ac97_read(as, AC97_REG_GPIO_CFG, ®);
1307 reg &= ~AC97_GPIO_LINE1_OH;
1308 ac97_write(as, AC97_REG_GPIO_CFG, reg);
1309 ac97_read(as, AC97_REG_GPIO_POLARITY, ®);
1310 reg &= ~AC97_GPIO_LINE1_OH;
1311 ac97_write(as, AC97_REG_GPIO_POLARITY, reg);
1312
1313 err = sysctl_createv(&as->log, 0, NULL, &node_line1,
1314 CTLFLAG_READWRITE, CTLTYPE_INT,
1315 "line1",
1316 SYSCTL_DESCR("off-hook line1"),
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_line1_mib = node_line1->sysctl_num;
1323 }
1324 if (as->ext_mid & AC97_EXT_MODEM_LINE2) {
1325 ac97_read(as, AC97_REG_GPIO_CFG, ®);
1326 reg &= ~AC97_GPIO_LINE2_OH;
1327 ac97_write(as, AC97_REG_GPIO_CFG, reg);
1328 ac97_read(as, AC97_REG_GPIO_POLARITY, ®);
1329 reg &= ~AC97_GPIO_LINE2_OH;
1330 ac97_write(as, AC97_REG_GPIO_POLARITY, reg);
1331
1332 err = sysctl_createv(&as->log, 0, NULL, &node_line2,
1333 CTLFLAG_READWRITE, CTLTYPE_INT,
1334 "line2",
1335 SYSCTL_DESCR("off-hook line2"),
1336 ac97_sysctl_verify, 0, as, 0,
1337 CTL_HW, node->sysctl_num,
1338 CTL_CREATE, CTL_EOL);
1339 if (err != 0)
1340 goto sysctl_err;
1341 as->offhook_line2_mib = node_line2->sysctl_num;
1342 }
1343 sysctl_err:
1344
1345 ac97_write(as, AC97_REG_GPIO_STICKY, 0xffff);
1346 ac97_write(as, AC97_REG_GPIO_WAKEUP, 0x0);
1347 ac97_write(as, AC97_REG_MISC_AFE, 0x0);
1348 }
1349
1350 as->source_info = (as->type == AC97_CODEC_TYPE_MODEM ?
1351 as->modem_source_info : as->audio_source_info);
1352 ac97_setup_source_info(as);
1353
1354 memset(&ctl, 0, sizeof(ctl));
1355 /* disable mutes */
1356 for (i = 0; i < 11; i++) {
1357 static struct {
1358 const char *class, *device;
1359 } d[11] = {
1360 { AudioCoutputs, AudioNmaster},
1361 { AudioCoutputs, AudioNheadphone},
1362 { AudioCoutputs, AudioNsurround},
1363 { AudioCoutputs, AudioNcenter},
1364 { AudioCoutputs, AudioNlfe},
1365 { AudioCinputs, AudioNdac},
1366 { AudioCinputs, AudioNcd},
1367 { AudioCinputs, AudioNline},
1368 { AudioCinputs, AudioNaux},
1369 { AudioCinputs, AudioNvideo},
1370 { AudioCrecord, AudioNvolume},
1371 };
1372
1373 ctl.type = AUDIO_MIXER_ENUM;
1374 ctl.un.ord = 0;
1375
1376 ctl.dev = ac97_get_portnum_by_name(&as->codec_if,
1377 d[i].class, d[i].device, AudioNmute);
1378 ac97_mixer_set_port(&as->codec_if, &ctl);
1379 }
1380 ctl.type = AUDIO_MIXER_ENUM;
1381 ctl.un.ord = 0;
1382 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
1383 AudioNsource, NULL);
1384 ac97_mixer_set_port(&as->codec_if, &ctl);
1385
1386 /* set a reasonable default volume */
1387 ctl.type = AUDIO_MIXER_VALUE;
1388 ctl.un.value.num_channels = 2;
1389 ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = \
1390 ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127;
1391 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1392 AudioNmaster, NULL);
1393 ac97_mixer_set_port(&as->codec_if, &ctl);
1394 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1395 AudioNsurround, NULL);
1396 ac97_mixer_set_port(&as->codec_if, &ctl);
1397 ctl.un.value.num_channels = 1;
1398 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1399 AudioNcenter, NULL);
1400 ac97_mixer_set_port(&as->codec_if, &ctl);
1401 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1402 AudioNlfe, NULL);
1403 ac97_mixer_set_port(&as->codec_if, &ctl);
1404
1405 if (initfunc != NULL)
1406 initfunc(as);
1407 return 0;
1408 }
1409
1410 static void
1411 ac97_detach(struct ac97_codec_if *codec_if)
1412 {
1413 struct ac97_softc *as;
1414
1415 as = (struct ac97_softc *)codec_if;
1416 ac97_write(as, AC97_REG_POWER, AC97_POWER_IN | AC97_POWER_OUT
1417 | AC97_POWER_MIXER | AC97_POWER_MIXER_VREF
1418 | AC97_POWER_ACLINK | AC97_POWER_CLK | AC97_POWER_AUX
1419 | AC97_POWER_EAMP);
1420 free(as, M_DEVBUF);
1421 }
1422
1423 static int
1424 ac97_query_devinfo(struct ac97_codec_if *codec_if, mixer_devinfo_t *dip)
1425 {
1426 struct ac97_softc *as;
1427 struct ac97_source_info *si;
1428 const char *name;
1429
1430 as = (struct ac97_softc *)codec_if;
1431 if (dip->index < as->num_source_info) {
1432 si = &as->source_info[dip->index];
1433 dip->type = si->type;
1434 dip->mixer_class = si->mixer_class;
1435 dip->prev = si->prev;
1436 dip->next = si->next;
1437
1438 if (si->qualifier)
1439 name = si->qualifier;
1440 else if (si->device)
1441 name = si->device;
1442 else if (si->class)
1443 name = si->class;
1444 else
1445 name = 0;
1446
1447 if (name)
1448 strcpy(dip->label.name, name);
1449
1450 memcpy(&dip->un, si->info, si->info_size);
1451
1452 /* Set the delta for volume sources */
1453 if (dip->type == AUDIO_MIXER_VALUE)
1454 dip->un.v.delta = 1 << (8 - si->bits);
1455
1456 return 0;
1457 }
1458
1459 return ENXIO;
1460 }
1461
1462 static int
1463 ac97_mixer_set_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
1464 {
1465 struct ac97_softc *as;
1466 struct ac97_source_info *si;
1467 uint16_t mask;
1468 uint16_t val, newval;
1469 int error;
1470
1471 as = (struct ac97_softc *)codec_if;
1472 si = &as->source_info[cp->dev];
1473 if (cp->dev < 0 || cp->dev >= as->num_source_info)
1474 return EINVAL;
1475
1476 if (cp->type != si->type)
1477 return EINVAL;
1478
1479 ac97_read(as, si->reg, &val);
1480
1481 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
1482
1483 mask = (1 << si->bits) - 1;
1484
1485 switch (cp->type) {
1486 case AUDIO_MIXER_ENUM:
1487 if (cp->un.ord > mask || cp->un.ord < 0)
1488 return EINVAL;
1489
1490 newval = (cp->un.ord << si->ofs);
1491 if (si->reg == AC97_REG_RECORD_SELECT) {
1492 newval |= (newval << (8 + si->ofs));
1493 mask |= (mask << 8);
1494 mask = mask << si->ofs;
1495 } else if (si->reg == AC97_REG_SURR_MASTER) {
1496 newval = cp->un.ord ? 0x8080 : 0x0000;
1497 mask = 0x8080;
1498 } else
1499 mask = mask << si->ofs;
1500 break;
1501 case AUDIO_MIXER_VALUE:
1502 {
1503 const struct audio_mixer_value *value = si->info;
1504 uint16_t l, r, ol, or;
1505 int deltal, deltar;
1506
1507 if ((cp->un.value.num_channels <= 0) ||
1508 (cp->un.value.num_channels > value->num_channels))
1509 return EINVAL;
1510
1511 if (cp->un.value.num_channels == 1) {
1512 l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
1513 } else {
1514 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
1515 l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1516 r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1517 } else { /* left/right is reversed here */
1518 r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1519 l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1520 }
1521
1522 }
1523
1524 if (!si->polarity) {
1525 l = 255 - l;
1526 r = 255 - r;
1527 }
1528
1529 ol = (val >> (8+si->ofs)) & mask;
1530 or = (val >> si->ofs) & mask;
1531
1532 deltal = (ol << (8 - si->bits)) - l;
1533 deltar = (or << (8 - si->bits)) - r;
1534
1535 l = l >> (8 - si->bits);
1536 r = r >> (8 - si->bits);
1537
1538 if (deltal && ol == l)
1539 l += (deltal > 0) ? (l ? -1 : 0) : (l < mask ? 1 : 0);
1540 if (deltar && or == r)
1541 r += (deltar > 0) ? (r ? -1 : 0) : (r < mask ? 1 : 0);
1542
1543 newval = ((r & mask) << si->ofs);
1544 if (value->num_channels == 2) {
1545 newval = newval | ((l & mask) << (si->ofs+8));
1546 mask |= (mask << 8);
1547 }
1548 mask = mask << si->ofs;
1549 break;
1550 }
1551 default:
1552 return EINVAL;
1553 }
1554
1555 error = ac97_write(as, si->reg, (val & ~mask) | newval);
1556 if (error)
1557 return error;
1558
1559 return 0;
1560 }
1561
1562 static int
1563 ac97_get_portnum_by_name(struct ac97_codec_if *codec_if, const char *class,
1564 const char *device, const char *qualifier)
1565 {
1566 struct ac97_softc *as;
1567 int idx;
1568
1569 as = (struct ac97_softc *)codec_if;
1570 for (idx = 0; idx < as->num_source_info; idx++) {
1571 struct ac97_source_info *si = &as->source_info[idx];
1572 if (ac97_str_equal(class, si->class) &&
1573 ac97_str_equal(device, si->device) &&
1574 ac97_str_equal(qualifier, si->qualifier))
1575 return idx;
1576 }
1577
1578 return -1;
1579 }
1580
1581 static int
1582 ac97_mixer_get_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
1583 {
1584 struct ac97_softc *as;
1585 struct ac97_source_info *si;
1586 uint16_t mask;
1587 uint16_t val;
1588
1589 as = (struct ac97_softc *)codec_if;
1590 si = &as->source_info[cp->dev];
1591 if (cp->dev < 0 || cp->dev >= as->num_source_info)
1592 return EINVAL;
1593
1594 if (cp->type != si->type)
1595 return EINVAL;
1596
1597 ac97_read(as, si->reg, &val);
1598
1599 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
1600
1601 mask = (1 << si->bits) - 1;
1602
1603 switch (cp->type) {
1604 case AUDIO_MIXER_ENUM:
1605 cp->un.ord = (val >> si->ofs) & mask;
1606 DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n",
1607 val, si->ofs, mask, cp->un.ord));
1608 break;
1609 case AUDIO_MIXER_VALUE:
1610 {
1611 const struct audio_mixer_value *value = si->info;
1612 uint16_t l, r;
1613
1614 if ((cp->un.value.num_channels <= 0) ||
1615 (cp->un.value.num_channels > value->num_channels))
1616 return EINVAL;
1617
1618 if (value->num_channels == 1) {
1619 l = r = (val >> si->ofs) & mask;
1620 } else {
1621 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
1622 l = (val >> (si->ofs + 8)) & mask;
1623 r = (val >> si->ofs) & mask;
1624 } else { /* host has reversed channels */
1625 r = (val >> (si->ofs + 8)) & mask;
1626 l = (val >> si->ofs) & mask;
1627 }
1628 }
1629
1630 l = (l << (8 - si->bits));
1631 r = (r << (8 - si->bits));
1632 if (!si->polarity) {
1633 l = 255 - l;
1634 r = 255 - r;
1635 }
1636
1637 /* The EAP driver averages l and r for stereo
1638 channels that are requested in MONO mode. Does this
1639 make sense? */
1640 if (cp->un.value.num_channels == 1) {
1641 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l;
1642 } else if (cp->un.value.num_channels == 2) {
1643 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
1644 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
1645 }
1646
1647 break;
1648 }
1649 default:
1650 return EINVAL;
1651 }
1652
1653 return 0;
1654 }
1655
1656
1657 static int
1658 ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_int *rate)
1659 {
1660 struct ac97_softc *as;
1661 u_int value;
1662 uint16_t ext_stat;
1663 uint16_t actual;
1664 uint16_t power;
1665 uint16_t power_bit;
1666
1667 as = (struct ac97_softc *)codec_if;
1668 if (target == AC97_REG_PCM_MIC_ADC_RATE) {
1669 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1670 *rate = AC97_SINGLE_RATE;
1671 return 0;
1672 }
1673 } else {
1674 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1675 *rate = AC97_SINGLE_RATE;
1676 return 0;
1677 }
1678 }
1679 value = *rate * AC97_STANDARD_CLOCK / as->ac97_clock;
1680 ext_stat = 0;
1681 /*
1682 * PCM_FRONT_DAC_RATE/PCM_SURR_DAC_RATE/PCM_LFE_DAC_RATE
1683 * Check VRA, DRA
1684 * PCM_LR_ADC_RATE
1685 * Check VRA
1686 * PCM_MIC_ADC_RATE
1687 * Check VRM
1688 */
1689 switch (target) {
1690 case AC97_REG_PCM_FRONT_DAC_RATE:
1691 case AC97_REG_PCM_SURR_DAC_RATE:
1692 case AC97_REG_PCM_LFE_DAC_RATE:
1693 power_bit = AC97_POWER_OUT;
1694 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1695 *rate = AC97_SINGLE_RATE;
1696 return 0;
1697 }
1698 if (as->ext_id & AC97_EXT_AUDIO_DRA) {
1699 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &ext_stat);
1700 if (value > 0x1ffff) {
1701 return EINVAL;
1702 } else if (value > 0xffff) {
1703 /* Enable DRA */
1704 ext_stat |= AC97_EXT_AUDIO_DRA;
1705 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1706 value /= 2;
1707 } else {
1708 /* Disable DRA */
1709 ext_stat &= ~AC97_EXT_AUDIO_DRA;
1710 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1711 }
1712 } else {
1713 if (value > 0xffff)
1714 return EINVAL;
1715 }
1716 break;
1717 case AC97_REG_PCM_LR_ADC_RATE:
1718 power_bit = AC97_POWER_IN;
1719 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1720 *rate = AC97_SINGLE_RATE;
1721 return 0;
1722 }
1723 if (value > 0xffff)
1724 return EINVAL;
1725 break;
1726 case AC97_REG_PCM_MIC_ADC_RATE:
1727 power_bit = AC97_POWER_IN;
1728 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1729 *rate = AC97_SINGLE_RATE;
1730 return 0;
1731 }
1732 if (value > 0xffff)
1733 return EINVAL;
1734 break;
1735 default:
1736 printf("%s: Unknown register: 0x%x\n", __func__, target);
1737 return EINVAL;
1738 }
1739
1740 ac97_read(as, AC97_REG_POWER, &power);
1741 ac97_write(as, AC97_REG_POWER, power | power_bit);
1742
1743 ac97_write(as, target, (uint16_t)value);
1744 ac97_read(as, target, &actual);
1745 actual = (uint32_t)actual * as->ac97_clock / AC97_STANDARD_CLOCK;
1746
1747 ac97_write(as, AC97_REG_POWER, power);
1748 if (ext_stat & AC97_EXT_AUDIO_DRA) {
1749 *rate = actual * 2;
1750 } else {
1751 *rate = actual;
1752 }
1753 return 0;
1754 }
1755
1756 static void
1757 ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock)
1758 {
1759 struct ac97_softc *as;
1760
1761 as = (struct ac97_softc *)codec_if;
1762 as->ac97_clock = clock;
1763 }
1764
1765 static uint16_t
1766 ac97_get_extcaps(struct ac97_codec_if *codec_if)
1767 {
1768 struct ac97_softc *as;
1769
1770 as = (struct ac97_softc *)codec_if;
1771 return as->ext_id;
1772 }
1773
1774 static int
1775 ac97_add_port(struct ac97_softc *as, const struct ac97_source_info *src)
1776 {
1777 struct ac97_source_info *si;
1778 int ouridx, idx;
1779
1780 if ((as->type == AC97_CODEC_TYPE_AUDIO &&
1781 as->num_source_info >= AUDIO_MAX_SOURCES) ||
1782 (as->type == AC97_CODEC_TYPE_MODEM &&
1783 as->num_source_info >= MODEM_MAX_SOURCES)) {
1784 printf("%s: internal error: increase MAX_SOURCES in %s\n",
1785 __func__, __FILE__);
1786 return -1;
1787 }
1788 if (!ac97_check_capability(as, src->req_feature))
1789 return -1;
1790 ouridx = as->num_source_info;
1791 si = &as->source_info[ouridx];
1792 memcpy(si, src, sizeof(*si));
1793
1794 switch (si->type) {
1795 case AUDIO_MIXER_CLASS:
1796 case AUDIO_MIXER_VALUE:
1797 printf("%s: adding class/value is not supported yet.\n",
1798 __func__);
1799 return -1;
1800 case AUDIO_MIXER_ENUM:
1801 break;
1802 default:
1803 printf("%s: unknown type: %d\n", __func__, si->type);
1804 return -1;
1805 }
1806 as->num_source_info++;
1807
1808 si->mixer_class = ac97_get_portnum_by_name(&as->codec_if, si->class,
1809 NULL, NULL);
1810 /* Find the root of the device */
1811 idx = ac97_get_portnum_by_name(&as->codec_if, si->class,
1812 si->device, NULL);
1813 /* Find the last item */
1814 while (as->source_info[idx].next != AUDIO_MIXER_LAST)
1815 idx = as->source_info[idx].next;
1816 /* Append */
1817 as->source_info[idx].next = ouridx;
1818 si->prev = idx;
1819 si->next = AUDIO_MIXER_LAST;
1820
1821 return 0;
1822 }
1823
1824 /**
1825 * Codec-dependent initialization
1826 */
1827
1828 #define AD1980_REG_MISC 0x76
1829 #define AD1980_MISC_MBG0 0x0001 /* 0 1888/1980/1981 /1985 */
1830 #define AD1980_MISC_MBG1 0x0002 /* 1 1888/1980/1981 /1985 */
1831 #define AD1980_MISC_VREFD 0x0004 /* 2 1888/1980/1981 /1985 */
1832 #define AD1980_MISC_VREFH 0x0008 /* 3 1888/1980/1981 /1985 */
1833 #define AD1980_MISC_SRU 0x0010 /* 4 1888/1980 /1985 */
1834 #define AD1980_MISC_LOSEL 0x0020 /* 5 1888/1980/1981 /1985 */
1835 #define AD1980_MISC_2CMIC 0x0040 /* 6 1980/1981B/1985 */
1836 #define AD1980_MISC_SPRD 0x0080 /* 7 1888/1980 /1985 */
1837 #define AD1980_MISC_DMIX0 0x0100 /* 8 1888/1980 /1985 */
1838 #define AD1980_MISC_DMIX1 0x0200 /* 9 1888/1980 /1985 */
1839 #define AD1980_MISC_HPSEL 0x0400 /*10 1888/1980 /1985 */
1840 #define AD1980_MISC_CLDIS 0x0800 /*11 1888/1980 /1985 */
1841 #define AD1980_MISC_LODIS 0x1000 /*12 1888/1980/1981 /1985 */
1842 #define AD1980_MISC_MSPLT 0x2000 /*13 1888/1980/1981 /1985 */
1843 #define AD1980_MISC_AC97NC 0x4000 /*14 1888/1980 /1985 */
1844 #define AD1980_MISC_DACZ 0x8000 /*15 1888/1980/1981 /1985 */
1845 #define AD1981_REG_MISC 0x76
1846 #define AD1981_MISC_MADST 0x0010 /* 4 */
1847 #define AD1981A_MISC_MADPD 0x0040 /* 6 */
1848 #define AD1981B_MISC_MADPD 0x0080 /* 7 */
1849 #define AD1981_MISC_FMXE 0x0200 /* 9 */
1850 #define AD1981_MISC_DAM 0x0800 /*11 */
1851 static void
1852 ac97_ad198x_init(struct ac97_softc *as)
1853 {
1854 int i;
1855 uint16_t misc;
1856
1857 ac97_read(as, AD1980_REG_MISC, &misc);
1858 ac97_write(as, AD1980_REG_MISC,
1859 misc | AD1980_MISC_LOSEL | AD1980_MISC_HPSEL);
1860
1861 for (i = 0; i < as->num_source_info; i++) {
1862 if (as->source_info[i].type != AUDIO_MIXER_VALUE)
1863 continue;
1864
1865 if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME)
1866 as->source_info[i].reg = AC97_REG_SURR_MASTER;
1867 else if (as->source_info[i].reg == AC97_REG_SURR_MASTER)
1868 as->source_info[i].reg = AC97_REG_MASTER_VOLUME;
1869 }
1870 }
1871
1872 #define ALC650_REG_MULTI_CHANNEL_CONTROL 0x6a
1873 #define ALC650_MCC_SLOT_MODIFY_MASK 0xc000
1874 #define ALC650_MCC_FRONTDAC_FROM_SPDIFIN 0x2000 /* 13 */
1875 #define ALC650_MCC_SPDIFOUT_FROM_ADC 0x1000 /* 12 */
1876 #define ALC650_MCC_PCM_FROM_SPDIFIN 0x0800 /* 11 */
1877 #define ALC650_MCC_MIC_OR_CENTERLFE 0x0400 /* 10 */
1878 #define ALC650_MCC_LINEIN_OR_SURROUND 0x0200 /* 9 */
1879 #define ALC650_MCC_INDEPENDENT_MASTER_L 0x0080 /* 7 */
1880 #define ALC650_MCC_INDEPENDENT_MASTER_R 0x0040 /* 6 */
1881 #define ALC650_MCC_ANALOG_TO_CENTERLFE 0x0020 /* 5 */
1882 #define ALC650_MCC_ANALOG_TO_SURROUND 0x0010 /* 4 */
1883 #define ALC650_MCC_EXCHANGE_CENTERLFE 0x0008 /* 3 */
1884 #define ALC650_MCC_CENTERLFE_DOWNMIX 0x0004 /* 2 */
1885 #define ALC650_MCC_SURROUND_DOWNMIX 0x0002 /* 1 */
1886 #define ALC650_MCC_LINEOUT_TO_SURROUND 0x0001 /* 0 */
1887 static void
1888 ac97_alc650_init(struct ac97_softc *as)
1889 {
1890 static const struct ac97_source_info sources[6] = {
1891 { AudioCoutputs, AudioNsurround, "lineinjack",
1892 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1893 ALC650_REG_MULTI_CHANNEL_CONTROL,
1894 0x0000, 1, 9, 0, 0, CHECK_SURROUND },
1895 { AudioCoutputs, AudioNsurround, "mixtofront",
1896 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1897 ALC650_REG_MULTI_CHANNEL_CONTROL,
1898 0x0000, 1, 1, 0, 0, CHECK_SURROUND },
1899 { AudioCoutputs, AudioNcenter, "micjack",
1900 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1901 ALC650_REG_MULTI_CHANNEL_CONTROL,
1902 0x0000, 1, 10, 0, 0, CHECK_CENTER },
1903 { AudioCoutputs, AudioNlfe, "micjack",
1904 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1905 ALC650_REG_MULTI_CHANNEL_CONTROL,
1906 0x0000, 1, 10, 0, 0, CHECK_LFE },
1907 { AudioCoutputs, AudioNcenter, "mixtofront",
1908 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1909 ALC650_REG_MULTI_CHANNEL_CONTROL,
1910 0x0000, 1, 2, 0, 0, CHECK_CENTER },
1911 { AudioCoutputs, AudioNlfe, "mixtofront",
1912 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1913 ALC650_REG_MULTI_CHANNEL_CONTROL,
1914 0x0000, 1, 2, 0, 0, CHECK_LFE },
1915 };
1916
1917 ac97_add_port(as, &sources[0]);
1918 ac97_add_port(as, &sources[1]);
1919 ac97_add_port(as, &sources[2]);
1920 ac97_add_port(as, &sources[3]);
1921 ac97_add_port(as, &sources[4]);
1922 ac97_add_port(as, &sources[5]);
1923 }
1924
1925 #define VT1616_REG_IO_CONTROL 0x5a
1926 #define VT1616_IC_LVL (1 << 15)
1927 #define VT1616_IC_LFECENTER_TO_FRONT (1 << 12)
1928 #define VT1616_IC_SURROUND_TO_FRONT (1 << 11)
1929 #define VT1616_IC_BPDC (1 << 10)
1930 #define VT1616_IC_DC (1 << 9)
1931 #define VT1616_IC_IB_MASK 0x000c
1932 static void
1933 ac97_vt1616_init(struct ac97_softc *as)
1934 {
1935 static const struct ac97_source_info sources[3] = {
1936 { AudioCoutputs, AudioNsurround, "mixtofront",
1937 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1938 VT1616_REG_IO_CONTROL,
1939 0x0000, 1, 11, 0, 0, CHECK_SURROUND },
1940 { AudioCoutputs, AudioNcenter, "mixtofront",
1941 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1942 VT1616_REG_IO_CONTROL,
1943 0x0000, 1, 12, 0, 0, CHECK_CENTER },
1944 { AudioCoutputs, AudioNlfe, "mixtofront",
1945 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1946 VT1616_REG_IO_CONTROL,
1947 0x0000, 1, 12, 0, 0, CHECK_LFE },
1948 };
1949
1950 ac97_add_port(as, &sources[0]);
1951 ac97_add_port(as, &sources[1]);
1952 ac97_add_port(as, &sources[2]);
1953 }
1954
1955 static int
1956 ac97_modem_offhook_set(struct ac97_softc *as, int line, int newval)
1957 {
1958 uint16_t val;
1959
1960 val = as->shadow_reg[AC97_REG_GPIO_STATUS >> 1];
1961 switch (newval) {
1962 case 0:
1963 val &= ~line;
1964 break;
1965 case 1:
1966 val |= line;
1967 break;
1968 }
1969 ac97_write(as, AC97_REG_GPIO_STATUS, val);
1970
1971 return 0;
1972 }
1973
1974 static int
1975 ac97_sysctl_verify(SYSCTLFN_ARGS)
1976 {
1977 int error, tmp;
1978 struct sysctlnode node;
1979 struct ac97_softc *as;
1980
1981 node = *rnode;
1982 as = rnode->sysctl_data;
1983 if (node.sysctl_num == as->offhook_line1_mib) {
1984 tmp = as->offhook_line1;
1985 node.sysctl_data = &tmp;
1986 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1987 if (error || newp == NULL)
1988 return error;
1989
1990 if (tmp < 0 || tmp > 1)
1991 return EINVAL;
1992
1993 as->offhook_line1 = tmp;
1994 ac97_modem_offhook_set(as, AC97_GPIO_LINE1_OH, tmp);
1995 } else if (node.sysctl_num == as->offhook_line2_mib) {
1996 tmp = as->offhook_line2;
1997 node.sysctl_data = &tmp;
1998 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1999 if (error || newp == NULL)
2000 return error;
2001
2002 if (tmp < 0 || tmp > 1)
2003 return EINVAL;
2004
2005 as->offhook_line2 = tmp;
2006 ac97_modem_offhook_set(as, AC97_GPIO_LINE2_OH, tmp);
2007 }
2008
2009 return 0;
2010 }
2011