ac97.c revision 1.32 1 /* $NetBSD: ac97.c,v 1.32 2002/10/11 02:32:23 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.32 2002/10/11 02:32:23 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 /* restore the default value */
768 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE,
769 AC97_SINGLE_RATE);
770 }
771 }
772
773 ac97_setup_source_info(as);
774
775 /* Just enable the DAC and master volumes by default */
776 memset(&ctl, 0, sizeof(ctl));
777
778 ctl.type = AUDIO_MIXER_ENUM;
779 ctl.un.ord = 0; /* off */
780 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
781 AudioNmaster, AudioNmute);
782 ac97_mixer_set_port(&as->codec_if, &ctl);
783 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCinputs,
784 AudioNdac, AudioNmute);
785
786 ac97_mixer_set_port(&as->codec_if, &ctl);
787 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
788 AudioNvolume, AudioNmute);
789 ac97_mixer_set_port(&as->codec_if, &ctl);
790
791 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
792 AudioNsource, NULL);
793 ctl.type = AUDIO_MIXER_ENUM;
794 ctl.un.ord = 0;
795 ac97_mixer_set_port(&as->codec_if, &ctl);
796
797 return (0);
798 }
799
800
801 int
802 ac97_query_devinfo(codec_if, dip)
803 struct ac97_codec_if *codec_if;
804 mixer_devinfo_t *dip;
805 {
806 struct ac97_softc *as = (struct ac97_softc *)codec_if;
807
808 if (dip->index < as->num_source_info) {
809 struct ac97_source_info *si = &as->source_info[dip->index];
810 const char *name;
811
812 dip->type = si->type;
813 dip->mixer_class = si->mixer_class;
814 dip->prev = si->prev;
815 dip->next = si->next;
816
817 if (si->qualifier)
818 name = si->qualifier;
819 else if (si->device)
820 name = si->device;
821 else if (si->class)
822 name = si->class;
823 else
824 name = 0;
825
826 if (name)
827 strcpy(dip->label.name, name);
828
829 memcpy(&dip->un, si->info, si->info_size);
830
831 /* Set the delta for volume sources */
832 if (dip->type == AUDIO_MIXER_VALUE)
833 dip->un.v.delta = 1 << (8 - si->bits);
834
835 return (0);
836 }
837
838 return (ENXIO);
839 }
840
841
842
843 int
844 ac97_mixer_set_port(codec_if, cp)
845 struct ac97_codec_if *codec_if;
846 mixer_ctrl_t *cp;
847 {
848 struct ac97_softc *as = (struct ac97_softc *)codec_if;
849 struct ac97_source_info *si = &as->source_info[cp->dev];
850 u_int16_t mask;
851 u_int16_t val, newval;
852 int error;
853
854 if (cp->dev < 0 || cp->dev >= as->num_source_info)
855 return (EINVAL);
856
857 if (cp->type != si->type)
858 return (EINVAL);
859
860 ac97_read(as, si->reg, &val);
861
862 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
863
864 mask = (1 << si->bits) - 1;
865
866 switch (cp->type) {
867 case AUDIO_MIXER_ENUM:
868 if (cp->un.ord > mask || cp->un.ord < 0)
869 return (EINVAL);
870
871 newval = (cp->un.ord << si->ofs);
872 if (si->reg == AC97_REG_RECORD_SELECT) {
873 newval |= (newval << (8 + si->ofs));
874 mask |= (mask << 8);
875 }
876 break;
877 case AUDIO_MIXER_VALUE:
878 {
879 const struct audio_mixer_value *value = si->info;
880 u_int16_t l, r;
881
882 if ((cp->un.value.num_channels <= 0) ||
883 (cp->un.value.num_channels > value->num_channels))
884 return (EINVAL);
885
886 if (cp->un.value.num_channels == 1) {
887 l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
888 } else {
889 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
890 l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
891 r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
892 } else { /* left/right is reversed here */
893 r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
894 l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
895 }
896
897 }
898
899 if (!si->polarity) {
900 l = 255 - l;
901 r = 255 - r;
902 }
903
904 l = l >> (8 - si->bits);
905 r = r >> (8 - si->bits);
906
907 newval = ((l & mask) << si->ofs);
908 if (value->num_channels == 2) {
909 newval |= ((r & mask) << (si->ofs + 8));
910 mask |= (mask << 8);
911 }
912
913 break;
914 }
915 default:
916 return (EINVAL);
917 }
918
919 mask = mask << si->ofs;
920 error = ac97_write(as, si->reg, (val & ~mask) | newval);
921 if (error)
922 return (error);
923
924 return (0);
925 }
926
927 int
928 ac97_get_portnum_by_name(codec_if, class, device, qualifier)
929 struct ac97_codec_if *codec_if;
930 char *class, *device, *qualifier;
931 {
932 struct ac97_softc *as = (struct ac97_softc *)codec_if;
933 int idx;
934
935 for (idx = 0; idx < as->num_source_info; idx++) {
936 struct ac97_source_info *si = &as->source_info[idx];
937 if (ac97_str_equal(class, si->class) &&
938 ac97_str_equal(device, si->device) &&
939 ac97_str_equal(qualifier, si->qualifier))
940 return (idx);
941 }
942
943 return (-1);
944 }
945
946 int
947 ac97_mixer_get_port(codec_if, cp)
948 struct ac97_codec_if *codec_if;
949 mixer_ctrl_t *cp;
950 {
951 struct ac97_softc *as = (struct ac97_softc *)codec_if;
952 struct ac97_source_info *si = &as->source_info[cp->dev];
953 u_int16_t mask;
954 u_int16_t val;
955
956 if (cp->dev < 0 || cp->dev >= as->num_source_info)
957 return (EINVAL);
958
959 if (cp->type != si->type)
960 return (EINVAL);
961
962 ac97_read(as, si->reg, &val);
963
964 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
965
966 mask = (1 << si->bits) - 1;
967
968 switch (cp->type) {
969 case AUDIO_MIXER_ENUM:
970 cp->un.ord = (val >> si->ofs) & mask;
971 DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n", val, si->ofs, mask, cp->un.ord));
972 break;
973 case AUDIO_MIXER_VALUE:
974 {
975 const struct audio_mixer_value *value = si->info;
976 u_int16_t l, r;
977
978 if ((cp->un.value.num_channels <= 0) ||
979 (cp->un.value.num_channels > value->num_channels))
980 return (EINVAL);
981
982 if (value->num_channels == 1) {
983 l = r = (val >> si->ofs) & mask;
984 } else {
985 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
986 l = (val >> si->ofs) & mask;
987 r = (val >> (si->ofs + 8)) & mask;
988 } else { /* host has reversed channels */
989 r = (val >> si->ofs) & mask;
990 l = (val >> (si->ofs + 8)) & mask;
991 }
992 }
993
994 l = (l << (8 - si->bits));
995 r = (r << (8 - si->bits));
996 if (!si->polarity) {
997 l = 255 - l;
998 r = 255 - r;
999 }
1000
1001 /* The EAP driver averages l and r for stereo
1002 channels that are requested in MONO mode. Does this
1003 make sense? */
1004 if (cp->un.value.num_channels == 1) {
1005 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l;
1006 } else if (cp->un.value.num_channels == 2) {
1007 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
1008 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
1009 }
1010
1011 break;
1012 }
1013 default:
1014 return (EINVAL);
1015 }
1016
1017 return (0);
1018 }
1019
1020
1021 int
1022 ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_long *rate)
1023 {
1024 struct ac97_softc *as;
1025 u_long value;
1026 u_int16_t ext_stat;
1027 u_int16_t actual;
1028 u_int16_t power;
1029 u_int16_t power_bit;
1030
1031 as = (struct ac97_softc *)codec_if;
1032 if (target == AC97_REG_PCM_MIC_ADC_RATE) {
1033 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1034 *rate = AC97_SINGLE_RATE;
1035 return 0;
1036 }
1037 } else {
1038 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1039 *rate = AC97_SINGLE_RATE;
1040 return 0;
1041 }
1042 }
1043 value = *rate * AC97_STANDARD_CLOCK / as->ac97_clock;
1044 ext_stat = 0;
1045 /*
1046 * PCM_FRONT_DAC_RATE/PCM_SURR_DAC_RATE/PCM_LFE_DAC_RATE
1047 * Check VRA, DRA
1048 * PCM_LR_ADC_RATE
1049 * Check VRA
1050 * PCM_MIC_ADC_RATE
1051 * Check VRM
1052 */
1053 switch (target) {
1054 case AC97_REG_PCM_FRONT_DAC_RATE:
1055 case AC97_REG_PCM_SURR_DAC_RATE:
1056 case AC97_REG_PCM_LFE_DAC_RATE:
1057 power_bit = AC97_POWER_OUT;
1058 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1059 *rate = AC97_SINGLE_RATE;
1060 return 0;
1061 }
1062 if (as->ext_id & AC97_EXT_AUDIO_DRA) {
1063 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &ext_stat);
1064 if (value > 0x1ffff) {
1065 return EINVAL;
1066 } else if (value > 0xffff) {
1067 /* Enable DRA */
1068 ext_stat |= AC97_EXT_AUDIO_DRA;
1069 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1070 value /= 2;
1071 } else {
1072 /* Disable DRA */
1073 ext_stat &= ~AC97_EXT_AUDIO_DRA;
1074 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1075 }
1076 } else {
1077 if (value > 0xffff)
1078 return EINVAL;
1079 }
1080 break;
1081 case AC97_REG_PCM_LR_ADC_RATE:
1082 power_bit = AC97_POWER_IN;
1083 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1084 *rate = AC97_SINGLE_RATE;
1085 return 0;
1086 }
1087 if (value > 0xffff)
1088 return EINVAL;
1089 break;
1090 case AC97_REG_PCM_MIC_ADC_RATE:
1091 power_bit = AC97_POWER_IN;
1092 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1093 *rate = AC97_SINGLE_RATE;
1094 return 0;
1095 }
1096 if (value > 0xffff)
1097 return EINVAL;
1098 break;
1099 default:
1100 printf("%s: Unknown register: 0x%x\n", __func__, target);
1101 return EINVAL;
1102 }
1103
1104 ac97_read(as, AC97_REG_POWER, &power);
1105 ac97_write(as, AC97_REG_POWER, power | power_bit);
1106
1107 ac97_write(as, target, (u_int16_t)value);
1108 ac97_read(as, target, &actual);
1109 actual = (u_int32_t)actual * as->ac97_clock / AC97_STANDARD_CLOCK;
1110
1111 ac97_write(as, AC97_REG_POWER, power);
1112 if (ext_stat & AC97_EXT_AUDIO_DRA) {
1113 *rate = actual * 2;
1114 } else {
1115 *rate = actual;
1116 }
1117 return 0;
1118 }
1119
1120 void
1121 ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock)
1122 {
1123 struct ac97_softc *as;
1124
1125 as = (struct ac97_softc *)codec_if;
1126 as->ac97_clock = clock;
1127 }
1128
1129 u_int16_t
1130 ac97_get_extcaps(struct ac97_codec_if *codec_if)
1131 {
1132 struct ac97_softc *as;
1133
1134 as = (struct ac97_softc *)codec_if;
1135 return as->ext_id;
1136 }
1137