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