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