1 /* $NetBSD: am7930.c,v 1.44 2001/11/13 13:14:34 lukem 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.44 2001/11/13 13:14:34 lukem 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 <machine/bus.h> 52 #include <machine/autoconf.h> 53 #include <machine/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 u_short 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 u_short 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(sc, flag) 146 struct am7930_softc *sc; 147 int flag; 148 { 149 150 DPRINTF(("am7930_init()\n")); 151 152 /* set boot defaults */ 153 sc->sc_rlevel = 128; 154 sc->sc_plevel = 128; 155 sc->sc_mlevel = 0; 156 sc->sc_out_port = AUDIOAMD_SPEAKER_VOL; 157 sc->sc_mic_mute = 0; 158 159 /* disable sample interrupts */ 160 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4, 0); 161 162 /* initialise voice and data, and disable interrupts */ 163 AM7930_IWRITE(sc, AM7930_IREG_INIT, 164 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); 165 166 if (flag == AUDIOAMD_DMA_MODE) { 167 168 /* configure PP for serial (SBP) mode */ 169 AM7930_IWRITE(sc, AM7930_IREG_PP_PPCR1, AM7930_PPCR1_SBP); 170 171 /* 172 * Initialise the MUX unit - route the MAP to the PP 173 */ 174 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR1, 175 (AM7930_MCRCHAN_BA << 4) | AM7930_MCRCHAN_BD); 176 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR2, AM7930_MCRCHAN_NC); 177 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR3, AM7930_MCRCHAN_NC); 178 179 } else { 180 181 /* 182 * Initialize the MUX unit. We use MCR3 to route the MAP 183 * through channel Bb. MCR1 and MCR2 are unused. 184 * Setting the INT enable bit in MCR4 will generate an 185 * interrupt on each converted audio sample. 186 */ 187 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR1, 0); 188 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR2, 0); 189 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR3, 190 (AM7930_MCRCHAN_BB << 4) | AM7930_MCRCHAN_BA); 191 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4, 192 AM7930_MCR4_INT_ENABLE); 193 } 194 195 } 196 197 198 int 199 am7930_open(addr, flags) 200 void *addr; 201 int flags; 202 { 203 struct am7930_softc *sc = addr; 204 205 DPRINTF(("sa_open: unit %p\n", sc)); 206 207 if (sc->sc_open) 208 return (EBUSY); 209 sc->sc_open = 1; 210 sc->sc_locked = 0; 211 212 sc->sc_glue->onopen(sc); 213 214 DPRINTF(("saopen: ok -> sc=0x%p\n",sc)); 215 216 return (0); 217 } 218 219 void 220 am7930_close(addr) 221 void *addr; 222 { 223 struct am7930_softc *sc = addr; 224 225 DPRINTF(("sa_close: sc=%p\n", sc)); 226 227 sc->sc_glue->onclose(sc); 228 sc->sc_open = 0; 229 230 DPRINTF(("sa_close: closed.\n")); 231 } 232 233 234 /* 235 * XXX should be extended to handle a few of the more common formats. 236 */ 237 int 238 am7930_set_params(addr, setmode, usemode, p, r) 239 void *addr; 240 int setmode, usemode; 241 struct audio_params *p, *r; 242 { 243 struct am7930_softc *sc = addr; 244 245 if ((usemode & AUMODE_PLAY) == AUMODE_PLAY) { 246 if (p->sample_rate < 7500 || p->sample_rate > 8500 || 247 p->encoding != AUDIO_ENCODING_ULAW || 248 p->precision != 8 || 249 p->channels != 1) 250 return EINVAL; 251 p->sample_rate = 8000; 252 if (sc->sc_glue->factor > 1) { 253 p->factor = sc->sc_glue->factor; 254 p->sw_code = sc->sc_glue->output_conv; 255 } 256 } 257 if ((usemode & AUMODE_RECORD) == AUMODE_RECORD) { 258 if (r->sample_rate < 7500 || r->sample_rate > 8500 || 259 r->encoding != AUDIO_ENCODING_ULAW || 260 r->precision != 8 || 261 r->channels != 1) 262 return EINVAL; 263 r->sample_rate = 8000; 264 if (sc->sc_glue->factor > 1) { 265 r->factor = sc->sc_glue->factor; 266 r->sw_code = sc->sc_glue->input_conv; 267 } 268 } 269 270 return 0; 271 } 272 273 int 274 am7930_query_encoding(addr, fp) 275 void *addr; 276 struct audio_encoding *fp; 277 { 278 switch (fp->index) { /* ??? */ 279 case 0: 280 strcpy(fp->name, AudioEmulaw); 281 fp->encoding = AUDIO_ENCODING_ULAW; 282 fp->precision = 8; 283 fp->flags = 0; 284 break; 285 default: 286 return(EINVAL); 287 /*NOTREACHED*/ 288 } 289 return(0); 290 } 291 292 293 int 294 am7930_round_blocksize(addr, blk) 295 void *addr; 296 int blk; 297 { 298 return(blk); 299 } 300 301 302 int 303 am7930_commit_settings(addr) 304 void *addr; 305 { 306 struct am7930_softc *sc = addr; 307 u_int16_t ger, gr, gx, stgr; 308 u_int8_t mmr2, mmr3; 309 int s, level; 310 311 DPRINTF(("sa_commit.\n")); 312 313 gx = gx_coeff[sc->sc_rlevel]; 314 stgr = gx_coeff[sc->sc_mlevel]; 315 316 level = (sc->sc_plevel * (256 + NGER)) >> 8; 317 if (level >= 256) { 318 ger = ger_coeff[level - 256]; 319 gr = gx_coeff[255]; 320 } else { 321 ger = ger_coeff[0]; 322 gr = gx_coeff[level]; 323 } 324 325 s = splaudio(); 326 327 mmr2 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR2); 328 if (sc->sc_out_port == AUDIOAMD_SPEAKER_VOL) 329 mmr2 |= AM7930_MMR2_LS; 330 else 331 mmr2 &= ~AM7930_MMR2_LS; 332 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR2, mmr2); 333 334 mmr3 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR3); 335 if (sc->sc_mic_mute) 336 mmr3 |= AM7930_MMR3_MUTE; 337 else 338 mmr3 &= ~AM7930_MMR3_MUTE; 339 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR3, mmr3); 340 341 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR1, 342 AM7930_MMR1_GX | AM7930_MMR1_GER | 343 AM7930_MMR1_GR | AM7930_MMR1_STG); 344 345 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GX, gx); 346 AM7930_IWRITE16(sc, AM7930_IREG_MAP_STG, stgr); 347 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GR, gr); 348 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GER, ger); 349 350 splx(s); 351 352 return(0); 353 } 354 355 356 int 357 am7930_halt_output(addr) 358 void *addr; 359 { 360 struct am7930_softc *sc = addr; 361 362 /* XXX only halt, if input is also halted ?? */ 363 AM7930_IWRITE(sc, AM7930_IREG_INIT, 364 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); 365 sc->sc_locked = 0; 366 367 return(0); 368 } 369 370 371 int 372 am7930_halt_input(addr) 373 void *addr; 374 { 375 struct am7930_softc *sc = addr; 376 377 /* XXX only halt, if output is also halted ?? */ 378 AM7930_IWRITE(sc, AM7930_IREG_INIT, 379 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); 380 sc->sc_locked = 0; 381 382 return(0); 383 } 384 385 386 /* 387 * XXX chip is full-duplex, but really attach-dependent. 388 * For now we know of no half-duplex attachments. 389 */ 390 int 391 am7930_get_props(addr) 392 void *addr; 393 { 394 return AUDIO_PROP_FULLDUPLEX; 395 } 396 397 /* 398 * Attach-dependent channel set/query 399 */ 400 int 401 am7930_set_port(addr, cp) 402 void *addr; 403 mixer_ctrl_t *cp; 404 { 405 struct am7930_softc *sc = addr; 406 407 DPRINTF(("am7930_set_port: port=%d", cp->dev)); 408 409 if (cp->dev == AUDIOAMD_RECORD_SOURCE || 410 cp->dev == AUDIOAMD_MONITOR_OUTPUT || 411 cp->dev == AUDIOAMD_MIC_MUTE) { 412 if (cp->type != AUDIO_MIXER_ENUM) 413 return(EINVAL); 414 } else if (cp->type != AUDIO_MIXER_VALUE || 415 cp->un.value.num_channels != 1) { 416 return(EINVAL); 417 } 418 419 switch(cp->dev) { 420 case AUDIOAMD_MIC_VOL: 421 sc->sc_rlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 422 break; 423 case AUDIOAMD_SPEAKER_VOL: 424 case AUDIOAMD_HEADPHONES_VOL: 425 sc->sc_plevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 426 break; 427 case AUDIOAMD_MONITOR_VOL: 428 sc->sc_mlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 429 break; 430 case AUDIOAMD_RECORD_SOURCE: 431 if (cp->un.ord != AUDIOAMD_MIC_VOL) 432 return EINVAL; 433 break; 434 case AUDIOAMD_MIC_MUTE: 435 sc->sc_mic_mute = cp->un.ord; 436 break; 437 case AUDIOAMD_MONITOR_OUTPUT: 438 if (cp->un.ord != AUDIOAMD_SPEAKER_VOL && 439 cp->un.ord != AUDIOAMD_HEADPHONES_VOL) 440 return EINVAL; 441 sc->sc_out_port = cp->un.ord; 442 break; 443 default: 444 return(EINVAL); 445 /* NOTREACHED */ 446 } 447 return 0; 448 } 449 450 int 451 am7930_get_port(addr, cp) 452 void *addr; 453 mixer_ctrl_t *cp; 454 { 455 struct am7930_softc *sc = addr; 456 457 DPRINTF(("am7930_get_port: port=%d\n", cp->dev)); 458 459 if (cp->dev == AUDIOAMD_RECORD_SOURCE || 460 cp->dev == AUDIOAMD_MONITOR_OUTPUT || 461 cp->dev == AUDIOAMD_MIC_MUTE) { 462 if (cp->type != AUDIO_MIXER_ENUM) 463 return(EINVAL); 464 } else if (cp->type != AUDIO_MIXER_VALUE || 465 cp->un.value.num_channels != 1) { 466 return(EINVAL); 467 } 468 469 switch(cp->dev) { 470 case AUDIOAMD_MIC_VOL: 471 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_rlevel; 472 break; 473 case AUDIOAMD_SPEAKER_VOL: 474 case AUDIOAMD_HEADPHONES_VOL: 475 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_plevel; 476 break; 477 case AUDIOAMD_MONITOR_VOL: 478 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_mlevel; 479 break; 480 case AUDIOAMD_RECORD_SOURCE: 481 cp->un.ord = AUDIOAMD_MIC_VOL; 482 break; 483 case AUDIOAMD_MIC_MUTE: 484 cp->un.ord = sc->sc_mic_mute; 485 break; 486 case AUDIOAMD_MONITOR_OUTPUT: 487 cp->un.ord = sc->sc_out_port; 488 break; 489 default: 490 return(EINVAL); 491 /* NOTREACHED */ 492 } 493 return 0; 494 } 495 496 497 /* 498 * Define mixer control facilities. 499 */ 500 int 501 am7930_query_devinfo(addr, dip) 502 void *addr; 503 mixer_devinfo_t *dip; 504 { 505 506 DPRINTF(("am7930_query_devinfo()\n")); 507 508 switch(dip->index) { 509 case AUDIOAMD_MIC_VOL: 510 dip->type = AUDIO_MIXER_VALUE; 511 dip->mixer_class = AUDIOAMD_INPUT_CLASS; 512 dip->prev = AUDIO_MIXER_LAST; 513 dip->next = AUDIOAMD_MIC_MUTE; 514 strcpy(dip->label.name, AudioNmicrophone); 515 dip->un.v.num_channels = 1; 516 strcpy(dip->un.v.units.name, AudioNvolume); 517 break; 518 case AUDIOAMD_SPEAKER_VOL: 519 dip->type = AUDIO_MIXER_VALUE; 520 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS; 521 dip->prev = dip->next = AUDIO_MIXER_LAST; 522 strcpy(dip->label.name, AudioNspeaker); 523 dip->un.v.num_channels = 1; 524 strcpy(dip->un.v.units.name, AudioNvolume); 525 break; 526 case AUDIOAMD_HEADPHONES_VOL: 527 dip->type = AUDIO_MIXER_VALUE; 528 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS; 529 dip->prev = dip->next = AUDIO_MIXER_LAST; 530 strcpy(dip->label.name, AudioNheadphone); 531 dip->un.v.num_channels = 1; 532 strcpy(dip->un.v.units.name, AudioNvolume); 533 break; 534 case AUDIOAMD_MONITOR_VOL: 535 dip->type = AUDIO_MIXER_VALUE; 536 dip->mixer_class = AUDIOAMD_MONITOR_CLASS; 537 dip->prev = dip->next = AUDIO_MIXER_LAST; 538 strcpy(dip->label.name, AudioNmonitor); 539 dip->un.v.num_channels = 1; 540 strcpy(dip->un.v.units.name, AudioNvolume); 541 break; 542 case AUDIOAMD_RECORD_SOURCE: 543 dip->type = AUDIO_MIXER_ENUM; 544 dip->mixer_class = AUDIOAMD_RECORD_CLASS; 545 dip->next = dip->prev = AUDIO_MIXER_LAST; 546 strcpy(dip->label.name, AudioNsource); 547 dip->un.e.num_mem = 1; 548 strcpy(dip->un.e.member[0].label.name, AudioNmicrophone); 549 dip->un.e.member[0].ord = AUDIOAMD_MIC_VOL; 550 break; 551 case AUDIOAMD_MONITOR_OUTPUT: 552 dip->type = AUDIO_MIXER_ENUM; 553 dip->mixer_class = AUDIOAMD_MONITOR_CLASS; 554 dip->next = dip->prev = AUDIO_MIXER_LAST; 555 strcpy(dip->label.name, AudioNoutput); 556 dip->un.e.num_mem = 2; 557 strcpy(dip->un.e.member[0].label.name, AudioNspeaker); 558 dip->un.e.member[0].ord = AUDIOAMD_SPEAKER_VOL; 559 strcpy(dip->un.e.member[1].label.name, AudioNheadphone); 560 dip->un.e.member[1].ord = AUDIOAMD_HEADPHONES_VOL; 561 break; 562 case AUDIOAMD_MIC_MUTE: 563 dip->type = AUDIO_MIXER_ENUM; 564 dip->mixer_class = AUDIOAMD_INPUT_CLASS; 565 dip->prev = AUDIOAMD_MIC_VOL; 566 dip->next = AUDIO_MIXER_LAST; 567 strcpy(dip->label.name, AudioNmute); 568 dip->un.e.num_mem = 2; 569 strcpy(dip->un.e.member[0].label.name, AudioNoff); 570 dip->un.e.member[0].ord = 0; 571 strcpy(dip->un.e.member[1].label.name, AudioNon); 572 dip->un.e.member[1].ord = 1; 573 break; 574 case AUDIOAMD_INPUT_CLASS: 575 dip->type = AUDIO_MIXER_CLASS; 576 dip->mixer_class = AUDIOAMD_INPUT_CLASS; 577 dip->next = dip->prev = AUDIO_MIXER_LAST; 578 strcpy(dip->label.name, AudioCinputs); 579 break; 580 case AUDIOAMD_OUTPUT_CLASS: 581 dip->type = AUDIO_MIXER_CLASS; 582 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS; 583 dip->next = dip->prev = AUDIO_MIXER_LAST; 584 strcpy(dip->label.name, AudioCoutputs); 585 break; 586 case AUDIOAMD_RECORD_CLASS: 587 dip->type = AUDIO_MIXER_CLASS; 588 dip->mixer_class = AUDIOAMD_RECORD_CLASS; 589 dip->next = dip->prev = AUDIO_MIXER_LAST; 590 strcpy(dip->label.name, AudioCrecord); 591 break; 592 case AUDIOAMD_MONITOR_CLASS: 593 dip->type = AUDIO_MIXER_CLASS; 594 dip->mixer_class = AUDIOAMD_MONITOR_CLASS; 595 dip->next = dip->prev = AUDIO_MIXER_LAST; 596 strcpy(dip->label.name, AudioCmonitor); 597 break; 598 default: 599 return ENXIO; 600 /*NOTREACHED*/ 601 } 602 603 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); 604 605 return(0); 606 } 607 608 #endif /* NAUDIO */ 609