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 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 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 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 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 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 280 am7930_round_blocksize(void *addr, int blk, 281 int mode, const audio_params_t *param) 282 { 283 return blk; 284 } 285 286 int 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 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 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 367 am7930_get_props(void *addr) 368 { 369 return AUDIO_PROP_FULLDUPLEX; 370 } 371 372 /* 373 * Attach-dependent channel set/query 374 */ 375 int 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 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 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