ac97.c revision 1.31 1 /* $NetBSD: ac97.c,v 1.31 2002/10/09 12:06:17 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.31 2002/10/09 12:06:17 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 static const struct audio_mixer_enum ac97_on_off = { 2,
81 { { { AudioNoff } , 0 },
82 { { AudioNon } , 1 } }};
83
84
85 static const struct audio_mixer_enum ac97_mic_select = { 2,
86 { { { AudioNmicrophone "0" },
87 0 },
88 { { AudioNmicrophone "1" },
89 1 } }};
90
91 static const struct audio_mixer_enum ac97_mono_select = { 2,
92 { { { AudioNmixerout },
93 0 },
94 { { AudioNmicrophone },
95 1 } }};
96
97 static const struct audio_mixer_enum ac97_source = { 8,
98 { { { AudioNmicrophone } , 0 },
99 { { AudioNcd }, 1 },
100 { { "video" }, 2 },
101 { { AudioNaux }, 3 },
102 { { AudioNline }, 4 },
103 { { AudioNmixerout }, 5 },
104 { { AudioNmixerout AudioNmono }, 6 },
105 { { "phone" }, 7 }}};
106
107 /*
108 * Due to different values for each source that uses these structures,
109 * the ac97_query_devinfo function sets delta in mixer_devinfo_t using
110 * ac97_source_info.bits.
111 */
112 static const struct audio_mixer_value ac97_volume_stereo = { { AudioNvolume },
113 2 };
114
115 static const struct audio_mixer_value ac97_volume_mono = { { AudioNvolume },
116 1 };
117
118 #define WRAP(a) &a, sizeof(a)
119
120 const struct ac97_source_info {
121 const char *class;
122 const char *device;
123 const char *qualifier;
124 int type;
125
126 const void *info;
127 int info_size;
128
129 u_int8_t reg;
130 u_int16_t default_value;
131 u_int8_t bits:3;
132 u_int8_t ofs:4;
133 u_int8_t mute:1;
134 u_int8_t polarity:1; /* Does 0 == MAX or MIN */
135
136 int prev;
137 int next;
138 int mixer_class;
139 } source_info[] = {
140 { AudioCinputs , NULL, NULL, AUDIO_MIXER_CLASS,
141 },
142 { AudioCoutputs, NULL, NULL, AUDIO_MIXER_CLASS,
143 },
144 { AudioCrecord , NULL, NULL, AUDIO_MIXER_CLASS,
145 },
146 /* Stereo master volume*/
147 { AudioCoutputs, AudioNmaster, NULL, AUDIO_MIXER_VALUE,
148 WRAP(ac97_volume_stereo),
149 AC97_REG_MASTER_VOLUME, 0x8000, 5, 0, 1,
150 },
151 /* Mono volume */
152 { AudioCoutputs, AudioNmono, NULL, AUDIO_MIXER_VALUE,
153 WRAP(ac97_volume_mono),
154 AC97_REG_MASTER_VOLUME_MONO, 0x8000, 6, 0, 1,
155 },
156 { AudioCoutputs, AudioNmono,AudioNsource, AUDIO_MIXER_ENUM,
157 WRAP(ac97_mono_select),
158 AC97_REG_GP, 0x0000, 1, 9, 0,
159 },
160 /* Headphone volume */
161 { AudioCoutputs, AudioNheadphone, NULL, AUDIO_MIXER_VALUE,
162 WRAP(ac97_volume_stereo),
163 AC97_REG_HEADPHONE_VOLUME, 0x8000, 6, 0, 1,
164 },
165 /* Tone */
166 { AudioCoutputs, "tone", NULL, AUDIO_MIXER_VALUE,
167 WRAP(ac97_volume_stereo),
168 AC97_REG_MASTER_TONE, 0x0f0f, 4, 0, 0,
169 },
170 /* PC Beep Volume */
171 { AudioCinputs, AudioNspeaker, NULL, AUDIO_MIXER_VALUE,
172 WRAP(ac97_volume_mono),
173 AC97_REG_PCBEEP_VOLUME, 0x0000, 4, 1, 1,
174 },
175 /* Phone */
176 { AudioCinputs, "phone", NULL, AUDIO_MIXER_VALUE,
177 WRAP(ac97_volume_mono),
178 AC97_REG_PHONE_VOLUME, 0x8008, 5, 0, 1,
179 },
180 /* Mic Volume */
181 { AudioCinputs, AudioNmicrophone, NULL, AUDIO_MIXER_VALUE,
182 WRAP(ac97_volume_mono),
183 AC97_REG_MIC_VOLUME, 0x8008, 5, 0, 1,
184 },
185 { AudioCinputs, AudioNmicrophone, AudioNpreamp, AUDIO_MIXER_ENUM,
186 WRAP(ac97_on_off),
187 AC97_REG_MIC_VOLUME, 0x8008, 1, 6, 0,
188 },
189 { AudioCinputs, AudioNmicrophone, AudioNsource, AUDIO_MIXER_ENUM,
190 WRAP(ac97_mic_select),
191 AC97_REG_GP, 0x0000, 1, 8, 0,
192 },
193 /* Line in Volume */
194 { AudioCinputs, AudioNline, NULL, AUDIO_MIXER_VALUE,
195 WRAP(ac97_volume_stereo),
196 AC97_REG_LINEIN_VOLUME, 0x8808, 5, 0, 1,
197 },
198 /* CD Volume */
199 { AudioCinputs, AudioNcd, NULL, AUDIO_MIXER_VALUE,
200 WRAP(ac97_volume_stereo),
201 AC97_REG_CD_VOLUME, 0x8808, 5, 0, 1,
202 },
203 /* Video Volume */
204 { AudioCinputs, "video", NULL, AUDIO_MIXER_VALUE,
205 WRAP(ac97_volume_stereo),
206 AC97_REG_VIDEO_VOLUME, 0x8808, 5, 0, 1,
207 },
208 /* AUX volume */
209 { AudioCinputs, AudioNaux, NULL, AUDIO_MIXER_VALUE,
210 WRAP(ac97_volume_stereo),
211 AC97_REG_AUX_VOLUME, 0x8808, 5, 0, 1,
212 },
213 /* PCM out volume */
214 { AudioCinputs, AudioNdac, NULL, AUDIO_MIXER_VALUE,
215 WRAP(ac97_volume_stereo),
216 AC97_REG_PCMOUT_VOLUME, 0x8808, 5, 0, 1,
217 },
218 /* Record Source - some logic for this is hard coded - see below */
219 { AudioCrecord, AudioNsource, NULL, AUDIO_MIXER_ENUM,
220 WRAP(ac97_source),
221 AC97_REG_RECORD_SELECT, 0x0000, 3, 0, 0,
222 },
223 /* Record Gain */
224 { AudioCrecord, AudioNvolume, NULL, AUDIO_MIXER_VALUE,
225 WRAP(ac97_volume_stereo),
226 AC97_REG_RECORD_GAIN, 0x8000, 4, 0, 1,
227 },
228 /* Record Gain mic */
229 { AudioCrecord, AudioNmicrophone, NULL, AUDIO_MIXER_VALUE,
230 WRAP(ac97_volume_mono),
231 AC97_REG_RECORD_GAIN_MIC, 0x8000, 4, 0, 1, 1,
232 },
233 /* */
234 { AudioCoutputs, AudioNloudness, NULL, AUDIO_MIXER_ENUM,
235 WRAP(ac97_on_off),
236 AC97_REG_GP, 0x0000, 1, 12, 0,
237 },
238 { AudioCoutputs, AudioNspatial, NULL, AUDIO_MIXER_ENUM,
239 WRAP(ac97_on_off),
240 AC97_REG_GP, 0x0000, 1, 13, 0,
241 },
242 { AudioCoutputs, AudioNspatial, "center", AUDIO_MIXER_VALUE,
243 WRAP(ac97_volume_mono),
244 AC97_REG_3D_CONTROL, 0x0000, 4, 8, 0, 1,
245 },
246 { AudioCoutputs, AudioNspatial, "depth", AUDIO_MIXER_VALUE,
247 WRAP(ac97_volume_mono),
248 AC97_REG_3D_CONTROL, 0x0000, 4, 0, 0, 1,
249 },
250
251 /* Missing features: Simulated Stereo, POP, Loopback mode */
252 } ;
253
254 #define SOURCE_INFO_SIZE (sizeof(source_info)/sizeof(source_info[0]))
255
256 /*
257 * Check out http://developer.intel.com/pc-supp/platform/ac97/ for
258 * information on AC-97
259 */
260
261 struct ac97_softc {
262 /* ac97_codec_if must be at the first of ac97_softc. */
263 struct ac97_codec_if codec_if;
264
265 struct ac97_host_if *host_if;
266
267 struct ac97_source_info source_info[2 * SOURCE_INFO_SIZE];
268 int num_source_info;
269
270 enum ac97_host_flags host_flags;
271 unsigned int ac97_clock; /* usually 48000 */
272 #define AC97_STANDARD_CLOCK 48000U
273 u_int16_t caps; /* -> AC97_REG_RESET */
274 u_int16_t ext_id; /* -> AC97_REG_EXT_AUDIO_ID */
275 u_int16_t shadow_reg[128];
276 };
277
278 int ac97_mixer_get_port __P((struct ac97_codec_if *self, mixer_ctrl_t *cp));
279 int ac97_mixer_set_port __P((struct ac97_codec_if *self, mixer_ctrl_t *));
280 int ac97_query_devinfo __P((struct ac97_codec_if *self, mixer_devinfo_t *));
281 int ac97_get_portnum_by_name __P((struct ac97_codec_if *, char *, char *,
282 char *));
283 void ac97_restore_shadow __P((struct ac97_codec_if *self));
284 int ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_long *rate);
285 void ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock);
286 u_int16_t ac97_get_extcaps(struct ac97_codec_if *codec_if);
287
288 struct ac97_codec_if_vtbl ac97civ = {
289 ac97_mixer_get_port,
290 ac97_mixer_set_port,
291 ac97_query_devinfo,
292 ac97_get_portnum_by_name,
293 ac97_restore_shadow,
294 ac97_get_extcaps,
295 ac97_set_rate,
296 ac97_set_clock,
297 };
298
299 static const struct ac97_codecid {
300 u_int32_t id;
301 u_int32_t mask;
302 const char *name;
303 } ac97codecid[] = {
304 { AC97_CODEC_ID('A', 'D', 'S', 3),
305 0xffffffff, "Analog Devices AD1819B" },
306 { AC97_CODEC_ID('A', 'D', 'S', 64),
307 0xffffffff, "Analog Devices AD1881" },
308 { AC97_CODEC_ID('A', 'D', 'S', 72),
309 0xffffffff, "Analog Devices AD1881A" },
310 { AC97_CODEC_ID('A', 'D', 'S', 96),
311 0xffffffff, "Analog Devices AD1885" },
312 { AC97_CODEC_ID('A', 'D', 'S', 99),
313 0xffffffff, "Analog Devices AD1886A" },
314
315 { AC97_CODEC_ID('A', 'K', 'M', 0),
316 0xffffffff, "Asahi Kasei AK4540" },
317 { AC97_CODEC_ID('A', 'K', 'M', 2),
318 0xffffffff, "Asahi Kasei AK4543" },
319
320 { AC97_CODEC_ID('A', 'L', 'G', 0x10),
321 0xffffffff, "Advance Logic ALC200" },
322 { AC97_CODEC_ID('A', 'L', 'G', 0x20),
323 0xffffffff, "Advance Logic ALC650" },
324 { AC97_CODEC_ID('A', 'L', 'G', 0x30),
325 0xffffffff, "Advance Logic ALC101" },
326 { AC97_CODEC_ID('A', 'L', 'G', 0x40),
327 0xffffffff, "Advance Logic ALC202" },
328 { AC97_CODEC_ID('A', 'L', 'G', 0x50),
329 0xffffffff, "Advance Logic ALC250" },
330
331 /* Cirrus Logic, Crystal series:
332 * 'C' 'R' 'Y' 0x0[0-7] - CS4297
333 * 0x1[0-7] - CS4297A
334 * 0x2[0-7] - CS4298
335 * 0x2[8-f] - CS4294
336 * 0x3[0-7] - CS4299
337 * 0x4[8-f] - CS4201
338 * 0x5[8-f] - CS4205
339 * 0x6[0-7] - CS4291
340 * 0x7[0-7] - CS4202
341 * Datasheets:
342 * http://www.cirrus.com/pubs/cs4297A-5.pdf?DocumentID=593
343 * http://www.cirrus.com/pubs/cs4294.pdf?DocumentID=32
344 * http://www.cirrus.com/pubs/cs4299-5.pdf?DocumentID=594
345 * http://www.cirrus.com/pubs/cs4201-2.pdf?DocumentID=492
346 * http://www.cirrus.com/pubs/cs4205-2.pdf?DocumentID=492
347 * http://www.cirrus.com/pubs/cs4202-1.pdf?DocumentID=852
348 */
349 { AC97_CODEC_ID('C', 'R', 'Y', 0x00),
350 0xfffffff8, "Crystal CS4297", },
351 { AC97_CODEC_ID('C', 'R', 'Y', 0x10),
352 0xfffffff8, "Crystal CS4297A", },
353 { AC97_CODEC_ID('C', 'R', 'Y', 0x20),
354 0xfffffff8, "Crystal CS4298", },
355 { AC97_CODEC_ID('C', 'R', 'Y', 0x28),
356 0xfffffff8, "Crystal CS4294", },
357 { AC97_CODEC_ID('C', 'R', 'Y', 0x30),
358 0xfffffff8, "Crystal CS4299", },
359 { AC97_CODEC_ID('C', 'R', 'Y', 0x48),
360 0xfffffff8, "Crystal CS4201", },
361 { AC97_CODEC_ID('C', 'R', 'Y', 0x58),
362 0xfffffff8, "Crystal CS4205", },
363 { AC97_CODEC_ID('C', 'R', 'Y', 0x60),
364 0xfffffff8, "Crystal CS4291", },
365 { AC97_CODEC_ID('C', 'R', 'Y', 0x70),
366 0xfffffff8, "Crystal CS4202", },
367
368 { AC97_CODEC_ID('N', 'S', 'C', 49),
369 0xffffffff, "National Semiconductor LM4549", },
370 { AC97_CODEC_ID('S', 'I', 'L', 34),
371 0xffffffff, "Silicon Laboratory Si3036", },
372 { AC97_CODEC_ID('S', 'I', 'L', 35),
373 0xffffffff, "Silicon Laboratory Si3038", },
374 { AC97_CODEC_ID('T', 'R', 'A', 2),
375 0xffffffff, "TriTech TR28022", },
376 { AC97_CODEC_ID('T', 'R', 'A', 3),
377 0xffffffff, "TriTech TR28023", },
378 { AC97_CODEC_ID('T', 'R', 'A', 6),
379 0xffffffff, "TriTech TR28026", },
380 { AC97_CODEC_ID('T', 'R', 'A', 8),
381 0xffffffff, "TriTech TR28028", },
382 { AC97_CODEC_ID('T', 'R', 'A', 35),
383 0xffffffff, "TriTech TR28602", },
384 { AC97_CODEC_ID('W', 'M', 'L', 0),
385 0xffffffff, "Wolfson WM9704", },
386 { AC97_CODEC_ID('W', 'M', 'L', 3),
387 0xffffffff, "Wolfson WM9707", },
388 { AC97_CODEC_ID('Y', 'M', 'H', 0),
389 0xffffffff, "Yamaha YMF743-S", },
390 { AC97_CODEC_ID('Y', 'M', 'H', 3),
391 0xffffffff, "Yamaha YMF753-S", },
392 { 0x45838308, 0xffffffff, "ESS Technology ES1921", },
393 { 0x83847600, 0xffffffff, "SigmaTel STAC9700", },
394 { 0x83847604, 0xffffffff, "SigmaTel STAC9701/3/4/5", },
395 { 0x83847605, 0xffffffff, "SigmaTel STAC9704", },
396 { 0x83847608, 0xffffffff, "SigmaTel STAC9708", },
397 { 0x83847609, 0xffffffff, "SigmaTel STAC9721/23", },
398 { 0x83847644, 0xffffffff, "SigmaTel STAC9744/45", },
399 { 0x83847684, 0xffffffff, "SigmaTel STAC9783/84", },
400 { 0,
401 0, NULL, }
402 };
403
404 static const char * const ac97enhancement[] = {
405 "no 3D stereo",
406 "Analog Devices Phat Stereo",
407 "Creative",
408 "National Semi 3D",
409 "Yamaha Ymersion",
410 "BBE 3D",
411 "Crystal Semi 3D",
412 "Qsound QXpander",
413 "Spatializer 3D",
414 "SRS 3D",
415 "Platform Tech 3D",
416 "AKM 3D",
417 "Aureal",
418 "AZTECH 3D",
419 "Binaura 3D",
420 "ESS Technology",
421 "Harman International VMAx",
422 "Nvidea 3D",
423 "Philips Incredible Sound",
424 "Texas Instruments' 3D",
425 "VLSI Technology 3D",
426 "TriTech 3D",
427 "Realtek 3D",
428 "Samsung 3D",
429 "Wolfson Microelectronics 3D",
430 "Delta Integration 3D",
431 "SigmaTel 3D",
432 "Unknown 3D",
433 "Rockwell 3D",
434 "Unknown 3D",
435 "Unknown 3D",
436 "Unknown 3D",
437 };
438
439 static const char * const ac97feature[] = {
440 "dedicated mic channel",
441 "reserved",
442 "tone",
443 "simulated stereo",
444 "headphone",
445 "bass boost",
446 "18 bit DAC",
447 "20 bit DAC",
448 "18 bit ADC",
449 "20 bit ADC"
450 };
451
452
453 int ac97_str_equal __P((const char *, const char *));
454 void ac97_setup_source_info __P((struct ac97_softc *));
455 void ac97_read __P((struct ac97_softc *, u_int8_t, u_int16_t *));
456 void ac97_setup_defaults __P((struct ac97_softc *));
457 int ac97_write __P((struct ac97_softc *, u_int8_t, u_int16_t));
458
459 /* #define AC97_DEBUG 10 */
460
461 #ifdef AUDIO_DEBUG
462 #define DPRINTF(x) if (ac97debug) printf x
463 #define DPRINTFN(n,x) if (ac97debug>(n)) printf x
464 #ifdef AC97_DEBUG
465 int ac97debug = AC97_DEBUG;
466 #else
467 int ac97debug = 0;
468 #endif
469 #else
470 #define DPRINTF(x)
471 #define DPRINTFN(n,x)
472 #endif
473
474 void
475 ac97_read(as, reg, val)
476 struct ac97_softc *as;
477 u_int8_t reg;
478 u_int16_t *val;
479 {
480 int error;
481
482 if (as->host_flags & AC97_HOST_DONT_READ &&
483 (reg != AC97_REG_VENDOR_ID1 && reg != AC97_REG_VENDOR_ID2 &&
484 reg != AC97_REG_RESET)) {
485 *val = as->shadow_reg[reg >> 1];
486 return;
487 }
488
489 if ((error = as->host_if->read(as->host_if->arg, reg, val))) {
490 *val = as->shadow_reg[reg >> 1];
491 }
492 }
493
494 int
495 ac97_write(as, reg, val)
496 struct ac97_softc *as;
497 u_int8_t reg;
498 u_int16_t val;
499 {
500
501 as->shadow_reg[reg >> 1] = val;
502
503 return (as->host_if->write(as->host_if->arg, reg, val));
504 }
505
506 void
507 ac97_setup_defaults(as)
508 struct ac97_softc *as;
509 {
510 int idx;
511 const struct ac97_source_info *si;
512
513 memset(as->shadow_reg, 0, sizeof(as->shadow_reg));
514
515 for (idx = 0; idx < SOURCE_INFO_SIZE; idx++) {
516 si = &source_info[idx];
517 ac97_write(as, si->reg, si->default_value);
518 }
519 }
520
521 void
522 ac97_restore_shadow(self)
523 struct ac97_codec_if *self;
524 {
525 struct ac97_softc *as = (struct ac97_softc *) self;
526 int idx;
527 const struct ac97_source_info *si;
528
529 for (idx = 0; idx < SOURCE_INFO_SIZE; idx++) {
530 si = &source_info[idx];
531 ac97_write(as, si->reg, as->shadow_reg[si->reg >> 1]);
532 }
533 }
534
535 int
536 ac97_str_equal(a, b)
537 const char *a, *b;
538 {
539 return ((a == b) || (a && b && (!strcmp(a, b))));
540 }
541
542 void
543 ac97_setup_source_info(as)
544 struct ac97_softc *as;
545 {
546 int idx, ouridx;
547 struct ac97_source_info *si, *si2;
548
549 for (idx = 0, ouridx = 0; idx < SOURCE_INFO_SIZE; idx++) {
550 si = &as->source_info[ouridx];
551
552 memcpy(si, &source_info[idx], sizeof(*si));
553
554 switch (si->type) {
555 case AUDIO_MIXER_CLASS:
556 si->mixer_class = ouridx;
557 ouridx++;
558 break;
559 case AUDIO_MIXER_VALUE:
560 /* Todo - Test to see if it works */
561 ouridx++;
562
563 /* Add an entry for mute, if necessary */
564 if (si->mute) {
565 si = &as->source_info[ouridx];
566 memcpy(si, &source_info[idx], sizeof(*si));
567 si->qualifier = AudioNmute;
568 si->type = AUDIO_MIXER_ENUM;
569 si->info = &ac97_on_off;
570 si->info_size = sizeof(ac97_on_off);
571 si->bits = 1;
572 si->ofs = 15;
573 si->mute = 0;
574 si->polarity = 0;
575 ouridx++;
576 }
577 break;
578 case AUDIO_MIXER_ENUM:
579 /* Todo - Test to see if it works */
580 ouridx++;
581 break;
582 default:
583 printf ("ac97: shouldn't get here\n");
584 break;
585 }
586 }
587
588 as->num_source_info = ouridx;
589
590 for (idx = 0; idx < as->num_source_info; idx++) {
591 int idx2, previdx;
592
593 si = &as->source_info[idx];
594
595 /* Find mixer class */
596 for (idx2 = 0; idx2 < as->num_source_info; idx2++) {
597 si2 = &as->source_info[idx2];
598
599 if (si2->type == AUDIO_MIXER_CLASS &&
600 ac97_str_equal(si->class,
601 si2->class)) {
602 si->mixer_class = idx2;
603 }
604 }
605
606
607 /* Setup prev and next pointers */
608 if (si->prev != 0)
609 continue;
610
611 if (si->qualifier)
612 continue;
613
614 si->prev = AUDIO_MIXER_LAST;
615 previdx = idx;
616
617 for (idx2 = 0; idx2 < as->num_source_info; idx2++) {
618 if (idx2 == idx)
619 continue;
620
621 si2 = &as->source_info[idx2];
622
623 if (!si2->prev &&
624 ac97_str_equal(si->class, si2->class) &&
625 ac97_str_equal(si->device, si2->device)) {
626 as->source_info[previdx].next = idx2;
627 as->source_info[idx2].prev = previdx;
628
629 previdx = idx2;
630 }
631 }
632
633 as->source_info[previdx].next = AUDIO_MIXER_LAST;
634 }
635 }
636
637 int
638 ac97_attach(host_if)
639 struct ac97_host_if *host_if;
640 {
641 struct ac97_softc *as;
642 struct device *sc_dev = (struct device *)host_if->arg;
643 int error, i, j;
644 u_int32_t id;
645 u_int16_t id1, id2;
646 u_int16_t extstat, rate;
647 mixer_ctrl_t ctl;
648 const char *delim;
649
650 as = malloc(sizeof(struct ac97_softc), M_DEVBUF, M_WAITOK|M_ZERO);
651
652 if (as == NULL)
653 return (ENOMEM);
654
655 as->codec_if.vtbl = &ac97civ;
656 as->host_if = host_if;
657
658 if ((error = host_if->attach(host_if->arg, &as->codec_if))) {
659 free (as, M_DEVBUF);
660 return (error);
661 }
662
663 host_if->reset(host_if->arg);
664
665 host_if->write(host_if->arg, AC97_REG_POWER, 0);
666 host_if->write(host_if->arg, AC97_REG_RESET, 0);
667
668 if (host_if->flags)
669 as->host_flags = host_if->flags(host_if->arg);
670
671 ac97_setup_defaults(as);
672 ac97_read(as, AC97_REG_VENDOR_ID1, &id1);
673 ac97_read(as, AC97_REG_VENDOR_ID2, &id2);
674 ac97_read(as, AC97_REG_RESET, &as->caps);
675
676 id = (id1 << 16) | id2;
677
678 printf("%s: ", sc_dev->dv_xname);
679
680 for (i = 0; ; i++) {
681 if (ac97codecid[i].id == 0) {
682 char pnp[4];
683
684 AC97_GET_CODEC_ID(id, pnp);
685 #define ISASCII(c) ((c) >= ' ' && (c) < 0x7f)
686 if (ISASCII(pnp[0]) && ISASCII(pnp[1]) &&
687 ISASCII(pnp[2]))
688 printf("%c%c%c%d", pnp[0], pnp[1], pnp[2],
689 pnp[3]);
690 else
691 printf("unknown (0x%08x)", id);
692 break;
693 }
694 if (ac97codecid[i].id == (id & ac97codecid[i].mask)) {
695 printf("%s", ac97codecid[i].name);
696 break;
697 }
698 }
699 printf(" codec; ");
700 for (i = j = 0; i < 10; i++) {
701 if (as->caps & (1 << i)) {
702 printf("%s%s", j? ", " : "", ac97feature[i]);
703 j++;
704 }
705 }
706 printf("%s%s\n", j ? ", " : "",
707 ac97enhancement[(as->caps >> 10) & 0x1f]);
708
709 as->ac97_clock = AC97_STANDARD_CLOCK;
710 ac97_read(as, AC97_REG_EXT_AUDIO_ID, &as->ext_id);
711 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA
712 | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM
713 | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC
714 | AC97_EXT_AUDIO_LDAC)) {
715 printf("%s:", sc_dev->dv_xname);
716 delim = "";
717
718 if (as->ext_id & AC97_EXT_AUDIO_VRA) {
719 printf("%s variable rate audio", delim);
720 delim = ",";
721 }
722 if (as->ext_id & AC97_EXT_AUDIO_DRA) {
723 printf("%s double rate output", delim);
724 delim = ",";
725 }
726 if (as->ext_id & AC97_EXT_AUDIO_SPDIF) {
727 printf("%s S/PDIF", delim);
728 delim = ",";
729 }
730 if (as->ext_id & AC97_EXT_AUDIO_VRM) {
731 printf("%s variable rate dedicated mic", delim);
732 delim = ",";
733 }
734 if (as->ext_id & AC97_EXT_AUDIO_CDAC) {
735 printf("%s center DAC", delim);
736 delim = ",";
737 }
738 if (as->ext_id & AC97_EXT_AUDIO_SDAC) {
739 printf("%s surround DAC", delim);
740 delim = ",";
741 }
742 if (as->ext_id & AC97_EXT_AUDIO_LDAC) {
743 printf("%s LFE DAC", delim);
744 }
745 printf("\n");
746
747 /* If VRA and/or VRM capablities, enable them. */
748 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_VRM)) {
749 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat);
750 if (as->ext_id & AC97_EXT_AUDIO_VRA) {
751 extstat |= AC97_EXT_AUDIO_VRA;
752 }
753 if (as->ext_id & AC97_EXT_AUDIO_VRM) {
754 extstat |= AC97_EXT_AUDIO_VRM;
755 }
756 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat);
757
758 /* so it claims to do variable rate, let's make sure */
759 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE, 44100);
760 ac97_read(as, AC97_REG_PCM_FRONT_DAC_RATE, &rate);
761 if (rate != 44100) {
762 /* We can't believe ext_id */
763 as->ext_id = 0;
764 printf("%s: Ignore these capabilities.\n",
765 sc_dev->dv_xname);
766 }
767 }
768 }
769
770 ac97_setup_source_info(as);
771
772 /* Just enable the DAC and master volumes by default */
773 memset(&ctl, 0, sizeof(ctl));
774
775 ctl.type = AUDIO_MIXER_ENUM;
776 ctl.un.ord = 0; /* off */
777 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
778 AudioNmaster, AudioNmute);
779 ac97_mixer_set_port(&as->codec_if, &ctl);
780 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCinputs,
781 AudioNdac, AudioNmute);
782
783 ac97_mixer_set_port(&as->codec_if, &ctl);
784 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
785 AudioNvolume, AudioNmute);
786 ac97_mixer_set_port(&as->codec_if, &ctl);
787
788 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
789 AudioNsource, NULL);
790 ctl.type = AUDIO_MIXER_ENUM;
791 ctl.un.ord = 0;
792 ac97_mixer_set_port(&as->codec_if, &ctl);
793
794 return (0);
795 }
796
797
798 int
799 ac97_query_devinfo(codec_if, dip)
800 struct ac97_codec_if *codec_if;
801 mixer_devinfo_t *dip;
802 {
803 struct ac97_softc *as = (struct ac97_softc *)codec_if;
804
805 if (dip->index < as->num_source_info) {
806 struct ac97_source_info *si = &as->source_info[dip->index];
807 const char *name;
808
809 dip->type = si->type;
810 dip->mixer_class = si->mixer_class;
811 dip->prev = si->prev;
812 dip->next = si->next;
813
814 if (si->qualifier)
815 name = si->qualifier;
816 else if (si->device)
817 name = si->device;
818 else if (si->class)
819 name = si->class;
820 else
821 name = 0;
822
823 if (name)
824 strcpy(dip->label.name, name);
825
826 memcpy(&dip->un, si->info, si->info_size);
827
828 /* Set the delta for volume sources */
829 if (dip->type == AUDIO_MIXER_VALUE)
830 dip->un.v.delta = 1 << (8 - si->bits);
831
832 return (0);
833 }
834
835 return (ENXIO);
836 }
837
838
839
840 int
841 ac97_mixer_set_port(codec_if, cp)
842 struct ac97_codec_if *codec_if;
843 mixer_ctrl_t *cp;
844 {
845 struct ac97_softc *as = (struct ac97_softc *)codec_if;
846 struct ac97_source_info *si = &as->source_info[cp->dev];
847 u_int16_t mask;
848 u_int16_t val, newval;
849 int error;
850
851 if (cp->dev < 0 || cp->dev >= as->num_source_info)
852 return (EINVAL);
853
854 if (cp->type != si->type)
855 return (EINVAL);
856
857 ac97_read(as, si->reg, &val);
858
859 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
860
861 mask = (1 << si->bits) - 1;
862
863 switch (cp->type) {
864 case AUDIO_MIXER_ENUM:
865 if (cp->un.ord > mask || cp->un.ord < 0)
866 return (EINVAL);
867
868 newval = (cp->un.ord << si->ofs);
869 if (si->reg == AC97_REG_RECORD_SELECT) {
870 newval |= (newval << (8 + si->ofs));
871 mask |= (mask << 8);
872 }
873 break;
874 case AUDIO_MIXER_VALUE:
875 {
876 const struct audio_mixer_value *value = si->info;
877 u_int16_t l, r;
878
879 if ((cp->un.value.num_channels <= 0) ||
880 (cp->un.value.num_channels > value->num_channels))
881 return (EINVAL);
882
883 if (cp->un.value.num_channels == 1) {
884 l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
885 } else {
886 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
887 l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
888 r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
889 } else { /* left/right is reversed here */
890 r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
891 l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
892 }
893
894 }
895
896 if (!si->polarity) {
897 l = 255 - l;
898 r = 255 - r;
899 }
900
901 l = l >> (8 - si->bits);
902 r = r >> (8 - si->bits);
903
904 newval = ((l & mask) << si->ofs);
905 if (value->num_channels == 2) {
906 newval |= ((r & mask) << (si->ofs + 8));
907 mask |= (mask << 8);
908 }
909
910 break;
911 }
912 default:
913 return (EINVAL);
914 }
915
916 mask = mask << si->ofs;
917 error = ac97_write(as, si->reg, (val & ~mask) | newval);
918 if (error)
919 return (error);
920
921 return (0);
922 }
923
924 int
925 ac97_get_portnum_by_name(codec_if, class, device, qualifier)
926 struct ac97_codec_if *codec_if;
927 char *class, *device, *qualifier;
928 {
929 struct ac97_softc *as = (struct ac97_softc *)codec_if;
930 int idx;
931
932 for (idx = 0; idx < as->num_source_info; idx++) {
933 struct ac97_source_info *si = &as->source_info[idx];
934 if (ac97_str_equal(class, si->class) &&
935 ac97_str_equal(device, si->device) &&
936 ac97_str_equal(qualifier, si->qualifier))
937 return (idx);
938 }
939
940 return (-1);
941 }
942
943 int
944 ac97_mixer_get_port(codec_if, cp)
945 struct ac97_codec_if *codec_if;
946 mixer_ctrl_t *cp;
947 {
948 struct ac97_softc *as = (struct ac97_softc *)codec_if;
949 struct ac97_source_info *si = &as->source_info[cp->dev];
950 u_int16_t mask;
951 u_int16_t val;
952
953 if (cp->dev < 0 || cp->dev >= as->num_source_info)
954 return (EINVAL);
955
956 if (cp->type != si->type)
957 return (EINVAL);
958
959 ac97_read(as, si->reg, &val);
960
961 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
962
963 mask = (1 << si->bits) - 1;
964
965 switch (cp->type) {
966 case AUDIO_MIXER_ENUM:
967 cp->un.ord = (val >> si->ofs) & mask;
968 DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n", val, si->ofs, mask, cp->un.ord));
969 break;
970 case AUDIO_MIXER_VALUE:
971 {
972 const struct audio_mixer_value *value = si->info;
973 u_int16_t l, r;
974
975 if ((cp->un.value.num_channels <= 0) ||
976 (cp->un.value.num_channels > value->num_channels))
977 return (EINVAL);
978
979 if (value->num_channels == 1) {
980 l = r = (val >> si->ofs) & mask;
981 } else {
982 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
983 l = (val >> si->ofs) & mask;
984 r = (val >> (si->ofs + 8)) & mask;
985 } else { /* host has reversed channels */
986 r = (val >> si->ofs) & mask;
987 l = (val >> (si->ofs + 8)) & mask;
988 }
989 }
990
991 l = (l << (8 - si->bits));
992 r = (r << (8 - si->bits));
993 if (!si->polarity) {
994 l = 255 - l;
995 r = 255 - r;
996 }
997
998 /* The EAP driver averages l and r for stereo
999 channels that are requested in MONO mode. Does this
1000 make sense? */
1001 if (cp->un.value.num_channels == 1) {
1002 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l;
1003 } else if (cp->un.value.num_channels == 2) {
1004 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
1005 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
1006 }
1007
1008 break;
1009 }
1010 default:
1011 return (EINVAL);
1012 }
1013
1014 return (0);
1015 }
1016
1017
1018 int
1019 ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_long *rate)
1020 {
1021 struct ac97_softc *as;
1022 u_long value;
1023 u_int16_t ext_stat;
1024 u_int16_t actual;
1025 u_int16_t power;
1026 u_int16_t power_bit;
1027
1028 as = (struct ac97_softc *)codec_if;
1029 if (target == AC97_REG_PCM_MIC_ADC_RATE) {
1030 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1031 *rate = AC97_SINGLE_RATE;
1032 return 0;
1033 }
1034 } else {
1035 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1036 *rate = AC97_SINGLE_RATE;
1037 return 0;
1038 }
1039 }
1040 value = *rate * AC97_STANDARD_CLOCK / as->ac97_clock;
1041 ext_stat = 0;
1042 /*
1043 * PCM_FRONT_DAC_RATE/PCM_SURR_DAC_RATE/PCM_LFE_DAC_RATE
1044 * Check VRA, DRA
1045 * PCM_LR_ADC_RATE
1046 * Check VRA
1047 * PCM_MIC_ADC_RATE
1048 * Check VRM
1049 */
1050 switch (target) {
1051 case AC97_REG_PCM_FRONT_DAC_RATE:
1052 case AC97_REG_PCM_SURR_DAC_RATE:
1053 case AC97_REG_PCM_LFE_DAC_RATE:
1054 power_bit = AC97_POWER_OUT;
1055 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1056 *rate = AC97_SINGLE_RATE;
1057 return 0;
1058 }
1059 if (as->ext_id & AC97_EXT_AUDIO_DRA) {
1060 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &ext_stat);
1061 if (value > 0x1ffff) {
1062 return EINVAL;
1063 } else if (value > 0xffff) {
1064 /* Enable DRA */
1065 ext_stat |= AC97_EXT_AUDIO_DRA;
1066 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1067 value /= 2;
1068 } else {
1069 /* Disable DRA */
1070 ext_stat &= ~AC97_EXT_AUDIO_DRA;
1071 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1072 }
1073 } else {
1074 if (value > 0xffff)
1075 return EINVAL;
1076 }
1077 break;
1078 case AC97_REG_PCM_LR_ADC_RATE:
1079 power_bit = AC97_POWER_IN;
1080 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1081 *rate = AC97_SINGLE_RATE;
1082 return 0;
1083 }
1084 if (value > 0xffff)
1085 return EINVAL;
1086 break;
1087 case AC97_REG_PCM_MIC_ADC_RATE:
1088 power_bit = AC97_POWER_IN;
1089 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1090 *rate = AC97_SINGLE_RATE;
1091 return 0;
1092 }
1093 if (value > 0xffff)
1094 return EINVAL;
1095 break;
1096 default:
1097 printf("%s: Unknown register: 0x%x\n", __func__, target);
1098 return EINVAL;
1099 }
1100
1101 ac97_read(as, AC97_REG_POWER, &power);
1102 ac97_write(as, AC97_REG_POWER, power | power_bit);
1103
1104 ac97_write(as, target, (u_int16_t)value);
1105 ac97_read(as, target, &actual);
1106 actual = (u_int32_t)actual * as->ac97_clock / AC97_STANDARD_CLOCK;
1107
1108 ac97_write(as, AC97_REG_POWER, power);
1109 if (ext_stat & AC97_EXT_AUDIO_DRA) {
1110 *rate = actual * 2;
1111 } else {
1112 *rate = actual;
1113 }
1114 return 0;
1115 }
1116
1117 void
1118 ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock)
1119 {
1120 struct ac97_softc *as;
1121
1122 as = (struct ac97_softc *)codec_if;
1123 as->ac97_clock = clock;
1124 }
1125
1126 u_int16_t
1127 ac97_get_extcaps(struct ac97_codec_if *codec_if)
1128 {
1129 struct ac97_softc *as;
1130
1131 as = (struct ac97_softc *)codec_if;
1132 return as->ext_id;
1133 }
1134