am7930.c revision 1.59 1 /* $NetBSD: am7930.c,v 1.59 2019/06/08 08:02:38 isaki 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.59 2019/06/08 08:02:38 isaki 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 <sys/cpu.h>
53
54 #include <sys/audioio.h>
55 #include <dev/audio/audio_if.h>
56 #include <dev/audio/mulaw.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 static const struct audio_format am7930_format = {
141 .mode = AUMODE_PLAY | AUMODE_RECORD,
142 .encoding = AUDIO_ENCODING_ULAW,
143 .validbits = 8,
144 .precision = 8,
145 .channels = 1,
146 .channel_mask = AUFMT_MONAURAL,
147 .frequency_type = 1,
148 .frequency = { 8000 },
149 };
150
151 /*
152 * Reset chip and set boot-time softc defaults.
153 */
154 void
155 am7930_init(struct am7930_softc *sc, int flag)
156 {
157
158 DPRINTF(("am7930_init()\n"));
159
160 /* set boot defaults */
161 sc->sc_rlevel = 128;
162 sc->sc_plevel = 128;
163 sc->sc_mlevel = 0;
164 sc->sc_out_port = AUDIOAMD_SPEAKER_VOL;
165 sc->sc_mic_mute = 0;
166
167 /* disable sample interrupts */
168 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4, 0);
169
170 /* initialise voice and data, and disable interrupts */
171 AM7930_IWRITE(sc, AM7930_IREG_INIT,
172 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE);
173
174 if (flag == AUDIOAMD_DMA_MODE) {
175
176 /* configure PP for serial (SBP) mode */
177 AM7930_IWRITE(sc, AM7930_IREG_PP_PPCR1, AM7930_PPCR1_SBP);
178
179 /*
180 * Initialise the MUX unit - route the MAP to the PP
181 */
182 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR1,
183 (AM7930_MCRCHAN_BA << 4) | AM7930_MCRCHAN_BD);
184 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR2, AM7930_MCRCHAN_NC);
185 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR3, AM7930_MCRCHAN_NC);
186
187 } else {
188
189 /*
190 * Initialize the MUX unit. We use MCR3 to route the MAP
191 * through channel Bb. MCR1 and MCR2 are unused.
192 * Setting the INT enable bit in MCR4 will generate an
193 * interrupt on each converted audio sample.
194 */
195 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR1, 0);
196 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR2, 0);
197 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR3,
198 (AM7930_MCRCHAN_BB << 4) | AM7930_MCRCHAN_BA);
199 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4,
200 AM7930_MCR4_INT_ENABLE);
201 }
202
203 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
204 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
205 }
206
207 int
208 am7930_open(void *addr, int flags)
209 {
210 struct am7930_softc *sc;
211
212 sc = addr;
213 DPRINTF(("sa_open: unit %p\n", sc));
214 sc->sc_glue->onopen(sc);
215 DPRINTF(("saopen: ok -> sc=%p\n",sc));
216 return 0;
217 }
218
219 void
220 am7930_close(void *addr)
221 {
222 struct am7930_softc *sc;
223
224 sc = addr;
225 DPRINTF(("sa_close: sc=%p\n", sc));
226 sc->sc_glue->onclose(sc);
227 DPRINTF(("sa_close: closed.\n"));
228 }
229
230 int
231 am7930_query_format(void *addr, audio_format_query_t *afp)
232 {
233
234 return audio_query_format(&am7930_format, 1, afp);
235 }
236
237 int
238 am7930_set_format(void *addr, int setmode,
239 const audio_params_t *play, const audio_params_t *rec,
240 audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
241 {
242
243 if ((setmode & AUMODE_PLAY) != 0) {
244 pfil->codec = audio_internal_to_mulaw;
245 }
246 if ((setmode & AUMODE_RECORD) != 0) {
247 rfil->codec = audio_mulaw_to_internal;
248 }
249
250 return 0;
251 }
252
253 int
254 am7930_commit_settings(void *addr)
255 {
256 struct am7930_softc *sc;
257 uint16_t ger, gr, gx, stgr;
258 uint8_t mmr2, mmr3;
259 int level;
260
261 DPRINTF(("sa_commit.\n"));
262 sc = addr;
263 gx = gx_coeff[sc->sc_rlevel];
264 stgr = gx_coeff[sc->sc_mlevel];
265
266 level = (sc->sc_plevel * (256 + NGER)) >> 8;
267 if (level >= 256) {
268 ger = ger_coeff[level - 256];
269 gr = gx_coeff[255];
270 } else {
271 ger = ger_coeff[0];
272 gr = gx_coeff[level];
273 }
274
275 mutex_enter(&sc->sc_intr_lock);
276
277 mmr2 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR2);
278 if (sc->sc_out_port == AUDIOAMD_SPEAKER_VOL)
279 mmr2 |= AM7930_MMR2_LS;
280 else
281 mmr2 &= ~AM7930_MMR2_LS;
282 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR2, mmr2);
283
284 mmr3 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR3);
285 if (sc->sc_mic_mute)
286 mmr3 |= AM7930_MMR3_MUTE;
287 else
288 mmr3 &= ~AM7930_MMR3_MUTE;
289 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR3, mmr3);
290
291 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR1,
292 AM7930_MMR1_GX | AM7930_MMR1_GER |
293 AM7930_MMR1_GR | AM7930_MMR1_STG);
294
295 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GX, gx);
296 AM7930_IWRITE16(sc, AM7930_IREG_MAP_STG, stgr);
297 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GR, gr);
298 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GER, ger);
299
300 mutex_exit(&sc->sc_intr_lock);
301
302 return 0;
303 }
304
305 int
306 am7930_halt_output(void *addr)
307 {
308 struct am7930_softc *sc;
309
310 sc = addr;
311 /* XXX only halt, if input is also halted ?? */
312 AM7930_IWRITE(sc, AM7930_IREG_INIT,
313 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE);
314 return 0;
315 }
316
317 int
318 am7930_halt_input(void *addr)
319 {
320 struct am7930_softc *sc;
321
322 sc = addr;
323 /* XXX only halt, if output is also halted ?? */
324 AM7930_IWRITE(sc, AM7930_IREG_INIT,
325 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE);
326 return 0;
327 }
328
329 /*
330 * XXX chip is full-duplex, but really attach-dependent.
331 * For now we know of no half-duplex attachments.
332 */
333 int
334 am7930_get_props(void *addr)
335 {
336
337 return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE |
338 AUDIO_PROP_FULLDUPLEX;
339 }
340
341 /*
342 * Attach-dependent channel set/query
343 */
344 int
345 am7930_set_port(void *addr, mixer_ctrl_t *cp)
346 {
347 struct am7930_softc *sc;
348
349 DPRINTF(("am7930_set_port: port=%d", cp->dev));
350 sc = addr;
351 if (cp->dev == AUDIOAMD_RECORD_SOURCE ||
352 cp->dev == AUDIOAMD_MONITOR_OUTPUT ||
353 cp->dev == AUDIOAMD_MIC_MUTE) {
354 if (cp->type != AUDIO_MIXER_ENUM)
355 return EINVAL;
356 } else if (cp->type != AUDIO_MIXER_VALUE ||
357 cp->un.value.num_channels != 1) {
358 return EINVAL;
359 }
360
361 switch(cp->dev) {
362 case AUDIOAMD_MIC_VOL:
363 sc->sc_rlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
364 break;
365 case AUDIOAMD_SPEAKER_VOL:
366 case AUDIOAMD_HEADPHONES_VOL:
367 sc->sc_plevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
368 break;
369 case AUDIOAMD_MONITOR_VOL:
370 sc->sc_mlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
371 break;
372 case AUDIOAMD_RECORD_SOURCE:
373 if (cp->un.ord != AUDIOAMD_MIC_VOL)
374 return EINVAL;
375 break;
376 case AUDIOAMD_MIC_MUTE:
377 sc->sc_mic_mute = cp->un.ord;
378 break;
379 case AUDIOAMD_MONITOR_OUTPUT:
380 if (cp->un.ord != AUDIOAMD_SPEAKER_VOL &&
381 cp->un.ord != AUDIOAMD_HEADPHONES_VOL)
382 return EINVAL;
383 sc->sc_out_port = cp->un.ord;
384 break;
385 default:
386 return EINVAL;
387 /* NOTREACHED */
388 }
389 return 0;
390 }
391
392 int
393 am7930_get_port(void *addr, mixer_ctrl_t *cp)
394 {
395 struct am7930_softc *sc;
396
397 DPRINTF(("am7930_get_port: port=%d\n", cp->dev));
398 sc = addr;
399 if (cp->dev == AUDIOAMD_RECORD_SOURCE ||
400 cp->dev == AUDIOAMD_MONITOR_OUTPUT ||
401 cp->dev == AUDIOAMD_MIC_MUTE) {
402 if (cp->type != AUDIO_MIXER_ENUM)
403 return EINVAL;
404 } else if (cp->type != AUDIO_MIXER_VALUE ||
405 cp->un.value.num_channels != 1) {
406 return EINVAL;
407 }
408
409 switch(cp->dev) {
410 case AUDIOAMD_MIC_VOL:
411 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_rlevel;
412 break;
413 case AUDIOAMD_SPEAKER_VOL:
414 case AUDIOAMD_HEADPHONES_VOL:
415 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_plevel;
416 break;
417 case AUDIOAMD_MONITOR_VOL:
418 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_mlevel;
419 break;
420 case AUDIOAMD_RECORD_SOURCE:
421 cp->un.ord = AUDIOAMD_MIC_VOL;
422 break;
423 case AUDIOAMD_MIC_MUTE:
424 cp->un.ord = sc->sc_mic_mute;
425 break;
426 case AUDIOAMD_MONITOR_OUTPUT:
427 cp->un.ord = sc->sc_out_port;
428 break;
429 default:
430 return EINVAL;
431 /* NOTREACHED */
432 }
433 return 0;
434 }
435
436
437 /*
438 * Define mixer control facilities.
439 */
440 int
441 am7930_query_devinfo(void *addr, mixer_devinfo_t *dip)
442 {
443
444 DPRINTF(("am7930_query_devinfo()\n"));
445
446 switch(dip->index) {
447 case AUDIOAMD_MIC_VOL:
448 dip->type = AUDIO_MIXER_VALUE;
449 dip->mixer_class = AUDIOAMD_INPUT_CLASS;
450 dip->prev = AUDIO_MIXER_LAST;
451 dip->next = AUDIOAMD_MIC_MUTE;
452 strcpy(dip->label.name, AudioNmicrophone);
453 dip->un.v.num_channels = 1;
454 strcpy(dip->un.v.units.name, AudioNvolume);
455 break;
456 case AUDIOAMD_SPEAKER_VOL:
457 dip->type = AUDIO_MIXER_VALUE;
458 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS;
459 dip->prev = dip->next = AUDIO_MIXER_LAST;
460 strcpy(dip->label.name, AudioNspeaker);
461 dip->un.v.num_channels = 1;
462 strcpy(dip->un.v.units.name, AudioNvolume);
463 break;
464 case AUDIOAMD_HEADPHONES_VOL:
465 dip->type = AUDIO_MIXER_VALUE;
466 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS;
467 dip->prev = dip->next = AUDIO_MIXER_LAST;
468 strcpy(dip->label.name, AudioNheadphone);
469 dip->un.v.num_channels = 1;
470 strcpy(dip->un.v.units.name, AudioNvolume);
471 break;
472 case AUDIOAMD_MONITOR_VOL:
473 dip->type = AUDIO_MIXER_VALUE;
474 dip->mixer_class = AUDIOAMD_MONITOR_CLASS;
475 dip->prev = dip->next = AUDIO_MIXER_LAST;
476 strcpy(dip->label.name, AudioNmonitor);
477 dip->un.v.num_channels = 1;
478 strcpy(dip->un.v.units.name, AudioNvolume);
479 break;
480 case AUDIOAMD_RECORD_SOURCE:
481 dip->type = AUDIO_MIXER_ENUM;
482 dip->mixer_class = AUDIOAMD_RECORD_CLASS;
483 dip->next = dip->prev = AUDIO_MIXER_LAST;
484 strcpy(dip->label.name, AudioNsource);
485 dip->un.e.num_mem = 1;
486 strcpy(dip->un.e.member[0].label.name, AudioNmicrophone);
487 dip->un.e.member[0].ord = AUDIOAMD_MIC_VOL;
488 break;
489 case AUDIOAMD_MONITOR_OUTPUT:
490 dip->type = AUDIO_MIXER_ENUM;
491 dip->mixer_class = AUDIOAMD_MONITOR_CLASS;
492 dip->next = dip->prev = AUDIO_MIXER_LAST;
493 strcpy(dip->label.name, AudioNoutput);
494 dip->un.e.num_mem = 2;
495 strcpy(dip->un.e.member[0].label.name, AudioNspeaker);
496 dip->un.e.member[0].ord = AUDIOAMD_SPEAKER_VOL;
497 strcpy(dip->un.e.member[1].label.name, AudioNheadphone);
498 dip->un.e.member[1].ord = AUDIOAMD_HEADPHONES_VOL;
499 break;
500 case AUDIOAMD_MIC_MUTE:
501 dip->type = AUDIO_MIXER_ENUM;
502 dip->mixer_class = AUDIOAMD_INPUT_CLASS;
503 dip->prev = AUDIOAMD_MIC_VOL;
504 dip->next = AUDIO_MIXER_LAST;
505 strcpy(dip->label.name, AudioNmute);
506 dip->un.e.num_mem = 2;
507 strcpy(dip->un.e.member[0].label.name, AudioNoff);
508 dip->un.e.member[0].ord = 0;
509 strcpy(dip->un.e.member[1].label.name, AudioNon);
510 dip->un.e.member[1].ord = 1;
511 break;
512 case AUDIOAMD_INPUT_CLASS:
513 dip->type = AUDIO_MIXER_CLASS;
514 dip->mixer_class = AUDIOAMD_INPUT_CLASS;
515 dip->next = dip->prev = AUDIO_MIXER_LAST;
516 strcpy(dip->label.name, AudioCinputs);
517 break;
518 case AUDIOAMD_OUTPUT_CLASS:
519 dip->type = AUDIO_MIXER_CLASS;
520 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS;
521 dip->next = dip->prev = AUDIO_MIXER_LAST;
522 strcpy(dip->label.name, AudioCoutputs);
523 break;
524 case AUDIOAMD_RECORD_CLASS:
525 dip->type = AUDIO_MIXER_CLASS;
526 dip->mixer_class = AUDIOAMD_RECORD_CLASS;
527 dip->next = dip->prev = AUDIO_MIXER_LAST;
528 strcpy(dip->label.name, AudioCrecord);
529 break;
530 case AUDIOAMD_MONITOR_CLASS:
531 dip->type = AUDIO_MIXER_CLASS;
532 dip->mixer_class = AUDIOAMD_MONITOR_CLASS;
533 dip->next = dip->prev = AUDIO_MIXER_LAST;
534 strcpy(dip->label.name, AudioCmonitor);
535 break;
536 default:
537 return ENXIO;
538 /*NOTREACHED*/
539 }
540
541 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
542
543 return 0;
544 }
545
546 #endif /* NAUDIO */
547