1 /* $NetBSD: cs4231.c,v 1.25 2010/04/16 18:59:12 dyoung Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Paul Kranenburg. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: cs4231.c,v 1.25 2010/04/16 18:59:12 dyoung Exp $"); 34 35 #include "audio.h" 36 #if NAUDIO > 0 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/errno.h> 41 #include <sys/device.h> 42 #include <sys/malloc.h> 43 #include <sys/bus.h> 44 45 #include <machine/autoconf.h> 46 #include <sys/cpu.h> 47 48 #include <sys/audioio.h> 49 #include <dev/audio_if.h> 50 51 #include <dev/ic/ad1848reg.h> 52 #include <dev/ic/cs4231reg.h> 53 #include <dev/ic/ad1848var.h> 54 #include <dev/ic/cs4231var.h> 55 56 /*---*/ 57 #define CSAUDIO_DAC_LVL 0 58 #define CSAUDIO_LINE_IN_LVL 1 59 #define CSAUDIO_MONO_LVL 2 60 #define CSAUDIO_CD_LVL 3 61 #define CSAUDIO_OUTPUT_LVL 4 62 #define CSAUDIO_OUT_LVL 5 63 #define CSAUDIO_LINE_IN_MUTE 6 64 #define CSAUDIO_DAC_MUTE 7 65 #define CSAUDIO_CD_MUTE 8 66 #define CSAUDIO_MONO_MUTE 9 67 #define CSAUDIO_OUTPUT_MUTE 10 68 #define CSAUDIO_OUT_MUTE 11 69 #define CSAUDIO_REC_LVL 12 70 #define CSAUDIO_RECORD_SOURCE 13 71 72 #define CSAUDIO_INPUT_CLASS 14 73 #define CSAUDIO_MONITOR_CLASS 15 74 #define CSAUDIO_RECORD_CLASS 16 75 76 #ifdef AUDIO_DEBUG 77 int cs4231_debug = 0; 78 #define DPRINTF(x) if (cs4231_debug) printf x 79 #else 80 #define DPRINTF(x) 81 #endif 82 83 struct audio_device cs4231_device = { 84 "cs4231", 85 "x", 86 "audio" 87 }; 88 89 90 /* ad1848 sc_{read,write}reg */ 91 static int cs4231_read(struct ad1848_softc *, int); 92 static void cs4231_write(struct ad1848_softc *, int, int); 93 94 int 95 cs4231_read(struct ad1848_softc *sc, int index) 96 { 97 98 return bus_space_read_1(sc->sc_iot, sc->sc_ioh, (index << 2)); 99 } 100 101 void 102 cs4231_write(struct ad1848_softc *sc, int index, int value) 103 { 104 105 bus_space_write_1(sc->sc_iot, sc->sc_ioh, (index << 2), value); 106 } 107 108 109 void 110 cs4231_common_attach(struct cs4231_softc *sc, bus_space_handle_t ioh) 111 { 112 char *buf; 113 int reg; 114 115 sc->sc_ad1848.parent = sc; 116 sc->sc_ad1848.sc_iot = sc->sc_bustag; 117 sc->sc_ad1848.sc_ioh = ioh; 118 sc->sc_ad1848.sc_readreg = cs4231_read; 119 sc->sc_ad1848.sc_writereg = cs4231_write; 120 121 sc->sc_playback.t_name = "playback"; 122 sc->sc_capture.t_name = "capture"; 123 124 evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, 125 NULL, 126 device_xname(&sc->sc_ad1848.sc_dev), "total"); 127 128 evcnt_attach_dynamic(&sc->sc_playback.t_intrcnt, EVCNT_TYPE_INTR, 129 &sc->sc_intrcnt, 130 device_xname(&sc->sc_ad1848.sc_dev), "playback"); 131 132 evcnt_attach_dynamic(&sc->sc_playback.t_ierrcnt, EVCNT_TYPE_INTR, 133 &sc->sc_intrcnt, 134 device_xname(&sc->sc_ad1848.sc_dev), "perrors"); 135 136 evcnt_attach_dynamic(&sc->sc_capture.t_intrcnt, EVCNT_TYPE_INTR, 137 &sc->sc_intrcnt, 138 device_xname(&sc->sc_ad1848.sc_dev), "capture"); 139 140 evcnt_attach_dynamic(&sc->sc_capture.t_ierrcnt, EVCNT_TYPE_INTR, 141 &sc->sc_intrcnt, 142 device_xname(&sc->sc_ad1848.sc_dev), "cerrors"); 143 144 /* put chip in native mode to access (extended) ID register */ 145 reg = ad_read(&sc->sc_ad1848, SP_MISC_INFO); 146 ad_write(&sc->sc_ad1848, SP_MISC_INFO, reg | MODE2); 147 148 /* read version numbers from I25 */ 149 reg = ad_read(&sc->sc_ad1848, CS_VERSION_ID); 150 switch (reg & (CS_VERSION_NUMBER | CS_VERSION_CHIPID)) { 151 case 0xa0: 152 sc->sc_ad1848.chip_name = "CS4231A"; 153 break; 154 case 0x80: 155 sc->sc_ad1848.chip_name = "CS4231"; 156 break; 157 case 0x82: 158 sc->sc_ad1848.chip_name = "CS4232"; 159 break; 160 case 0xa2: 161 sc->sc_ad1848.chip_name = "CS4232C"; 162 break; 163 default: 164 if ((buf = malloc(32, M_TEMP, M_NOWAIT)) != NULL) { 165 snprintf(buf, 32, "unknown rev: %x/%x", 166 reg&0xe0, reg&7); 167 sc->sc_ad1848.chip_name = buf; 168 } 169 } 170 171 sc->sc_ad1848.mode = 2; /* put ad1848 driver in `MODE 2' mode */ 172 ad1848_attach(&sc->sc_ad1848); 173 } 174 175 void * 176 cs4231_malloc(void *addr, int direction, size_t size, 177 struct malloc_type *pool, int flags) 178 { 179 struct cs4231_softc *sc; 180 bus_dma_tag_t dmatag; 181 struct cs_dma *p; 182 183 sc = addr; 184 dmatag = sc->sc_dmatag; 185 p = malloc(sizeof(*p), pool, flags); 186 if (p == NULL) 187 return NULL; 188 189 /* Allocate a DMA map */ 190 if (bus_dmamap_create(dmatag, size, 1, size, 0, 191 BUS_DMA_NOWAIT, &p->dmamap) != 0) 192 goto fail1; 193 194 /* Allocate DMA memory */ 195 p->size = size; 196 if (bus_dmamem_alloc(dmatag, size, 64*1024, 0, 197 p->segs, sizeof(p->segs)/sizeof(p->segs[0]), 198 &p->nsegs, BUS_DMA_NOWAIT) != 0) 199 goto fail2; 200 201 /* Map DMA memory into kernel space */ 202 if (bus_dmamem_map(dmatag, p->segs, p->nsegs, p->size, 203 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT) != 0) 204 goto fail3; 205 206 /* Load the buffer */ 207 if (bus_dmamap_load(dmatag, p->dmamap, 208 p->addr, size, NULL, BUS_DMA_NOWAIT) != 0) 209 goto fail4; 210 211 p->next = sc->sc_dmas; 212 sc->sc_dmas = p; 213 return p->addr; 214 215 fail4: 216 bus_dmamem_unmap(dmatag, p->addr, p->size); 217 fail3: 218 bus_dmamem_free(dmatag, p->segs, p->nsegs); 219 fail2: 220 bus_dmamap_destroy(dmatag, p->dmamap); 221 fail1: 222 free(p, pool); 223 return NULL; 224 } 225 226 void 227 cs4231_free(void *addr, void *ptr, struct malloc_type *pool) 228 { 229 struct cs4231_softc *sc; 230 bus_dma_tag_t dmatag; 231 struct cs_dma *p, **pp; 232 233 sc = addr; 234 dmatag = sc->sc_dmatag; 235 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &(*pp)->next) { 236 if (p->addr != ptr) 237 continue; 238 bus_dmamap_unload(dmatag, p->dmamap); 239 bus_dmamem_unmap(dmatag, p->addr, p->size); 240 bus_dmamem_free(dmatag, p->segs, p->nsegs); 241 bus_dmamap_destroy(dmatag, p->dmamap); 242 *pp = p->next; 243 free(p, pool); 244 return; 245 } 246 printf("cs4231_free: rogue pointer\n"); 247 } 248 249 250 /* 251 * Set up transfer and return DMA address and byte count in paddr and psize 252 * for bus dependent trigger_{in,out}put to load into the DMA controller. 253 */ 254 int 255 cs4231_transfer_init( 256 struct cs4231_softc *sc, 257 struct cs_transfer *t, 258 bus_addr_t *paddr, 259 bus_size_t *psize, 260 void *start, void *end, 261 int blksize, 262 void (*intr)(void *), 263 void *arg) 264 { 265 struct cs_dma *p; 266 vsize_t n; 267 268 if (t->t_active) { 269 printf("%s: %s already running\n", 270 device_xname(&sc->sc_ad1848.sc_dev), t->t_name); 271 return EINVAL; 272 } 273 274 t->t_intr = intr; 275 t->t_arg = arg; 276 277 for (p = sc->sc_dmas; p != NULL && p->addr != start; p = p->next) 278 continue; 279 if (p == NULL) { 280 printf("%s: bad %s addr %p\n", 281 device_xname(&sc->sc_ad1848.sc_dev), t->t_name, start); 282 return EINVAL; 283 } 284 285 n = (char *)end - (char *)start; 286 287 t->t_dma = p; /* the DMA memory segment */ 288 t->t_segsz = n; /* size of DMA segment */ 289 t->t_blksz = blksize; /* do transfers in blksize chunks */ 290 291 if (n > t->t_blksz) 292 n = t->t_blksz; 293 294 t->t_cnt = n; 295 296 /* for caller to load into DMA controller */ 297 *paddr = t->t_dma->dmamap->dm_segs[0].ds_addr; 298 *psize = n; 299 300 DPRINTF(("%s: init %s: [%p..%p] %lu bytes %lu blocks;" 301 " DMA at 0x%lx count %lu\n", 302 device_xname(&sc->sc_ad1848.sc_dev), t->t_name, 303 start, end, (u_long)t->t_segsz, (u_long)t->t_blksz, 304 (u_long)*paddr, (u_long)*psize)); 305 306 t->t_active = 1; 307 return 0; 308 } 309 310 /* 311 * Compute next DMA address/counter, update transfer status. 312 */ 313 void 314 cs4231_transfer_advance(struct cs_transfer *t, bus_addr_t *paddr, 315 bus_size_t *psize) 316 { 317 bus_addr_t dmabase, nextaddr; 318 bus_size_t togo; 319 320 dmabase = t->t_dma->dmamap->dm_segs[0].ds_addr; 321 322 togo = t->t_segsz - t->t_cnt; 323 if (togo == 0) { /* roll over */ 324 nextaddr = dmabase; 325 t->t_cnt = togo = t->t_blksz; 326 } else { 327 nextaddr = dmabase + t->t_cnt; 328 if (togo > t->t_blksz) 329 togo = t->t_blksz; 330 t->t_cnt += togo; 331 } 332 333 /* for caller to load into DMA controller */ 334 *paddr = nextaddr; 335 *psize = togo; 336 } 337 338 339 int 340 cs4231_open(void *addr, int flags) 341 { 342 struct cs4231_softc *sc; 343 344 sc = addr; 345 DPRINTF(("sa_open: unit %p\n", sc)); 346 347 sc->sc_playback.t_active = 0; 348 sc->sc_playback.t_intr = NULL; 349 sc->sc_playback.t_arg = NULL; 350 351 sc->sc_capture.t_active = 0; 352 sc->sc_capture.t_intr = NULL; 353 sc->sc_capture.t_arg = NULL; 354 355 /* no interrupts from ad1848 */ 356 ad_write(&sc->sc_ad1848, SP_PIN_CONTROL, 0); 357 ad1848_reset(&sc->sc_ad1848); 358 359 DPRINTF(("sa_open: ok -> sc=%p\n", sc)); 360 return 0; 361 } 362 363 void 364 cs4231_close(void *addr) 365 { 366 367 DPRINTF(("sa_close: sc=%p\n", addr)); 368 369 /* audio(9) already called halt methods */ 370 371 DPRINTF(("sa_close: closed.\n")); 372 } 373 374 int 375 cs4231_getdev(void *addr, struct audio_device *retp) 376 { 377 378 *retp = cs4231_device; 379 return 0; 380 } 381 382 static const ad1848_devmap_t csmapping[] = { 383 { CSAUDIO_DAC_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL }, 384 { CSAUDIO_LINE_IN_LVL, AD1848_KIND_LVL, AD1848_LINE_CHANNEL }, 385 { CSAUDIO_MONO_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL }, 386 { CSAUDIO_CD_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL }, 387 { CSAUDIO_OUTPUT_LVL, AD1848_KIND_LVL, AD1848_MONITOR_CHANNEL }, 388 { CSAUDIO_OUT_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL }, 389 { CSAUDIO_DAC_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL }, 390 { CSAUDIO_LINE_IN_MUTE, AD1848_KIND_MUTE, AD1848_LINE_CHANNEL }, 391 { CSAUDIO_MONO_MUTE, AD1848_KIND_MUTE, AD1848_MONO_CHANNEL }, 392 { CSAUDIO_CD_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL }, 393 { CSAUDIO_OUTPUT_MUTE, AD1848_KIND_MUTE, AD1848_MONITOR_CHANNEL }, 394 { CSAUDIO_OUT_MUTE, AD1848_KIND_MUTE, AD1848_OUT_CHANNEL }, 395 { CSAUDIO_REC_LVL, AD1848_KIND_RECORDGAIN, -1 }, 396 { CSAUDIO_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1 } 397 }; 398 399 static int nummap = sizeof(csmapping) / sizeof(csmapping[0]); 400 401 402 int 403 cs4231_set_port(void *addr, mixer_ctrl_t *cp) 404 { 405 struct ad1848_softc *ac; 406 407 DPRINTF(("cs4231_set_port: port=%d", cp->dev)); 408 ac = addr; 409 return ad1848_mixer_set_port(ac, csmapping, nummap, cp); 410 } 411 412 int 413 cs4231_get_port(void *addr, mixer_ctrl_t *cp) 414 { 415 struct ad1848_softc *ac; 416 417 DPRINTF(("cs4231_get_port: port=%d", cp->dev)); 418 ac = addr; 419 return ad1848_mixer_get_port(ac, csmapping, nummap, cp); 420 } 421 422 int 423 cs4231_get_props(void *addr) 424 { 425 426 return AUDIO_PROP_FULLDUPLEX; 427 } 428 429 int 430 cs4231_query_devinfo(void *addr, mixer_devinfo_t *dip) 431 { 432 433 switch(dip->index) { 434 435 case CSAUDIO_DAC_LVL: /* dacout */ 436 dip->type = AUDIO_MIXER_VALUE; 437 dip->mixer_class = CSAUDIO_INPUT_CLASS; 438 dip->prev = AUDIO_MIXER_LAST; 439 dip->next = CSAUDIO_DAC_MUTE; 440 strcpy(dip->label.name, AudioNdac); 441 dip->un.v.num_channels = 2; 442 strcpy(dip->un.v.units.name, AudioNvolume); 443 break; 444 445 case CSAUDIO_LINE_IN_LVL: /* line */ 446 dip->type = AUDIO_MIXER_VALUE; 447 dip->mixer_class = CSAUDIO_INPUT_CLASS; 448 dip->prev = AUDIO_MIXER_LAST; 449 dip->next = CSAUDIO_LINE_IN_MUTE; 450 strcpy(dip->label.name, AudioNline); 451 dip->un.v.num_channels = 2; 452 strcpy(dip->un.v.units.name, AudioNvolume); 453 break; 454 455 case CSAUDIO_MONO_LVL: /* mono/microphone mixer */ 456 dip->type = AUDIO_MIXER_VALUE; 457 dip->mixer_class = CSAUDIO_INPUT_CLASS; 458 dip->prev = AUDIO_MIXER_LAST; 459 dip->next = CSAUDIO_MONO_MUTE; 460 strcpy(dip->label.name, AudioNmicrophone); 461 dip->un.v.num_channels = 1; 462 strcpy(dip->un.v.units.name, AudioNvolume); 463 break; 464 465 case CSAUDIO_CD_LVL: /* cd */ 466 dip->type = AUDIO_MIXER_VALUE; 467 dip->mixer_class = CSAUDIO_INPUT_CLASS; 468 dip->prev = AUDIO_MIXER_LAST; 469 dip->next = CSAUDIO_CD_MUTE; 470 strcpy(dip->label.name, AudioNcd); 471 dip->un.v.num_channels = 2; 472 strcpy(dip->un.v.units.name, AudioNvolume); 473 break; 474 475 476 case CSAUDIO_OUTPUT_LVL: /* monitor level */ 477 dip->type = AUDIO_MIXER_VALUE; 478 dip->mixer_class = CSAUDIO_MONITOR_CLASS; 479 dip->next = CSAUDIO_OUTPUT_MUTE; 480 dip->prev = AUDIO_MIXER_LAST; 481 strcpy(dip->label.name, AudioNmonitor); 482 dip->un.v.num_channels = 1; 483 strcpy(dip->un.v.units.name, AudioNvolume); 484 break; 485 486 case CSAUDIO_OUT_LVL: /* cs4231 output volume */ 487 dip->type = AUDIO_MIXER_VALUE; 488 dip->mixer_class = CSAUDIO_MONITOR_CLASS; 489 dip->next = dip->prev = AUDIO_MIXER_LAST; 490 strcpy(dip->label.name, AudioNmaster); 491 dip->un.v.num_channels = 2; 492 dip->un.v.delta = 16; 493 strcpy(dip->un.v.units.name, AudioNvolume); 494 break; 495 496 case CSAUDIO_OUT_MUTE: /* mute built-in speaker */ 497 dip->mixer_class = CSAUDIO_MONITOR_CLASS; 498 dip->type = AUDIO_MIXER_ENUM; 499 dip->prev = CSAUDIO_MONITOR_CLASS; 500 dip->next = AUDIO_MIXER_LAST; 501 strcpy(dip->label.name, AudioNmono); 502 /* names reversed, this is a "mute" value used as "mono enabled" */ 503 dip->un.e.num_mem = 2; 504 strcpy(dip->un.e.member[0].label.name, AudioNon); 505 dip->un.e.member[0].ord = 0; 506 strcpy(dip->un.e.member[1].label.name, AudioNoff); 507 dip->un.e.member[1].ord = 1; 508 break; 509 510 case CSAUDIO_LINE_IN_MUTE: 511 dip->mixer_class = CSAUDIO_INPUT_CLASS; 512 dip->type = AUDIO_MIXER_ENUM; 513 dip->prev = CSAUDIO_LINE_IN_LVL; 514 dip->next = AUDIO_MIXER_LAST; 515 goto mute; 516 517 case CSAUDIO_DAC_MUTE: 518 dip->mixer_class = CSAUDIO_INPUT_CLASS; 519 dip->type = AUDIO_MIXER_ENUM; 520 dip->prev = CSAUDIO_DAC_LVL; 521 dip->next = AUDIO_MIXER_LAST; 522 goto mute; 523 524 case CSAUDIO_CD_MUTE: 525 dip->mixer_class = CSAUDIO_INPUT_CLASS; 526 dip->type = AUDIO_MIXER_ENUM; 527 dip->prev = CSAUDIO_CD_LVL; 528 dip->next = AUDIO_MIXER_LAST; 529 goto mute; 530 531 case CSAUDIO_MONO_MUTE: 532 dip->mixer_class = CSAUDIO_INPUT_CLASS; 533 dip->type = AUDIO_MIXER_ENUM; 534 dip->prev = CSAUDIO_MONO_LVL; 535 dip->next = AUDIO_MIXER_LAST; 536 goto mute; 537 538 case CSAUDIO_OUTPUT_MUTE: 539 dip->mixer_class = CSAUDIO_MONITOR_CLASS; 540 dip->type = AUDIO_MIXER_ENUM; 541 dip->prev = CSAUDIO_OUTPUT_LVL; 542 dip->next = AUDIO_MIXER_LAST; 543 mute: 544 strcpy(dip->label.name, AudioNmute); 545 dip->un.e.num_mem = 2; 546 strcpy(dip->un.e.member[0].label.name, AudioNoff); 547 dip->un.e.member[0].ord = 0; 548 strcpy(dip->un.e.member[1].label.name, AudioNon); 549 dip->un.e.member[1].ord = 1; 550 break; 551 552 case CSAUDIO_REC_LVL: /* record level */ 553 dip->type = AUDIO_MIXER_VALUE; 554 dip->mixer_class = CSAUDIO_RECORD_CLASS; 555 dip->prev = AUDIO_MIXER_LAST; 556 dip->next = CSAUDIO_RECORD_SOURCE; 557 strcpy(dip->label.name, AudioNrecord); 558 dip->un.v.num_channels = 2; 559 strcpy(dip->un.v.units.name, AudioNvolume); 560 break; 561 562 case CSAUDIO_RECORD_SOURCE: 563 dip->mixer_class = CSAUDIO_RECORD_CLASS; 564 dip->type = AUDIO_MIXER_ENUM; 565 dip->prev = CSAUDIO_REC_LVL; 566 dip->next = AUDIO_MIXER_LAST; 567 strcpy(dip->label.name, AudioNsource); 568 dip->un.e.num_mem = 4; 569 strcpy(dip->un.e.member[0].label.name, AudioNoutput); 570 dip->un.e.member[0].ord = DAC_IN_PORT; 571 strcpy(dip->un.e.member[1].label.name, AudioNmicrophone); 572 dip->un.e.member[1].ord = MIC_IN_PORT; 573 strcpy(dip->un.e.member[2].label.name, AudioNdac); 574 dip->un.e.member[2].ord = AUX1_IN_PORT; 575 strcpy(dip->un.e.member[3].label.name, AudioNline); 576 dip->un.e.member[3].ord = LINE_IN_PORT; 577 break; 578 579 case CSAUDIO_INPUT_CLASS: /* input class descriptor */ 580 dip->type = AUDIO_MIXER_CLASS; 581 dip->mixer_class = CSAUDIO_INPUT_CLASS; 582 dip->next = dip->prev = AUDIO_MIXER_LAST; 583 strcpy(dip->label.name, AudioCinputs); 584 break; 585 586 case CSAUDIO_MONITOR_CLASS: /* output class descriptor */ 587 dip->type = AUDIO_MIXER_CLASS; 588 dip->mixer_class = CSAUDIO_MONITOR_CLASS; 589 dip->next = dip->prev = AUDIO_MIXER_LAST; 590 strcpy(dip->label.name, AudioCoutputs); 591 break; 592 593 case CSAUDIO_RECORD_CLASS: /* record source class */ 594 dip->type = AUDIO_MIXER_CLASS; 595 dip->mixer_class = CSAUDIO_RECORD_CLASS; 596 dip->next = dip->prev = AUDIO_MIXER_LAST; 597 strcpy(dip->label.name, AudioCrecord); 598 break; 599 600 default: 601 return ENXIO; 602 /*NOTREACHED*/ 603 } 604 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); 605 606 return 0; 607 } 608 609 #endif /* NAUDIO > 0 */ 610