1 /* $NetBSD: am7930.c,v 1.59 2019/06/08 08:02:38 isaki 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.59 2019/06/08 08:02:38 isaki 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/audio_if.h> 56 #include <dev/audio/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 static const struct audio_format am7930_format = { 141 .mode = AUMODE_PLAY | AUMODE_RECORD, 142 .encoding = AUDIO_ENCODING_ULAW, 143 .validbits = 8, 144 .precision = 8, 145 .channels = 1, 146 .channel_mask = AUFMT_MONAURAL, 147 .frequency_type = 1, 148 .frequency = { 8000 }, 149 }; 150 151 /* 152 * Reset chip and set boot-time softc defaults. 153 */ 154 void 155 am7930_init(struct am7930_softc *sc, int flag) 156 { 157 158 DPRINTF(("am7930_init()\n")); 159 160 /* set boot defaults */ 161 sc->sc_rlevel = 128; 162 sc->sc_plevel = 128; 163 sc->sc_mlevel = 0; 164 sc->sc_out_port = AUDIOAMD_SPEAKER_VOL; 165 sc->sc_mic_mute = 0; 166 167 /* disable sample interrupts */ 168 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4, 0); 169 170 /* initialise voice and data, and disable interrupts */ 171 AM7930_IWRITE(sc, AM7930_IREG_INIT, 172 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); 173 174 if (flag == AUDIOAMD_DMA_MODE) { 175 176 /* configure PP for serial (SBP) mode */ 177 AM7930_IWRITE(sc, AM7930_IREG_PP_PPCR1, AM7930_PPCR1_SBP); 178 179 /* 180 * Initialise the MUX unit - route the MAP to the PP 181 */ 182 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR1, 183 (AM7930_MCRCHAN_BA << 4) | AM7930_MCRCHAN_BD); 184 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR2, AM7930_MCRCHAN_NC); 185 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR3, AM7930_MCRCHAN_NC); 186 187 } else { 188 189 /* 190 * Initialize the MUX unit. We use MCR3 to route the MAP 191 * through channel Bb. MCR1 and MCR2 are unused. 192 * Setting the INT enable bit in MCR4 will generate an 193 * interrupt on each converted audio sample. 194 */ 195 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR1, 0); 196 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR2, 0); 197 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR3, 198 (AM7930_MCRCHAN_BB << 4) | AM7930_MCRCHAN_BA); 199 AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4, 200 AM7930_MCR4_INT_ENABLE); 201 } 202 203 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 204 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED); 205 } 206 207 int 208 am7930_open(void *addr, int flags) 209 { 210 struct am7930_softc *sc; 211 212 sc = addr; 213 DPRINTF(("sa_open: unit %p\n", sc)); 214 sc->sc_glue->onopen(sc); 215 DPRINTF(("saopen: ok -> sc=%p\n",sc)); 216 return 0; 217 } 218 219 void 220 am7930_close(void *addr) 221 { 222 struct am7930_softc *sc; 223 224 sc = addr; 225 DPRINTF(("sa_close: sc=%p\n", sc)); 226 sc->sc_glue->onclose(sc); 227 DPRINTF(("sa_close: closed.\n")); 228 } 229 230 int 231 am7930_query_format(void *addr, audio_format_query_t *afp) 232 { 233 234 return audio_query_format(&am7930_format, 1, afp); 235 } 236 237 int 238 am7930_set_format(void *addr, int setmode, 239 const audio_params_t *play, const audio_params_t *rec, 240 audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 241 { 242 243 if ((setmode & AUMODE_PLAY) != 0) { 244 pfil->codec = audio_internal_to_mulaw; 245 } 246 if ((setmode & AUMODE_RECORD) != 0) { 247 rfil->codec = audio_mulaw_to_internal; 248 } 249 250 return 0; 251 } 252 253 int 254 am7930_commit_settings(void *addr) 255 { 256 struct am7930_softc *sc; 257 uint16_t ger, gr, gx, stgr; 258 uint8_t mmr2, mmr3; 259 int level; 260 261 DPRINTF(("sa_commit.\n")); 262 sc = addr; 263 gx = gx_coeff[sc->sc_rlevel]; 264 stgr = gx_coeff[sc->sc_mlevel]; 265 266 level = (sc->sc_plevel * (256 + NGER)) >> 8; 267 if (level >= 256) { 268 ger = ger_coeff[level - 256]; 269 gr = gx_coeff[255]; 270 } else { 271 ger = ger_coeff[0]; 272 gr = gx_coeff[level]; 273 } 274 275 mutex_enter(&sc->sc_intr_lock); 276 277 mmr2 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR2); 278 if (sc->sc_out_port == AUDIOAMD_SPEAKER_VOL) 279 mmr2 |= AM7930_MMR2_LS; 280 else 281 mmr2 &= ~AM7930_MMR2_LS; 282 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR2, mmr2); 283 284 mmr3 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR3); 285 if (sc->sc_mic_mute) 286 mmr3 |= AM7930_MMR3_MUTE; 287 else 288 mmr3 &= ~AM7930_MMR3_MUTE; 289 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR3, mmr3); 290 291 AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR1, 292 AM7930_MMR1_GX | AM7930_MMR1_GER | 293 AM7930_MMR1_GR | AM7930_MMR1_STG); 294 295 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GX, gx); 296 AM7930_IWRITE16(sc, AM7930_IREG_MAP_STG, stgr); 297 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GR, gr); 298 AM7930_IWRITE16(sc, AM7930_IREG_MAP_GER, ger); 299 300 mutex_exit(&sc->sc_intr_lock); 301 302 return 0; 303 } 304 305 int 306 am7930_halt_output(void *addr) 307 { 308 struct am7930_softc *sc; 309 310 sc = addr; 311 /* XXX only halt, if input is also halted ?? */ 312 AM7930_IWRITE(sc, AM7930_IREG_INIT, 313 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); 314 return 0; 315 } 316 317 int 318 am7930_halt_input(void *addr) 319 { 320 struct am7930_softc *sc; 321 322 sc = addr; 323 /* XXX only halt, if output is also halted ?? */ 324 AM7930_IWRITE(sc, AM7930_IREG_INIT, 325 AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); 326 return 0; 327 } 328 329 /* 330 * XXX chip is full-duplex, but really attach-dependent. 331 * For now we know of no half-duplex attachments. 332 */ 333 int 334 am7930_get_props(void *addr) 335 { 336 337 return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE | 338 AUDIO_PROP_FULLDUPLEX; 339 } 340 341 /* 342 * Attach-dependent channel set/query 343 */ 344 int 345 am7930_set_port(void *addr, mixer_ctrl_t *cp) 346 { 347 struct am7930_softc *sc; 348 349 DPRINTF(("am7930_set_port: port=%d", cp->dev)); 350 sc = addr; 351 if (cp->dev == AUDIOAMD_RECORD_SOURCE || 352 cp->dev == AUDIOAMD_MONITOR_OUTPUT || 353 cp->dev == AUDIOAMD_MIC_MUTE) { 354 if (cp->type != AUDIO_MIXER_ENUM) 355 return EINVAL; 356 } else if (cp->type != AUDIO_MIXER_VALUE || 357 cp->un.value.num_channels != 1) { 358 return EINVAL; 359 } 360 361 switch(cp->dev) { 362 case AUDIOAMD_MIC_VOL: 363 sc->sc_rlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 364 break; 365 case AUDIOAMD_SPEAKER_VOL: 366 case AUDIOAMD_HEADPHONES_VOL: 367 sc->sc_plevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 368 break; 369 case AUDIOAMD_MONITOR_VOL: 370 sc->sc_mlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 371 break; 372 case AUDIOAMD_RECORD_SOURCE: 373 if (cp->un.ord != AUDIOAMD_MIC_VOL) 374 return EINVAL; 375 break; 376 case AUDIOAMD_MIC_MUTE: 377 sc->sc_mic_mute = cp->un.ord; 378 break; 379 case AUDIOAMD_MONITOR_OUTPUT: 380 if (cp->un.ord != AUDIOAMD_SPEAKER_VOL && 381 cp->un.ord != AUDIOAMD_HEADPHONES_VOL) 382 return EINVAL; 383 sc->sc_out_port = cp->un.ord; 384 break; 385 default: 386 return EINVAL; 387 /* NOTREACHED */ 388 } 389 return 0; 390 } 391 392 int 393 am7930_get_port(void *addr, mixer_ctrl_t *cp) 394 { 395 struct am7930_softc *sc; 396 397 DPRINTF(("am7930_get_port: port=%d\n", 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 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_rlevel; 412 break; 413 case AUDIOAMD_SPEAKER_VOL: 414 case AUDIOAMD_HEADPHONES_VOL: 415 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_plevel; 416 break; 417 case AUDIOAMD_MONITOR_VOL: 418 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_mlevel; 419 break; 420 case AUDIOAMD_RECORD_SOURCE: 421 cp->un.ord = AUDIOAMD_MIC_VOL; 422 break; 423 case AUDIOAMD_MIC_MUTE: 424 cp->un.ord = sc->sc_mic_mute; 425 break; 426 case AUDIOAMD_MONITOR_OUTPUT: 427 cp->un.ord = sc->sc_out_port; 428 break; 429 default: 430 return EINVAL; 431 /* NOTREACHED */ 432 } 433 return 0; 434 } 435 436 437 /* 438 * Define mixer control facilities. 439 */ 440 int 441 am7930_query_devinfo(void *addr, mixer_devinfo_t *dip) 442 { 443 444 DPRINTF(("am7930_query_devinfo()\n")); 445 446 switch(dip->index) { 447 case AUDIOAMD_MIC_VOL: 448 dip->type = AUDIO_MIXER_VALUE; 449 dip->mixer_class = AUDIOAMD_INPUT_CLASS; 450 dip->prev = AUDIO_MIXER_LAST; 451 dip->next = AUDIOAMD_MIC_MUTE; 452 strcpy(dip->label.name, AudioNmicrophone); 453 dip->un.v.num_channels = 1; 454 strcpy(dip->un.v.units.name, AudioNvolume); 455 break; 456 case AUDIOAMD_SPEAKER_VOL: 457 dip->type = AUDIO_MIXER_VALUE; 458 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS; 459 dip->prev = dip->next = AUDIO_MIXER_LAST; 460 strcpy(dip->label.name, AudioNspeaker); 461 dip->un.v.num_channels = 1; 462 strcpy(dip->un.v.units.name, AudioNvolume); 463 break; 464 case AUDIOAMD_HEADPHONES_VOL: 465 dip->type = AUDIO_MIXER_VALUE; 466 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS; 467 dip->prev = dip->next = AUDIO_MIXER_LAST; 468 strcpy(dip->label.name, AudioNheadphone); 469 dip->un.v.num_channels = 1; 470 strcpy(dip->un.v.units.name, AudioNvolume); 471 break; 472 case AUDIOAMD_MONITOR_VOL: 473 dip->type = AUDIO_MIXER_VALUE; 474 dip->mixer_class = AUDIOAMD_MONITOR_CLASS; 475 dip->prev = dip->next = AUDIO_MIXER_LAST; 476 strcpy(dip->label.name, AudioNmonitor); 477 dip->un.v.num_channels = 1; 478 strcpy(dip->un.v.units.name, AudioNvolume); 479 break; 480 case AUDIOAMD_RECORD_SOURCE: 481 dip->type = AUDIO_MIXER_ENUM; 482 dip->mixer_class = AUDIOAMD_RECORD_CLASS; 483 dip->next = dip->prev = AUDIO_MIXER_LAST; 484 strcpy(dip->label.name, AudioNsource); 485 dip->un.e.num_mem = 1; 486 strcpy(dip->un.e.member[0].label.name, AudioNmicrophone); 487 dip->un.e.member[0].ord = AUDIOAMD_MIC_VOL; 488 break; 489 case AUDIOAMD_MONITOR_OUTPUT: 490 dip->type = AUDIO_MIXER_ENUM; 491 dip->mixer_class = AUDIOAMD_MONITOR_CLASS; 492 dip->next = dip->prev = AUDIO_MIXER_LAST; 493 strcpy(dip->label.name, AudioNoutput); 494 dip->un.e.num_mem = 2; 495 strcpy(dip->un.e.member[0].label.name, AudioNspeaker); 496 dip->un.e.member[0].ord = AUDIOAMD_SPEAKER_VOL; 497 strcpy(dip->un.e.member[1].label.name, AudioNheadphone); 498 dip->un.e.member[1].ord = AUDIOAMD_HEADPHONES_VOL; 499 break; 500 case AUDIOAMD_MIC_MUTE: 501 dip->type = AUDIO_MIXER_ENUM; 502 dip->mixer_class = AUDIOAMD_INPUT_CLASS; 503 dip->prev = AUDIOAMD_MIC_VOL; 504 dip->next = AUDIO_MIXER_LAST; 505 strcpy(dip->label.name, AudioNmute); 506 dip->un.e.num_mem = 2; 507 strcpy(dip->un.e.member[0].label.name, AudioNoff); 508 dip->un.e.member[0].ord = 0; 509 strcpy(dip->un.e.member[1].label.name, AudioNon); 510 dip->un.e.member[1].ord = 1; 511 break; 512 case AUDIOAMD_INPUT_CLASS: 513 dip->type = AUDIO_MIXER_CLASS; 514 dip->mixer_class = AUDIOAMD_INPUT_CLASS; 515 dip->next = dip->prev = AUDIO_MIXER_LAST; 516 strcpy(dip->label.name, AudioCinputs); 517 break; 518 case AUDIOAMD_OUTPUT_CLASS: 519 dip->type = AUDIO_MIXER_CLASS; 520 dip->mixer_class = AUDIOAMD_OUTPUT_CLASS; 521 dip->next = dip->prev = AUDIO_MIXER_LAST; 522 strcpy(dip->label.name, AudioCoutputs); 523 break; 524 case AUDIOAMD_RECORD_CLASS: 525 dip->type = AUDIO_MIXER_CLASS; 526 dip->mixer_class = AUDIOAMD_RECORD_CLASS; 527 dip->next = dip->prev = AUDIO_MIXER_LAST; 528 strcpy(dip->label.name, AudioCrecord); 529 break; 530 case AUDIOAMD_MONITOR_CLASS: 531 dip->type = AUDIO_MIXER_CLASS; 532 dip->mixer_class = AUDIOAMD_MONITOR_CLASS; 533 dip->next = dip->prev = AUDIO_MIXER_LAST; 534 strcpy(dip->label.name, AudioCmonitor); 535 break; 536 default: 537 return ENXIO; 538 /*NOTREACHED*/ 539 } 540 541 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); 542 543 return 0; 544 } 545 546 #endif /* NAUDIO */ 547