1 /* $NetBSD: am7930.c,v 1.51 2011/11/23 23:07:32 jmcneill 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.51 2011/11/23 23:07:32 jmcneill 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