1 /* $NetBSD: am7930.c,v 1.53 2016/12/28 10:04:53 nat 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.53 2016/12/28 10:04:53 nat 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 #include <dev/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 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->encoding != AUDIO_ENCODING_SLINEAR) || 235 p->precision != 8 || 236 p->channels != 1) 237 return EINVAL; 238 p->sample_rate = 8000; 239 if (sc->sc_glue->output_conv != NULL) { 240 hw = *p; 241 hw.encoding = AUDIO_ENCODING_NONE; 242 hw.precision *= sc->sc_glue->factor; 243 pfil->append(pfil, sc->sc_glue->output_conv, &hw); 244 } 245 } 246 if ((usemode & AUMODE_RECORD) == AUMODE_RECORD) { 247 if (r->sample_rate < 7500 || r->sample_rate > 8500 || 248 (r->encoding != AUDIO_ENCODING_ULAW && 249 r->encoding != AUDIO_ENCODING_SLINEAR) || 250 r->precision != 8 || 251 r->channels != 1) 252 return EINVAL; 253 r->sample_rate = 8000; 254 if (sc->sc_glue->input_conv != NULL) { 255 hw = *r; 256 hw.encoding = AUDIO_ENCODING_NONE; 257 hw.precision *= sc->sc_glue->factor; 258 pfil->append(rfil, sc->sc_glue->input_conv, &hw); 259 } 260 } 261 262 if (p->encoding == AUDIO_ENCODING_SLINEAR || 263 r->encoding == AUDIO_ENCODING_SLINEAR) { 264 hw.encoding = AUDIO_ENCODING_ULAW; 265 pfil->req_size = rfil->req_size = 0; 266 pfil->append(rfil, mulaw_to_linear8, &hw); 267 rfil->append(pfil, linear8_to_mulaw, &hw); 268 } 269 270 return 0; 271 } 272 273 int 274 am7930_query_encoding(void *addr, struct audio_encoding *fp) 275 { 276 switch (fp->index) { 277 case 0: 278 strcpy(fp->name, AudioEmulaw); 279 fp->encoding = AUDIO_ENCODING_ULAW; 280 fp->precision = 8; 281 fp->flags = 0; 282 break; 283 case 1: 284 strcpy(fp->name, AudioEslinear); 285 fp->encoding = AUDIO_ENCODING_SLINEAR; 286 fp->precision = 8; 287 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 288 break; 289 default: 290 return EINVAL; 291 /*NOTREACHED*/ 292 } 293 return 0; 294 } 295 296 int 297 am7930_round_blocksize(void *addr, int blk, 298 int mode, const audio_params_t *param) 299 { 300 return blk; 301 } 302 303 int 304 am7930_commit_settings(void *addr) 305 { 306 struct am7930_softc *sc; 307 uint16_t ger, gr, gx, stgr; 308 uint8_t mmr2, mmr3; 309 int level; 310 311 DPRINTF(("sa_commit.\n")); 312 sc = addr; 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 mutex_enter(&sc->sc_intr_lock); 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 mutex_exit(&sc->sc_intr_lock); 351 352 return 0; 353 } 354 355 int 356 am7930_halt_output(void *addr) 357 { 358 struct am7930_softc *sc; 359 360 sc = addr; 361 /* XXX only halt, if input is also halted ?? */ 362 AM7930_IWRITE(sc, AM7930_IREG_INIT, 363 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); 364 return 0; 365 } 366 367 int 368 am7930_halt_input(void *addr) 369 { 370 struct am7930_softc *sc; 371 372 sc = addr; 373 /* XXX only halt, if output is also halted ?? */ 374 AM7930_IWRITE(sc, AM7930_IREG_INIT, 375 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); 376 return 0; 377 } 378 379 /* 380 * XXX chip is full-duplex, but really attach-dependent. 381 * For now we know of no half-duplex attachments. 382 */ 383 int 384 am7930_get_props(void *addr) 385 { 386 return AUDIO_PROP_FULLDUPLEX; 387 } 388 389 /* 390 * Attach-dependent channel set/query 391 */ 392 int 393 am7930_set_port(void *addr, mixer_ctrl_t *cp) 394 { 395 struct am7930_softc *sc; 396 397 DPRINTF(("am7930_set_port: port=%d", 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 sc->sc_rlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 412 break; 413 case AUDIOAMD_SPEAKER_VOL: 414 case AUDIOAMD_HEADPHONES_VOL: 415 sc->sc_plevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 416 break; 417 case AUDIOAMD_MONITOR_VOL: 418 sc->sc_mlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 419 break; 420 case AUDIOAMD_RECORD_SOURCE: 421 if (cp->un.ord != AUDIOAMD_MIC_VOL) 422 return EINVAL; 423 break; 424 case AUDIOAMD_MIC_MUTE: 425 sc->sc_mic_mute = cp->un.ord; 426 break; 427 case AUDIOAMD_MONITOR_OUTPUT: 428 if (cp->un.ord != AUDIOAMD_SPEAKER_VOL && 429 cp->un.ord != AUDIOAMD_HEADPHONES_VOL) 430 return EINVAL; 431 sc->sc_out_port = cp->un.ord; 432 break; 433 default: 434 return EINVAL; 435 /* NOTREACHED */ 436 } 437 return 0; 438 } 439 440 int 441 am7930_get_port(void *addr, mixer_ctrl_t *cp) 442 { 443 struct am7930_softc *sc; 444 445 DPRINTF(("am7930_get_port: port=%d\n", cp->dev)); 446 sc = addr; 447 if (cp->dev == AUDIOAMD_RECORD_SOURCE || 448 cp->dev == AUDIOAMD_MONITOR_OUTPUT || 449 cp->dev == AUDIOAMD_MIC_MUTE) { 450 if (cp->type != AUDIO_MIXER_ENUM) 451 return EINVAL; 452 } else if (cp->type != AUDIO_MIXER_VALUE || 453 cp->un.value.num_channels != 1) { 454 return EINVAL; 455 } 456 457 switch(cp->dev) { 458 case AUDIOAMD_MIC_VOL: 459 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_rlevel; 460 break; 461 case AUDIOAMD_SPEAKER_VOL: 462 case AUDIOAMD_HEADPHONES_VOL: 463 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_plevel; 464 break; 465 case AUDIOAMD_MONITOR_VOL: 466 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_mlevel; 467 break; 468 case AUDIOAMD_RECORD_SOURCE: 469 cp->un.ord = AUDIOAMD_MIC_VOL; 470 break; 471 case AUDIOAMD_MIC_MUTE: 472 cp->un.ord = sc->sc_mic_mute; 473 break; 474 case AUDIOAMD_MONITOR_OUTPUT: 475 cp->un.ord = sc->sc_out_port; 476 break; 477 default: 478 return EINVAL; 479 /* NOTREACHED */ 480 } 481 return 0; 482 } 483 484 485 /* 486 * Define mixer control facilities. 487 */ 488 int 489 am7930_query_devinfo(void *addr, mixer_devinfo_t *dip) 490 { 491 492 DPRINTF(("am7930_query_devinfo()\n")); 493 494 switch(dip->index) { 495 case AUDIOAMD_MIC_VOL: 496 dip->type = AUDIO_MIXER_VALUE; 497 dip->mixer_class = AUDIOAMD_INPUT_CLASS; 498 dip->prev = AUDIO_MIXER_LAST; 499 dip->next = AUDIOAMD_MIC_MUTE; 500 strcpy(dip->label.name, AudioNmicrophone); 501 dip->un.v.num_channels = 1; 502 strcpy(dip->un.v.units.name, AudioNvolume); 503 break; 504 case AUDIOAMD_SPEAKER_VOL: 505 dip->type = AUDIO_MIXER_VALUE; 506 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS; 507 dip->prev = dip->next = AUDIO_MIXER_LAST; 508 strcpy(dip->label.name, AudioNspeaker); 509 dip->un.v.num_channels = 1; 510 strcpy(dip->un.v.units.name, AudioNvolume); 511 break; 512 case AUDIOAMD_HEADPHONES_VOL: 513 dip->type = AUDIO_MIXER_VALUE; 514 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS; 515 dip->prev = dip->next = AUDIO_MIXER_LAST; 516 strcpy(dip->label.name, AudioNheadphone); 517 dip->un.v.num_channels = 1; 518 strcpy(dip->un.v.units.name, AudioNvolume); 519 break; 520 case AUDIOAMD_MONITOR_VOL: 521 dip->type = AUDIO_MIXER_VALUE; 522 dip->mixer_class = AUDIOAMD_MONITOR_CLASS; 523 dip->prev = dip->next = AUDIO_MIXER_LAST; 524 strcpy(dip->label.name, AudioNmonitor); 525 dip->un.v.num_channels = 1; 526 strcpy(dip->un.v.units.name, AudioNvolume); 527 break; 528 case AUDIOAMD_RECORD_SOURCE: 529 dip->type = AUDIO_MIXER_ENUM; 530 dip->mixer_class = AUDIOAMD_RECORD_CLASS; 531 dip->next = dip->prev = AUDIO_MIXER_LAST; 532 strcpy(dip->label.name, AudioNsource); 533 dip->un.e.num_mem = 1; 534 strcpy(dip->un.e.member[0].label.name, AudioNmicrophone); 535 dip->un.e.member[0].ord = AUDIOAMD_MIC_VOL; 536 break; 537 case AUDIOAMD_MONITOR_OUTPUT: 538 dip->type = AUDIO_MIXER_ENUM; 539 dip->mixer_class = AUDIOAMD_MONITOR_CLASS; 540 dip->next = dip->prev = AUDIO_MIXER_LAST; 541 strcpy(dip->label.name, AudioNoutput); 542 dip->un.e.num_mem = 2; 543 strcpy(dip->un.e.member[0].label.name, AudioNspeaker); 544 dip->un.e.member[0].ord = AUDIOAMD_SPEAKER_VOL; 545 strcpy(dip->un.e.member[1].label.name, AudioNheadphone); 546 dip->un.e.member[1].ord = AUDIOAMD_HEADPHONES_VOL; 547 break; 548 case AUDIOAMD_MIC_MUTE: 549 dip->type = AUDIO_MIXER_ENUM; 550 dip->mixer_class = AUDIOAMD_INPUT_CLASS; 551 dip->prev = AUDIOAMD_MIC_VOL; 552 dip->next = AUDIO_MIXER_LAST; 553 strcpy(dip->label.name, AudioNmute); 554 dip->un.e.num_mem = 2; 555 strcpy(dip->un.e.member[0].label.name, AudioNoff); 556 dip->un.e.member[0].ord = 0; 557 strcpy(dip->un.e.member[1].label.name, AudioNon); 558 dip->un.e.member[1].ord = 1; 559 break; 560 case AUDIOAMD_INPUT_CLASS: 561 dip->type = AUDIO_MIXER_CLASS; 562 dip->mixer_class = AUDIOAMD_INPUT_CLASS; 563 dip->next = dip->prev = AUDIO_MIXER_LAST; 564 strcpy(dip->label.name, AudioCinputs); 565 break; 566 case AUDIOAMD_OUTPUT_CLASS: 567 dip->type = AUDIO_MIXER_CLASS; 568 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS; 569 dip->next = dip->prev = AUDIO_MIXER_LAST; 570 strcpy(dip->label.name, AudioCoutputs); 571 break; 572 case AUDIOAMD_RECORD_CLASS: 573 dip->type = AUDIO_MIXER_CLASS; 574 dip->mixer_class = AUDIOAMD_RECORD_CLASS; 575 dip->next = dip->prev = AUDIO_MIXER_LAST; 576 strcpy(dip->label.name, AudioCrecord); 577 break; 578 case AUDIOAMD_MONITOR_CLASS: 579 dip->type = AUDIO_MIXER_CLASS; 580 dip->mixer_class = AUDIOAMD_MONITOR_CLASS; 581 dip->next = dip->prev = AUDIO_MIXER_LAST; 582 strcpy(dip->label.name, AudioCmonitor); 583 break; 584 default: 585 return ENXIO; 586 /*NOTREACHED*/ 587 } 588 589 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); 590 591 return 0; 592 } 593 594 #endif /* NAUDIO */ 595