am7930.c revision 1.50.54.1 1 /* $NetBSD: am7930.c,v 1.50.54.1 2012/04/17 00:07:31 yamt 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.54.1 2012/04/17 00:07:31 yamt 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 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
195 }
196
197 int
198 am7930_open(void *addr, int flags)
199 {
200 struct am7930_softc *sc;
201
202 sc = addr;
203 DPRINTF(("sa_open: unit %p\n", sc));
204 sc->sc_glue->onopen(sc);
205 DPRINTF(("saopen: ok -> sc=%p\n",sc));
206 return 0;
207 }
208
209 void
210 am7930_close(void *addr)
211 {
212 struct am7930_softc *sc;
213
214 sc = addr;
215 DPRINTF(("sa_close: sc=%p\n", sc));
216 sc->sc_glue->onclose(sc);
217 DPRINTF(("sa_close: closed.\n"));
218 }
219
220 /*
221 * XXX should be extended to handle a few of the more common formats.
222 */
223 int
224 am7930_set_params(void *addr, int setmode, int usemode, audio_params_t *p,
225 audio_params_t *r, stream_filter_list_t *pfil, stream_filter_list_t *rfil)
226 {
227 audio_params_t hw;
228 struct am7930_softc *sc;
229
230 sc = addr;
231 if ((usemode & AUMODE_PLAY) == AUMODE_PLAY) {
232 if (p->sample_rate < 7500 || p->sample_rate > 8500 ||
233 p->encoding != AUDIO_ENCODING_ULAW ||
234 p->precision != 8 ||
235 p->channels != 1)
236 return EINVAL;
237 p->sample_rate = 8000;
238 if (sc->sc_glue->output_conv != NULL) {
239 hw = *p;
240 hw.encoding = AUDIO_ENCODING_NONE;
241 hw.precision *= sc->sc_glue->factor;
242 pfil->append(pfil, sc->sc_glue->output_conv, &hw);
243 }
244 }
245 if ((usemode & AUMODE_RECORD) == AUMODE_RECORD) {
246 if (r->sample_rate < 7500 || r->sample_rate > 8500 ||
247 r->encoding != AUDIO_ENCODING_ULAW ||
248 r->precision != 8 ||
249 r->channels != 1)
250 return EINVAL;
251 r->sample_rate = 8000;
252 if (sc->sc_glue->input_conv != NULL) {
253 hw = *r;
254 hw.encoding = AUDIO_ENCODING_NONE;
255 hw.precision *= sc->sc_glue->factor;
256 pfil->append(rfil, sc->sc_glue->input_conv, &hw);
257 }
258 }
259
260 return 0;
261 }
262
263 int
264 am7930_query_encoding(void *addr, struct audio_encoding *fp)
265 {
266 switch (fp->index) {
267 case 0:
268 strcpy(fp->name, AudioEmulaw);
269 fp->encoding = AUDIO_ENCODING_ULAW;
270 fp->precision = 8;
271 fp->flags = 0;
272 break;
273 default:
274 return EINVAL;
275 /*NOTREACHED*/
276 }
277 return 0;
278 }
279
280 int
281 am7930_round_blocksize(void *addr, int blk,
282 int mode, const audio_params_t *param)
283 {
284 return blk;
285 }
286
287 int
288 am7930_commit_settings(void *addr)
289 {
290 struct am7930_softc *sc;
291 uint16_t ger, gr, gx, stgr;
292 uint8_t mmr2, mmr3;
293 int level;
294
295 DPRINTF(("sa_commit.\n"));
296 sc = addr;
297 gx = gx_coeff[sc->sc_rlevel];
298 stgr = gx_coeff[sc->sc_mlevel];
299
300 level = (sc->sc_plevel * (256 + NGER)) >> 8;
301 if (level >= 256) {
302 ger = ger_coeff[level - 256];
303 gr = gx_coeff[255];
304 } else {
305 ger = ger_coeff[0];
306 gr = gx_coeff[level];
307 }
308
309 mutex_enter(&sc->sc_intr_lock);
310
311 mmr2 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR2);
312 if (sc->sc_out_port == AUDIOAMD_SPEAKER_VOL)
313 mmr2 |= AM7930_MMR2_LS;
314 else
315 mmr2 &= ~AM7930_MMR2_LS;
316 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR2, mmr2);
317
318 mmr3 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR3);
319 if (sc->sc_mic_mute)
320 mmr3 |= AM7930_MMR3_MUTE;
321 else
322 mmr3 &= ~AM7930_MMR3_MUTE;
323 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR3, mmr3);
324
325 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR1,
326 AM7930_MMR1_GX | AM7930_MMR1_GER |
327 AM7930_MMR1_GR | AM7930_MMR1_STG);
328
329 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GX, gx);
330 AM7930_IWRITE16(sc, AM7930_IREG_MAP_STG, stgr);
331 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GR, gr);
332 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GER, ger);
333
334 mutex_exit(&sc->sc_intr_lock);
335
336 return 0;
337 }
338
339 int
340 am7930_halt_output(void *addr)
341 {
342 struct am7930_softc *sc;
343
344 sc = addr;
345 /* XXX only halt, if input is also halted ?? */
346 AM7930_IWRITE(sc, AM7930_IREG_INIT,
347 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE);
348 return 0;
349 }
350
351 int
352 am7930_halt_input(void *addr)
353 {
354 struct am7930_softc *sc;
355
356 sc = addr;
357 /* XXX only halt, if output is also halted ?? */
358 AM7930_IWRITE(sc, AM7930_IREG_INIT,
359 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE);
360 return 0;
361 }
362
363 /*
364 * XXX chip is full-duplex, but really attach-dependent.
365 * For now we know of no half-duplex attachments.
366 */
367 int
368 am7930_get_props(void *addr)
369 {
370 return AUDIO_PROP_FULLDUPLEX;
371 }
372
373 /*
374 * Attach-dependent channel set/query
375 */
376 int
377 am7930_set_port(void *addr, mixer_ctrl_t *cp)
378 {
379 struct am7930_softc *sc;
380
381 DPRINTF(("am7930_set_port: port=%d", cp->dev));
382 sc = addr;
383 if (cp->dev == AUDIOAMD_RECORD_SOURCE ||
384 cp->dev == AUDIOAMD_MONITOR_OUTPUT ||
385 cp->dev == AUDIOAMD_MIC_MUTE) {
386 if (cp->type != AUDIO_MIXER_ENUM)
387 return EINVAL;
388 } else if (cp->type != AUDIO_MIXER_VALUE ||
389 cp->un.value.num_channels != 1) {
390 return EINVAL;
391 }
392
393 switch(cp->dev) {
394 case AUDIOAMD_MIC_VOL:
395 sc->sc_rlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
396 break;
397 case AUDIOAMD_SPEAKER_VOL:
398 case AUDIOAMD_HEADPHONES_VOL:
399 sc->sc_plevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
400 break;
401 case AUDIOAMD_MONITOR_VOL:
402 sc->sc_mlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
403 break;
404 case AUDIOAMD_RECORD_SOURCE:
405 if (cp->un.ord != AUDIOAMD_MIC_VOL)
406 return EINVAL;
407 break;
408 case AUDIOAMD_MIC_MUTE:
409 sc->sc_mic_mute = cp->un.ord;
410 break;
411 case AUDIOAMD_MONITOR_OUTPUT:
412 if (cp->un.ord != AUDIOAMD_SPEAKER_VOL &&
413 cp->un.ord != AUDIOAMD_HEADPHONES_VOL)
414 return EINVAL;
415 sc->sc_out_port = cp->un.ord;
416 break;
417 default:
418 return EINVAL;
419 /* NOTREACHED */
420 }
421 return 0;
422 }
423
424 int
425 am7930_get_port(void *addr, mixer_ctrl_t *cp)
426 {
427 struct am7930_softc *sc;
428
429 DPRINTF(("am7930_get_port: port=%d\n", cp->dev));
430 sc = addr;
431 if (cp->dev == AUDIOAMD_RECORD_SOURCE ||
432 cp->dev == AUDIOAMD_MONITOR_OUTPUT ||
433 cp->dev == AUDIOAMD_MIC_MUTE) {
434 if (cp->type != AUDIO_MIXER_ENUM)
435 return EINVAL;
436 } else if (cp->type != AUDIO_MIXER_VALUE ||
437 cp->un.value.num_channels != 1) {
438 return EINVAL;
439 }
440
441 switch(cp->dev) {
442 case AUDIOAMD_MIC_VOL:
443 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_rlevel;
444 break;
445 case AUDIOAMD_SPEAKER_VOL:
446 case AUDIOAMD_HEADPHONES_VOL:
447 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_plevel;
448 break;
449 case AUDIOAMD_MONITOR_VOL:
450 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_mlevel;
451 break;
452 case AUDIOAMD_RECORD_SOURCE:
453 cp->un.ord = AUDIOAMD_MIC_VOL;
454 break;
455 case AUDIOAMD_MIC_MUTE:
456 cp->un.ord = sc->sc_mic_mute;
457 break;
458 case AUDIOAMD_MONITOR_OUTPUT:
459 cp->un.ord = sc->sc_out_port;
460 break;
461 default:
462 return EINVAL;
463 /* NOTREACHED */
464 }
465 return 0;
466 }
467
468
469 /*
470 * Define mixer control facilities.
471 */
472 int
473 am7930_query_devinfo(void *addr, mixer_devinfo_t *dip)
474 {
475
476 DPRINTF(("am7930_query_devinfo()\n"));
477
478 switch(dip->index) {
479 case AUDIOAMD_MIC_VOL:
480 dip->type = AUDIO_MIXER_VALUE;
481 dip->mixer_class = AUDIOAMD_INPUT_CLASS;
482 dip->prev = AUDIO_MIXER_LAST;
483 dip->next = AUDIOAMD_MIC_MUTE;
484 strcpy(dip->label.name, AudioNmicrophone);
485 dip->un.v.num_channels = 1;
486 strcpy(dip->un.v.units.name, AudioNvolume);
487 break;
488 case AUDIOAMD_SPEAKER_VOL:
489 dip->type = AUDIO_MIXER_VALUE;
490 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS;
491 dip->prev = dip->next = AUDIO_MIXER_LAST;
492 strcpy(dip->label.name, AudioNspeaker);
493 dip->un.v.num_channels = 1;
494 strcpy(dip->un.v.units.name, AudioNvolume);
495 break;
496 case AUDIOAMD_HEADPHONES_VOL:
497 dip->type = AUDIO_MIXER_VALUE;
498 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS;
499 dip->prev = dip->next = AUDIO_MIXER_LAST;
500 strcpy(dip->label.name, AudioNheadphone);
501 dip->un.v.num_channels = 1;
502 strcpy(dip->un.v.units.name, AudioNvolume);
503 break;
504 case AUDIOAMD_MONITOR_VOL:
505 dip->type = AUDIO_MIXER_VALUE;
506 dip->mixer_class = AUDIOAMD_MONITOR_CLASS;
507 dip->prev = dip->next = AUDIO_MIXER_LAST;
508 strcpy(dip->label.name, AudioNmonitor);
509 dip->un.v.num_channels = 1;
510 strcpy(dip->un.v.units.name, AudioNvolume);
511 break;
512 case AUDIOAMD_RECORD_SOURCE:
513 dip->type = AUDIO_MIXER_ENUM;
514 dip->mixer_class = AUDIOAMD_RECORD_CLASS;
515 dip->next = dip->prev = AUDIO_MIXER_LAST;
516 strcpy(dip->label.name, AudioNsource);
517 dip->un.e.num_mem = 1;
518 strcpy(dip->un.e.member[0].label.name, AudioNmicrophone);
519 dip->un.e.member[0].ord = AUDIOAMD_MIC_VOL;
520 break;
521 case AUDIOAMD_MONITOR_OUTPUT:
522 dip->type = AUDIO_MIXER_ENUM;
523 dip->mixer_class = AUDIOAMD_MONITOR_CLASS;
524 dip->next = dip->prev = AUDIO_MIXER_LAST;
525 strcpy(dip->label.name, AudioNoutput);
526 dip->un.e.num_mem = 2;
527 strcpy(dip->un.e.member[0].label.name, AudioNspeaker);
528 dip->un.e.member[0].ord = AUDIOAMD_SPEAKER_VOL;
529 strcpy(dip->un.e.member[1].label.name, AudioNheadphone);
530 dip->un.e.member[1].ord = AUDIOAMD_HEADPHONES_VOL;
531 break;
532 case AUDIOAMD_MIC_MUTE:
533 dip->type = AUDIO_MIXER_ENUM;
534 dip->mixer_class = AUDIOAMD_INPUT_CLASS;
535 dip->prev = AUDIOAMD_MIC_VOL;
536 dip->next = AUDIO_MIXER_LAST;
537 strcpy(dip->label.name, AudioNmute);
538 dip->un.e.num_mem = 2;
539 strcpy(dip->un.e.member[0].label.name, AudioNoff);
540 dip->un.e.member[0].ord = 0;
541 strcpy(dip->un.e.member[1].label.name, AudioNon);
542 dip->un.e.member[1].ord = 1;
543 break;
544 case AUDIOAMD_INPUT_CLASS:
545 dip->type = AUDIO_MIXER_CLASS;
546 dip->mixer_class = AUDIOAMD_INPUT_CLASS;
547 dip->next = dip->prev = AUDIO_MIXER_LAST;
548 strcpy(dip->label.name, AudioCinputs);
549 break;
550 case AUDIOAMD_OUTPUT_CLASS:
551 dip->type = AUDIO_MIXER_CLASS;
552 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS;
553 dip->next = dip->prev = AUDIO_MIXER_LAST;
554 strcpy(dip->label.name, AudioCoutputs);
555 break;
556 case AUDIOAMD_RECORD_CLASS:
557 dip->type = AUDIO_MIXER_CLASS;
558 dip->mixer_class = AUDIOAMD_RECORD_CLASS;
559 dip->next = dip->prev = AUDIO_MIXER_LAST;
560 strcpy(dip->label.name, AudioCrecord);
561 break;
562 case AUDIOAMD_MONITOR_CLASS:
563 dip->type = AUDIO_MIXER_CLASS;
564 dip->mixer_class = AUDIOAMD_MONITOR_CLASS;
565 dip->next = dip->prev = AUDIO_MIXER_LAST;
566 strcpy(dip->label.name, AudioCmonitor);
567 break;
568 default:
569 return ENXIO;
570 /*NOTREACHED*/
571 }
572
573 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
574
575 return 0;
576 }
577
578 #endif /* NAUDIO */
579