am7930.c revision 1.50.56.1 1 /* $NetBSD: am7930.c,v 1.50.56.1 2011/11/20 10:56:18 mrg Exp $ */
2
3 /*
4 * Copyright (c) 1995 Rolf Grossmann
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Rolf Grossmann.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * Front-end attachment independent layer for AMD 79c30
35 * audio driver. No ISDN support.
36 */
37
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: am7930.c,v 1.50.56.1 2011/11/20 10:56:18 mrg Exp $");
40
41 #include "audio.h"
42 #if NAUDIO > 0
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/errno.h>
47 #include <sys/ioctl.h>
48 #include <sys/device.h>
49 #include <sys/proc.h>
50
51 #include <sys/bus.h>
52 #include <machine/autoconf.h>
53 #include <sys/cpu.h>
54
55 #include <sys/audioio.h>
56 #include <dev/audio_if.h>
57
58 #include <dev/ic/am7930reg.h>
59 #include <dev/ic/am7930var.h>
60
61 #ifdef AUDIO_DEBUG
62 int am7930debug = 0;
63 #define DPRINTF(x) if (am7930debug) printf x
64 #else
65 #define DPRINTF(x)
66 #endif
67
68
69 /* The following tables stolen from former (4.4Lite's) sys/sparc/bsd_audio.c */
70
71 /*
72 * gx, gr & stg gains. this table must contain 256 elements with
73 * the 0th being "infinity" (the magic value 9008). The remaining
74 * elements match sun's gain curve (but with higher resolution):
75 * -18 to 0dB in .16dB steps then 0 to 12dB in .08dB steps.
76 */
77 static const uint16_t gx_coeff[256] = {
78 0x9008, 0x8e7c, 0x8e51, 0x8e45, 0x8d42, 0x8d3b, 0x8c36, 0x8c33,
79 0x8b32, 0x8b2a, 0x8b2b, 0x8b2c, 0x8b25, 0x8b23, 0x8b22, 0x8b22,
80 0x9122, 0x8b1a, 0x8aa3, 0x8aa3, 0x8b1c, 0x8aa6, 0x912d, 0x912b,
81 0x8aab, 0x8b12, 0x8aaa, 0x8ab2, 0x9132, 0x8ab4, 0x913c, 0x8abb,
82 0x9142, 0x9144, 0x9151, 0x8ad5, 0x8aeb, 0x8a79, 0x8a5a, 0x8a4a,
83 0x8b03, 0x91c2, 0x91bb, 0x8a3f, 0x8a33, 0x91b2, 0x9212, 0x9213,
84 0x8a2c, 0x921d, 0x8a23, 0x921a, 0x9222, 0x9223, 0x922d, 0x9231,
85 0x9234, 0x9242, 0x925b, 0x92dd, 0x92c1, 0x92b3, 0x92ab, 0x92a4,
86 0x92a2, 0x932b, 0x9341, 0x93d3, 0x93b2, 0x93a2, 0x943c, 0x94b2,
87 0x953a, 0x9653, 0x9782, 0x9e21, 0x9d23, 0x9cd2, 0x9c23, 0x9baa,
88 0x9bde, 0x9b33, 0x9b22, 0x9b1d, 0x9ab2, 0xa142, 0xa1e5, 0x9a3b,
89 0xa213, 0xa1a2, 0xa231, 0xa2eb, 0xa313, 0xa334, 0xa421, 0xa54b,
90 0xada4, 0xac23, 0xab3b, 0xaaab, 0xaa5c, 0xb1a3, 0xb2ca, 0xb3bd,
91 0xbe24, 0xbb2b, 0xba33, 0xc32b, 0xcb5a, 0xd2a2, 0xe31d, 0x0808,
92 0x72ba, 0x62c2, 0x5c32, 0x52db, 0x513e, 0x4cce, 0x43b2, 0x4243,
93 0x41b4, 0x3b12, 0x3bc3, 0x3df2, 0x34bd, 0x3334, 0x32c2, 0x3224,
94 0x31aa, 0x2a7b, 0x2aaa, 0x2b23, 0x2bba, 0x2c42, 0x2e23, 0x25bb,
95 0x242b, 0x240f, 0x231a, 0x22bb, 0x2241, 0x2223, 0x221f, 0x1a33,
96 0x1a4a, 0x1acd, 0x2132, 0x1b1b, 0x1b2c, 0x1b62, 0x1c12, 0x1c32,
97 0x1d1b, 0x1e71, 0x16b1, 0x1522, 0x1434, 0x1412, 0x1352, 0x1323,
98 0x1315, 0x12bc, 0x127a, 0x1235, 0x1226, 0x11a2, 0x1216, 0x0a2a,
99 0x11bc, 0x11d1, 0x1163, 0x0ac2, 0x0ab2, 0x0aab, 0x0b1b, 0x0b23,
100 0x0b33, 0x0c0f, 0x0bb3, 0x0c1b, 0x0c3e, 0x0cb1, 0x0d4c, 0x0ec1,
101 0x079a, 0x0614, 0x0521, 0x047c, 0x0422, 0x03b1, 0x03e3, 0x0333,
102 0x0322, 0x031c, 0x02aa, 0x02ba, 0x02f2, 0x0242, 0x0232, 0x0227,
103 0x0222, 0x021b, 0x01ad, 0x0212, 0x01b2, 0x01bb, 0x01cb, 0x01f6,
104 0x0152, 0x013a, 0x0133, 0x0131, 0x012c, 0x0123, 0x0122, 0x00a2,
105 0x011b, 0x011e, 0x0114, 0x00b1, 0x00aa, 0x00b3, 0x00bd, 0x00ba,
106 0x00c5, 0x00d3, 0x00f3, 0x0062, 0x0051, 0x0042, 0x003b, 0x0033,
107 0x0032, 0x002a, 0x002c, 0x0025, 0x0023, 0x0022, 0x001a, 0x0021,
108 0x001b, 0x001b, 0x001d, 0x0015, 0x0013, 0x0013, 0x0012, 0x0012,
109 0x000a, 0x000a, 0x0011, 0x0011, 0x000b, 0x000b, 0x000c, 0x000e,
110 };
111
112 /*
113 * second stage play gain.
114 */
115 static const uint16_t ger_coeff[] = {
116 0x431f, /* 5. dB */
117 0x331f, /* 5.5 dB */
118 0x40dd, /* 6. dB */
119 0x11dd, /* 6.5 dB */
120 0x440f, /* 7. dB */
121 0x411f, /* 7.5 dB */
122 0x311f, /* 8. dB */
123 0x5520, /* 8.5 dB */
124 0x10dd, /* 9. dB */
125 0x4211, /* 9.5 dB */
126 0x410f, /* 10. dB */
127 0x111f, /* 10.5 dB */
128 0x600b, /* 11. dB */
129 0x00dd, /* 11.5 dB */
130 0x4210, /* 12. dB */
131 0x110f, /* 13. dB */
132 0x7200, /* 14. dB */
133 0x2110, /* 15. dB */
134 0x2200, /* 15.9 dB */
135 0x000b, /* 16.9 dB */
136 0x000f /* 18. dB */
137 #define NGER (sizeof(ger_coeff) / sizeof(ger_coeff[0]))
138 };
139
140
141 /*
142 * Reset chip and set boot-time softc defaults.
143 */
144 void
145 am7930_init(struct am7930_softc *sc, int flag)
146 {
147
148 DPRINTF(("am7930_init()\n"));
149
150 /* set boot defaults */
151 sc->sc_rlevel = 128;
152 sc->sc_plevel = 128;
153 sc->sc_mlevel = 0;
154 sc->sc_out_port = AUDIOAMD_SPEAKER_VOL;
155 sc->sc_mic_mute = 0;
156
157 /* disable sample interrupts */
158 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4, 0);
159
160 /* initialise voice and data, and disable interrupts */
161 AM7930_IWRITE(sc, AM7930_IREG_INIT,
162 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE);
163
164 if (flag == AUDIOAMD_DMA_MODE) {
165
166 /* configure PP for serial (SBP) mode */
167 AM7930_IWRITE(sc, AM7930_IREG_PP_PPCR1, AM7930_PPCR1_SBP);
168
169 /*
170 * Initialise the MUX unit - route the MAP to the PP
171 */
172 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR1,
173 (AM7930_MCRCHAN_BA << 4) | AM7930_MCRCHAN_BD);
174 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR2, AM7930_MCRCHAN_NC);
175 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR3, AM7930_MCRCHAN_NC);
176
177 } else {
178
179 /*
180 * Initialize the MUX unit. We use MCR3 to route the MAP
181 * through channel Bb. MCR1 and MCR2 are unused.
182 * Setting the INT enable bit in MCR4 will generate an
183 * interrupt on each converted audio sample.
184 */
185 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR1, 0);
186 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR2, 0);
187 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR3,
188 (AM7930_MCRCHAN_BB << 4) | AM7930_MCRCHAN_BA);
189 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4,
190 AM7930_MCR4_INT_ENABLE);
191 }
192
193 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
194 /* We used to take splaudio() in commit_settings */
195 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_VM);
196 }
197
198 int
199 am7930_open(void *addr, int flags)
200 {
201 struct am7930_softc *sc;
202
203 sc = addr;
204 DPRINTF(("sa_open: unit %p\n", sc));
205 sc->sc_glue->onopen(sc);
206 DPRINTF(("saopen: ok -> sc=%p\n",sc));
207 return 0;
208 }
209
210 void
211 am7930_close(void *addr)
212 {
213 struct am7930_softc *sc;
214
215 sc = addr;
216 DPRINTF(("sa_close: sc=%p\n", sc));
217 sc->sc_glue->onclose(sc);
218 DPRINTF(("sa_close: closed.\n"));
219 }
220
221 /*
222 * XXX should be extended to handle a few of the more common formats.
223 */
224 int
225 am7930_set_params(void *addr, int setmode, int usemode, audio_params_t *p,
226 audio_params_t *r, stream_filter_list_t *pfil, stream_filter_list_t *rfil)
227 {
228 audio_params_t hw;
229 struct am7930_softc *sc;
230
231 sc = addr;
232 if ((usemode & AUMODE_PLAY) == AUMODE_PLAY) {
233 if (p->sample_rate < 7500 || p->sample_rate > 8500 ||
234 p->encoding != AUDIO_ENCODING_ULAW ||
235 p->precision != 8 ||
236 p->channels != 1)
237 return EINVAL;
238 p->sample_rate = 8000;
239 if (sc->sc_glue->output_conv != NULL) {
240 hw = *p;
241 hw.encoding = AUDIO_ENCODING_NONE;
242 hw.precision *= sc->sc_glue->factor;
243 pfil->append(pfil, sc->sc_glue->output_conv, &hw);
244 }
245 }
246 if ((usemode & AUMODE_RECORD) == AUMODE_RECORD) {
247 if (r->sample_rate < 7500 || r->sample_rate > 8500 ||
248 r->encoding != AUDIO_ENCODING_ULAW ||
249 r->precision != 8 ||
250 r->channels != 1)
251 return EINVAL;
252 r->sample_rate = 8000;
253 if (sc->sc_glue->input_conv != NULL) {
254 hw = *r;
255 hw.encoding = AUDIO_ENCODING_NONE;
256 hw.precision *= sc->sc_glue->factor;
257 pfil->append(rfil, sc->sc_glue->input_conv, &hw);
258 }
259 }
260
261 return 0;
262 }
263
264 int
265 am7930_query_encoding(void *addr, struct audio_encoding *fp)
266 {
267 switch (fp->index) {
268 case 0:
269 strcpy(fp->name, AudioEmulaw);
270 fp->encoding = AUDIO_ENCODING_ULAW;
271 fp->precision = 8;
272 fp->flags = 0;
273 break;
274 default:
275 return EINVAL;
276 /*NOTREACHED*/
277 }
278 return 0;
279 }
280
281 int
282 am7930_round_blocksize(void *addr, int blk,
283 int mode, const audio_params_t *param)
284 {
285 return blk;
286 }
287
288 int
289 am7930_commit_settings(void *addr)
290 {
291 struct am7930_softc *sc;
292 uint16_t ger, gr, gx, stgr;
293 uint8_t mmr2, mmr3;
294 int level;
295
296 DPRINTF(("sa_commit.\n"));
297 sc = addr;
298 gx = gx_coeff[sc->sc_rlevel];
299 stgr = gx_coeff[sc->sc_mlevel];
300
301 level = (sc->sc_plevel * (256 + NGER)) >> 8;
302 if (level >= 256) {
303 ger = ger_coeff[level - 256];
304 gr = gx_coeff[255];
305 } else {
306 ger = ger_coeff[0];
307 gr = gx_coeff[level];
308 }
309
310 mutex_enter(&sc->sc_intr_lock);
311
312 mmr2 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR2);
313 if (sc->sc_out_port == AUDIOAMD_SPEAKER_VOL)
314 mmr2 |= AM7930_MMR2_LS;
315 else
316 mmr2 &= ~AM7930_MMR2_LS;
317 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR2, mmr2);
318
319 mmr3 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR3);
320 if (sc->sc_mic_mute)
321 mmr3 |= AM7930_MMR3_MUTE;
322 else
323 mmr3 &= ~AM7930_MMR3_MUTE;
324 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR3, mmr3);
325
326 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR1,
327 AM7930_MMR1_GX | AM7930_MMR1_GER |
328 AM7930_MMR1_GR | AM7930_MMR1_STG);
329
330 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GX, gx);
331 AM7930_IWRITE16(sc, AM7930_IREG_MAP_STG, stgr);
332 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GR, gr);
333 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GER, ger);
334
335 mutex_exit(&sc->sc_intr_lock);
336
337 return 0;
338 }
339
340 int
341 am7930_halt_output(void *addr)
342 {
343 struct am7930_softc *sc;
344
345 sc = addr;
346 /* XXX only halt, if input is also halted ?? */
347 AM7930_IWRITE(sc, AM7930_IREG_INIT,
348 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE);
349 return 0;
350 }
351
352 int
353 am7930_halt_input(void *addr)
354 {
355 struct am7930_softc *sc;
356
357 sc = addr;
358 /* XXX only halt, if output is also halted ?? */
359 AM7930_IWRITE(sc, AM7930_IREG_INIT,
360 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE);
361 return 0;
362 }
363
364 /*
365 * XXX chip is full-duplex, but really attach-dependent.
366 * For now we know of no half-duplex attachments.
367 */
368 int
369 am7930_get_props(void *addr)
370 {
371 return AUDIO_PROP_FULLDUPLEX;
372 }
373
374 /*
375 * Attach-dependent channel set/query
376 */
377 int
378 am7930_set_port(void *addr, mixer_ctrl_t *cp)
379 {
380 struct am7930_softc *sc;
381
382 DPRINTF(("am7930_set_port: port=%d", cp->dev));
383 sc = addr;
384 if (cp->dev == AUDIOAMD_RECORD_SOURCE ||
385 cp->dev == AUDIOAMD_MONITOR_OUTPUT ||
386 cp->dev == AUDIOAMD_MIC_MUTE) {
387 if (cp->type != AUDIO_MIXER_ENUM)
388 return EINVAL;
389 } else if (cp->type != AUDIO_MIXER_VALUE ||
390 cp->un.value.num_channels != 1) {
391 return EINVAL;
392 }
393
394 switch(cp->dev) {
395 case AUDIOAMD_MIC_VOL:
396 sc->sc_rlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
397 break;
398 case AUDIOAMD_SPEAKER_VOL:
399 case AUDIOAMD_HEADPHONES_VOL:
400 sc->sc_plevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
401 break;
402 case AUDIOAMD_MONITOR_VOL:
403 sc->sc_mlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
404 break;
405 case AUDIOAMD_RECORD_SOURCE:
406 if (cp->un.ord != AUDIOAMD_MIC_VOL)
407 return EINVAL;
408 break;
409 case AUDIOAMD_MIC_MUTE:
410 sc->sc_mic_mute = cp->un.ord;
411 break;
412 case AUDIOAMD_MONITOR_OUTPUT:
413 if (cp->un.ord != AUDIOAMD_SPEAKER_VOL &&
414 cp->un.ord != AUDIOAMD_HEADPHONES_VOL)
415 return EINVAL;
416 sc->sc_out_port = cp->un.ord;
417 break;
418 default:
419 return EINVAL;
420 /* NOTREACHED */
421 }
422 return 0;
423 }
424
425 int
426 am7930_get_port(void *addr, mixer_ctrl_t *cp)
427 {
428 struct am7930_softc *sc;
429
430 DPRINTF(("am7930_get_port: port=%d\n", cp->dev));
431 sc = addr;
432 if (cp->dev == AUDIOAMD_RECORD_SOURCE ||
433 cp->dev == AUDIOAMD_MONITOR_OUTPUT ||
434 cp->dev == AUDIOAMD_MIC_MUTE) {
435 if (cp->type != AUDIO_MIXER_ENUM)
436 return EINVAL;
437 } else if (cp->type != AUDIO_MIXER_VALUE ||
438 cp->un.value.num_channels != 1) {
439 return EINVAL;
440 }
441
442 switch(cp->dev) {
443 case AUDIOAMD_MIC_VOL:
444 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_rlevel;
445 break;
446 case AUDIOAMD_SPEAKER_VOL:
447 case AUDIOAMD_HEADPHONES_VOL:
448 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_plevel;
449 break;
450 case AUDIOAMD_MONITOR_VOL:
451 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_mlevel;
452 break;
453 case AUDIOAMD_RECORD_SOURCE:
454 cp->un.ord = AUDIOAMD_MIC_VOL;
455 break;
456 case AUDIOAMD_MIC_MUTE:
457 cp->un.ord = sc->sc_mic_mute;
458 break;
459 case AUDIOAMD_MONITOR_OUTPUT:
460 cp->un.ord = sc->sc_out_port;
461 break;
462 default:
463 return EINVAL;
464 /* NOTREACHED */
465 }
466 return 0;
467 }
468
469
470 /*
471 * Define mixer control facilities.
472 */
473 int
474 am7930_query_devinfo(void *addr, mixer_devinfo_t *dip)
475 {
476
477 DPRINTF(("am7930_query_devinfo()\n"));
478
479 switch(dip->index) {
480 case AUDIOAMD_MIC_VOL:
481 dip->type = AUDIO_MIXER_VALUE;
482 dip->mixer_class = AUDIOAMD_INPUT_CLASS;
483 dip->prev = AUDIO_MIXER_LAST;
484 dip->next = AUDIOAMD_MIC_MUTE;
485 strcpy(dip->label.name, AudioNmicrophone);
486 dip->un.v.num_channels = 1;
487 strcpy(dip->un.v.units.name, AudioNvolume);
488 break;
489 case AUDIOAMD_SPEAKER_VOL:
490 dip->type = AUDIO_MIXER_VALUE;
491 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS;
492 dip->prev = dip->next = AUDIO_MIXER_LAST;
493 strcpy(dip->label.name, AudioNspeaker);
494 dip->un.v.num_channels = 1;
495 strcpy(dip->un.v.units.name, AudioNvolume);
496 break;
497 case AUDIOAMD_HEADPHONES_VOL:
498 dip->type = AUDIO_MIXER_VALUE;
499 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS;
500 dip->prev = dip->next = AUDIO_MIXER_LAST;
501 strcpy(dip->label.name, AudioNheadphone);
502 dip->un.v.num_channels = 1;
503 strcpy(dip->un.v.units.name, AudioNvolume);
504 break;
505 case AUDIOAMD_MONITOR_VOL:
506 dip->type = AUDIO_MIXER_VALUE;
507 dip->mixer_class = AUDIOAMD_MONITOR_CLASS;
508 dip->prev = dip->next = AUDIO_MIXER_LAST;
509 strcpy(dip->label.name, AudioNmonitor);
510 dip->un.v.num_channels = 1;
511 strcpy(dip->un.v.units.name, AudioNvolume);
512 break;
513 case AUDIOAMD_RECORD_SOURCE:
514 dip->type = AUDIO_MIXER_ENUM;
515 dip->mixer_class = AUDIOAMD_RECORD_CLASS;
516 dip->next = dip->prev = AUDIO_MIXER_LAST;
517 strcpy(dip->label.name, AudioNsource);
518 dip->un.e.num_mem = 1;
519 strcpy(dip->un.e.member[0].label.name, AudioNmicrophone);
520 dip->un.e.member[0].ord = AUDIOAMD_MIC_VOL;
521 break;
522 case AUDIOAMD_MONITOR_OUTPUT:
523 dip->type = AUDIO_MIXER_ENUM;
524 dip->mixer_class = AUDIOAMD_MONITOR_CLASS;
525 dip->next = dip->prev = AUDIO_MIXER_LAST;
526 strcpy(dip->label.name, AudioNoutput);
527 dip->un.e.num_mem = 2;
528 strcpy(dip->un.e.member[0].label.name, AudioNspeaker);
529 dip->un.e.member[0].ord = AUDIOAMD_SPEAKER_VOL;
530 strcpy(dip->un.e.member[1].label.name, AudioNheadphone);
531 dip->un.e.member[1].ord = AUDIOAMD_HEADPHONES_VOL;
532 break;
533 case AUDIOAMD_MIC_MUTE:
534 dip->type = AUDIO_MIXER_ENUM;
535 dip->mixer_class = AUDIOAMD_INPUT_CLASS;
536 dip->prev = AUDIOAMD_MIC_VOL;
537 dip->next = AUDIO_MIXER_LAST;
538 strcpy(dip->label.name, AudioNmute);
539 dip->un.e.num_mem = 2;
540 strcpy(dip->un.e.member[0].label.name, AudioNoff);
541 dip->un.e.member[0].ord = 0;
542 strcpy(dip->un.e.member[1].label.name, AudioNon);
543 dip->un.e.member[1].ord = 1;
544 break;
545 case AUDIOAMD_INPUT_CLASS:
546 dip->type = AUDIO_MIXER_CLASS;
547 dip->mixer_class = AUDIOAMD_INPUT_CLASS;
548 dip->next = dip->prev = AUDIO_MIXER_LAST;
549 strcpy(dip->label.name, AudioCinputs);
550 break;
551 case AUDIOAMD_OUTPUT_CLASS:
552 dip->type = AUDIO_MIXER_CLASS;
553 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS;
554 dip->next = dip->prev = AUDIO_MIXER_LAST;
555 strcpy(dip->label.name, AudioCoutputs);
556 break;
557 case AUDIOAMD_RECORD_CLASS:
558 dip->type = AUDIO_MIXER_CLASS;
559 dip->mixer_class = AUDIOAMD_RECORD_CLASS;
560 dip->next = dip->prev = AUDIO_MIXER_LAST;
561 strcpy(dip->label.name, AudioCrecord);
562 break;
563 case AUDIOAMD_MONITOR_CLASS:
564 dip->type = AUDIO_MIXER_CLASS;
565 dip->mixer_class = AUDIOAMD_MONITOR_CLASS;
566 dip->next = dip->prev = AUDIO_MIXER_LAST;
567 strcpy(dip->label.name, AudioCmonitor);
568 break;
569 default:
570 return ENXIO;
571 /*NOTREACHED*/
572 }
573
574 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
575
576 return 0;
577 }
578
579 #endif /* NAUDIO */
580