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