1 /* $NetBSD: cs4231.c,v 1.5 2001/10/03 00:04:49 augustss 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include "audio.h" 40 #if NAUDIO > 0 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/errno.h> 45 #include <sys/device.h> 46 #include <sys/malloc.h> 47 48 #include <machine/autoconf.h> 49 #include <machine/cpu.h> 50 51 #include <sys/audioio.h> 52 #include <dev/audio_if.h> 53 54 #include <dev/ic/ad1848reg.h> 55 #include <dev/ic/cs4231reg.h> 56 #include <dev/ic/ad1848var.h> 57 #include <dev/ic/cs4231var.h> 58 #include <dev/ic/apcdmareg.h> 59 60 /*---*/ 61 #define CSAUDIO_DAC_LVL 0 62 #define CSAUDIO_LINE_IN_LVL 1 63 #define CSAUDIO_MONO_LVL 2 64 #define CSAUDIO_CD_LVL 3 65 #define CSAUDIO_MONITOR_LVL 4 66 #define CSAUDIO_OUT_LVL 5 67 #define CSAUDIO_LINE_IN_MUTE 6 68 #define CSAUDIO_DAC_MUTE 7 69 #define CSAUDIO_CD_MUTE 8 70 #define CSAUDIO_MONO_MUTE 9 71 #define CSAUDIO_MONITOR_MUTE 10 72 #define CSAUDIO_REC_LVL 11 73 #define CSAUDIO_RECORD_SOURCE 12 74 75 #define CSAUDIO_INPUT_CLASS 13 76 #define CSAUDIO_OUTPUT_CLASS 14 77 #define CSAUDIO_RECORD_CLASS 15 78 #define CSAUDIO_MONITOR_CLASS 16 79 80 #ifdef AUDIO_DEBUG 81 int cs4231debug = 0; 82 #define DPRINTF(x) if (cs4231debug) printf x 83 #else 84 #define DPRINTF(x) 85 #endif 86 87 struct audio_device cs4231_device = { 88 "cs4231", 89 "x", 90 "audio" 91 }; 92 93 94 /* 95 * Define our interface to the higher level audio driver. 96 */ 97 int cs4231_open __P((void *, int)); 98 void cs4231_close __P((void *)); 99 size_t cs4231_round_buffersize __P((void *, int, size_t)); 100 int cs4231_round_blocksize __P((void *, int)); 101 int cs4231_halt_output __P((void *)); 102 int cs4231_halt_input __P((void *)); 103 int cs4231_getdev __P((void *, struct audio_device *)); 104 int cs4231_set_port __P((void *, mixer_ctrl_t *)); 105 int cs4231_get_port __P((void *, mixer_ctrl_t *)); 106 int cs4231_query_devinfo __P((void *, mixer_devinfo_t *)); 107 int cs4231_get_props __P((void *)); 108 109 void *cs4231_malloc __P((void *, int, size_t, int, int)); 110 void cs4231_free __P((void *, void *, int)); 111 int cs4231_trigger_output __P((void *, void *, void *, int, 112 void (*)(void *), void *, 113 struct audio_params *)); 114 int cs4231_trigger_input __P((void *, void *, void *, int, 115 void (*)(void *), void *, 116 struct audio_params *)); 117 118 #ifdef AUDIO_DEBUG 119 static void cs4231_regdump __P((char *, struct cs4231_softc *)); 120 #endif 121 122 int 123 cs4231_read(sc, index) 124 struct ad1848_softc *sc; 125 int index; 126 { 127 return bus_space_read_1(sc->sc_iot, sc->sc_ioh, (index << 2)); 128 } 129 130 void 131 cs4231_write(sc, index, value) 132 struct ad1848_softc *sc; 133 int index, value; 134 { 135 bus_space_write_1(sc->sc_iot, sc->sc_ioh, (index << 2), value); 136 } 137 138 struct audio_hw_if audiocs_hw_if = { 139 cs4231_open, 140 cs4231_close, 141 0, 142 ad1848_query_encoding, 143 ad1848_set_params, 144 cs4231_round_blocksize, 145 ad1848_commit_settings, 146 0, 147 0, 148 NULL, 149 NULL, 150 cs4231_halt_output, 151 cs4231_halt_input, 152 0, 153 cs4231_getdev, 154 0, 155 cs4231_set_port, 156 cs4231_get_port, 157 cs4231_query_devinfo, 158 cs4231_malloc, 159 cs4231_free, 160 cs4231_round_buffersize, 161 0, 162 cs4231_get_props, 163 cs4231_trigger_output, 164 cs4231_trigger_input, 165 NULL, 166 }; 167 168 169 #ifdef AUDIO_DEBUG 170 static void 171 cs4231_regdump(label, sc) 172 char *label; 173 struct cs4231_softc *sc; 174 { 175 char bits[128]; 176 volatile struct apc_dma *dma = sc->sc_dmareg; 177 178 printf("cs4231regdump(%s): regs:", label); 179 printf("dmapva: 0x%x; ", dma->dmapva); 180 printf("dmapc: 0x%x; ", dma->dmapc); 181 printf("dmapnva: 0x%x; ", dma->dmapnva); 182 printf("dmapnc: 0x%x\n", dma->dmapnc); 183 printf("dmacva: 0x%x; ", dma->dmacva); 184 printf("dmacc: 0x%x; ", dma->dmacc); 185 printf("dmacnva: 0x%x; ", dma->dmacnva); 186 printf("dmacnc: 0x%x\n", dma->dmacnc); 187 188 printf("apc_dmacsr=%s\n", 189 bitmask_snprintf(dma->dmacsr, APC_BITS, bits, sizeof(bits)) ); 190 191 ad1848_dump_regs(&sc->sc_ad1848); 192 } 193 #endif 194 195 void 196 cs4231_init(sc) 197 struct cs4231_softc *sc; 198 { 199 char *buf; 200 #if 0 201 volatile struct apc_dma *dma = sc->sc_dmareg; 202 #endif 203 int reg; 204 205 #if 0 206 dma->dmacsr = APC_CODEC_PDN; 207 delay(20); 208 dma->dmacsr &= ~APC_CODEC_PDN; 209 #endif 210 /* First, put chip in native mode */ 211 reg = ad_read(&sc->sc_ad1848, SP_MISC_INFO); 212 ad_write(&sc->sc_ad1848, SP_MISC_INFO, reg | MODE2); 213 214 /* Read version numbers from I25 */ 215 reg = ad_read(&sc->sc_ad1848, CS_VERSION_ID); 216 switch (reg & (CS_VERSION_NUMBER | CS_VERSION_CHIPID)) { 217 case 0xa0: 218 sc->sc_ad1848.chip_name = "CS4231A"; 219 break; 220 case 0x80: 221 sc->sc_ad1848.chip_name = "CS4231"; 222 break; 223 case 0x82: 224 sc->sc_ad1848.chip_name = "CS4232"; 225 break; 226 default: 227 if ((buf = malloc(32, M_TEMP, M_NOWAIT)) != NULL) { 228 sprintf(buf, "unknown rev: %x/%x", reg&0xe, reg&7); 229 sc->sc_ad1848.chip_name = buf; 230 } 231 } 232 } 233 234 void * 235 cs4231_malloc(addr, direction, size, pool, flags) 236 void *addr; 237 int direction; 238 size_t size; 239 int pool, flags; 240 { 241 struct cs4231_softc *sc = addr; 242 bus_dma_tag_t dmatag = sc->sc_dmatag; 243 struct cs_dma *p; 244 245 p = malloc(sizeof(*p), pool, flags); 246 if (p == NULL) 247 return (NULL); 248 249 /* Allocate a DMA map */ 250 if (bus_dmamap_create(dmatag, size, 1, size, 0, 251 BUS_DMA_NOWAIT, &p->dmamap) != 0) 252 goto fail1; 253 254 /* Allocate DMA memory */ 255 p->size = size; 256 if (bus_dmamem_alloc(dmatag, size, 64*1024, 0, 257 p->segs, sizeof(p->segs)/sizeof(p->segs[0]), 258 &p->nsegs, BUS_DMA_NOWAIT) != 0) 259 goto fail2; 260 261 /* Map DMA memory into kernel space */ 262 if (bus_dmamem_map(dmatag, p->segs, p->nsegs, p->size, 263 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT) != 0) 264 goto fail3; 265 266 /* Load the buffer */ 267 if (bus_dmamap_load(dmatag, p->dmamap, 268 p->addr, size, NULL, BUS_DMA_NOWAIT) != 0) 269 goto fail4; 270 271 p->next = sc->sc_dmas; 272 sc->sc_dmas = p; 273 return (p->addr); 274 275 fail4: 276 bus_dmamem_unmap(dmatag, p->addr, p->size); 277 fail3: 278 bus_dmamem_free(dmatag, p->segs, p->nsegs); 279 fail2: 280 bus_dmamap_destroy(dmatag, p->dmamap); 281 fail1: 282 free(p, pool); 283 return (NULL); 284 } 285 286 void 287 cs4231_free(addr, ptr, pool) 288 void *addr; 289 void *ptr; 290 int pool; 291 { 292 struct cs4231_softc *sc = addr; 293 bus_dma_tag_t dmatag = sc->sc_dmatag; 294 struct cs_dma *p, **pp; 295 296 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &(*pp)->next) { 297 if (p->addr != ptr) 298 continue; 299 bus_dmamap_unload(dmatag, p->dmamap); 300 bus_dmamem_unmap(dmatag, p->addr, p->size); 301 bus_dmamem_free(dmatag, p->segs, p->nsegs); 302 bus_dmamap_destroy(dmatag, p->dmamap); 303 *pp = p->next; 304 free(p, pool); 305 return; 306 } 307 printf("cs4231_free: rogue pointer\n"); 308 } 309 310 int 311 cs4231_open(addr, flags) 312 void *addr; 313 int flags; 314 { 315 struct cs4231_softc *sc = addr; 316 #if 0 317 struct apc_dma *dma = sc->sc_dmareg; 318 #endif 319 320 DPRINTF(("sa_open: unit %p\n", sc)); 321 322 if (sc->sc_open) 323 return (EBUSY); 324 sc->sc_open = 1; 325 sc->sc_locked = 0; 326 sc->sc_rintr = 0; 327 sc->sc_rarg = 0; 328 sc->sc_pintr = 0; 329 sc->sc_parg = 0; 330 #if 1 331 /*No interrupts from ad1848 */ 332 ad_write(&sc->sc_ad1848, SP_PIN_CONTROL, 0); 333 #endif 334 #if 0 335 dma->dmacsr = APC_RESET; 336 delay(10); 337 dma->dmacsr = 0; 338 delay(10); 339 #endif 340 ad1848_reset(&sc->sc_ad1848); 341 342 DPRINTF(("saopen: ok -> sc=%p\n", sc)); 343 return (0); 344 } 345 346 void 347 cs4231_close(addr) 348 void *addr; 349 { 350 struct cs4231_softc *sc = addr; 351 352 DPRINTF(("sa_close: sc=%p\n", sc)); 353 /* 354 * halt i/o, clear open flag, and done. 355 */ 356 cs4231_halt_input(sc); 357 cs4231_halt_output(sc); 358 sc->sc_open = 0; 359 360 DPRINTF(("sa_close: closed.\n")); 361 } 362 363 size_t 364 cs4231_round_buffersize(addr, direction, size) 365 void *addr; 366 int direction; 367 size_t size; 368 { 369 #if 0 370 if (size > APC_MAX) 371 size = APC_MAX; 372 #endif 373 return (size); 374 } 375 376 int 377 cs4231_round_blocksize(addr, blk) 378 void *addr; 379 int blk; 380 { 381 return (blk & -4); 382 } 383 384 int 385 cs4231_getdev(addr, retp) 386 void *addr; 387 struct audio_device *retp; 388 { 389 *retp = cs4231_device; 390 return (0); 391 } 392 393 static ad1848_devmap_t csmapping[] = { 394 { CSAUDIO_DAC_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL }, 395 { CSAUDIO_LINE_IN_LVL, AD1848_KIND_LVL, AD1848_LINE_CHANNEL }, 396 { CSAUDIO_MONO_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL }, 397 { CSAUDIO_CD_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL }, 398 { CSAUDIO_MONITOR_LVL, AD1848_KIND_LVL, AD1848_MONITOR_CHANNEL }, 399 { CSAUDIO_OUT_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL }, 400 { CSAUDIO_DAC_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL }, 401 { CSAUDIO_LINE_IN_MUTE, AD1848_KIND_MUTE, AD1848_LINE_CHANNEL }, 402 { CSAUDIO_MONO_MUTE, AD1848_KIND_MUTE, AD1848_MONO_CHANNEL }, 403 { CSAUDIO_CD_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL }, 404 { CSAUDIO_MONITOR_MUTE, AD1848_KIND_MUTE, AD1848_MONITOR_CHANNEL }, 405 { CSAUDIO_REC_LVL, AD1848_KIND_RECORDGAIN, -1 }, 406 { CSAUDIO_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1 } 407 }; 408 409 static int nummap = sizeof(csmapping) / sizeof(csmapping[0]); 410 411 412 int 413 cs4231_set_port(addr, cp) 414 void *addr; 415 mixer_ctrl_t *cp; 416 { 417 struct ad1848_softc *ac = addr; 418 419 DPRINTF(("cs4231_set_port: port=%d", cp->dev)); 420 return (ad1848_mixer_set_port(ac, csmapping, nummap, cp)); 421 } 422 423 int 424 cs4231_get_port(addr, cp) 425 void *addr; 426 mixer_ctrl_t *cp; 427 { 428 struct ad1848_softc *ac = addr; 429 430 DPRINTF(("cs4231_get_port: port=%d", cp->dev)); 431 return (ad1848_mixer_get_port(ac, csmapping, nummap, cp)); 432 } 433 434 int 435 cs4231_get_props(addr) 436 void *addr; 437 { 438 return (AUDIO_PROP_FULLDUPLEX); 439 } 440 441 int 442 cs4231_query_devinfo(addr, dip) 443 void *addr; 444 mixer_devinfo_t *dip; 445 { 446 447 switch(dip->index) { 448 #if 0 449 case CSAUDIO_MIC_IN_LVL: /* Microphone */ 450 dip->type = AUDIO_MIXER_VALUE; 451 dip->mixer_class = CSAUDIO_INPUT_CLASS; 452 dip->prev = AUDIO_MIXER_LAST; 453 dip->next = CSAUDIO_MIC_IN_MUTE; 454 strcpy(dip->label.name, AudioNmicrophone); 455 dip->un.v.num_channels = 2; 456 strcpy(dip->un.v.units.name, AudioNvolume); 457 break; 458 #endif 459 460 case CSAUDIO_MONO_LVL: /* mono/microphone mixer */ 461 dip->type = AUDIO_MIXER_VALUE; 462 dip->mixer_class = CSAUDIO_INPUT_CLASS; 463 dip->prev = AUDIO_MIXER_LAST; 464 dip->next = CSAUDIO_MONO_MUTE; 465 strcpy(dip->label.name, AudioNmicrophone); 466 dip->un.v.num_channels = 1; 467 strcpy(dip->un.v.units.name, AudioNvolume); 468 break; 469 470 case CSAUDIO_DAC_LVL: /* dacout */ 471 dip->type = AUDIO_MIXER_VALUE; 472 dip->mixer_class = CSAUDIO_INPUT_CLASS; 473 dip->prev = AUDIO_MIXER_LAST; 474 dip->next = CSAUDIO_DAC_MUTE; 475 strcpy(dip->label.name, AudioNdac); 476 dip->un.v.num_channels = 2; 477 strcpy(dip->un.v.units.name, AudioNvolume); 478 break; 479 480 case CSAUDIO_LINE_IN_LVL: /* line */ 481 dip->type = AUDIO_MIXER_VALUE; 482 dip->mixer_class = CSAUDIO_INPUT_CLASS; 483 dip->prev = AUDIO_MIXER_LAST; 484 dip->next = CSAUDIO_LINE_IN_MUTE; 485 strcpy(dip->label.name, AudioNline); 486 dip->un.v.num_channels = 2; 487 strcpy(dip->un.v.units.name, AudioNvolume); 488 break; 489 490 case CSAUDIO_CD_LVL: /* cd */ 491 dip->type = AUDIO_MIXER_VALUE; 492 dip->mixer_class = CSAUDIO_INPUT_CLASS; 493 dip->prev = AUDIO_MIXER_LAST; 494 dip->next = CSAUDIO_CD_MUTE; 495 strcpy(dip->label.name, AudioNcd); 496 dip->un.v.num_channels = 2; 497 strcpy(dip->un.v.units.name, AudioNvolume); 498 break; 499 500 501 case CSAUDIO_MONITOR_LVL: /* monitor level */ 502 dip->type = AUDIO_MIXER_VALUE; 503 dip->mixer_class = CSAUDIO_MONITOR_CLASS; 504 dip->next = CSAUDIO_MONITOR_MUTE; 505 dip->prev = 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 511 case CSAUDIO_OUT_LVL: /* cs4231 output volume: not useful? */ 512 dip->type = AUDIO_MIXER_VALUE; 513 dip->mixer_class = CSAUDIO_MONITOR_CLASS; 514 dip->prev = dip->next = AUDIO_MIXER_LAST; 515 strcpy(dip->label.name, AudioNoutput); 516 dip->un.v.num_channels = 2; 517 strcpy(dip->un.v.units.name, AudioNvolume); 518 break; 519 520 case CSAUDIO_LINE_IN_MUTE: 521 dip->mixer_class = CSAUDIO_INPUT_CLASS; 522 dip->type = AUDIO_MIXER_ENUM; 523 dip->prev = CSAUDIO_LINE_IN_LVL; 524 dip->next = AUDIO_MIXER_LAST; 525 goto mute; 526 527 case CSAUDIO_DAC_MUTE: 528 dip->mixer_class = CSAUDIO_INPUT_CLASS; 529 dip->type = AUDIO_MIXER_ENUM; 530 dip->prev = CSAUDIO_DAC_LVL; 531 dip->next = AUDIO_MIXER_LAST; 532 goto mute; 533 534 case CSAUDIO_CD_MUTE: 535 dip->mixer_class = CSAUDIO_INPUT_CLASS; 536 dip->type = AUDIO_MIXER_ENUM; 537 dip->prev = CSAUDIO_CD_LVL; 538 dip->next = AUDIO_MIXER_LAST; 539 goto mute; 540 541 case CSAUDIO_MONO_MUTE: 542 dip->mixer_class = CSAUDIO_INPUT_CLASS; 543 dip->type = AUDIO_MIXER_ENUM; 544 dip->prev = CSAUDIO_MONO_LVL; 545 dip->next = AUDIO_MIXER_LAST; 546 goto mute; 547 548 case CSAUDIO_MONITOR_MUTE: 549 dip->mixer_class = CSAUDIO_OUTPUT_CLASS; 550 dip->type = AUDIO_MIXER_ENUM; 551 dip->prev = CSAUDIO_MONITOR_LVL; 552 dip->next = AUDIO_MIXER_LAST; 553 mute: 554 strcpy(dip->label.name, AudioNmute); 555 dip->un.e.num_mem = 2; 556 strcpy(dip->un.e.member[0].label.name, AudioNoff); 557 dip->un.e.member[0].ord = 0; 558 strcpy(dip->un.e.member[1].label.name, AudioNon); 559 dip->un.e.member[1].ord = 1; 560 break; 561 562 case CSAUDIO_REC_LVL: /* record level */ 563 dip->type = AUDIO_MIXER_VALUE; 564 dip->mixer_class = CSAUDIO_RECORD_CLASS; 565 dip->prev = AUDIO_MIXER_LAST; 566 dip->next = CSAUDIO_RECORD_SOURCE; 567 strcpy(dip->label.name, AudioNrecord); 568 dip->un.v.num_channels = 2; 569 strcpy(dip->un.v.units.name, AudioNvolume); 570 break; 571 572 case CSAUDIO_RECORD_SOURCE: 573 dip->mixer_class = CSAUDIO_RECORD_CLASS; 574 dip->type = AUDIO_MIXER_ENUM; 575 dip->prev = CSAUDIO_REC_LVL; 576 dip->next = AUDIO_MIXER_LAST; 577 strcpy(dip->label.name, AudioNsource); 578 dip->un.e.num_mem = 4; 579 strcpy(dip->un.e.member[0].label.name, AudioNoutput); 580 dip->un.e.member[0].ord = DAC_IN_PORT; 581 strcpy(dip->un.e.member[1].label.name, AudioNmicrophone); 582 dip->un.e.member[1].ord = MIC_IN_PORT; 583 strcpy(dip->un.e.member[2].label.name, AudioNdac); 584 dip->un.e.member[2].ord = AUX1_IN_PORT; 585 strcpy(dip->un.e.member[3].label.name, AudioNline); 586 dip->un.e.member[3].ord = LINE_IN_PORT; 587 break; 588 589 case CSAUDIO_INPUT_CLASS: /* input class descriptor */ 590 dip->type = AUDIO_MIXER_CLASS; 591 dip->mixer_class = CSAUDIO_INPUT_CLASS; 592 dip->next = dip->prev = AUDIO_MIXER_LAST; 593 strcpy(dip->label.name, AudioCinputs); 594 break; 595 596 case CSAUDIO_OUTPUT_CLASS: /* output class descriptor */ 597 dip->type = AUDIO_MIXER_CLASS; 598 dip->mixer_class = CSAUDIO_OUTPUT_CLASS; 599 dip->next = dip->prev = AUDIO_MIXER_LAST; 600 strcpy(dip->label.name, AudioCoutputs); 601 break; 602 603 case CSAUDIO_MONITOR_CLASS: /* monitor class descriptor */ 604 dip->type = AUDIO_MIXER_CLASS; 605 dip->mixer_class = CSAUDIO_MONITOR_CLASS; 606 dip->next = dip->prev = AUDIO_MIXER_LAST; 607 strcpy(dip->label.name, AudioCmonitor); 608 break; 609 610 case CSAUDIO_RECORD_CLASS: /* record source class */ 611 dip->type = AUDIO_MIXER_CLASS; 612 dip->mixer_class = CSAUDIO_RECORD_CLASS; 613 dip->next = dip->prev = AUDIO_MIXER_LAST; 614 strcpy(dip->label.name, AudioCrecord); 615 break; 616 617 default: 618 return ENXIO; 619 /*NOTREACHED*/ 620 } 621 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); 622 623 return (0); 624 } 625 626 int 627 cs4231_trigger_output(addr, start, end, blksize, intr, arg, param) 628 void *addr; 629 void *start, *end; 630 int blksize; 631 void (*intr) __P((void *)); 632 void *arg; 633 struct audio_params *param; 634 { 635 struct cs4231_softc *sc = addr; 636 struct cs_dma *p; 637 volatile struct apc_dma *dma = sc->sc_dmareg; 638 int csr; 639 vsize_t n; 640 641 if (sc->sc_locked != 0) { 642 printf("cs4231_trigger_output: already running\n"); 643 return (EINVAL); 644 } 645 646 sc->sc_locked = 1; 647 sc->sc_pintr = intr; 648 sc->sc_parg = arg; 649 650 for (p = sc->sc_dmas; p != NULL && p->addr != start; p = p->next) 651 /*void*/; 652 if (p == NULL) { 653 printf("cs4231_trigger_output: bad addr %p\n", start); 654 return (EINVAL); 655 } 656 657 n = (char *)end - (char *)start; 658 659 /* XXX 660 * Do only `blksize' at a time, so audio_pint() is kept 661 * synchronous with us... 662 */ 663 /*XXX*/sc->sc_blksz = blksize; 664 /*XXX*/sc->sc_nowplaying = p; 665 /*XXX*/sc->sc_playsegsz = n; 666 667 if (n > APC_MAX) 668 n = APC_MAX; 669 670 sc->sc_playcnt = n; 671 672 DPRINTF(("trigger_out: start %p, end %p, size %lu; " 673 "dmaaddr 0x%lx, dmacnt %lu, segsize %lu\n", 674 start, end, (u_long)sc->sc_playsegsz, 675 (u_long)p->dmamap->dm_segs[0].ds_addr, 676 (u_long)n, (u_long)p->size)); 677 678 csr = dma->dmacsr; 679 dma->dmapnva = (u_long)p->dmamap->dm_segs[0].ds_addr; 680 dma->dmapnc = (u_long)n; 681 if ((csr & PDMA_GO) == 0 || (csr & APC_PPAUSE) != 0) { 682 int reg; 683 684 dma->dmacsr &= ~(APC_PIE|APC_PPAUSE); 685 dma->dmacsr |= APC_EI|APC_IE|APC_PIE|APC_EIE|APC_PMIE|PDMA_GO; 686 687 /* Start chip */ 688 689 /* Probably should just ignore this.. */ 690 ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff); 691 ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff); 692 693 reg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 694 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, 695 (PLAYBACK_ENABLE|reg)); 696 } 697 698 return (0); 699 } 700 701 int 702 cs4231_trigger_input(addr, start, end, blksize, intr, arg, param) 703 void *addr; 704 void *start, *end; 705 int blksize; 706 void (*intr) __P((void *)); 707 void *arg; 708 struct audio_params *param; 709 { 710 return (ENXIO); 711 } 712 713 int 714 cs4231_halt_output(addr) 715 void *addr; 716 { 717 struct cs4231_softc *sc = addr; 718 volatile struct apc_dma *dma = sc->sc_dmareg; 719 int reg; 720 721 dma->dmacsr &= ~(APC_EI | APC_IE | APC_PIE | APC_EIE | PDMA_GO | APC_PMIE); 722 reg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 723 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, (reg & ~PLAYBACK_ENABLE)); 724 sc->sc_locked = 0; 725 726 return (0); 727 } 728 729 int 730 cs4231_halt_input(addr) 731 void *addr; 732 { 733 struct cs4231_softc *sc = addr; 734 int reg; 735 736 reg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 737 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, (reg & ~CAPTURE_ENABLE)); 738 sc->sc_locked = 0; 739 740 return (0); 741 } 742 743 744 int 745 cs4231_intr(arg) 746 void *arg; 747 { 748 struct cs4231_softc *sc = arg; 749 volatile struct apc_dma *dma = sc->sc_dmareg; 750 struct cs_dma *p; 751 int ret = 0; 752 int csr; 753 int reg, status; 754 #if defined(DEBUG) || defined(AUDIO_DEBUG) 755 char bits[128]; 756 #endif 757 758 #ifdef AUDIO_DEBUG 759 if (cs4231debug > 1) 760 cs4231_regdump("audiointr", sc); 761 #endif 762 763 /* Read DMA status */ 764 csr = dma->dmacsr; 765 DPRINTF(( 766 "intr: csr=%s; dmapva=0x%lx,dmapc=%lu;dmapnva=0x%lx,dmapnc=%lu\n", 767 bitmask_snprintf(csr, APC_BITS, bits, sizeof(bits)), 768 (u_long)dma->dmapva, (u_long)dma->dmapc, 769 (u_long)dma->dmapnva, (u_long)dma->dmapnc)); 770 771 status = ADREAD(&sc->sc_ad1848, AD1848_STATUS); 772 DPRINTF(("%s: status: %s\n", sc->sc_ad1848.sc_dev.dv_xname, 773 bitmask_snprintf(status, AD_R2_BITS, bits, sizeof(bits)))); 774 if (status & (INTERRUPT_STATUS | SAMPLE_ERROR)) { 775 reg = ad_read(&sc->sc_ad1848, CS_IRQ_STATUS); 776 DPRINTF(("%s: i24: %s\n", sc->sc_ad1848.sc_dev.dv_xname, 777 bitmask_snprintf(reg, CS_I24_BITS, bits, sizeof(bits)))); 778 779 if (reg & CS_IRQ_PI) { 780 ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff); 781 ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff); 782 } 783 /* Clear interrupt bit */ 784 ADWRITE(&sc->sc_ad1848, AD1848_STATUS, 0); 785 } 786 787 /* Write back DMA status (clears interrupt) */ 788 dma->dmacsr = csr; 789 790 /* 791 * Simplistic.. if "play emtpy" is set advance to next chunk. 792 */ 793 #if 1 794 /* Ack all play interrupts*/ 795 if ((csr & (APC_PI|APC_PD|APC_PIE|APC_PMI)) != 0) 796 ret = 1; 797 #endif 798 if (csr & APC_PM) { 799 u_long nextaddr, togo; 800 801 p = sc->sc_nowplaying; 802 803 togo = sc->sc_playsegsz - sc->sc_playcnt; 804 if (togo == 0) { 805 /* Roll over */ 806 nextaddr = (u_long)p->dmamap->dm_segs[0].ds_addr; 807 sc->sc_playcnt = togo = APC_MAX; 808 } else { 809 nextaddr = dma->dmapnva + APC_MAX; 810 if (togo > APC_MAX) 811 togo = APC_MAX; 812 sc->sc_playcnt += togo; 813 } 814 815 dma->dmapnva = nextaddr; 816 dma->dmapnc = togo; 817 818 if (sc->sc_pintr != NULL) 819 (*sc->sc_pintr)(sc->sc_parg); 820 821 ret = 1; 822 } 823 824 if (csr & APC_CI) { 825 if (sc->sc_rintr != NULL) { 826 ret = 1; 827 (*sc->sc_rintr)(sc->sc_rarg); 828 } 829 } 830 831 #ifdef DEBUG 832 if (ret == 0) { 833 printf( 834 "oops: csr=%s; dmapva=0x%lx,dmapc=%lu;dmapnva=0x%lx,dmapnc=%lu\n", 835 bitmask_snprintf(csr, APC_BITS, bits, sizeof(bits)), 836 (u_long)dma->dmapva, (u_long)dma->dmapc, 837 (u_long)dma->dmapnva, (u_long)dma->dmapnc); 838 ret = 1; 839 } 840 #endif 841 842 return (ret); 843 } 844 #endif /* NAUDIO > 0 */ 845