am7930.c revision 1.47
1/* $NetBSD: am7930.c,v 1.47 2005/01/15 15:19:52 kent 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.47 2005/01/15 15:19:52 kent 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 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 140 141/* 142 * Reset chip and set boot-time softc defaults. 143 */ 144void 145am7930_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} 194 195int 196am7930_open(void *addr, int flags) 197{ 198 struct am7930_softc *sc; 199 200 sc = addr; 201 DPRINTF(("sa_open: unit %p\n", sc)); 202 sc->sc_glue->onopen(sc); 203 DPRINTF(("saopen: ok -> sc=0x%p\n",sc)); 204 return 0; 205} 206 207void 208am7930_close(void *addr) 209{ 210 struct am7930_softc *sc; 211 212 sc = addr; 213 DPRINTF(("sa_close: sc=%p\n", sc)); 214 sc->sc_glue->onclose(sc); 215 DPRINTF(("sa_close: closed.\n")); 216} 217 218/* 219 * XXX should be extended to handle a few of the more common formats. 220 */ 221int 222am7930_set_params(void *addr, int setmode, int usemode, audio_params_t *p, 223 audio_params_t *r, stream_filter_list_t *pfil, stream_filter_list_t *rfil) 224{ 225 audio_params_t hw; 226 struct am7930_softc *sc; 227 228 sc = addr; 229 if ((usemode & AUMODE_PLAY) == AUMODE_PLAY) { 230 if (p->sample_rate < 7500 || p->sample_rate > 8500 || 231 p->encoding != AUDIO_ENCODING_ULAW || 232 p->precision != 8 || 233 p->channels != 1) 234 return EINVAL; 235 p->sample_rate = 8000; 236 if (sc->sc_glue->output_conv != NULL) { 237 hw = *p; 238 hw.encoding = AUDIO_ENCODING_NONE; 239 hw.precision *= sc->sc_glue->factor; 240 pfil->append(pfil, sc->sc_glue->output_conv, &hw); 241 } 242 } 243 if ((usemode & AUMODE_RECORD) == AUMODE_RECORD) { 244 if (r->sample_rate < 7500 || r->sample_rate > 8500 || 245 r->encoding != AUDIO_ENCODING_ULAW || 246 r->precision != 8 || 247 r->channels != 1) 248 return EINVAL; 249 r->sample_rate = 8000; 250 if (sc->sc_glue->input_conv != NULL) { 251 hw = *r; 252 hw.encoding = AUDIO_ENCODING_NONE; 253 hw.precision *= sc->sc_glue->factor; 254 pfil->append(rfil, sc->sc_glue->input_conv, &hw); 255 } 256 } 257 258 return 0; 259} 260 261int 262am7930_query_encoding(void *addr, struct audio_encoding *fp) 263{ 264 switch (fp->index) { 265 case 0: 266 strcpy(fp->name, AudioEmulaw); 267 fp->encoding = AUDIO_ENCODING_ULAW; 268 fp->precision = 8; 269 fp->flags = 0; 270 break; 271 default: 272 return EINVAL; 273 /*NOTREACHED*/ 274 } 275 return 0; 276} 277 278int 279am7930_round_blocksize(void *addr, int blk, 280 int mode, const audio_params_t *param) 281{ 282 return blk; 283} 284 285int 286am7930_commit_settings(void *addr) 287{ 288 struct am7930_softc *sc; 289 uint16_t ger, gr, gx, stgr; 290 uint8_t mmr2, mmr3; 291 int s, level; 292 293 DPRINTF(("sa_commit.\n")); 294 sc = addr; 295 gx = gx_coeff[sc->sc_rlevel]; 296 stgr = gx_coeff[sc->sc_mlevel]; 297 298 level = (sc->sc_plevel * (256 + NGER)) >> 8; 299 if (level >= 256) { 300 ger = ger_coeff[level - 256]; 301 gr = gx_coeff[255]; 302 } else { 303 ger = ger_coeff[0]; 304 gr = gx_coeff[level]; 305 } 306 307 s = splaudio(); 308 309 mmr2 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR2); 310 if (sc->sc_out_port == AUDIOAMD_SPEAKER_VOL) 311 mmr2 |= AM7930_MMR2_LS; 312 else 313 mmr2 &= ~AM7930_MMR2_LS; 314 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR2, mmr2); 315 316 mmr3 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR3); 317 if (sc->sc_mic_mute) 318 mmr3 |= AM7930_MMR3_MUTE; 319 else 320 mmr3 &= ~AM7930_MMR3_MUTE; 321 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR3, mmr3); 322 323 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR1, 324 AM7930_MMR1_GX | AM7930_MMR1_GER | 325 AM7930_MMR1_GR | AM7930_MMR1_STG); 326 327 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GX, gx); 328 AM7930_IWRITE16(sc, AM7930_IREG_MAP_STG, stgr); 329 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GR, gr); 330 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GER, ger); 331 332 splx(s); 333 334 return 0; 335} 336 337int 338am7930_halt_output(void *addr) 339{ 340 struct am7930_softc *sc; 341 342 sc = addr; 343 /* XXX only halt, if input is also halted ?? */ 344 AM7930_IWRITE(sc, AM7930_IREG_INIT, 345 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); 346 return 0; 347} 348 349int 350am7930_halt_input(void *addr) 351{ 352 struct am7930_softc *sc; 353 354 sc = addr; 355 /* XXX only halt, if output is also halted ?? */ 356 AM7930_IWRITE(sc, AM7930_IREG_INIT, 357 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); 358 return 0; 359} 360 361/* 362 * XXX chip is full-duplex, but really attach-dependent. 363 * For now we know of no half-duplex attachments. 364 */ 365int 366am7930_get_props(void *addr) 367{ 368 return AUDIO_PROP_FULLDUPLEX; 369} 370 371/* 372 * Attach-dependent channel set/query 373 */ 374int 375am7930_set_port(void *addr, mixer_ctrl_t *cp) 376{ 377 struct am7930_softc *sc; 378 379 DPRINTF(("am7930_set_port: port=%d", cp->dev)); 380 sc = addr; 381 if (cp->dev == AUDIOAMD_RECORD_SOURCE || 382 cp->dev == AUDIOAMD_MONITOR_OUTPUT || 383 cp->dev == AUDIOAMD_MIC_MUTE) { 384 if (cp->type != AUDIO_MIXER_ENUM) 385 return EINVAL; 386 } else if (cp->type != AUDIO_MIXER_VALUE || 387 cp->un.value.num_channels != 1) { 388 return EINVAL; 389 } 390 391 switch(cp->dev) { 392 case AUDIOAMD_MIC_VOL: 393 sc->sc_rlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 394 break; 395 case AUDIOAMD_SPEAKER_VOL: 396 case AUDIOAMD_HEADPHONES_VOL: 397 sc->sc_plevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 398 break; 399 case AUDIOAMD_MONITOR_VOL: 400 sc->sc_mlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 401 break; 402 case AUDIOAMD_RECORD_SOURCE: 403 if (cp->un.ord != AUDIOAMD_MIC_VOL) 404 return EINVAL; 405 break; 406 case AUDIOAMD_MIC_MUTE: 407 sc->sc_mic_mute = cp->un.ord; 408 break; 409 case AUDIOAMD_MONITOR_OUTPUT: 410 if (cp->un.ord != AUDIOAMD_SPEAKER_VOL && 411 cp->un.ord != AUDIOAMD_HEADPHONES_VOL) 412 return EINVAL; 413 sc->sc_out_port = cp->un.ord; 414 break; 415 default: 416 return EINVAL; 417 /* NOTREACHED */ 418 } 419 return 0; 420} 421 422int 423am7930_get_port(void *addr, mixer_ctrl_t *cp) 424{ 425 struct am7930_softc *sc; 426 427 DPRINTF(("am7930_get_port: port=%d\n", cp->dev)); 428 sc = addr; 429 if (cp->dev == AUDIOAMD_RECORD_SOURCE || 430 cp->dev == AUDIOAMD_MONITOR_OUTPUT || 431 cp->dev == AUDIOAMD_MIC_MUTE) { 432 if (cp->type != AUDIO_MIXER_ENUM) 433 return EINVAL; 434 } else if (cp->type != AUDIO_MIXER_VALUE || 435 cp->un.value.num_channels != 1) { 436 return EINVAL; 437 } 438 439 switch(cp->dev) { 440 case AUDIOAMD_MIC_VOL: 441 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_rlevel; 442 break; 443 case AUDIOAMD_SPEAKER_VOL: 444 case AUDIOAMD_HEADPHONES_VOL: 445 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_plevel; 446 break; 447 case AUDIOAMD_MONITOR_VOL: 448 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_mlevel; 449 break; 450 case AUDIOAMD_RECORD_SOURCE: 451 cp->un.ord = AUDIOAMD_MIC_VOL; 452 break; 453 case AUDIOAMD_MIC_MUTE: 454 cp->un.ord = sc->sc_mic_mute; 455 break; 456 case AUDIOAMD_MONITOR_OUTPUT: 457 cp->un.ord = sc->sc_out_port; 458 break; 459 default: 460 return EINVAL; 461 /* NOTREACHED */ 462 } 463 return 0; 464} 465 466 467/* 468 * Define mixer control facilities. 469 */ 470int 471am7930_query_devinfo(void *addr, mixer_devinfo_t *dip) 472{ 473 474 DPRINTF(("am7930_query_devinfo()\n")); 475 476 switch(dip->index) { 477 case AUDIOAMD_MIC_VOL: 478 dip->type = AUDIO_MIXER_VALUE; 479 dip->mixer_class = AUDIOAMD_INPUT_CLASS; 480 dip->prev = AUDIO_MIXER_LAST; 481 dip->next = AUDIOAMD_MIC_MUTE; 482 strcpy(dip->label.name, AudioNmicrophone); 483 dip->un.v.num_channels = 1; 484 strcpy(dip->un.v.units.name, AudioNvolume); 485 break; 486 case AUDIOAMD_SPEAKER_VOL: 487 dip->type = AUDIO_MIXER_VALUE; 488 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS; 489 dip->prev = dip->next = AUDIO_MIXER_LAST; 490 strcpy(dip->label.name, AudioNspeaker); 491 dip->un.v.num_channels = 1; 492 strcpy(dip->un.v.units.name, AudioNvolume); 493 break; 494 case AUDIOAMD_HEADPHONES_VOL: 495 dip->type = AUDIO_MIXER_VALUE; 496 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS; 497 dip->prev = dip->next = AUDIO_MIXER_LAST; 498 strcpy(dip->label.name, AudioNheadphone); 499 dip->un.v.num_channels = 1; 500 strcpy(dip->un.v.units.name, AudioNvolume); 501 break; 502 case AUDIOAMD_MONITOR_VOL: 503 dip->type = AUDIO_MIXER_VALUE; 504 dip->mixer_class = AUDIOAMD_MONITOR_CLASS; 505 dip->prev = dip->next = AUDIO_MIXER_LAST; 506 strcpy(dip->label.name, AudioNmonitor); 507 dip->un.v.num_channels = 1; 508 strcpy(dip->un.v.units.name, AudioNvolume); 509 break; 510 case AUDIOAMD_RECORD_SOURCE: 511 dip->type = AUDIO_MIXER_ENUM; 512 dip->mixer_class = AUDIOAMD_RECORD_CLASS; 513 dip->next = dip->prev = AUDIO_MIXER_LAST; 514 strcpy(dip->label.name, AudioNsource); 515 dip->un.e.num_mem = 1; 516 strcpy(dip->un.e.member[0].label.name, AudioNmicrophone); 517 dip->un.e.member[0].ord = AUDIOAMD_MIC_VOL; 518 break; 519 case AUDIOAMD_MONITOR_OUTPUT: 520 dip->type = AUDIO_MIXER_ENUM; 521 dip->mixer_class = AUDIOAMD_MONITOR_CLASS; 522 dip->next = dip->prev = AUDIO_MIXER_LAST; 523 strcpy(dip->label.name, AudioNoutput); 524 dip->un.e.num_mem = 2; 525 strcpy(dip->un.e.member[0].label.name, AudioNspeaker); 526 dip->un.e.member[0].ord = AUDIOAMD_SPEAKER_VOL; 527 strcpy(dip->un.e.member[1].label.name, AudioNheadphone); 528 dip->un.e.member[1].ord = AUDIOAMD_HEADPHONES_VOL; 529 break; 530 case AUDIOAMD_MIC_MUTE: 531 dip->type = AUDIO_MIXER_ENUM; 532 dip->mixer_class = AUDIOAMD_INPUT_CLASS; 533 dip->prev = AUDIOAMD_MIC_VOL; 534 dip->next = AUDIO_MIXER_LAST; 535 strcpy(dip->label.name, AudioNmute); 536 dip->un.e.num_mem = 2; 537 strcpy(dip->un.e.member[0].label.name, AudioNoff); 538 dip->un.e.member[0].ord = 0; 539 strcpy(dip->un.e.member[1].label.name, AudioNon); 540 dip->un.e.member[1].ord = 1; 541 break; 542 case AUDIOAMD_INPUT_CLASS: 543 dip->type = AUDIO_MIXER_CLASS; 544 dip->mixer_class = AUDIOAMD_INPUT_CLASS; 545 dip->next = dip->prev = AUDIO_MIXER_LAST; 546 strcpy(dip->label.name, AudioCinputs); 547 break; 548 case AUDIOAMD_OUTPUT_CLASS: 549 dip->type = AUDIO_MIXER_CLASS; 550 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS; 551 dip->next = dip->prev = AUDIO_MIXER_LAST; 552 strcpy(dip->label.name, AudioCoutputs); 553 break; 554 case AUDIOAMD_RECORD_CLASS: 555 dip->type = AUDIO_MIXER_CLASS; 556 dip->mixer_class = AUDIOAMD_RECORD_CLASS; 557 dip->next = dip->prev = AUDIO_MIXER_LAST; 558 strcpy(dip->label.name, AudioCrecord); 559 break; 560 case AUDIOAMD_MONITOR_CLASS: 561 dip->type = AUDIO_MIXER_CLASS; 562 dip->mixer_class = AUDIOAMD_MONITOR_CLASS; 563 dip->next = dip->prev = AUDIO_MIXER_LAST; 564 strcpy(dip->label.name, AudioCmonitor); 565 break; 566 default: 567 return ENXIO; 568 /*NOTREACHED*/ 569 } 570 571 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); 572 573 return 0; 574} 575 576#endif /* NAUDIO */ 577