1 /* $NetBSD: cs4231.c,v 1.4 2000/06/16 11:47:35 pk 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 }; 166 167 168 #ifdef AUDIO_DEBUG 169 static void 170 cs4231_regdump(label, sc) 171 char *label; 172 struct cs4231_softc *sc; 173 { 174 char bits[128]; 175 volatile struct apc_dma *dma = sc->sc_dmareg; 176 177 printf("cs4231regdump(%s): regs:", label); 178 printf("dmapva: 0x%x; ", dma->dmapva); 179 printf("dmapc: 0x%x; ", dma->dmapc); 180 printf("dmapnva: 0x%x; ", dma->dmapnva); 181 printf("dmapnc: 0x%x\n", dma->dmapnc); 182 printf("dmacva: 0x%x; ", dma->dmacva); 183 printf("dmacc: 0x%x; ", dma->dmacc); 184 printf("dmacnva: 0x%x; ", dma->dmacnva); 185 printf("dmacnc: 0x%x\n", dma->dmacnc); 186 187 printf("apc_dmacsr=%s\n", 188 bitmask_snprintf(dma->dmacsr, APC_BITS, bits, sizeof(bits)) ); 189 190 ad1848_dump_regs(&sc->sc_ad1848); 191 } 192 #endif 193 194 void 195 cs4231_init(sc) 196 struct cs4231_softc *sc; 197 { 198 char *buf; 199 #if 0 200 volatile struct apc_dma *dma = sc->sc_dmareg; 201 #endif 202 int reg; 203 204 #if 0 205 dma->dmacsr = APC_CODEC_PDN; 206 delay(20); 207 dma->dmacsr &= ~APC_CODEC_PDN; 208 #endif 209 /* First, put chip in native mode */ 210 reg = ad_read(&sc->sc_ad1848, SP_MISC_INFO); 211 ad_write(&sc->sc_ad1848, SP_MISC_INFO, reg | MODE2); 212 213 /* Read version numbers from I25 */ 214 reg = ad_read(&sc->sc_ad1848, CS_VERSION_ID); 215 switch (reg & (CS_VERSION_NUMBER | CS_VERSION_CHIPID)) { 216 case 0xa0: 217 sc->sc_ad1848.chip_name = "CS4231A"; 218 break; 219 case 0x80: 220 sc->sc_ad1848.chip_name = "CS4231"; 221 break; 222 case 0x82: 223 sc->sc_ad1848.chip_name = "CS4232"; 224 break; 225 default: 226 if ((buf = malloc(32, M_TEMP, M_NOWAIT)) != NULL) { 227 sprintf(buf, "unknown rev: %x/%x", reg&0xe, reg&7); 228 sc->sc_ad1848.chip_name = buf; 229 } 230 } 231 } 232 233 void * 234 cs4231_malloc(addr, direction, size, pool, flags) 235 void *addr; 236 int direction; 237 size_t size; 238 int pool, flags; 239 { 240 struct cs4231_softc *sc = addr; 241 bus_dma_tag_t dmatag = sc->sc_dmatag; 242 struct cs_dma *p; 243 244 p = malloc(sizeof(*p), pool, flags); 245 if (p == NULL) 246 return (NULL); 247 248 /* Allocate a DMA map */ 249 if (bus_dmamap_create(dmatag, size, 1, size, 0, 250 BUS_DMA_NOWAIT, &p->dmamap) != 0) 251 goto fail1; 252 253 /* Allocate DMA memory */ 254 p->size = size; 255 if (bus_dmamem_alloc(dmatag, size, 64*1024, 0, 256 p->segs, sizeof(p->segs)/sizeof(p->segs[0]), 257 &p->nsegs, BUS_DMA_NOWAIT) != 0) 258 goto fail2; 259 260 /* Map DMA memory into kernel space */ 261 if (bus_dmamem_map(dmatag, p->segs, p->nsegs, p->size, 262 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT) != 0) 263 goto fail3; 264 265 /* Load the buffer */ 266 if (bus_dmamap_load(dmatag, p->dmamap, 267 p->addr, size, NULL, BUS_DMA_NOWAIT) != 0) 268 goto fail4; 269 270 p->next = sc->sc_dmas; 271 sc->sc_dmas = p; 272 return (p->addr); 273 274 fail4: 275 bus_dmamem_unmap(dmatag, p->addr, p->size); 276 fail3: 277 bus_dmamem_free(dmatag, p->segs, p->nsegs); 278 fail2: 279 bus_dmamap_destroy(dmatag, p->dmamap); 280 fail1: 281 free(p, pool); 282 return (NULL); 283 } 284 285 void 286 cs4231_free(addr, ptr, pool) 287 void *addr; 288 void *ptr; 289 int pool; 290 { 291 struct cs4231_softc *sc = addr; 292 bus_dma_tag_t dmatag = sc->sc_dmatag; 293 struct cs_dma *p, **pp; 294 295 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &(*pp)->next) { 296 if (p->addr != ptr) 297 continue; 298 bus_dmamap_unload(dmatag, p->dmamap); 299 bus_dmamem_unmap(dmatag, p->addr, p->size); 300 bus_dmamem_free(dmatag, p->segs, p->nsegs); 301 bus_dmamap_destroy(dmatag, p->dmamap); 302 *pp = p->next; 303 free(p, pool); 304 return; 305 } 306 printf("cs4231_free: rogue pointer\n"); 307 } 308 309 int 310 cs4231_open(addr, flags) 311 void *addr; 312 int flags; 313 { 314 struct cs4231_softc *sc = addr; 315 #if 0 316 struct apc_dma *dma = sc->sc_dmareg; 317 #endif 318 319 DPRINTF(("sa_open: unit %p\n", sc)); 320 321 if (sc->sc_open) 322 return (EBUSY); 323 sc->sc_open = 1; 324 sc->sc_locked = 0; 325 sc->sc_rintr = 0; 326 sc->sc_rarg = 0; 327 sc->sc_pintr = 0; 328 sc->sc_parg = 0; 329 #if 1 330 /*No interrupts from ad1848 */ 331 ad_write(&sc->sc_ad1848, SP_PIN_CONTROL, 0); 332 #endif 333 #if 0 334 dma->dmacsr = APC_RESET; 335 delay(10); 336 dma->dmacsr = 0; 337 delay(10); 338 #endif 339 ad1848_reset(&sc->sc_ad1848); 340 341 DPRINTF(("saopen: ok -> sc=%p\n", sc)); 342 return (0); 343 } 344 345 void 346 cs4231_close(addr) 347 void *addr; 348 { 349 struct cs4231_softc *sc = addr; 350 351 DPRINTF(("sa_close: sc=%p\n", sc)); 352 /* 353 * halt i/o, clear open flag, and done. 354 */ 355 cs4231_halt_input(sc); 356 cs4231_halt_output(sc); 357 sc->sc_open = 0; 358 359 DPRINTF(("sa_close: closed.\n")); 360 } 361 362 size_t 363 cs4231_round_buffersize(addr, direction, size) 364 void *addr; 365 int direction; 366 size_t size; 367 { 368 #if 0 369 if (size > APC_MAX) 370 size = APC_MAX; 371 #endif 372 return (size); 373 } 374 375 int 376 cs4231_round_blocksize(addr, blk) 377 void *addr; 378 int blk; 379 { 380 return (blk & -4); 381 } 382 383 int 384 cs4231_getdev(addr, retp) 385 void *addr; 386 struct audio_device *retp; 387 { 388 *retp = cs4231_device; 389 return (0); 390 } 391 392 static ad1848_devmap_t csmapping[] = { 393 { CSAUDIO_DAC_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL }, 394 { CSAUDIO_LINE_IN_LVL, AD1848_KIND_LVL, AD1848_LINE_CHANNEL }, 395 { CSAUDIO_MONO_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL }, 396 { CSAUDIO_CD_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL }, 397 { CSAUDIO_MONITOR_LVL, AD1848_KIND_LVL, AD1848_MONITOR_CHANNEL }, 398 { CSAUDIO_OUT_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL }, 399 { CSAUDIO_DAC_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL }, 400 { CSAUDIO_LINE_IN_MUTE, AD1848_KIND_MUTE, AD1848_LINE_CHANNEL }, 401 { CSAUDIO_MONO_MUTE, AD1848_KIND_MUTE, AD1848_MONO_CHANNEL }, 402 { CSAUDIO_CD_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL }, 403 { CSAUDIO_MONITOR_MUTE, AD1848_KIND_MUTE, AD1848_MONITOR_CHANNEL }, 404 { CSAUDIO_REC_LVL, AD1848_KIND_RECORDGAIN, -1 }, 405 { CSAUDIO_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1 } 406 }; 407 408 static int nummap = sizeof(csmapping) / sizeof(csmapping[0]); 409 410 411 int 412 cs4231_set_port(addr, cp) 413 void *addr; 414 mixer_ctrl_t *cp; 415 { 416 struct ad1848_softc *ac = addr; 417 418 DPRINTF(("cs4231_set_port: port=%d", cp->dev)); 419 return (ad1848_mixer_set_port(ac, csmapping, nummap, cp)); 420 } 421 422 int 423 cs4231_get_port(addr, cp) 424 void *addr; 425 mixer_ctrl_t *cp; 426 { 427 struct ad1848_softc *ac = addr; 428 429 DPRINTF(("cs4231_get_port: port=%d", cp->dev)); 430 return (ad1848_mixer_get_port(ac, csmapping, nummap, cp)); 431 } 432 433 int 434 cs4231_get_props(addr) 435 void *addr; 436 { 437 return (AUDIO_PROP_FULLDUPLEX); 438 } 439 440 int 441 cs4231_query_devinfo(addr, dip) 442 void *addr; 443 mixer_devinfo_t *dip; 444 { 445 446 switch(dip->index) { 447 #if 0 448 case CSAUDIO_MIC_IN_LVL: /* Microphone */ 449 dip->type = AUDIO_MIXER_VALUE; 450 dip->mixer_class = CSAUDIO_INPUT_CLASS; 451 dip->prev = AUDIO_MIXER_LAST; 452 dip->next = CSAUDIO_MIC_IN_MUTE; 453 strcpy(dip->label.name, AudioNmicrophone); 454 dip->un.v.num_channels = 2; 455 strcpy(dip->un.v.units.name, AudioNvolume); 456 break; 457 #endif 458 459 case CSAUDIO_MONO_LVL: /* mono/microphone mixer */ 460 dip->type = AUDIO_MIXER_VALUE; 461 dip->mixer_class = CSAUDIO_INPUT_CLASS; 462 dip->prev = AUDIO_MIXER_LAST; 463 dip->next = CSAUDIO_MONO_MUTE; 464 strcpy(dip->label.name, AudioNmicrophone); 465 dip->un.v.num_channels = 1; 466 strcpy(dip->un.v.units.name, AudioNvolume); 467 break; 468 469 case CSAUDIO_DAC_LVL: /* dacout */ 470 dip->type = AUDIO_MIXER_VALUE; 471 dip->mixer_class = CSAUDIO_INPUT_CLASS; 472 dip->prev = AUDIO_MIXER_LAST; 473 dip->next = CSAUDIO_DAC_MUTE; 474 strcpy(dip->label.name, AudioNdac); 475 dip->un.v.num_channels = 2; 476 strcpy(dip->un.v.units.name, AudioNvolume); 477 break; 478 479 case CSAUDIO_LINE_IN_LVL: /* line */ 480 dip->type = AUDIO_MIXER_VALUE; 481 dip->mixer_class = CSAUDIO_INPUT_CLASS; 482 dip->prev = AUDIO_MIXER_LAST; 483 dip->next = CSAUDIO_LINE_IN_MUTE; 484 strcpy(dip->label.name, AudioNline); 485 dip->un.v.num_channels = 2; 486 strcpy(dip->un.v.units.name, AudioNvolume); 487 break; 488 489 case CSAUDIO_CD_LVL: /* cd */ 490 dip->type = AUDIO_MIXER_VALUE; 491 dip->mixer_class = CSAUDIO_INPUT_CLASS; 492 dip->prev = AUDIO_MIXER_LAST; 493 dip->next = CSAUDIO_CD_MUTE; 494 strcpy(dip->label.name, AudioNcd); 495 dip->un.v.num_channels = 2; 496 strcpy(dip->un.v.units.name, AudioNvolume); 497 break; 498 499 500 case CSAUDIO_MONITOR_LVL: /* monitor level */ 501 dip->type = AUDIO_MIXER_VALUE; 502 dip->mixer_class = CSAUDIO_MONITOR_CLASS; 503 dip->next = CSAUDIO_MONITOR_MUTE; 504 dip->prev = AUDIO_MIXER_LAST; 505 strcpy(dip->label.name, AudioNmonitor); 506 dip->un.v.num_channels = 1; 507 strcpy(dip->un.v.units.name, AudioNvolume); 508 break; 509 510 case CSAUDIO_OUT_LVL: /* cs4231 output volume: not useful? */ 511 dip->type = AUDIO_MIXER_VALUE; 512 dip->mixer_class = CSAUDIO_MONITOR_CLASS; 513 dip->prev = dip->next = AUDIO_MIXER_LAST; 514 strcpy(dip->label.name, AudioNoutput); 515 dip->un.v.num_channels = 2; 516 strcpy(dip->un.v.units.name, AudioNvolume); 517 break; 518 519 case CSAUDIO_LINE_IN_MUTE: 520 dip->mixer_class = CSAUDIO_INPUT_CLASS; 521 dip->type = AUDIO_MIXER_ENUM; 522 dip->prev = CSAUDIO_LINE_IN_LVL; 523 dip->next = AUDIO_MIXER_LAST; 524 goto mute; 525 526 case CSAUDIO_DAC_MUTE: 527 dip->mixer_class = CSAUDIO_INPUT_CLASS; 528 dip->type = AUDIO_MIXER_ENUM; 529 dip->prev = CSAUDIO_DAC_LVL; 530 dip->next = AUDIO_MIXER_LAST; 531 goto mute; 532 533 case CSAUDIO_CD_MUTE: 534 dip->mixer_class = CSAUDIO_INPUT_CLASS; 535 dip->type = AUDIO_MIXER_ENUM; 536 dip->prev = CSAUDIO_CD_LVL; 537 dip->next = AUDIO_MIXER_LAST; 538 goto mute; 539 540 case CSAUDIO_MONO_MUTE: 541 dip->mixer_class = CSAUDIO_INPUT_CLASS; 542 dip->type = AUDIO_MIXER_ENUM; 543 dip->prev = CSAUDIO_MONO_LVL; 544 dip->next = AUDIO_MIXER_LAST; 545 goto mute; 546 547 case CSAUDIO_MONITOR_MUTE: 548 dip->mixer_class = CSAUDIO_OUTPUT_CLASS; 549 dip->type = AUDIO_MIXER_ENUM; 550 dip->prev = CSAUDIO_MONITOR_LVL; 551 dip->next = AUDIO_MIXER_LAST; 552 mute: 553 strcpy(dip->label.name, AudioNmute); 554 dip->un.e.num_mem = 2; 555 strcpy(dip->un.e.member[0].label.name, AudioNoff); 556 dip->un.e.member[0].ord = 0; 557 strcpy(dip->un.e.member[1].label.name, AudioNon); 558 dip->un.e.member[1].ord = 1; 559 break; 560 561 case CSAUDIO_REC_LVL: /* record level */ 562 dip->type = AUDIO_MIXER_VALUE; 563 dip->mixer_class = CSAUDIO_RECORD_CLASS; 564 dip->prev = AUDIO_MIXER_LAST; 565 dip->next = CSAUDIO_RECORD_SOURCE; 566 strcpy(dip->label.name, AudioNrecord); 567 dip->un.v.num_channels = 2; 568 strcpy(dip->un.v.units.name, AudioNvolume); 569 break; 570 571 case CSAUDIO_RECORD_SOURCE: 572 dip->mixer_class = CSAUDIO_RECORD_CLASS; 573 dip->type = AUDIO_MIXER_ENUM; 574 dip->prev = CSAUDIO_REC_LVL; 575 dip->next = AUDIO_MIXER_LAST; 576 strcpy(dip->label.name, AudioNsource); 577 dip->un.e.num_mem = 4; 578 strcpy(dip->un.e.member[0].label.name, AudioNoutput); 579 dip->un.e.member[0].ord = DAC_IN_PORT; 580 strcpy(dip->un.e.member[1].label.name, AudioNmicrophone); 581 dip->un.e.member[1].ord = MIC_IN_PORT; 582 strcpy(dip->un.e.member[2].label.name, AudioNdac); 583 dip->un.e.member[2].ord = AUX1_IN_PORT; 584 strcpy(dip->un.e.member[3].label.name, AudioNline); 585 dip->un.e.member[3].ord = LINE_IN_PORT; 586 break; 587 588 case CSAUDIO_INPUT_CLASS: /* input class descriptor */ 589 dip->type = AUDIO_MIXER_CLASS; 590 dip->mixer_class = CSAUDIO_INPUT_CLASS; 591 dip->next = dip->prev = AUDIO_MIXER_LAST; 592 strcpy(dip->label.name, AudioCinputs); 593 break; 594 595 case CSAUDIO_OUTPUT_CLASS: /* output class descriptor */ 596 dip->type = AUDIO_MIXER_CLASS; 597 dip->mixer_class = CSAUDIO_OUTPUT_CLASS; 598 dip->next = dip->prev = AUDIO_MIXER_LAST; 599 strcpy(dip->label.name, AudioCoutputs); 600 break; 601 602 case CSAUDIO_MONITOR_CLASS: /* monitor class descriptor */ 603 dip->type = AUDIO_MIXER_CLASS; 604 dip->mixer_class = CSAUDIO_MONITOR_CLASS; 605 dip->next = dip->prev = AUDIO_MIXER_LAST; 606 strcpy(dip->label.name, AudioCmonitor); 607 break; 608 609 case CSAUDIO_RECORD_CLASS: /* record source class */ 610 dip->type = AUDIO_MIXER_CLASS; 611 dip->mixer_class = CSAUDIO_RECORD_CLASS; 612 dip->next = dip->prev = AUDIO_MIXER_LAST; 613 strcpy(dip->label.name, AudioCrecord); 614 break; 615 616 default: 617 return ENXIO; 618 /*NOTREACHED*/ 619 } 620 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); 621 622 return (0); 623 } 624 625 int 626 cs4231_trigger_output(addr, start, end, blksize, intr, arg, param) 627 void *addr; 628 void *start, *end; 629 int blksize; 630 void (*intr) __P((void *)); 631 void *arg; 632 struct audio_params *param; 633 { 634 struct cs4231_softc *sc = addr; 635 struct cs_dma *p; 636 volatile struct apc_dma *dma = sc->sc_dmareg; 637 int csr; 638 vsize_t n; 639 640 if (sc->sc_locked != 0) { 641 printf("cs4231_trigger_output: already running\n"); 642 return (EINVAL); 643 } 644 645 sc->sc_locked = 1; 646 sc->sc_pintr = intr; 647 sc->sc_parg = arg; 648 649 for (p = sc->sc_dmas; p != NULL && p->addr != start; p = p->next) 650 /*void*/; 651 if (p == NULL) { 652 printf("cs4231_trigger_output: bad addr %p\n", start); 653 return (EINVAL); 654 } 655 656 n = (char *)end - (char *)start; 657 658 /* XXX 659 * Do only `blksize' at a time, so audio_pint() is kept 660 * synchronous with us... 661 */ 662 /*XXX*/sc->sc_blksz = blksize; 663 /*XXX*/sc->sc_nowplaying = p; 664 /*XXX*/sc->sc_playsegsz = n; 665 666 if (n > APC_MAX) 667 n = APC_MAX; 668 669 sc->sc_playcnt = n; 670 671 DPRINTF(("trigger_out: start %p, end %p, size %lu; " 672 "dmaaddr 0x%lx, dmacnt %lu, segsize %lu\n", 673 start, end, (u_long)sc->sc_playsegsz, 674 (u_long)p->dmamap->dm_segs[0].ds_addr, 675 (u_long)n, (u_long)p->size)); 676 677 csr = dma->dmacsr; 678 dma->dmapnva = (u_long)p->dmamap->dm_segs[0].ds_addr; 679 dma->dmapnc = (u_long)n; 680 if ((csr & PDMA_GO) == 0 || (csr & APC_PPAUSE) != 0) { 681 int reg; 682 683 dma->dmacsr &= ~(APC_PIE|APC_PPAUSE); 684 dma->dmacsr |= APC_EI|APC_IE|APC_PIE|APC_EIE|APC_PMIE|PDMA_GO; 685 686 /* Start chip */ 687 688 /* Probably should just ignore this.. */ 689 ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff); 690 ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff); 691 692 reg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 693 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, 694 (PLAYBACK_ENABLE|reg)); 695 } 696 697 return (0); 698 } 699 700 int 701 cs4231_trigger_input(addr, start, end, blksize, intr, arg, param) 702 void *addr; 703 void *start, *end; 704 int blksize; 705 void (*intr) __P((void *)); 706 void *arg; 707 struct audio_params *param; 708 { 709 return (ENXIO); 710 } 711 712 int 713 cs4231_halt_output(addr) 714 void *addr; 715 { 716 struct cs4231_softc *sc = addr; 717 volatile struct apc_dma *dma = sc->sc_dmareg; 718 int reg; 719 720 dma->dmacsr &= ~(APC_EI | APC_IE | APC_PIE | APC_EIE | PDMA_GO | APC_PMIE); 721 reg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 722 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, (reg & ~PLAYBACK_ENABLE)); 723 sc->sc_locked = 0; 724 725 return (0); 726 } 727 728 int 729 cs4231_halt_input(addr) 730 void *addr; 731 { 732 struct cs4231_softc *sc = addr; 733 int reg; 734 735 reg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 736 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, (reg & ~CAPTURE_ENABLE)); 737 sc->sc_locked = 0; 738 739 return (0); 740 } 741 742 743 int 744 cs4231_intr(arg) 745 void *arg; 746 { 747 struct cs4231_softc *sc = arg; 748 volatile struct apc_dma *dma = sc->sc_dmareg; 749 struct cs_dma *p; 750 int ret = 0; 751 int csr; 752 int reg, status; 753 #if defined(DEBUG) || defined(AUDIO_DEBUG) 754 char bits[128]; 755 #endif 756 757 #ifdef AUDIO_DEBUG 758 if (cs4231debug > 1) 759 cs4231_regdump("audiointr", sc); 760 #endif 761 762 /* Read DMA status */ 763 csr = dma->dmacsr; 764 DPRINTF(( 765 "intr: csr=%s; dmapva=0x%lx,dmapc=%lu;dmapnva=0x%lx,dmapnc=%lu\n", 766 bitmask_snprintf(csr, APC_BITS, bits, sizeof(bits)), 767 (u_long)dma->dmapva, (u_long)dma->dmapc, 768 (u_long)dma->dmapnva, (u_long)dma->dmapnc)); 769 770 status = ADREAD(&sc->sc_ad1848, AD1848_STATUS); 771 DPRINTF(("%s: status: %s\n", sc->sc_ad1848.sc_dev.dv_xname, 772 bitmask_snprintf(status, AD_R2_BITS, bits, sizeof(bits)))); 773 if (status & (INTERRUPT_STATUS | SAMPLE_ERROR)) { 774 reg = ad_read(&sc->sc_ad1848, CS_IRQ_STATUS); 775 DPRINTF(("%s: i24: %s\n", sc->sc_ad1848.sc_dev.dv_xname, 776 bitmask_snprintf(reg, CS_I24_BITS, bits, sizeof(bits)))); 777 778 if (reg & CS_IRQ_PI) { 779 ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff); 780 ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff); 781 } 782 /* Clear interrupt bit */ 783 ADWRITE(&sc->sc_ad1848, AD1848_STATUS, 0); 784 } 785 786 /* Write back DMA status (clears interrupt) */ 787 dma->dmacsr = csr; 788 789 /* 790 * Simplistic.. if "play emtpy" is set advance to next chunk. 791 */ 792 #if 1 793 /* Ack all play interrupts*/ 794 if ((csr & (APC_PI|APC_PD|APC_PIE|APC_PMI)) != 0) 795 ret = 1; 796 #endif 797 if (csr & APC_PM) { 798 u_long nextaddr, togo; 799 800 p = sc->sc_nowplaying; 801 802 togo = sc->sc_playsegsz - sc->sc_playcnt; 803 if (togo == 0) { 804 /* Roll over */ 805 nextaddr = (u_long)p->dmamap->dm_segs[0].ds_addr; 806 sc->sc_playcnt = togo = APC_MAX; 807 } else { 808 nextaddr = dma->dmapnva + APC_MAX; 809 if (togo > APC_MAX) 810 togo = APC_MAX; 811 sc->sc_playcnt += togo; 812 } 813 814 dma->dmapnva = nextaddr; 815 dma->dmapnc = togo; 816 817 if (sc->sc_pintr != NULL) 818 (*sc->sc_pintr)(sc->sc_parg); 819 820 ret = 1; 821 } 822 823 if (csr & APC_CI) { 824 if (sc->sc_rintr != NULL) { 825 ret = 1; 826 (*sc->sc_rintr)(sc->sc_rarg); 827 } 828 } 829 830 #ifdef DEBUG 831 if (ret == 0) { 832 printf( 833 "oops: csr=%s; dmapva=0x%lx,dmapc=%lu;dmapnva=0x%lx,dmapnc=%lu\n", 834 bitmask_snprintf(csr, APC_BITS, bits, sizeof(bits)), 835 (u_long)dma->dmapva, (u_long)dma->dmapc, 836 (u_long)dma->dmapnva, (u_long)dma->dmapnc); 837 ret = 1; 838 } 839 #endif 840 841 return (ret); 842 } 843 #endif /* NAUDIO > 0 */ 844