ac97.c revision 1.63 1 /* $NetBSD: ac97.c,v 1.63 2004/10/12 14:34:41 kent Exp $ */
2 /* $OpenBSD: ac97.c,v 1.8 2000/07/19 09:01:35 csapuntz Exp $ */
3
4 /*
5 * Copyright (c) 1999, 2000 Constantine Sapuntzakis
6 *
7 * Author: Constantine Sapuntzakis <csapuntz (at) stanford.edu>
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior written
19 * permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
21 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
30 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 * DAMAGE
32 */
33
34 /* Partially inspired by FreeBSD's sys/dev/pcm/ac97.c. It came with
35 the following copyright */
36
37 /*
38 * Copyright (c) 1999 Cameron Grant <gandalf (at) vilnya.demon.co.uk>
39 * All rights reserved.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE.
61 *
62 * $FreeBSD$
63 */
64
65 #include <sys/cdefs.h>
66 __KERNEL_RCSID(0, "$NetBSD: ac97.c,v 1.63 2004/10/12 14:34:41 kent Exp $");
67
68 #include <sys/param.h>
69 #include <sys/systm.h>
70 #include <sys/kernel.h>
71 #include <sys/malloc.h>
72 #include <sys/device.h>
73
74 #include <sys/audioio.h>
75 #include <dev/audio_if.h>
76
77 #include <dev/ic/ac97reg.h>
78 #include <dev/ic/ac97var.h>
79
80 struct ac97_softc;
81 struct ac97_source_info;
82 static int ac97_mixer_get_port(struct ac97_codec_if *, mixer_ctrl_t *);
83 static int ac97_mixer_set_port(struct ac97_codec_if *, mixer_ctrl_t *);
84 static int ac97_query_devinfo(struct ac97_codec_if *, mixer_devinfo_t *);
85 static int ac97_get_portnum_by_name(struct ac97_codec_if *, const char *,
86 const char *, const char *);
87 static void ac97_restore_shadow(struct ac97_codec_if *);
88 static int ac97_set_rate(struct ac97_codec_if *, int, u_long *);
89 static void ac97_set_clock(struct ac97_codec_if *, unsigned int);
90 static u_int16_t ac97_get_extcaps(struct ac97_codec_if *);
91 static int ac97_add_port(struct ac97_softc *,
92 const struct ac97_source_info *);
93 static int ac97_str_equal(const char *, const char *);
94 static int ac97_check_capability(struct ac97_softc *, int);
95 static void ac97_setup_source_info(struct ac97_softc *);
96 static void ac97_read(struct ac97_softc *, u_int8_t, u_int16_t *);
97 static void ac97_setup_defaults(struct ac97_softc *);
98 static int ac97_write(struct ac97_softc *, u_int8_t, u_int16_t);
99
100 static void ac97_ad198x_init(struct ac97_softc *);
101 static void ac97_alc650_init(struct ac97_softc *);
102 static void ac97_vt1616_init(struct ac97_softc *);
103
104 #define Ac97Nphone "phone"
105
106 static const struct audio_mixer_enum
107 ac97_on_off = { 2, { { { AudioNoff } , 0 },
108 { { AudioNon } , 1 } } };
109
110 static const struct audio_mixer_enum
111 ac97_mic_select = { 2, { { { AudioNmicrophone "0" }, 0 },
112 { { AudioNmicrophone "1" }, 1 } } };
113
114 static const struct audio_mixer_enum
115 ac97_mono_select = { 2, { { { AudioNmixerout }, 0 },
116 { { AudioNmicrophone }, 1 } } };
117
118 static const struct audio_mixer_enum
119 ac97_source = { 8, { { { AudioNmicrophone } , 0 },
120 { { AudioNcd }, 1 },
121 { { AudioNvideo }, 2 },
122 { { AudioNaux }, 3 },
123 { { AudioNline }, 4 },
124 { { AudioNmixerout }, 5 },
125 { { AudioNmixerout AudioNmono }, 6 },
126 { { Ac97Nphone }, 7 } } };
127
128 /*
129 * Due to different values for each source that uses these structures,
130 * the ac97_query_devinfo function sets delta in mixer_devinfo_t using
131 * ac97_source_info.bits.
132 */
133 static const struct audio_mixer_value
134 ac97_volume_stereo = { { AudioNvolume }, 2 };
135
136 static const struct audio_mixer_value
137 ac97_volume_mono = { { AudioNvolume }, 1 };
138
139 #define WRAP(a) &a, sizeof(a)
140
141 static const struct ac97_source_info {
142 const char *class;
143 const char *device;
144 const char *qualifier;
145
146 int type;
147 const void *info;
148 int info_size;
149
150 u_int8_t reg;
151 u_int16_t default_value;
152 u_int8_t bits:3;
153 u_int8_t ofs:4;
154 u_int8_t mute:1;
155 u_int8_t polarity:1; /* Does 0 == MAX or MIN */
156 enum {
157 CHECK_NONE = 0,
158 CHECK_SURROUND,
159 CHECK_CENTER,
160 CHECK_LFE,
161 CHECK_HEADPHONES,
162 CHECK_TONE,
163 CHECK_MIC,
164 CHECK_LOUDNESS,
165 CHECK_3D
166 } req_feature;
167
168 int prev;
169 int next;
170 int mixer_class;
171 } source_info[] = {
172 { AudioCinputs, NULL, NULL,
173 AUDIO_MIXER_CLASS, },
174 { AudioCoutputs, NULL, NULL,
175 AUDIO_MIXER_CLASS, },
176 { AudioCrecord, NULL, NULL,
177 AUDIO_MIXER_CLASS, },
178 /* Stereo master volume*/
179 { AudioCoutputs, AudioNmaster, NULL,
180 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
181 AC97_REG_MASTER_VOLUME, 0x8000, 5, 0, 1,
182 },
183 /* Mono volume */
184 { AudioCoutputs, AudioNmono, NULL,
185 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
186 AC97_REG_MASTER_VOLUME_MONO, 0x8000, 6, 0, 1,
187 },
188 { AudioCoutputs, AudioNmono, AudioNsource,
189 AUDIO_MIXER_ENUM, WRAP(ac97_mono_select),
190 AC97_REG_GP, 0x0000, 1, 9, 0,
191 },
192 /* Headphone volume */
193 { AudioCoutputs, AudioNheadphone, NULL,
194 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
195 AC97_REG_HEADPHONE_VOLUME, 0x8000, 6, 0, 1, 0, CHECK_HEADPHONES
196 },
197 /* Surround volume - logic hard coded for mute */
198 { AudioCoutputs, AudioNsurround, NULL,
199 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
200 AC97_REG_SURR_MASTER, 0x8080, 5, 0, 1, 0, CHECK_SURROUND
201 },
202 /* Center volume*/
203 { AudioCoutputs, AudioNcenter, NULL,
204 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
205 AC97_REG_CENTER_LFE_MASTER, 0x8080, 5, 0, 0, 0, CHECK_CENTER
206 },
207 { AudioCoutputs, AudioNcenter, AudioNmute,
208 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
209 AC97_REG_CENTER_LFE_MASTER, 0x8080, 1, 7, 0, 0, CHECK_CENTER
210 },
211 /* LFE volume*/
212 { AudioCoutputs, AudioNlfe, NULL,
213 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
214 AC97_REG_CENTER_LFE_MASTER, 0x8080, 5, 8, 0, 0, CHECK_LFE
215 },
216 { AudioCoutputs, AudioNlfe, AudioNmute,
217 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
218 AC97_REG_CENTER_LFE_MASTER, 0x8080, 1, 15, 0, 0, CHECK_LFE
219 },
220 /* Tone - bass */
221 { AudioCoutputs, AudioNbass, NULL,
222 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
223 AC97_REG_MASTER_TONE, 0x0f0f, 4, 8, 0, 0, CHECK_TONE
224 },
225 /* Tone - treble */
226 { AudioCoutputs, AudioNtreble, NULL,
227 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
228 AC97_REG_MASTER_TONE, 0x0f0f, 4, 0, 0, 0, CHECK_TONE
229 },
230 /* PC Beep Volume */
231 { AudioCinputs, AudioNspeaker, NULL,
232 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
233 AC97_REG_PCBEEP_VOLUME, 0x0000, 4, 1, 1,
234 },
235
236 /* Phone */
237 { AudioCinputs, Ac97Nphone, NULL,
238 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
239 AC97_REG_PHONE_VOLUME, 0x8008, 5, 0, 1,
240 },
241 /* Mic Volume */
242 { AudioCinputs, AudioNmicrophone, NULL,
243 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
244 AC97_REG_MIC_VOLUME, 0x8008, 5, 0, 1,
245 },
246 { AudioCinputs, AudioNmicrophone, AudioNpreamp,
247 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
248 AC97_REG_MIC_VOLUME, 0x8008, 1, 6, 0,
249 },
250 { AudioCinputs, AudioNmicrophone, AudioNsource,
251 AUDIO_MIXER_ENUM, WRAP(ac97_mic_select),
252 AC97_REG_GP, 0x0000, 1, 8, 0,
253 },
254 /* Line in Volume */
255 { AudioCinputs, AudioNline, NULL,
256 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
257 AC97_REG_LINEIN_VOLUME, 0x8808, 5, 0, 1,
258 },
259 /* CD Volume */
260 { AudioCinputs, AudioNcd, NULL,
261 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
262 AC97_REG_CD_VOLUME, 0x8808, 5, 0, 1,
263 },
264 /* Video Volume */
265 { AudioCinputs, AudioNvideo, NULL,
266 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
267 AC97_REG_VIDEO_VOLUME, 0x8808, 5, 0, 1,
268 },
269 /* AUX volume */
270 { AudioCinputs, AudioNaux, NULL,
271 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
272 AC97_REG_AUX_VOLUME, 0x8808, 5, 0, 1,
273 },
274 /* PCM out volume */
275 { AudioCinputs, AudioNdac, NULL,
276 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
277 AC97_REG_PCMOUT_VOLUME, 0x8808, 5, 0, 1,
278 },
279 /* Record Source - some logic for this is hard coded - see below */
280 { AudioCrecord, AudioNsource, NULL,
281 AUDIO_MIXER_ENUM, WRAP(ac97_source),
282 AC97_REG_RECORD_SELECT, 0x0000, 3, 0, 0,
283 },
284 /* Record Gain */
285 { AudioCrecord, AudioNvolume, NULL,
286 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
287 AC97_REG_RECORD_GAIN, 0x8000, 4, 0, 1, 1,
288 },
289 /* Record Gain mic */
290 { AudioCrecord, AudioNmicrophone, NULL,
291 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
292 AC97_REG_RECORD_GAIN_MIC, 0x8000, 4, 0, 1, 1, CHECK_MIC
293 },
294 /* */
295 { AudioCoutputs, AudioNloudness, NULL,
296 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
297 AC97_REG_GP, 0x0000, 1, 12, 0, 0, CHECK_LOUDNESS
298 },
299 { AudioCoutputs, AudioNspatial, NULL,
300 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
301 AC97_REG_GP, 0x0000, 1, 13, 0, 1, CHECK_3D
302 },
303 { AudioCoutputs, AudioNspatial, "center",
304 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
305 AC97_REG_3D_CONTROL, 0x0000, 4, 8, 0, 1, CHECK_3D
306 },
307 { AudioCoutputs, AudioNspatial, "depth",
308 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
309 AC97_REG_3D_CONTROL, 0x0000, 4, 0, 0, 1, CHECK_3D
310 },
311
312 /* Missing features: Simulated Stereo, POP, Loopback mode */
313 };
314
315 #define SOURCE_INFO_SIZE (sizeof(source_info)/sizeof(source_info[0]))
316
317 /*
318 * Check out http://developer.intel.com/pc-supp/platform/ac97/ for
319 * information on AC-97
320 */
321
322 struct ac97_softc {
323 /* ac97_codec_if must be at the first of ac97_softc. */
324 struct ac97_codec_if codec_if;
325
326 struct ac97_host_if *host_if;
327
328 #define MAX_SOURCES (2 * SOURCE_INFO_SIZE)
329 struct ac97_source_info source_info[MAX_SOURCES];
330 int num_source_info;
331
332 enum ac97_host_flags host_flags;
333 unsigned int ac97_clock; /* usually 48000 */
334 #define AC97_STANDARD_CLOCK 48000U
335 u_int16_t caps; /* -> AC97_REG_RESET */
336 u_int16_t ext_id; /* -> AC97_REG_EXT_AUDIO_ID */
337 u_int16_t shadow_reg[128];
338 };
339
340 static struct ac97_codec_if_vtbl ac97civ = {
341 ac97_mixer_get_port,
342 ac97_mixer_set_port,
343 ac97_query_devinfo,
344 ac97_get_portnum_by_name,
345 ac97_restore_shadow,
346 ac97_get_extcaps,
347 ac97_set_rate,
348 ac97_set_clock,
349 };
350
351 static const struct ac97_codecid {
352 u_int32_t id;
353 u_int32_t mask;
354 const char *name;
355 void (*init)(struct ac97_softc *);
356 } ac97codecid[] = {
357 /*
358 * Analog Devices SoundMAX
359 * http://www.soundmax.com/products/information/codecs.html
360 * http://www.analog.com/productSelection/pdf/AD1881A_0.pdf
361 * http://www.analog.com/productSelection/pdf/AD1885_0.pdf
362 * http://www.analog.com/UploadedFiles/Data_Sheets/206585810AD1980_0.pdf
363 * http://www.analog.com/productSelection/pdf/AD1981A_0.pdf
364 * http://www.analog.com/productSelection/pdf/AD1981B_0.pdf
365 * http://www.analog.com/UploadedFiles/Data_Sheets/180644528AD1985_0.pdf
366 */
367 { AC97_CODEC_ID('A', 'D', 'S', 3),
368 0xffffffff, "Analog Devices AD1819B" },
369 { AC97_CODEC_ID('A', 'D', 'S', 0x40),
370 0xffffffff, "Analog Devices AD1881" },
371 { AC97_CODEC_ID('A', 'D', 'S', 0x48),
372 0xffffffff, "Analog Devices AD1881A" },
373 { AC97_CODEC_ID('A', 'D', 'S', 0x60),
374 0xffffffff, "Analog Devices AD1885" },
375 { AC97_CODEC_ID('A', 'D', 'S', 0x61),
376 0xffffffff, "Analog Devices AD1886" },
377 { AC97_CODEC_ID('A', 'D', 'S', 0x63),
378 0xffffffff, "Analog Devices AD1886A" },
379 { AC97_CODEC_ID('A', 'D', 'S', 0x68),
380 0xffffffff, "Analog Devices AD1888", ac97_ad198x_init },
381 { AC97_CODEC_ID('A', 'D', 'S', 0x70),
382 0xffffffff, "Analog Devices AD1980", ac97_ad198x_init },
383 { AC97_CODEC_ID('A', 'D', 'S', 0x72),
384 0xffffffff, "Analog Devices AD1981A" },
385 { AC97_CODEC_ID('A', 'D', 'S', 0x74),
386 0xffffffff, "Analog Devices AD1981B" },
387 { AC97_CODEC_ID('A', 'D', 'S', 0x75),
388 0xffffffff, "Analog Devices AD1985", ac97_ad198x_init },
389 { AC97_CODEC_ID('A', 'D', 'S', 0),
390 AC97_VENDOR_ID_MASK, "Analog Devices unknown" },
391
392 /*
393 * Datasheets:
394 * http://www.asahi-kasei.co.jp/akm/usa/product/ak4541/ek4541.pdf
395 * http://www.asahi-kasei.co.jp/akm/usa/product/ak4543/ek4543.pdf
396 * http://www.asahi-kasei.co.jp/akm/usa/product/ak4544a/ek4544a.pdf
397 * http://www.asahi-kasei.co.jp/akm/usa/product/ak4545/ek4545.pdf
398 */
399 { AC97_CODEC_ID('A', 'K', 'M', 0),
400 0xffffffff, "Asahi Kasei AK4540" },
401 { AC97_CODEC_ID('A', 'K', 'M', 1),
402 0xffffffff, "Asahi Kasei AK4542" },
403 { AC97_CODEC_ID('A', 'K', 'M', 2),
404 0xffffffff, "Asahi Kasei AK4541/AK4543" },
405 { AC97_CODEC_ID('A', 'K', 'M', 5),
406 0xffffffff, "Asahi Kasei AK4544" },
407 { AC97_CODEC_ID('A', 'K', 'M', 6),
408 0xffffffff, "Asahi Kasei AK4544A" },
409 { AC97_CODEC_ID('A', 'K', 'M', 7),
410 0xffffffff, "Asahi Kasei AK4545" },
411 { AC97_CODEC_ID('A', 'K', 'M', 0),
412 AC97_VENDOR_ID_MASK, "Asahi Kasei unknown" },
413
414 /*
415 * Realtek & Avance Logic
416 * http://www.realtek.com.tw/downloads/downloads1-3.aspx?lineid=5&famid=All&series=All&Spec=True
417 *
418 * ALC650 and ALC658 support VRA, but it supports only 8000, 11025,
419 * 12000, 16000, 22050, 24000, 32000, 44100, and 48000 Hz.
420 */
421 { AC97_CODEC_ID('A', 'L', 'C', 0x00),
422 0xfffffff0, "Realtek RL5306" },
423 { AC97_CODEC_ID('A', 'L', 'C', 0x10),
424 0xfffffff0, "Realtek RL5382" },
425 { AC97_CODEC_ID('A', 'L', 'C', 0x20),
426 0xfffffff0, "Realtek RL5383/RL5522/ALC100" },
427 { AC97_CODEC_ID('A', 'L', 'G', 0x10),
428 0xffffffff, "Avance Logic ALC200/ALC201" },
429 { AC97_CODEC_ID('A', 'L', 'G', 0x20),
430 0xfffffff0, "Avance Logic ALC650", ac97_alc650_init },
431 { AC97_CODEC_ID('A', 'L', 'G', 0x30),
432 0xffffffff, "Avance Logic ALC101" },
433 { AC97_CODEC_ID('A', 'L', 'G', 0x40),
434 0xffffffff, "Avance Logic ALC202" },
435 { AC97_CODEC_ID('A', 'L', 'G', 0x50),
436 0xffffffff, "Avance Logic ALC250" },
437 { AC97_CODEC_ID('A', 'L', 'G', 0x60),
438 0xfffffff0, "Avance Logic ALC655" },
439 { AC97_CODEC_ID('A', 'L', 'G', 0x80),
440 0xfffffff0, "Avance Logic ALC658" },
441 { AC97_CODEC_ID('A', 'L', 'G', 0x90),
442 0xfffffff0, "Avance Logic ALC850" },
443 { AC97_CODEC_ID('A', 'L', 'C', 0),
444 AC97_VENDOR_ID_MASK, "Realtek unknown" },
445 { AC97_CODEC_ID('A', 'L', 'G', 0),
446 AC97_VENDOR_ID_MASK, "Avance Logic unknown" },
447
448 /**
449 * C-Media Electronics Inc.
450 * http://www.cmedia.com.tw/doc/CMI9739%206CH%20Audio%20Codec%20SPEC_Ver12.pdf
451 */
452 { AC97_CODEC_ID('C', 'M', 'I', 0x61),
453 0xffffffff, "C-Media CMI9739" },
454 { AC97_CODEC_ID('C', 'M', 'I', 0),
455 AC97_VENDOR_ID_MASK, "C-Media unknown" },
456
457 /* Cirrus Logic, Crystal series:
458 * 'C' 'R' 'Y' 0x0[0-7] - CS4297
459 * 0x1[0-7] - CS4297A
460 * 0x2[0-7] - CS4298
461 * 0x2[8-f] - CS4294
462 * 0x3[0-7] - CS4299
463 * 0x4[8-f] - CS4201
464 * 0x5[8-f] - CS4205
465 * 0x6[0-7] - CS4291
466 * 0x7[0-7] - CS4202
467 * Datasheets:
468 * http://www.cirrus.com/pubs/cs4297A-5.pdf?DocumentID=593
469 * http://www.cirrus.com/pubs/cs4294.pdf?DocumentID=32
470 * http://www.cirrus.com/pubs/cs4299-5.pdf?DocumentID=594
471 * http://www.cirrus.com/pubs/cs4201-2.pdf?DocumentID=492
472 * http://www.cirrus.com/pubs/cs4205-2.pdf?DocumentID=492
473 * http://www.cirrus.com/pubs/cs4202-1.pdf?DocumentID=852
474 */
475 { AC97_CODEC_ID('C', 'R', 'Y', 0x00),
476 0xfffffff8, "Crystal CS4297", },
477 { AC97_CODEC_ID('C', 'R', 'Y', 0x10),
478 0xfffffff8, "Crystal CS4297A", },
479 { AC97_CODEC_ID('C', 'R', 'Y', 0x20),
480 0xfffffff8, "Crystal CS4298", },
481 { AC97_CODEC_ID('C', 'R', 'Y', 0x28),
482 0xfffffff8, "Crystal CS4294", },
483 { AC97_CODEC_ID('C', 'R', 'Y', 0x30),
484 0xfffffff8, "Crystal CS4299", },
485 { AC97_CODEC_ID('C', 'R', 'Y', 0x48),
486 0xfffffff8, "Crystal CS4201", },
487 { AC97_CODEC_ID('C', 'R', 'Y', 0x58),
488 0xfffffff8, "Crystal CS4205", },
489 { AC97_CODEC_ID('C', 'R', 'Y', 0x60),
490 0xfffffff8, "Crystal CS4291", },
491 { AC97_CODEC_ID('C', 'R', 'Y', 0x70),
492 0xfffffff8, "Crystal CS4202", },
493 { AC97_CODEC_ID('C', 'R', 'Y', 0),
494 AC97_VENDOR_ID_MASK, "Cirrus Logic unknown", },
495
496 { 0x45838308, 0xffffffff, "ESS Technology ES1921", },
497 { 0x45838300, AC97_VENDOR_ID_MASK, "ESS Technology unknown", },
498
499 { AC97_CODEC_ID('H', 'R', 'S', 0),
500 0xffffffff, "Intersil HMP9701", },
501 { AC97_CODEC_ID('H', 'R', 'S', 0),
502 AC97_VENDOR_ID_MASK, "Intersil unknown", },
503
504 /*
505 * IC Ensemble (VIA)
506 * http://www.viatech.com/en/datasheet/DS1616.pdf
507 */
508 { AC97_CODEC_ID('I', 'C', 'E', 0x01),
509 0xffffffff, "ICEnsemble ICE1230/VT1611", },
510 { AC97_CODEC_ID('I', 'C', 'E', 0x11),
511 0xffffffff, "ICEnsemble ICE1232/VT1611A", },
512 { AC97_CODEC_ID('I', 'C', 'E', 0x14),
513 0xffffffff, "ICEnsemble ICE1232A", },
514 { AC97_CODEC_ID('I', 'C', 'E', 0x51),
515 0xffffffff, "VIA Technologies VT1616", ac97_vt1616_init },
516 { AC97_CODEC_ID('I', 'C', 'E', 0x52),
517 0xffffffff, "VIA Technologies VT1616i", ac97_vt1616_init },
518 { AC97_CODEC_ID('I', 'C', 'E', 0),
519 AC97_VENDOR_ID_MASK, "ICEnsemble/VIA unknown", },
520
521 { AC97_CODEC_ID('N', 'S', 'C', 0),
522 0xffffffff, "National Semiconductor LM454[03568]", },
523 { AC97_CODEC_ID('N', 'S', 'C', 49),
524 0xffffffff, "National Semiconductor LM4549", },
525 { AC97_CODEC_ID('N', 'S', 'C', 0),
526 AC97_VENDOR_ID_MASK, "National Semiconductor unknown", },
527
528 { AC97_CODEC_ID('P', 'S', 'C', 4),
529 0xffffffff, "Philips Semiconductor UCB1400", },
530 { AC97_CODEC_ID('P', 'S', 'C', 0),
531 AC97_VENDOR_ID_MASK, "Philips Semiconductor unknown", },
532
533 { AC97_CODEC_ID('S', 'I', 'L', 34),
534 0xffffffff, "Silicon Laboratory Si3036", },
535 { AC97_CODEC_ID('S', 'I', 'L', 35),
536 0xffffffff, "Silicon Laboratory Si3038", },
537 { AC97_CODEC_ID('S', 'I', 'L', 0),
538 AC97_VENDOR_ID_MASK, "Silicon Laboratory unknown", },
539
540 { AC97_CODEC_ID('T', 'R', 'A', 2),
541 0xffffffff, "TriTech TR28022", },
542 { AC97_CODEC_ID('T', 'R', 'A', 3),
543 0xffffffff, "TriTech TR28023", },
544 { AC97_CODEC_ID('T', 'R', 'A', 6),
545 0xffffffff, "TriTech TR28026", },
546 { AC97_CODEC_ID('T', 'R', 'A', 8),
547 0xffffffff, "TriTech TR28028", },
548 { AC97_CODEC_ID('T', 'R', 'A', 35),
549 0xffffffff, "TriTech TR28602", },
550 { AC97_CODEC_ID('T', 'R', 'A', 0),
551 AC97_VENDOR_ID_MASK, "TriTech unknown", },
552
553 { AC97_CODEC_ID('T', 'X', 'N', 0x20),
554 0xffffffff, "Texas Instruments TLC320AD9xC", },
555 { AC97_CODEC_ID('T', 'X', 'N', 0),
556 AC97_VENDOR_ID_MASK, "Texas Instruments unknown", },
557
558 /*
559 * VIA
560 * http://www.viatech.com/en/multimedia/audio.jsp
561 */
562 { AC97_CODEC_ID('V', 'I', 'A', 0x61),
563 0xffffffff, "VIA Technologies VT1612A", },
564 { AC97_CODEC_ID('V', 'I', 'A', 0),
565 AC97_VENDOR_ID_MASK, "VIA Technologies unknown", },
566
567 { AC97_CODEC_ID('W', 'E', 'C', 1),
568 0xffffffff, "Winbond W83971D", },
569 { AC97_CODEC_ID('W', 'E', 'C', 0),
570 AC97_VENDOR_ID_MASK, "Winbond unknown", },
571
572 /*
573 * http://www.wolfsonmicro.com/product_list.asp?cid=64
574 * http://www.wolfsonmicro.com/download.asp/did.56/WM9701A.pdf - 00
575 * http://www.wolfsonmicro.com/download.asp/did.57/WM9703.pdf - 03
576 * http://www.wolfsonmicro.com/download.asp/did.58/WM9704M.pdf - 04
577 * http://www.wolfsonmicro.com/download.asp/did.59/WM9704Q.pdf - 04
578 * http://www.wolfsonmicro.com/download.asp/did.184/WM9705_Rev34.pdf - 05
579 * http://www.wolfsonmicro.com/download.asp/did.60/WM9707.pdf - 03
580 * http://www.wolfsonmicro.com/download.asp/did.136/WM9708.pdf - 03
581 * http://www.wolfsonmicro.com/download.asp/did.243/WM9710.pdf - 05
582 */
583 { AC97_CODEC_ID('W', 'M', 'L', 0),
584 0xffffffff, "Wolfson WM9701A", },
585 { AC97_CODEC_ID('W', 'M', 'L', 3),
586 0xffffffff, "Wolfson WM9703/WM9707/WM9708", },
587 { AC97_CODEC_ID('W', 'M', 'L', 4),
588 0xffffffff, "Wolfson WM9704", },
589 { AC97_CODEC_ID('W', 'M', 'L', 5),
590 0xffffffff, "Wolfson WM9705/WM9710", },
591 { AC97_CODEC_ID('W', 'M', 'L', 0),
592 AC97_VENDOR_ID_MASK, "Wolfson unknown", },
593
594 /*
595 * http://www.yamaha.co.jp/english/product/lsi/us/products/pcaudio.html
596 * Datasheets:
597 * http://www.yamaha.co.jp/english/product/lsi/us/products/pdf/4MF743A20.pdf
598 * http://www.yamaha.co.jp/english/product/lsi/us/products/pdf/4MF753A20.pdf
599 */
600 { AC97_CODEC_ID('Y', 'M', 'H', 0),
601 0xffffffff, "Yamaha YMF743-S", },
602 { AC97_CODEC_ID('Y', 'M', 'H', 3),
603 0xffffffff, "Yamaha YMF753-S", },
604 { AC97_CODEC_ID('Y', 'M', 'H', 0),
605 AC97_VENDOR_ID_MASK, "Yamaha unknown", },
606
607 /*
608 * http://www.sigmatel.com/products/technical_docs.htm
609 * and
610 * http://www.sigmatel.com/documents/c-major-brochure-9-0.pdf
611 */
612 { 0x83847600, 0xffffffff, "SigmaTel STAC9700", },
613 { 0x83847604, 0xffffffff, "SigmaTel STAC9701/3/4/5", },
614 { 0x83847605, 0xffffffff, "SigmaTel STAC9704", },
615 { 0x83847608, 0xffffffff, "SigmaTel STAC9708", },
616 { 0x83847609, 0xffffffff, "SigmaTel STAC9721/23", },
617 { 0x83847644, 0xffffffff, "SigmaTel STAC9744/45", },
618 { 0x83847650, 0xffffffff, "SigmaTel STAC9750/51", },
619 { 0x83847656, 0xffffffff, "SigmaTel STAC9756/57", },
620 { 0x83847658, 0xffffffff, "SigmaTel STAC9758/59", },
621 { 0x83847666, 0xffffffff, "SigmaTel STAC9766/67", },
622 { 0x83847684, 0xffffffff, "SigmaTel STAC9783/84", },
623 { 0x83847600, AC97_VENDOR_ID_MASK, "SigmaTel unknown", },
624
625 { 0,
626 0, NULL, }
627 };
628
629 static const char * const ac97enhancement[] = {
630 "no 3D stereo",
631 "Analog Devices Phat Stereo",
632 "Creative",
633 "National Semi 3D",
634 "Yamaha Ymersion",
635 "BBE 3D",
636 "Crystal Semi 3D",
637 "Qsound QXpander",
638 "Spatializer 3D",
639 "SRS 3D",
640 "Platform Tech 3D",
641 "AKM 3D",
642 "Aureal",
643 "AZTECH 3D",
644 "Binaura 3D",
645 "ESS Technology",
646 "Harman International VMAx",
647 "Nvidea 3D",
648 "Philips Incredible Sound",
649 "Texas Instruments' 3D",
650 "VLSI Technology 3D",
651 "TriTech 3D",
652 "Realtek 3D",
653 "Samsung 3D",
654 "Wolfson Microelectronics 3D",
655 "Delta Integration 3D",
656 "SigmaTel 3D",
657 "KS Waves 3D",
658 "Rockwell 3D",
659 "Unknown 3D",
660 "Unknown 3D",
661 "Unknown 3D",
662 };
663
664 static const char * const ac97feature[] = {
665 "dedicated mic channel",
666 "reserved",
667 "tone",
668 "simulated stereo",
669 "headphone",
670 "bass boost",
671 "18 bit DAC",
672 "20 bit DAC",
673 "18 bit ADC",
674 "20 bit ADC"
675 };
676
677
678 /* #define AC97_DEBUG 10 */
679 /* #define AC97_IO_DEBUG */
680
681 #ifdef AUDIO_DEBUG
682 #define DPRINTF(x) if (ac97debug) printf x
683 #define DPRINTFN(n,x) if (ac97debug>(n)) printf x
684 #ifdef AC97_DEBUG
685 int ac97debug = AC97_DEBUG;
686 #else
687 int ac97debug = 0;
688 #endif
689 #else
690 #define DPRINTF(x)
691 #define DPRINTFN(n,x)
692 #endif
693
694 #ifdef AC97_IO_DEBUG
695 static const char *ac97_register_names[0x80 / 2] = {
696 "RESET", "MASTER_VOLUME", "HEADPHONE_VOLUME", "MASTER_VOLUME_MONO",
697 "MASTER_TONE", "PCBEEP_VOLUME", "PHONE_VOLUME", "MIC_VOLUME",
698 "LINEIN_VOLUME", "CD_VOLUME", "VIDEO_VOLUME", "AUX_VOLUME",
699 "PCMOUT_VOLUME", "RECORD_SELECT", "RECORD_GATIN", "RECORD_GAIN_MIC",
700 "GP", "3D_CONTROL", "AUDIO_INT", "POWER",
701 "EXT_AUDIO_ID", "EXT_AUDIO_CTRL", "PCM_FRONT_DAC_RATE", "PCM_SURR_DAC_RATE",
702 "PCM_LFE_DAC_RATE", "PCM_LR_ADC_RATE", "PCM_MIC_ADC_RATE", "CENTER_LFE_MASTER",
703 "SURR_MASTER", "SPDIF_CTRL", "EXT_MODEM_ID", "EXT_MODEM_CTRL",
704 "LINE1_RATE", "LINE2_RATE", "HANDSET_RATE", "LINE1_LEVEL",
705 "LINE2_LEVEL", "HANDSET_LEVEL", "GPIO_PIN_CONFIG", "GPIO_PIN_POLARITY",
706 "GPIO_PIN_STICKY", "GPIO_PIN_WAKEUP", "GPIO_PIN_STATUS", "MISC_MODEM_CTRL",
707 "0x58", "VENDOR-5A", "VENDOR-5C", "VENDOR-5E",
708 "0x60", "0x62", "0x64", "0x66",
709 "0x68", "0x6a", "0x6c", "0x6e",
710 "VENDOR-70", "VENDOR-72", "VENDOR-74", "VENDOR-76",
711 "VENDOR-78", "VENDOR-7A", "VENDOR_ID1", "VENDOR_ID2"
712 };
713 #endif
714
715 static void
716 ac97_read(struct ac97_softc *as, u_int8_t reg, u_int16_t *val)
717 {
718 if (as->host_flags & AC97_HOST_DONT_READ &&
719 (reg != AC97_REG_VENDOR_ID1 && reg != AC97_REG_VENDOR_ID2 &&
720 reg != AC97_REG_RESET)) {
721 *val = as->shadow_reg[reg >> 1];
722 return;
723 }
724
725 if (as->host_if->read(as->host_if->arg, reg, val)) {
726 *val = as->shadow_reg[reg >> 1];
727 }
728 }
729
730 static int
731 ac97_write(struct ac97_softc *as, u_int8_t reg, u_int16_t val)
732 {
733 #ifndef AC97_IO_DEBUG
734 as->shadow_reg[reg >> 1] = val;
735 return as->host_if->write(as->host_if->arg, reg, val);
736 #else
737 int ret;
738 uint16_t actual;
739
740 as->shadow_reg[reg >> 1] = val;
741 ret = as->host_if->write(as->host_if->arg, reg, val);
742 as->host_if->read(as->host_if->arg, reg, &actual);
743 if (val != actual && reg < 0x80) {
744 printf("ac97_write: reg=%s, written=0x%04x, read=0x%04x\n",
745 ac97_register_names[reg / 2], val, actual);
746 }
747 return ret;
748 #endif
749 }
750
751 static void
752 ac97_setup_defaults(struct ac97_softc *as)
753 {
754 int idx;
755 const struct ac97_source_info *si;
756
757 memset(as->shadow_reg, 0, sizeof(as->shadow_reg));
758
759 for (idx = 0; idx < SOURCE_INFO_SIZE; idx++) {
760 si = &source_info[idx];
761 ac97_write(as, si->reg, si->default_value);
762 }
763 }
764
765 static void
766 ac97_restore_shadow(struct ac97_codec_if *self)
767 {
768 struct ac97_softc *as;
769 const struct ac97_source_info *si;
770 int idx;
771 uint16_t val;
772
773 as = (struct ac97_softc *) self;
774
775 /* make sure chip is fully operational */
776 #define AC97_POWER_ALL (AC97_POWER_REF | AC97_POWER_ANL | AC97_POWER_DAC \
777 | AC97_POWER_ADC)
778 for (idx = 500000; idx >= 0; idx--) {
779 ac97_read(as, AC97_REG_POWER, &val);
780 if ((val & AC97_POWER_ALL) == AC97_POWER_ALL)
781 break;
782 DELAY(1);
783 }
784 #undef AC97_POWER_ALL
785 printf("%s: power counter: %d\n", __func__, idx);
786
787 for (idx = 0; idx < SOURCE_INFO_SIZE; idx++) {
788 si = &source_info[idx];
789 /* don't "restore" to the reset reg! */
790 if (si->reg != AC97_REG_RESET)
791 ac97_write(as, si->reg, as->shadow_reg[si->reg >> 1]);
792 }
793
794 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA
795 | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM
796 | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC
797 | AC97_EXT_AUDIO_LDAC)) {
798 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL,
799 as->shadow_reg[AC97_REG_EXT_AUDIO_CTRL >> 1]);
800 }
801 }
802
803 static int
804 ac97_str_equal(const char *a, const char *b)
805 {
806 return (a == b) || (a && b && (!strcmp(a, b)));
807 }
808
809 static int
810 ac97_check_capability(struct ac97_softc *as, int check)
811 {
812 switch (check) {
813 case CHECK_NONE:
814 return 1;
815 case CHECK_SURROUND:
816 return as->ext_id & AC97_EXT_AUDIO_SDAC;
817 case CHECK_CENTER:
818 return as->ext_id & AC97_EXT_AUDIO_CDAC;
819 case CHECK_LFE:
820 return as->ext_id & AC97_EXT_AUDIO_LDAC;
821 case CHECK_HEADPHONES:
822 return as->caps & AC97_CAPS_HEADPHONES;
823 case CHECK_TONE:
824 return as->caps & AC97_CAPS_TONECTRL;
825 case CHECK_MIC:
826 return as->caps & AC97_CAPS_MICIN;
827 case CHECK_LOUDNESS:
828 return as->caps & AC97_CAPS_LOUDNESS;
829 case CHECK_3D:
830 return AC97_CAPS_ENHANCEMENT(as->caps) != 0;
831 default:
832 printf("%s: internal error: feature=%d\n", __func__, check);
833 return 0;
834 }
835 }
836
837 static void
838 ac97_setup_source_info(struct ac97_softc *as)
839 {
840 int idx, ouridx;
841 struct ac97_source_info *si, *si2;
842
843 for (idx = 0, ouridx = 0; idx < SOURCE_INFO_SIZE; idx++) {
844 si = &as->source_info[ouridx];
845
846 if (!ac97_check_capability(as, source_info[idx].req_feature))
847 continue;
848
849 memcpy(si, &source_info[idx], sizeof(*si));
850
851 switch (si->type) {
852 case AUDIO_MIXER_CLASS:
853 si->mixer_class = ouridx;
854 ouridx++;
855 break;
856 case AUDIO_MIXER_VALUE:
857 /* Todo - Test to see if it works */
858 ouridx++;
859
860 /* Add an entry for mute, if necessary */
861 if (si->mute) {
862 si = &as->source_info[ouridx];
863 memcpy(si, &source_info[idx], sizeof(*si));
864 si->qualifier = AudioNmute;
865 si->type = AUDIO_MIXER_ENUM;
866 si->info = &ac97_on_off;
867 si->info_size = sizeof(ac97_on_off);
868 si->bits = 1;
869 si->ofs = 15;
870 si->mute = 0;
871 si->polarity = 0;
872 ouridx++;
873 }
874 break;
875 case AUDIO_MIXER_ENUM:
876 /* Todo - Test to see if it works */
877 ouridx++;
878 break;
879 default:
880 aprint_error ("ac97: shouldn't get here\n");
881 break;
882 }
883 }
884
885 as->num_source_info = ouridx;
886
887 for (idx = 0; idx < as->num_source_info; idx++) {
888 int idx2, previdx;
889
890 si = &as->source_info[idx];
891
892 /* Find mixer class */
893 for (idx2 = 0; idx2 < as->num_source_info; idx2++) {
894 si2 = &as->source_info[idx2];
895
896 if (si2->type == AUDIO_MIXER_CLASS &&
897 ac97_str_equal(si->class,
898 si2->class)) {
899 si->mixer_class = idx2;
900 }
901 }
902
903
904 /* Setup prev and next pointers */
905 if (si->prev != 0)
906 continue;
907
908 if (si->qualifier)
909 continue;
910
911 si->prev = AUDIO_MIXER_LAST;
912 previdx = idx;
913
914 for (idx2 = 0; idx2 < as->num_source_info; idx2++) {
915 if (idx2 == idx)
916 continue;
917
918 si2 = &as->source_info[idx2];
919
920 if (!si2->prev &&
921 ac97_str_equal(si->class, si2->class) &&
922 ac97_str_equal(si->device, si2->device)) {
923 as->source_info[previdx].next = idx2;
924 as->source_info[idx2].prev = previdx;
925
926 previdx = idx2;
927 }
928 }
929
930 as->source_info[previdx].next = AUDIO_MIXER_LAST;
931 }
932 }
933
934 int
935 ac97_attach(struct ac97_host_if *host_if)
936 {
937 struct ac97_softc *as;
938 struct device *sc_dev;
939 int error, i, j;
940 uint32_t id;
941 uint16_t id1, id2;
942 uint16_t extstat, rate;
943 uint16_t val;
944 mixer_ctrl_t ctl;
945 void (*initfunc)(struct ac97_softc *);
946 #define FLAGBUFLEN 140
947 char flagbuf[FLAGBUFLEN];
948
949 sc_dev = (struct device *)host_if->arg;
950 initfunc = NULL;
951 as = malloc(sizeof(struct ac97_softc), M_DEVBUF, M_WAITOK|M_ZERO);
952
953 if (as == NULL)
954 return ENOMEM;
955
956 as->codec_if.vtbl = &ac97civ;
957 as->host_if = host_if;
958
959 if ((error = host_if->attach(host_if->arg, &as->codec_if))) {
960 free(as, M_DEVBUF);
961 return error;
962 }
963
964 if ((error = host_if->reset(host_if->arg))) {
965 free(as, M_DEVBUF);
966 return error;
967 }
968
969 host_if->write(host_if->arg, AC97_REG_RESET, 0);
970 host_if->write(host_if->arg, AC97_REG_POWER, 0);
971
972 if (host_if->flags)
973 as->host_flags = host_if->flags(host_if->arg);
974
975 #define AC97_POWER_ALL (AC97_POWER_REF | AC97_POWER_ANL | AC97_POWER_DAC \
976 | AC97_POWER_ADC)
977 for (i = 500000; i >= 0; i--) {
978 ac97_read(as, AC97_REG_POWER, &val);
979 if ((val & AC97_POWER_ALL) == AC97_POWER_ALL)
980 break;
981 DELAY(1);
982 }
983 #undef AC97_POWER_ALL
984
985 ac97_setup_defaults(as);
986 ac97_read(as, AC97_REG_RESET, &as->caps);
987 ac97_read(as, AC97_REG_VENDOR_ID1, &id1);
988 ac97_read(as, AC97_REG_VENDOR_ID2, &id2);
989
990 id = (id1 << 16) | id2;
991
992 aprint_normal("%s: ac97: ", sc_dev->dv_xname);
993
994 for (i = 0; ; i++) {
995 if (ac97codecid[i].id == 0) {
996 char pnp[4];
997
998 AC97_GET_CODEC_ID(id, pnp);
999 #define ISASCII(c) ((c) >= ' ' && (c) < 0x7f)
1000 if (ISASCII(pnp[0]) && ISASCII(pnp[1]) &&
1001 ISASCII(pnp[2]))
1002 aprint_normal("%c%c%c%d",
1003 pnp[0], pnp[1], pnp[2], pnp[3]);
1004 else
1005 aprint_normal("unknown (0x%08x)", id);
1006 break;
1007 }
1008 if (ac97codecid[i].id == (id & ac97codecid[i].mask)) {
1009 aprint_normal("%s", ac97codecid[i].name);
1010 if (ac97codecid[i].mask == AC97_VENDOR_ID_MASK) {
1011 aprint_normal(" (0x%08x)", id);
1012 }
1013 initfunc = ac97codecid[i].init;
1014 break;
1015 }
1016 }
1017 aprint_normal(" codec; ");
1018 for (i = j = 0; i < 10; i++) {
1019 if (as->caps & (1 << i)) {
1020 aprint_normal("%s%s", j ? ", " : "", ac97feature[i]);
1021 j++;
1022 }
1023 }
1024 aprint_normal("%s%s\n", j ? ", " : "",
1025 ac97enhancement[AC97_CAPS_ENHANCEMENT(as->caps)]);
1026
1027 as->ac97_clock = AC97_STANDARD_CLOCK;
1028 ac97_read(as, AC97_REG_EXT_AUDIO_ID, &as->ext_id);
1029 if (as->ext_id != 0) {
1030 /* Print capabilities */
1031 bitmask_snprintf(as->ext_id, "\20\20SECONDARY10\17SECONDARY01"
1032 "\14AC97_23\13AC97_22\12AMAP\11LDAC\10SDAC"
1033 "\7CDAC\4VRM\3SPDIF\2DRA\1VRA",
1034 flagbuf, FLAGBUFLEN);
1035 aprint_normal("%s: ac97: ext id %s\n", sc_dev->dv_xname, flagbuf);
1036
1037 /* Print unusual settings */
1038 if (as->ext_id & AC97_EXT_AUDIO_DSA_MASK) {
1039 aprint_normal("%s: ac97: Slot assignment: ",
1040 sc_dev->dv_xname);
1041 switch (as->ext_id & AC97_EXT_AUDIO_DSA_MASK) {
1042 case AC97_EXT_AUDIO_DSA01:
1043 aprint_normal("7&8, 6&9, 10&11.\n");
1044 break;
1045 case AC97_EXT_AUDIO_DSA10:
1046 aprint_normal("6&9, 10&11, 3&4.\n");
1047 break;
1048 case AC97_EXT_AUDIO_DSA11:
1049 aprint_normal("10&11, 3&4, 7&8.\n");
1050 break;
1051 }
1052 }
1053
1054 /* Enable and disable features */
1055 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat);
1056 extstat &= ~AC97_EXT_AUDIO_DRA;
1057 if (as->ext_id & AC97_EXT_AUDIO_LDAC)
1058 extstat |= AC97_EXT_AUDIO_LDAC;
1059 if (as->ext_id & AC97_EXT_AUDIO_SDAC)
1060 extstat |= AC97_EXT_AUDIO_SDAC;
1061 if (as->ext_id & AC97_EXT_AUDIO_CDAC)
1062 extstat |= AC97_EXT_AUDIO_CDAC;
1063 if (as->ext_id & AC97_EXT_AUDIO_VRM)
1064 extstat |= AC97_EXT_AUDIO_VRM;
1065 if (as->ext_id & AC97_EXT_AUDIO_SPDIF) {
1066 /* Output the same data as DAC to SPDIF output */
1067 extstat &= ~AC97_EXT_AUDIO_SPSA_MASK;
1068 extstat |= AC97_EXT_AUDIO_SPSA34;
1069 }
1070 if (as->ext_id & AC97_EXT_AUDIO_VRA)
1071 extstat |= AC97_EXT_AUDIO_VRA;
1072 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat);
1073 if (as->ext_id & AC97_EXT_AUDIO_VRA) {
1074 /* VRA should be enabled. */
1075 /* so it claims to do variable rate, let's make sure */
1076 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE, 44100);
1077 ac97_read(as, AC97_REG_PCM_FRONT_DAC_RATE, &rate);
1078 if (rate != 44100) {
1079 /* We can't believe ext_id */
1080 as->ext_id = 0;
1081 aprint_normal(
1082 "%s: Ignore these capabilities.\n",
1083 sc_dev->dv_xname);
1084 }
1085 /* restore the default value */
1086 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE,
1087 AC97_SINGLE_RATE);
1088 }
1089 }
1090
1091 ac97_setup_source_info(as);
1092
1093 memset(&ctl, 0, sizeof(ctl));
1094 /* disable mutes */
1095 for (i = 0; i < 11; i++) {
1096 static struct {
1097 char *class, *device;
1098 } d[11] = {
1099 { AudioCoutputs, AudioNmaster},
1100 { AudioCoutputs, AudioNheadphone},
1101 { AudioCoutputs, AudioNsurround},
1102 { AudioCoutputs, AudioNcenter},
1103 { AudioCoutputs, AudioNlfe},
1104 { AudioCinputs, AudioNdac},
1105 { AudioCinputs, AudioNcd},
1106 { AudioCinputs, AudioNline},
1107 { AudioCinputs, AudioNaux},
1108 { AudioCinputs, AudioNvideo},
1109 { AudioCrecord, AudioNvolume},
1110 };
1111
1112 ctl.type = AUDIO_MIXER_ENUM;
1113 ctl.un.ord = 0;
1114
1115 ctl.dev = ac97_get_portnum_by_name(&as->codec_if,
1116 d[i].class, d[i].device, AudioNmute);
1117 ac97_mixer_set_port(&as->codec_if, &ctl);
1118 }
1119 ctl.type = AUDIO_MIXER_ENUM;
1120 ctl.un.ord = 0;
1121 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
1122 AudioNsource, NULL);
1123 ac97_mixer_set_port(&as->codec_if, &ctl);
1124
1125 /* set a reasonable default volume */
1126 ctl.type = AUDIO_MIXER_VALUE;
1127 ctl.un.value.num_channels = 2;
1128 ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = \
1129 ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127;
1130 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1131 AudioNmaster, NULL);
1132 ac97_mixer_set_port(&as->codec_if, &ctl);
1133 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1134 AudioNsurround, NULL);
1135 ac97_mixer_set_port(&as->codec_if, &ctl);
1136 ctl.un.value.num_channels = 1;
1137 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1138 AudioNcenter, NULL);
1139 ac97_mixer_set_port(&as->codec_if, &ctl);
1140 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
1141 AudioNlfe, NULL);
1142 ac97_mixer_set_port(&as->codec_if, &ctl);
1143
1144 if (initfunc != NULL)
1145 initfunc(as);
1146 return 0;
1147 }
1148
1149
1150 static int
1151 ac97_query_devinfo(struct ac97_codec_if *codec_if, mixer_devinfo_t *dip)
1152 {
1153 struct ac97_softc *as;
1154 struct ac97_source_info *si;
1155 const char *name;
1156
1157 as = (struct ac97_softc *)codec_if;
1158 if (dip->index < as->num_source_info) {
1159 si = &as->source_info[dip->index];
1160 dip->type = si->type;
1161 dip->mixer_class = si->mixer_class;
1162 dip->prev = si->prev;
1163 dip->next = si->next;
1164
1165 if (si->qualifier)
1166 name = si->qualifier;
1167 else if (si->device)
1168 name = si->device;
1169 else if (si->class)
1170 name = si->class;
1171 else
1172 name = 0;
1173
1174 if (name)
1175 strcpy(dip->label.name, name);
1176
1177 memcpy(&dip->un, si->info, si->info_size);
1178
1179 /* Set the delta for volume sources */
1180 if (dip->type == AUDIO_MIXER_VALUE)
1181 dip->un.v.delta = 1 << (8 - si->bits);
1182
1183 return 0;
1184 }
1185
1186 return ENXIO;
1187 }
1188
1189
1190
1191 static int
1192 ac97_mixer_set_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
1193 {
1194 struct ac97_softc *as;
1195 struct ac97_source_info *si;
1196 u_int16_t mask;
1197 u_int16_t val, newval;
1198 int error;
1199
1200 as = (struct ac97_softc *)codec_if;
1201 si = &as->source_info[cp->dev];
1202 if (cp->dev < 0 || cp->dev >= as->num_source_info)
1203 return EINVAL;
1204
1205 if (cp->type != si->type)
1206 return EINVAL;
1207
1208 ac97_read(as, si->reg, &val);
1209
1210 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
1211
1212 mask = (1 << si->bits) - 1;
1213
1214 switch (cp->type) {
1215 case AUDIO_MIXER_ENUM:
1216 if (cp->un.ord > mask || cp->un.ord < 0)
1217 return EINVAL;
1218
1219 newval = (cp->un.ord << si->ofs);
1220 if (si->reg == AC97_REG_RECORD_SELECT) {
1221 newval |= (newval << (8 + si->ofs));
1222 mask |= (mask << 8);
1223 mask = mask << si->ofs;
1224 } else if (si->reg == AC97_REG_SURR_MASTER) {
1225 newval = cp->un.ord ? 0x8080 : 0x0000;
1226 mask = 0x8080;
1227 } else
1228 mask = mask << si->ofs;
1229 break;
1230 case AUDIO_MIXER_VALUE:
1231 {
1232 const struct audio_mixer_value *value = si->info;
1233 u_int16_t l, r, ol, or;
1234 int deltal, deltar;
1235
1236 if ((cp->un.value.num_channels <= 0) ||
1237 (cp->un.value.num_channels > value->num_channels))
1238 return EINVAL;
1239
1240 if (cp->un.value.num_channels == 1) {
1241 l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
1242 } else {
1243 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
1244 l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1245 r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1246 } else { /* left/right is reversed here */
1247 r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1248 l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1249 }
1250
1251 }
1252
1253 if (!si->polarity) {
1254 l = 255 - l;
1255 r = 255 - r;
1256 }
1257
1258 ol = (val >> (8+si->ofs)) & mask;
1259 or = (val >> si->ofs) & mask;
1260
1261 deltal = (ol << (8 - si->bits)) - l;
1262 deltar = (or << (8 - si->bits)) - r;
1263
1264 l = l >> (8 - si->bits);
1265 r = r >> (8 - si->bits);
1266
1267 if (deltal && ol == l)
1268 l += (deltal > 0) ? (l ? -1 : 0) : (l < mask ? 1 : 0);
1269 if (deltar && or == r)
1270 r += (deltar > 0) ? (r ? -1 : 0) : (r < mask ? 1 : 0);
1271
1272 newval = ((r & mask) << si->ofs);
1273 if (value->num_channels == 2) {
1274 newval = newval | ((l & mask) << (si->ofs+8));
1275 mask |= (mask << 8);
1276 }
1277 mask = mask << si->ofs;
1278 break;
1279 }
1280 default:
1281 return EINVAL;
1282 }
1283
1284 error = ac97_write(as, si->reg, (val & ~mask) | newval);
1285 if (error)
1286 return error;
1287
1288 return 0;
1289 }
1290
1291 static int
1292 ac97_get_portnum_by_name(struct ac97_codec_if *codec_if, const char *class,
1293 const char *device, const char *qualifier)
1294 {
1295 struct ac97_softc *as;
1296 int idx;
1297
1298 as = (struct ac97_softc *)codec_if;
1299 for (idx = 0; idx < as->num_source_info; idx++) {
1300 struct ac97_source_info *si = &as->source_info[idx];
1301 if (ac97_str_equal(class, si->class) &&
1302 ac97_str_equal(device, si->device) &&
1303 ac97_str_equal(qualifier, si->qualifier))
1304 return idx;
1305 }
1306
1307 return -1;
1308 }
1309
1310 static int
1311 ac97_mixer_get_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
1312 {
1313 struct ac97_softc *as;
1314 struct ac97_source_info *si;
1315 u_int16_t mask;
1316 u_int16_t val;
1317
1318 as = (struct ac97_softc *)codec_if;
1319 si = &as->source_info[cp->dev];
1320 if (cp->dev < 0 || cp->dev >= as->num_source_info)
1321 return EINVAL;
1322
1323 if (cp->type != si->type)
1324 return EINVAL;
1325
1326 ac97_read(as, si->reg, &val);
1327
1328 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
1329
1330 mask = (1 << si->bits) - 1;
1331
1332 switch (cp->type) {
1333 case AUDIO_MIXER_ENUM:
1334 cp->un.ord = (val >> si->ofs) & mask;
1335 DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n",
1336 val, si->ofs, mask, cp->un.ord));
1337 break;
1338 case AUDIO_MIXER_VALUE:
1339 {
1340 const struct audio_mixer_value *value = si->info;
1341 u_int16_t l, r;
1342
1343 if ((cp->un.value.num_channels <= 0) ||
1344 (cp->un.value.num_channels > value->num_channels))
1345 return EINVAL;
1346
1347 if (value->num_channels == 1) {
1348 l = r = (val >> si->ofs) & mask;
1349 } else {
1350 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
1351 l = (val >> (si->ofs + 8)) & mask;
1352 r = (val >> si->ofs) & mask;
1353 } else { /* host has reversed channels */
1354 r = (val >> (si->ofs + 8)) & mask;
1355 l = (val >> si->ofs) & mask;
1356 }
1357 }
1358
1359 l = (l << (8 - si->bits));
1360 r = (r << (8 - si->bits));
1361 if (!si->polarity) {
1362 l = 255 - l;
1363 r = 255 - r;
1364 }
1365
1366 /* The EAP driver averages l and r for stereo
1367 channels that are requested in MONO mode. Does this
1368 make sense? */
1369 if (cp->un.value.num_channels == 1) {
1370 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l;
1371 } else if (cp->un.value.num_channels == 2) {
1372 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
1373 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
1374 }
1375
1376 break;
1377 }
1378 default:
1379 return EINVAL;
1380 }
1381
1382 return 0;
1383 }
1384
1385
1386 static int
1387 ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_long *rate)
1388 {
1389 struct ac97_softc *as;
1390 u_long value;
1391 u_int16_t ext_stat;
1392 u_int16_t actual;
1393 u_int16_t power;
1394 u_int16_t power_bit;
1395
1396 as = (struct ac97_softc *)codec_if;
1397 if (target == AC97_REG_PCM_MIC_ADC_RATE) {
1398 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1399 *rate = AC97_SINGLE_RATE;
1400 return 0;
1401 }
1402 } else {
1403 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1404 *rate = AC97_SINGLE_RATE;
1405 return 0;
1406 }
1407 }
1408 value = *rate * AC97_STANDARD_CLOCK / as->ac97_clock;
1409 ext_stat = 0;
1410 /*
1411 * PCM_FRONT_DAC_RATE/PCM_SURR_DAC_RATE/PCM_LFE_DAC_RATE
1412 * Check VRA, DRA
1413 * PCM_LR_ADC_RATE
1414 * Check VRA
1415 * PCM_MIC_ADC_RATE
1416 * Check VRM
1417 */
1418 switch (target) {
1419 case AC97_REG_PCM_FRONT_DAC_RATE:
1420 case AC97_REG_PCM_SURR_DAC_RATE:
1421 case AC97_REG_PCM_LFE_DAC_RATE:
1422 power_bit = AC97_POWER_OUT;
1423 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1424 *rate = AC97_SINGLE_RATE;
1425 return 0;
1426 }
1427 if (as->ext_id & AC97_EXT_AUDIO_DRA) {
1428 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &ext_stat);
1429 if (value > 0x1ffff) {
1430 return EINVAL;
1431 } else if (value > 0xffff) {
1432 /* Enable DRA */
1433 ext_stat |= AC97_EXT_AUDIO_DRA;
1434 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1435 value /= 2;
1436 } else {
1437 /* Disable DRA */
1438 ext_stat &= ~AC97_EXT_AUDIO_DRA;
1439 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1440 }
1441 } else {
1442 if (value > 0xffff)
1443 return EINVAL;
1444 }
1445 break;
1446 case AC97_REG_PCM_LR_ADC_RATE:
1447 power_bit = AC97_POWER_IN;
1448 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1449 *rate = AC97_SINGLE_RATE;
1450 return 0;
1451 }
1452 if (value > 0xffff)
1453 return EINVAL;
1454 break;
1455 case AC97_REG_PCM_MIC_ADC_RATE:
1456 power_bit = AC97_POWER_IN;
1457 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1458 *rate = AC97_SINGLE_RATE;
1459 return 0;
1460 }
1461 if (value > 0xffff)
1462 return EINVAL;
1463 break;
1464 default:
1465 printf("%s: Unknown register: 0x%x\n", __func__, target);
1466 return EINVAL;
1467 }
1468
1469 ac97_read(as, AC97_REG_POWER, &power);
1470 ac97_write(as, AC97_REG_POWER, power | power_bit);
1471
1472 ac97_write(as, target, (u_int16_t)value);
1473 ac97_read(as, target, &actual);
1474 actual = (u_int32_t)actual * as->ac97_clock / AC97_STANDARD_CLOCK;
1475
1476 ac97_write(as, AC97_REG_POWER, power);
1477 if (ext_stat & AC97_EXT_AUDIO_DRA) {
1478 *rate = actual * 2;
1479 } else {
1480 *rate = actual;
1481 }
1482 return 0;
1483 }
1484
1485 static void
1486 ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock)
1487 {
1488 struct ac97_softc *as;
1489
1490 as = (struct ac97_softc *)codec_if;
1491 as->ac97_clock = clock;
1492 }
1493
1494 static u_int16_t
1495 ac97_get_extcaps(struct ac97_codec_if *codec_if)
1496 {
1497 struct ac97_softc *as;
1498
1499 as = (struct ac97_softc *)codec_if;
1500 return as->ext_id;
1501 }
1502
1503 static int
1504 ac97_add_port(struct ac97_softc *as, const struct ac97_source_info *src)
1505 {
1506 struct ac97_source_info *si;
1507 int ouridx, idx;
1508
1509 if (as->num_source_info >= MAX_SOURCES) {
1510 printf("%s: internal error: increase MAX_SOURCES in %s\n",
1511 __func__, __FILE__);
1512 return -1;
1513 }
1514 if (!ac97_check_capability(as, src->req_feature))
1515 return -1;
1516 ouridx = as->num_source_info;
1517 si = &as->source_info[ouridx];
1518 memcpy(si, src, sizeof(*si));
1519
1520 switch (si->type) {
1521 case AUDIO_MIXER_CLASS:
1522 case AUDIO_MIXER_VALUE:
1523 printf("%s: adding class/value is not supported yet.\n",
1524 __func__);
1525 return -1;
1526 case AUDIO_MIXER_ENUM:
1527 break;
1528 default:
1529 printf("%s: unknown type: %d\n", __func__, si->type);
1530 return -1;
1531 }
1532 as->num_source_info++;
1533
1534 si->mixer_class = ac97_get_portnum_by_name(&as->codec_if, si->class,
1535 NULL, NULL);
1536 /* Find the root of the device */
1537 idx = ac97_get_portnum_by_name(&as->codec_if, si->class,
1538 si->device, NULL);
1539 /* Find the last item */
1540 while (as->source_info[idx].next != AUDIO_MIXER_LAST)
1541 idx = as->source_info[idx].next;
1542 /* Append */
1543 as->source_info[idx].next = ouridx;
1544 si->prev = idx;
1545 si->next = AUDIO_MIXER_LAST;
1546
1547 return 0;
1548 }
1549
1550 /**
1551 * Codec-dependent initialization
1552 */
1553
1554 #define AD1980_REG_MISC 0x76
1555 #define AD1980_MISC_MBG0 0x0001 /* 0 1888/1980/1981 /1985 */
1556 #define AD1980_MISC_MBG1 0x0002 /* 1 1888/1980/1981 /1985 */
1557 #define AD1980_MISC_VREFD 0x0004 /* 2 1888/1980/1981 /1985 */
1558 #define AD1980_MISC_VREFH 0x0008 /* 3 1888/1980/1981 /1985 */
1559 #define AD1980_MISC_SRU 0x0010 /* 4 1888/1980 /1985 */
1560 #define AD1980_MISC_LOSEL 0x0020 /* 5 1888/1980/1981 /1985 */
1561 #define AD1980_MISC_2CMIC 0x0040 /* 6 1980/1981B/1985 */
1562 #define AD1980_MISC_SPRD 0x0080 /* 7 1888/1980 /1985 */
1563 #define AD1980_MISC_DMIX0 0x0100 /* 8 1888/1980 /1985 */
1564 #define AD1980_MISC_DMIX1 0x0200 /* 9 1888/1980 /1985 */
1565 #define AD1980_MISC_HPSEL 0x0400 /*10 1888/1980 /1985 */
1566 #define AD1980_MISC_CLDIS 0x0800 /*11 1888/1980 /1985 */
1567 #define AD1980_MISC_LODIS 0x1000 /*12 1888/1980/1981 /1985 */
1568 #define AD1980_MISC_MSPLT 0x2000 /*13 1888/1980/1981 /1985 */
1569 #define AD1980_MISC_AC97NC 0x4000 /*14 1888/1980 /1985 */
1570 #define AD1980_MISC_DACZ 0x8000 /*15 1888/1980/1981 /1985 */
1571 #define AD1981_REG_MISC 0x76
1572 #define AD1981_MISC_MADST 0x0010 /* 4 */
1573 #define AD1981A_MISC_MADPD 0x0040 /* 6 */
1574 #define AD1981B_MISC_MADPD 0x0080 /* 7 */
1575 #define AD1981_MISC_FMXE 0x0200 /* 9 */
1576 #define AD1981_MISC_DAM 0x0800 /*11 */
1577 static void
1578 ac97_ad198x_init(struct ac97_softc *as)
1579 {
1580 int i;
1581 uint16_t misc;
1582
1583 ac97_read(as, AD1980_REG_MISC, &misc);
1584 ac97_write(as, AD1980_REG_MISC,
1585 misc | AD1980_MISC_LOSEL | AD1980_MISC_HPSEL);
1586
1587 for (i = 0; i < as->num_source_info; i++) {
1588 if (as->source_info[i].type != AUDIO_MIXER_VALUE)
1589 continue;
1590
1591 if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME)
1592 as->source_info[i].reg = AC97_REG_SURR_MASTER;
1593 else if (as->source_info[i].reg == AC97_REG_SURR_MASTER)
1594 as->source_info[i].reg = AC97_REG_MASTER_VOLUME;
1595 }
1596 }
1597
1598 #define ALC650_REG_MULTI_CHANNEL_CONTROL 0x6a
1599 #define ALC650_MCC_SLOT_MODIFY_MASK 0xc000
1600 #define ALC650_MCC_FRONTDAC_FROM_SPDIFIN 0x2000 /* 13 */
1601 #define ALC650_MCC_SPDIFOUT_FROM_ADC 0x1000 /* 12 */
1602 #define ALC650_MCC_PCM_FROM_SPDIFIN 0x0800 /* 11 */
1603 #define ALC650_MCC_MIC_OR_CENTERLFE 0x0400 /* 10 */
1604 #define ALC650_MCC_LINEIN_OR_SURROUND 0x0200 /* 9 */
1605 #define ALC650_MCC_INDEPENDENT_MASTER_L 0x0080 /* 7 */
1606 #define ALC650_MCC_INDEPENDENT_MASTER_R 0x0040 /* 6 */
1607 #define ALC650_MCC_ANALOG_TO_CENTERLFE 0x0020 /* 5 */
1608 #define ALC650_MCC_ANALOG_TO_SURROUND 0x0010 /* 4 */
1609 #define ALC650_MCC_EXCHANGE_CENTERLFE 0x0008 /* 3 */
1610 #define ALC650_MCC_CENTERLFE_DOWNMIX 0x0004 /* 2 */
1611 #define ALC650_MCC_SURROUND_DOWNMIX 0x0002 /* 1 */
1612 #define ALC650_MCC_LINEOUT_TO_SURROUND 0x0001 /* 0 */
1613 static void
1614 ac97_alc650_init(struct ac97_softc *as)
1615 {
1616 static const struct ac97_source_info sources[6] = {
1617 { AudioCoutputs, AudioNsurround, "lineinjack",
1618 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1619 ALC650_REG_MULTI_CHANNEL_CONTROL,
1620 0x0000, 1, 9, 0, 0, CHECK_SURROUND },
1621 { AudioCoutputs, AudioNsurround, "mixtofront",
1622 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1623 ALC650_REG_MULTI_CHANNEL_CONTROL,
1624 0x0000, 1, 1, 0, 0, CHECK_SURROUND },
1625 { AudioCoutputs, AudioNcenter, "micjack",
1626 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1627 ALC650_REG_MULTI_CHANNEL_CONTROL,
1628 0x0000, 1, 10, 0, 0, CHECK_CENTER },
1629 { AudioCoutputs, AudioNlfe, "micjack",
1630 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1631 ALC650_REG_MULTI_CHANNEL_CONTROL,
1632 0x0000, 1, 10, 0, 0, CHECK_LFE },
1633 { AudioCoutputs, AudioNcenter, "mixtofront",
1634 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1635 ALC650_REG_MULTI_CHANNEL_CONTROL,
1636 0x0000, 1, 2, 0, 0, CHECK_CENTER },
1637 { AudioCoutputs, AudioNlfe, "mixtofront",
1638 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1639 ALC650_REG_MULTI_CHANNEL_CONTROL,
1640 0x0000, 1, 2, 0, 0, CHECK_LFE },
1641 };
1642
1643 ac97_add_port(as, &sources[0]);
1644 ac97_add_port(as, &sources[1]);
1645 ac97_add_port(as, &sources[2]);
1646 ac97_add_port(as, &sources[3]);
1647 ac97_add_port(as, &sources[4]);
1648 ac97_add_port(as, &sources[5]);
1649 }
1650
1651 #define VT1616_REG_IO_CONTROL 0x5a
1652 #define VT1616_IC_LVL (1 << 15)
1653 #define VT1616_IC_LFECENTER_TO_FRONT (1 << 12)
1654 #define VT1616_IC_SURROUND_TO_FRONT (1 << 11)
1655 #define VT1616_IC_BPDC (1 << 10)
1656 #define VT1616_IC_DC (1 << 9)
1657 #define VT1616_IC_IB_MASK 0x000c
1658 static void
1659 ac97_vt1616_init(struct ac97_softc *as)
1660 {
1661 static const struct ac97_source_info sources[3] = {
1662 { AudioCoutputs, AudioNsurround, "mixtofront",
1663 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1664 VT1616_REG_IO_CONTROL,
1665 0x0000, 1, 11, 0, 0, CHECK_SURROUND },
1666 { AudioCoutputs, AudioNcenter, "mixtofront",
1667 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1668 VT1616_REG_IO_CONTROL,
1669 0x0000, 1, 12, 0, 0, CHECK_CENTER },
1670 { AudioCoutputs, AudioNlfe, "mixtofront",
1671 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1672 VT1616_REG_IO_CONTROL,
1673 0x0000, 1, 12, 0, 0, CHECK_LFE },
1674 };
1675
1676 ac97_add_port(as, &sources[0]);
1677 ac97_add_port(as, &sources[1]);
1678 ac97_add_port(as, &sources[2]);
1679 }
1680