ac97.c revision 1.29 1 /* $NetBSD: ac97.c,v 1.29 2002/10/08 12:33:34 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.29 2002/10/08 12:33:34 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 const char *name;
302 } ac97codecid[] = {
303 { AC97_CODEC_ID('A', 'D', 'S', 3), "Analog Devices AD1819B" },
304 { AC97_CODEC_ID('A', 'D', 'S', 64), "Analog Devices AD1881" },
305 { AC97_CODEC_ID('A', 'D', 'S', 72), "Analog Devices AD1881A" },
306 { AC97_CODEC_ID('A', 'D', 'S', 96), "Analog Devices AD1885" },
307 { AC97_CODEC_ID('A', 'D', 'S', 99), "Analog Devices AD1886A" },
308 { AC97_CODEC_ID('A', 'K', 'M', 0), "Asahi Kasei AK4540" },
309 { AC97_CODEC_ID('A', 'K', 'M', 2), "Asahi Kasei AK4543" },
310 { AC97_CODEC_ID('A', 'L', 'G', 16), "Advance Logic ALC200" },
311 { AC97_CODEC_ID('A', 'L', 'G', 32), "Advance Logic ALC650" },
312 { AC97_CODEC_ID('A', 'L', 'G', 48), "Advance Logic ALC101" },
313 { AC97_CODEC_ID('A', 'L', 'G', 64), "Advance Logic ALC202" },
314 { AC97_CODEC_ID('A', 'L', 'G', 80), "Advance Logic ALC250" },
315 { AC97_CODEC_ID('C', 'R', 'Y', 0), "Crystal CS4297" },
316 { AC97_CODEC_ID('C', 'R', 'Y', 3), "Crystal CS4297" },
317 { AC97_CODEC_ID('C', 'R', 'Y', 19), "Crystal CS4297A" },
318 { AC97_CODEC_ID('C', 'R', 'Y', 35), "Crystal CS4298", },
319 { AC97_CODEC_ID('C', 'R', 'Y', 43), "Crystal CS4294", },
320 { AC97_CODEC_ID('C', 'R', 'Y', 49), "Crystal CS4299", },
321 { AC97_CODEC_ID('C', 'R', 'Y', 51), "Crystal CS4298A", },
322 { AC97_CODEC_ID('C', 'R', 'Y', 52), "Crystal CS4299", },
323 { AC97_CODEC_ID('N', 'S', 'C', 49), "National Semiconductor LM4549", },
324 { AC97_CODEC_ID('S', 'I', 'L', 34), "Silicon Laboratory Si3036", },
325 { AC97_CODEC_ID('S', 'I', 'L', 35), "Silicon Laboratory Si3038", },
326 { AC97_CODEC_ID('T', 'R', 'A', 2), "TriTech TR28022", },
327 { AC97_CODEC_ID('T', 'R', 'A', 3), "TriTech TR28023", },
328 { AC97_CODEC_ID('T', 'R', 'A', 6), "TriTech TR28026", },
329 { AC97_CODEC_ID('T', 'R', 'A', 8), "TriTech TR28028", },
330 { AC97_CODEC_ID('T', 'R', 'A', 35), "TriTech unknown", },
331 { AC97_CODEC_ID('W', 'M', 'L', 0), "Wolfson WM9704", },
332 { AC97_CODEC_ID('W', 'M', 'L', 3), "Wolfson WM9707", },
333 { AC97_CODEC_ID('Y', 'M', 'H', 0), "Yamaha YMF743-S", },
334 { AC97_CODEC_ID('Y', 'M', 'H', 3), "Yamaha YMF753-S", },
335 { 0x45838308, "ESS Technology ES1921", },
336 { 0x83847600, "SigmaTel STAC9700", },
337 { 0x83847604, "SigmaTel STAC9701/3/4/5", },
338 { 0x83847605, "SigmaTel STAC9704", },
339 { 0x83847608, "SigmaTel STAC9708", },
340 { 0x83847609, "SigmaTel STAC9721/23", },
341 { 0x83847644, "SigmaTel STAC9744/45", },
342 { 0x83847684, "SigmaTel STAC9783/84", },
343 { 0, NULL, }
344 };
345
346 static const char * const ac97enhancement[] = {
347 "no 3D stereo",
348 "Analog Devices Phat Stereo",
349 "Creative",
350 "National Semi 3D",
351 "Yamaha Ymersion",
352 "BBE 3D",
353 "Crystal Semi 3D",
354 "Qsound QXpander",
355 "Spatializer 3D",
356 "SRS 3D",
357 "Platform Tech 3D",
358 "AKM 3D",
359 "Aureal",
360 "AZTECH 3D",
361 "Binaura 3D",
362 "ESS Technology",
363 "Harman International VMAx",
364 "Nvidea 3D",
365 "Philips Incredible Sound",
366 "Texas Instruments' 3D",
367 "VLSI Technology 3D",
368 "TriTech 3D",
369 "Realtek 3D",
370 "Samsung 3D",
371 "Wolfson Microelectronics 3D",
372 "Delta Integration 3D",
373 "SigmaTel 3D",
374 "Unknown 3D",
375 "Rockwell 3D",
376 "Unknown 3D",
377 "Unknown 3D",
378 "Unknown 3D",
379 };
380
381 static const char * const ac97feature[] = {
382 "dedicated mic channel",
383 "reserved",
384 "tone",
385 "simulated stereo",
386 "headphone",
387 "bass boost",
388 "18 bit DAC",
389 "20 bit DAC",
390 "18 bit ADC",
391 "20 bit ADC"
392 };
393
394
395 int ac97_str_equal __P((const char *, const char *));
396 void ac97_setup_source_info __P((struct ac97_softc *));
397 void ac97_read __P((struct ac97_softc *, u_int8_t, u_int16_t *));
398 void ac97_setup_defaults __P((struct ac97_softc *));
399 int ac97_write __P((struct ac97_softc *, u_int8_t, u_int16_t));
400
401 /* #define AC97_DEBUG 10 */
402
403 #ifdef AUDIO_DEBUG
404 #define DPRINTF(x) if (ac97debug) printf x
405 #define DPRINTFN(n,x) if (ac97debug>(n)) printf x
406 #ifdef AC97_DEBUG
407 int ac97debug = AC97_DEBUG;
408 #else
409 int ac97debug = 0;
410 #endif
411 #else
412 #define DPRINTF(x)
413 #define DPRINTFN(n,x)
414 #endif
415
416 void
417 ac97_read(as, reg, val)
418 struct ac97_softc *as;
419 u_int8_t reg;
420 u_int16_t *val;
421 {
422 int error;
423
424 if (as->host_flags & AC97_HOST_DONT_READ &&
425 (reg != AC97_REG_VENDOR_ID1 && reg != AC97_REG_VENDOR_ID2 &&
426 reg != AC97_REG_RESET)) {
427 *val = as->shadow_reg[reg >> 1];
428 return;
429 }
430
431 if ((error = as->host_if->read(as->host_if->arg, reg, val))) {
432 *val = as->shadow_reg[reg >> 1];
433 }
434 }
435
436 int
437 ac97_write(as, reg, val)
438 struct ac97_softc *as;
439 u_int8_t reg;
440 u_int16_t val;
441 {
442
443 as->shadow_reg[reg >> 1] = val;
444
445 return (as->host_if->write(as->host_if->arg, reg, val));
446 }
447
448 void
449 ac97_setup_defaults(as)
450 struct ac97_softc *as;
451 {
452 int idx;
453 const struct ac97_source_info *si;
454
455 memset(as->shadow_reg, 0, sizeof(as->shadow_reg));
456
457 for (idx = 0; idx < SOURCE_INFO_SIZE; idx++) {
458 si = &source_info[idx];
459 ac97_write(as, si->reg, si->default_value);
460 }
461 }
462
463 void
464 ac97_restore_shadow(self)
465 struct ac97_codec_if *self;
466 {
467 struct ac97_softc *as = (struct ac97_softc *) self;
468 int idx;
469 const struct ac97_source_info *si;
470
471 for (idx = 0; idx < SOURCE_INFO_SIZE; idx++) {
472 si = &source_info[idx];
473 ac97_write(as, si->reg, as->shadow_reg[si->reg >> 1]);
474 }
475 }
476
477 int
478 ac97_str_equal(a, b)
479 const char *a, *b;
480 {
481 return ((a == b) || (a && b && (!strcmp(a, b))));
482 }
483
484 void
485 ac97_setup_source_info(as)
486 struct ac97_softc *as;
487 {
488 int idx, ouridx;
489 struct ac97_source_info *si, *si2;
490
491 for (idx = 0, ouridx = 0; idx < SOURCE_INFO_SIZE; idx++) {
492 si = &as->source_info[ouridx];
493
494 memcpy(si, &source_info[idx], sizeof(*si));
495
496 switch (si->type) {
497 case AUDIO_MIXER_CLASS:
498 si->mixer_class = ouridx;
499 ouridx++;
500 break;
501 case AUDIO_MIXER_VALUE:
502 /* Todo - Test to see if it works */
503 ouridx++;
504
505 /* Add an entry for mute, if necessary */
506 if (si->mute) {
507 si = &as->source_info[ouridx];
508 memcpy(si, &source_info[idx], sizeof(*si));
509 si->qualifier = AudioNmute;
510 si->type = AUDIO_MIXER_ENUM;
511 si->info = &ac97_on_off;
512 si->info_size = sizeof(ac97_on_off);
513 si->bits = 1;
514 si->ofs = 15;
515 si->mute = 0;
516 si->polarity = 0;
517 ouridx++;
518 }
519 break;
520 case AUDIO_MIXER_ENUM:
521 /* Todo - Test to see if it works */
522 ouridx++;
523 break;
524 default:
525 printf ("ac97: shouldn't get here\n");
526 break;
527 }
528 }
529
530 as->num_source_info = ouridx;
531
532 for (idx = 0; idx < as->num_source_info; idx++) {
533 int idx2, previdx;
534
535 si = &as->source_info[idx];
536
537 /* Find mixer class */
538 for (idx2 = 0; idx2 < as->num_source_info; idx2++) {
539 si2 = &as->source_info[idx2];
540
541 if (si2->type == AUDIO_MIXER_CLASS &&
542 ac97_str_equal(si->class,
543 si2->class)) {
544 si->mixer_class = idx2;
545 }
546 }
547
548
549 /* Setup prev and next pointers */
550 if (si->prev != 0)
551 continue;
552
553 if (si->qualifier)
554 continue;
555
556 si->prev = AUDIO_MIXER_LAST;
557 previdx = idx;
558
559 for (idx2 = 0; idx2 < as->num_source_info; idx2++) {
560 if (idx2 == idx)
561 continue;
562
563 si2 = &as->source_info[idx2];
564
565 if (!si2->prev &&
566 ac97_str_equal(si->class, si2->class) &&
567 ac97_str_equal(si->device, si2->device)) {
568 as->source_info[previdx].next = idx2;
569 as->source_info[idx2].prev = previdx;
570
571 previdx = idx2;
572 }
573 }
574
575 as->source_info[previdx].next = AUDIO_MIXER_LAST;
576 }
577 }
578
579 int
580 ac97_attach(host_if)
581 struct ac97_host_if *host_if;
582 {
583 struct ac97_softc *as;
584 struct device *sc_dev = (struct device *)host_if->arg;
585 int error, i, j;
586 u_int32_t id;
587 u_int16_t id1, id2;
588 u_int16_t extstat, rate;
589 mixer_ctrl_t ctl;
590 const char *delim;
591
592 as = malloc(sizeof(struct ac97_softc), M_DEVBUF, M_WAITOK|M_ZERO);
593
594 if (as == NULL)
595 return (ENOMEM);
596
597 as->codec_if.vtbl = &ac97civ;
598 as->host_if = host_if;
599
600 if ((error = host_if->attach(host_if->arg, &as->codec_if))) {
601 free (as, M_DEVBUF);
602 return (error);
603 }
604
605 host_if->reset(host_if->arg);
606
607 host_if->write(host_if->arg, AC97_REG_POWER, 0);
608 host_if->write(host_if->arg, AC97_REG_RESET, 0);
609
610 if (host_if->flags)
611 as->host_flags = host_if->flags(host_if->arg);
612
613 ac97_setup_defaults(as);
614 ac97_read(as, AC97_REG_VENDOR_ID1, &id1);
615 ac97_read(as, AC97_REG_VENDOR_ID2, &id2);
616 ac97_read(as, AC97_REG_RESET, &as->caps);
617
618 id = (id1 << 16) | id2;
619
620 printf("%s: ", sc_dev->dv_xname);
621
622 for (i = 0; ; i++) {
623 if (ac97codecid[i].id == 0) {
624 char pnp[4];
625
626 AC97_GET_CODEC_ID(id, pnp);
627 #define ISASCII(c) ((c) >= ' ' && (c) < 0x7f)
628 if (ISASCII(pnp[0]) && ISASCII(pnp[1]) &&
629 ISASCII(pnp[2]))
630 printf("%c%c%c%d", pnp[0], pnp[1], pnp[2],
631 pnp[3]);
632 else
633 printf("unknown (0x%08x)", id);
634 break;
635 }
636 if (ac97codecid[i].id == id) {
637 printf("%s", ac97codecid[i].name);
638 break;
639 }
640 }
641 printf(" codec; ");
642 for (i = j = 0; i < 10; i++) {
643 if (as->caps & (1 << i)) {
644 printf("%s%s", j? ", " : "", ac97feature[i]);
645 j++;
646 }
647 }
648 printf("%s%s\n", j ? ", " : "",
649 ac97enhancement[(as->caps >> 10) & 0x1f]);
650
651 as->ac97_clock = AC97_STANDARD_CLOCK;
652 ac97_read(as, AC97_REG_EXT_AUDIO_ID, &as->ext_id);
653 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA
654 | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM
655 | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC
656 | AC97_EXT_AUDIO_LDAC)) {
657 printf("%s:", sc_dev->dv_xname);
658 delim = "";
659
660 if (as->ext_id & AC97_EXT_AUDIO_VRA) {
661 printf("%s variable rate audio", delim);
662 delim = ",";
663 }
664 if (as->ext_id & AC97_EXT_AUDIO_DRA) {
665 printf("%s double rate output", delim);
666 delim = ",";
667 }
668 if (as->ext_id & AC97_EXT_AUDIO_SPDIF) {
669 printf("%s S/PDIF", delim);
670 delim = ",";
671 }
672 if (as->ext_id & AC97_EXT_AUDIO_VRM) {
673 printf("%s variable rate dedicated mic", delim);
674 delim = ",";
675 }
676 if (as->ext_id & AC97_EXT_AUDIO_CDAC) {
677 printf("%s center DAC", delim);
678 delim = ",";
679 }
680 if (as->ext_id & AC97_EXT_AUDIO_SDAC) {
681 printf("%s surround DAC", delim);
682 delim = ",";
683 }
684 if (as->ext_id & AC97_EXT_AUDIO_LDAC) {
685 printf("%s LFE DAC", delim);
686 }
687 printf("\n");
688
689 /* If VRA and/or VRM capablities, enable them. */
690 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_VRM)) {
691 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat);
692 if (as->ext_id & AC97_EXT_AUDIO_VRA) {
693 extstat |= AC97_EXT_AUDIO_VRA;
694 }
695 if (as->ext_id & AC97_EXT_AUDIO_VRM) {
696 extstat |= AC97_EXT_AUDIO_VRM;
697 }
698 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat);
699
700 /* so it claims to do variable rate, let's make sure */
701 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE, 44100);
702 ac97_read(as, AC97_REG_PCM_FRONT_DAC_RATE, &rate);
703 if (rate != 44100) {
704 /* We can't believe ext_id */
705 as->ext_id = 0;
706 printf("%s: Ignore these capabilities.\n",
707 sc_dev->dv_xname);
708 }
709 }
710 }
711
712 ac97_setup_source_info(as);
713
714 /* Just enable the DAC and master volumes by default */
715 memset(&ctl, 0, sizeof(ctl));
716
717 ctl.type = AUDIO_MIXER_ENUM;
718 ctl.un.ord = 0; /* off */
719 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
720 AudioNmaster, AudioNmute);
721 ac97_mixer_set_port(&as->codec_if, &ctl);
722 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCinputs,
723 AudioNdac, AudioNmute);
724
725 ac97_mixer_set_port(&as->codec_if, &ctl);
726 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
727 AudioNvolume, AudioNmute);
728 ac97_mixer_set_port(&as->codec_if, &ctl);
729
730 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
731 AudioNsource, NULL);
732 ctl.type = AUDIO_MIXER_ENUM;
733 ctl.un.ord = 0;
734 ac97_mixer_set_port(&as->codec_if, &ctl);
735
736 return (0);
737 }
738
739
740 int
741 ac97_query_devinfo(codec_if, dip)
742 struct ac97_codec_if *codec_if;
743 mixer_devinfo_t *dip;
744 {
745 struct ac97_softc *as = (struct ac97_softc *)codec_if;
746
747 if (dip->index < as->num_source_info) {
748 struct ac97_source_info *si = &as->source_info[dip->index];
749 const char *name;
750
751 dip->type = si->type;
752 dip->mixer_class = si->mixer_class;
753 dip->prev = si->prev;
754 dip->next = si->next;
755
756 if (si->qualifier)
757 name = si->qualifier;
758 else if (si->device)
759 name = si->device;
760 else if (si->class)
761 name = si->class;
762 else
763 name = 0;
764
765 if (name)
766 strcpy(dip->label.name, name);
767
768 memcpy(&dip->un, si->info, si->info_size);
769
770 /* Set the delta for volume sources */
771 if (dip->type == AUDIO_MIXER_VALUE)
772 dip->un.v.delta = 1 << (8 - si->bits);
773
774 return (0);
775 }
776
777 return (ENXIO);
778 }
779
780
781
782 int
783 ac97_mixer_set_port(codec_if, cp)
784 struct ac97_codec_if *codec_if;
785 mixer_ctrl_t *cp;
786 {
787 struct ac97_softc *as = (struct ac97_softc *)codec_if;
788 struct ac97_source_info *si = &as->source_info[cp->dev];
789 u_int16_t mask;
790 u_int16_t val, newval;
791 int error;
792
793 if (cp->dev < 0 || cp->dev >= as->num_source_info)
794 return (EINVAL);
795
796 if (cp->type != si->type)
797 return (EINVAL);
798
799 ac97_read(as, si->reg, &val);
800
801 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
802
803 mask = (1 << si->bits) - 1;
804
805 switch (cp->type) {
806 case AUDIO_MIXER_ENUM:
807 if (cp->un.ord > mask || cp->un.ord < 0)
808 return (EINVAL);
809
810 newval = (cp->un.ord << si->ofs);
811 if (si->reg == AC97_REG_RECORD_SELECT) {
812 newval |= (newval << (8 + si->ofs));
813 mask |= (mask << 8);
814 }
815 break;
816 case AUDIO_MIXER_VALUE:
817 {
818 const struct audio_mixer_value *value = si->info;
819 u_int16_t l, r;
820
821 if ((cp->un.value.num_channels <= 0) ||
822 (cp->un.value.num_channels > value->num_channels))
823 return (EINVAL);
824
825 if (cp->un.value.num_channels == 1) {
826 l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
827 } else {
828 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
829 l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
830 r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
831 } else { /* left/right is reversed here */
832 r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
833 l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
834 }
835
836 }
837
838 if (!si->polarity) {
839 l = 255 - l;
840 r = 255 - r;
841 }
842
843 l = l >> (8 - si->bits);
844 r = r >> (8 - si->bits);
845
846 newval = ((l & mask) << si->ofs);
847 if (value->num_channels == 2) {
848 newval |= ((r & mask) << (si->ofs + 8));
849 mask |= (mask << 8);
850 }
851
852 break;
853 }
854 default:
855 return (EINVAL);
856 }
857
858 mask = mask << si->ofs;
859 error = ac97_write(as, si->reg, (val & ~mask) | newval);
860 if (error)
861 return (error);
862
863 return (0);
864 }
865
866 int
867 ac97_get_portnum_by_name(codec_if, class, device, qualifier)
868 struct ac97_codec_if *codec_if;
869 char *class, *device, *qualifier;
870 {
871 struct ac97_softc *as = (struct ac97_softc *)codec_if;
872 int idx;
873
874 for (idx = 0; idx < as->num_source_info; idx++) {
875 struct ac97_source_info *si = &as->source_info[idx];
876 if (ac97_str_equal(class, si->class) &&
877 ac97_str_equal(device, si->device) &&
878 ac97_str_equal(qualifier, si->qualifier))
879 return (idx);
880 }
881
882 return (-1);
883 }
884
885 int
886 ac97_mixer_get_port(codec_if, cp)
887 struct ac97_codec_if *codec_if;
888 mixer_ctrl_t *cp;
889 {
890 struct ac97_softc *as = (struct ac97_softc *)codec_if;
891 struct ac97_source_info *si = &as->source_info[cp->dev];
892 u_int16_t mask;
893 u_int16_t val;
894
895 if (cp->dev < 0 || cp->dev >= as->num_source_info)
896 return (EINVAL);
897
898 if (cp->type != si->type)
899 return (EINVAL);
900
901 ac97_read(as, si->reg, &val);
902
903 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
904
905 mask = (1 << si->bits) - 1;
906
907 switch (cp->type) {
908 case AUDIO_MIXER_ENUM:
909 cp->un.ord = (val >> si->ofs) & mask;
910 DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n", val, si->ofs, mask, cp->un.ord));
911 break;
912 case AUDIO_MIXER_VALUE:
913 {
914 const struct audio_mixer_value *value = si->info;
915 u_int16_t l, r;
916
917 if ((cp->un.value.num_channels <= 0) ||
918 (cp->un.value.num_channels > value->num_channels))
919 return (EINVAL);
920
921 if (value->num_channels == 1) {
922 l = r = (val >> si->ofs) & mask;
923 } else {
924 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
925 l = (val >> si->ofs) & mask;
926 r = (val >> (si->ofs + 8)) & mask;
927 } else { /* host has reversed channels */
928 r = (val >> si->ofs) & mask;
929 l = (val >> (si->ofs + 8)) & mask;
930 }
931 }
932
933 l = (l << (8 - si->bits));
934 r = (r << (8 - si->bits));
935 if (!si->polarity) {
936 l = 255 - l;
937 r = 255 - r;
938 }
939
940 /* The EAP driver averages l and r for stereo
941 channels that are requested in MONO mode. Does this
942 make sense? */
943 if (cp->un.value.num_channels == 1) {
944 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l;
945 } else if (cp->un.value.num_channels == 2) {
946 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
947 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
948 }
949
950 break;
951 }
952 default:
953 return (EINVAL);
954 }
955
956 return (0);
957 }
958
959
960 int
961 ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_long *rate)
962 {
963 struct ac97_softc *as;
964 u_long value;
965 u_int16_t ext_stat;
966 u_int16_t actual;
967 u_int16_t power;
968 u_int16_t power_bit;
969
970 as = (struct ac97_softc *)codec_if;
971 if (target == AC97_REG_PCM_MIC_ADC_RATE) {
972 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
973 *rate = AC97_SINGLE_RATE;
974 return 0;
975 }
976 } else {
977 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
978 *rate = AC97_SINGLE_RATE;
979 return 0;
980 }
981 }
982 value = *rate * AC97_STANDARD_CLOCK / as->ac97_clock;
983 ext_stat = 0;
984 /*
985 * PCM_FRONT_DAC_RATE/PCM_SURR_DAC_RATE/PCM_LFE_DAC_RATE
986 * Check VRA, DRA
987 * PCM_LR_ADC_RATE
988 * Check VRA
989 * PCM_MIC_ADC_RATE
990 * Check VRM
991 */
992 switch (target) {
993 case AC97_REG_PCM_FRONT_DAC_RATE:
994 case AC97_REG_PCM_SURR_DAC_RATE:
995 case AC97_REG_PCM_LFE_DAC_RATE:
996 power_bit = AC97_POWER_OUT;
997 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
998 *rate = AC97_SINGLE_RATE;
999 return 0;
1000 }
1001 if (as->ext_id & AC97_EXT_AUDIO_DRA) {
1002 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &ext_stat);
1003 if (value > 0x1ffff) {
1004 return EINVAL;
1005 } else if (value > 0xffff) {
1006 /* Enable DRA */
1007 ext_stat |= AC97_EXT_AUDIO_DRA;
1008 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1009 value /= 2;
1010 } else {
1011 /* Disable DRA */
1012 ext_stat &= ~AC97_EXT_AUDIO_DRA;
1013 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1014 }
1015 } else {
1016 if (value > 0xffff)
1017 return EINVAL;
1018 }
1019 break;
1020 case AC97_REG_PCM_LR_ADC_RATE:
1021 power_bit = AC97_POWER_IN;
1022 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1023 *rate = AC97_SINGLE_RATE;
1024 return 0;
1025 }
1026 if (value > 0xffff)
1027 return EINVAL;
1028 break;
1029 case AC97_REG_PCM_MIC_ADC_RATE:
1030 power_bit = AC97_POWER_IN;
1031 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1032 *rate = AC97_SINGLE_RATE;
1033 return 0;
1034 }
1035 if (value > 0xffff)
1036 return EINVAL;
1037 break;
1038 default:
1039 printf("%s: Unknown register: 0x%x\n", __func__, target);
1040 return EINVAL;
1041 }
1042
1043 ac97_read(as, AC97_REG_POWER, &power);
1044 ac97_write(as, AC97_REG_POWER, power | power_bit);
1045
1046 ac97_write(as, target, (u_int16_t)value);
1047 ac97_read(as, target, &actual);
1048 actual = (u_int32_t)actual * as->ac97_clock / AC97_STANDARD_CLOCK;
1049
1050 ac97_write(as, AC97_REG_POWER, power);
1051 if (ext_stat & AC97_EXT_AUDIO_DRA) {
1052 *rate = actual * 2;
1053 } else {
1054 *rate = actual;
1055 }
1056 return 0;
1057 }
1058
1059 void
1060 ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock)
1061 {
1062 struct ac97_softc *as;
1063
1064 as = (struct ac97_softc *)codec_if;
1065 as->ac97_clock = clock;
1066 }
1067
1068 u_int16_t
1069 ac97_get_extcaps(struct ac97_codec_if *codec_if)
1070 {
1071 struct ac97_softc *as;
1072
1073 as = (struct ac97_softc *)codec_if;
1074 return as->ext_id;
1075 }
1076