1 /* 2 * Copyright (c) 1991, 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * All advertising materials mentioning features or use of this software 10 * must display the following acknowledgement: 11 * This product includes software developed by the University of 12 * California, Lawrence Berkeley Laboratory. 13 * 14 * %sccs.include.redist.c% 15 * 16 * @(#)bsd_audio.c 7.4 (Berkeley) 04/20/93 17 * 18 * from: $Header: bsd_audio.c,v 1.17 93/04/20 05:31:28 torek Exp $ (LBL) 19 */ 20 #include "bsdaudio.h" 21 #if NBSDAUDIO > 0 22 23 #include <sys/param.h> 24 #include <sys/systm.h> 25 26 #if BSD < 199103 27 #ifndef SUNOS 28 #define SUNOS 29 #endif 30 #endif 31 32 #include <sys/errno.h> 33 #include <sys/file.h> 34 #include <sys/proc.h> 35 #include <sys/user.h> 36 #include <sys/vnode.h> 37 #include <sys/ioctl.h> 38 #include <sys/time.h> 39 #ifndef SUNOS 40 #include <sys/tty.h> 41 #endif 42 #include <sys/uio.h> 43 44 #ifdef SUNOS 45 #include <sundev/mbvar.h> 46 #include <sun4c/intreg.h> 47 #else 48 #include <sys/device.h> 49 #include <machine/autoconf.h> 50 #endif 51 #include <machine/cpu.h> 52 53 /* 54 * Avoid name clashes with SunOS so we can config either the bsd or sun 55 * streams driver in a SunOS kernel. 56 */ 57 #ifdef SUNOS 58 #include <sbusdev/bsd_audioreg.h> 59 #include <sbusdev/bsd_audiovar.h> 60 #include <sbusdev/bsd_audioio.h> 61 struct selinfo { 62 struct proc *si_proc; 63 int si_coll; 64 }; 65 #else 66 #include <sparc/dev/bsd_audioreg.h> 67 #include <sparc/dev/bsd_audiovar.h> 68 #include <machine/bsd_audioio.h> 69 #endif 70 71 #ifdef SUNOS 72 #include "bsd_audiocompat.h" 73 #endif 74 75 /* 76 * Initial/default block size is patchable. 77 */ 78 int audio_blocksize = DEFBLKSIZE; 79 int audio_backlog = 400; /* 50ms in samples */ 80 81 /* 82 * Software state, per AMD79C30 audio chip. 83 */ 84 struct audio_softc { 85 #ifndef SUNOS 86 struct device sc_dev; /* base device */ 87 struct intrhand sc_hwih; /* hardware interrupt vector */ 88 struct intrhand sc_swih; /* software interrupt vector */ 89 #endif 90 int sc_interrupts; /* number of interrupts taken */ 91 92 int sc_open; /* single use device */ 93 u_long sc_wseek; /* timestamp of last frame written */ 94 u_long sc_rseek; /* timestamp of last frame read */ 95 struct mapreg sc_map; /* current contents of map registers */ 96 struct selinfo sc_wsel; /* write selector */ 97 struct selinfo sc_rsel; /* read selector */ 98 /* 99 * keep track of levels so we don't have to convert back from 100 * MAP gain constants 101 */ 102 int sc_rlevel; /* record level */ 103 int sc_plevel; /* play level */ 104 int sc_mlevel; /* monitor level */ 105 106 /* sc_au is special in that the hardware interrupt handler uses it */ 107 struct auio sc_au; /* recv and xmit buffers, etc */ 108 109 }; 110 111 /* interrupt interfaces */ 112 #ifndef AUDIO_C_HANDLER 113 int audiohwintr __P((void *)); 114 #endif 115 int audioswintr __P((void *)); 116 117 /* forward declarations */ 118 int audio_sleep __P((struct aucb *, int)); 119 void audio_setmap __P((volatile struct amd7930 *, struct mapreg *)); 120 121 static void init_amd(); 122 123 #if !defined(AUDIO_C_HANDLER) || defined(SUNOS) 124 struct auio *audio_au; 125 extern void audio_trap(); 126 #endif 127 128 #ifdef SUNOS 129 struct audio_softc audio_softc; 130 #define SOFTC(dev) &audio_softc 131 #define UIOMOVE(cp, len, code, uio) uiomove(cp, len, code, uio) 132 133 #define AUDIOOPEN(d, f, i, p)\ 134 audioopen(d, f, i)\ 135 dev_t d; int f, i; 136 #define AUDIOCLOSE(d, f, i, p)\ 137 audioclose(d, f, i)\ 138 dev_t d; int f, i; 139 #define AUDIOREAD(d, u, f) \ 140 audioread(d, u) dev_t d; struct uio *u; 141 #define AUDIOWRITE(d, u, f) \ 142 audiowrite(d, u) dev_t d; struct uio *u; 143 #define AUDIOIOCTL(d, c, a, f, o)\ 144 audioioctl(d, c, a, f)\ 145 dev_t d; int c; caddr_t a; int f; 146 #define AUDIOSELECT(d, r, p)\ 147 audio_select(d, r, p)\ 148 dev_t d; int r; struct proc *p; 149 150 151 #define AUDIO_SET_SWINTR set_intreg(IR_SOFT_INT4, 1) 152 153 int 154 audioselect(dev, rw) 155 register dev_t dev; 156 int rw; 157 { 158 return (audio_select(dev, rw, u.u_procp)); 159 } 160 161 static void 162 selrecord(p, si) 163 struct proc *p; 164 struct selinfo *si; 165 { 166 if (si->si_proc != 0) 167 si->si_coll = 1; 168 else 169 si->si_proc = p; 170 } 171 #define SELWAKEUP(si) \ 172 {\ 173 if ((si)->si_proc != 0) {\ 174 selwakeup((si)->si_proc, (si)->si_coll); \ 175 (si)->si_proc = 0;\ 176 (si)->si_coll = 0;\ 177 }\ 178 } 179 180 181 static int audioattach(); 182 static int audioidentify(); 183 184 struct dev_ops bsdaudio_ops = { 185 0, 186 audioidentify, 187 audioattach, 188 }; 189 190 static int 191 audioidentify(cp) 192 char *cp; 193 { 194 return (strcmp(cp, "audio") == 0); 195 } 196 197 static int 198 audioattach(dev) 199 struct dev_info *dev; 200 { 201 register struct audio_softc *sc; 202 register volatile struct amd7930 *amd; 203 struct dev_reg *reg; 204 205 sc = &audio_softc; 206 if (dev->devi_nreg != 1 || dev->devi_nintr != 1) { 207 printf("audio: bad config\n"); 208 return (-1); 209 } 210 reg = dev->devi_reg; 211 amd = (struct amd7930 *)map_regs(reg->reg_addr, reg->reg_size, 212 reg->reg_bustype); 213 sc->sc_au.au_amd = amd; 214 init_amd(amd); 215 216 audio_au = &sc->sc_au; 217 #ifndef AUDIO_C_HANDLER 218 settrap(dev->devi_intr->int_pri, audio_trap); 219 #else 220 /* XXX */ 221 addintr(dev->devi_intr->int_pri, audiohwintr, dev->devi_name, 222 dev->devi_unit); 223 #endif 224 addintr(4, audioswintr, dev->devi_name, dev->devi_unit); 225 report_dev(dev); 226 227 return (0); 228 } 229 #else 230 #define AUDIOOPEN(d, f, i, p) audioopen(dev_t d, int f, int i, struct proc *p) 231 #define AUDIOCLOSE(d, f, i, p) audioclose(dev_t d, int f, int i, \ 232 struct proc *p) 233 #define AUDIOREAD(d, u, f) audioread(dev_t d, struct uio *u, int f) 234 #define AUDIOWRITE(d, u, f) audiowrite(dev_t d, struct uio *u, int f) 235 #define AUDIOIOCTL(d, c, a, f, o)\ 236 audioioctl(dev_t dev, int c, caddr_t a, int f, struct proc *p) 237 #define AUDIOSELECT(d, r, p) audioselect(dev_t dev, int rw, struct proc *p) 238 #define SELWAKEUP selwakeup 239 240 #define AUDIO_SET_SWINTR ienab_bis(IE_L6) 241 242 /* autoconfiguration driver */ 243 void audioattach(struct device *, struct device *, void *); 244 struct cfdriver audiocd = 245 { NULL, "audio", matchbyname, audioattach, 246 DV_DULL, sizeof(struct audio_softc) }; 247 #define SOFTC(dev) audiocd.cd_devs[minor(dev)] 248 #define UIOMOVE(cp, len, code, uio) uiomove(cp, len, uio) 249 250 /* 251 * Audio chip found. 252 */ 253 void 254 audioattach(parent, self, args) 255 struct device *parent, *self; 256 void *args; 257 { 258 register struct audio_softc *sc = (struct audio_softc *)self; 259 register struct romaux *ra = args; 260 register volatile struct amd7930 *amd; 261 register int pri; 262 263 if (ra->ra_nintr != 1) { 264 printf(": expected 1 interrupt, got %d\n", ra->ra_nintr); 265 return; 266 } 267 pri = ra->ra_intr[0].int_pri; 268 printf(" pri %d, softpri %d\n", pri, PIL_AUSOFT); 269 amd = (volatile struct amd7930 *)(ra->ra_vaddr ? 270 ra->ra_vaddr : mapiodev(ra->ra_paddr, sizeof *amd)); 271 sc->sc_au.au_amd = amd; 272 273 init_amd(amd); 274 275 #ifndef AUDIO_C_HANDLER 276 audio_au = &sc->sc_au; 277 intr_fasttrap(pri, audio_trap); 278 #else 279 sc->sc_hwih.ih_fun = audiohwintr; 280 sc->sc_hwih.ih_arg = &sc->sc_au; 281 intr_establish(pri, &sc->sc_hwih); 282 #endif 283 sc->sc_swih.ih_fun = audioswintr; 284 sc->sc_swih.ih_arg = sc; 285 intr_establish(PIL_AUSOFT, &sc->sc_swih); 286 } 287 #endif 288 289 static void 290 init_amd(amd) 291 register volatile struct amd7930 *amd; 292 { 293 /* disable interrupts */ 294 amd->cr = AMDR_INIT; 295 amd->dr = AMD_INIT_PMS_ACTIVE | AMD_INIT_INT_DISABLE; 296 297 /* 298 * Initialize the mux unit. We use MCR3 to route audio (MAP) 299 * through channel Bb. MCR1 and MCR2 are unused. 300 * Setting the INT enable bit in MCR4 will generate an interrupt 301 * on each converted audio sample. 302 */ 303 amd->cr = AMDR_MUX_1_4; 304 amd->dr = 0; 305 amd->dr = 0; 306 amd->dr = (AMD_MCRCHAN_BB << 4) | AMD_MCRCHAN_BA; 307 amd->dr = AMD_MCR4_INT_ENABLE; 308 } 309 310 static int audio_default_level = 150; 311 static void ausetrgain __P((struct audio_softc *, int)); 312 static void ausetpgain __P((struct audio_softc *, int)); 313 static void ausetmgain __P((struct audio_softc *, int)); 314 static int audiosetinfo __P((struct audio_softc *, struct audio_info *)); 315 static int audiogetinfo __P((struct audio_softc *, struct audio_info *)); 316 struct sun_audio_info; 317 static int sunaudiosetinfo __P((struct audio_softc *, 318 struct sun_audio_info *)); 319 static int sunaudiogetinfo __P((struct audio_softc *, 320 struct sun_audio_info *)); 321 static void audio_setmmr2 __P((volatile struct amd7930 *, int)); 322 323 int 324 AUDIOOPEN(dev, flags, ifmt, p) 325 { 326 register struct audio_softc *sc; 327 register volatile struct amd7930 *amd; 328 int unit = minor(dev), error, s; 329 330 #ifdef SUNOS 331 if (unit > 0) 332 return (ENXIO); 333 sc = &audio_softc; 334 #else 335 if (unit >= audiocd.cd_ndevs || (sc = audiocd.cd_devs[unit]) == NULL) 336 return (ENXIO); 337 #endif 338 if (sc->sc_open) 339 return (EBUSY); 340 sc->sc_open = 1; 341 342 sc->sc_au.au_lowat = audio_blocksize; 343 sc->sc_au.au_hiwat = AUCB_SIZE - sc->sc_au.au_lowat; 344 sc->sc_au.au_blksize = audio_blocksize; 345 sc->sc_au.au_backlog = audio_backlog; 346 347 /* set up read and write blocks and `dead sound' zero value. */ 348 AUCB_INIT(&sc->sc_au.au_rb); 349 sc->sc_au.au_rb.cb_thresh = AUCB_SIZE; 350 AUCB_INIT(&sc->sc_au.au_wb); 351 sc->sc_au.au_wb.cb_thresh = -1; 352 353 /* nothing read or written yet */ 354 sc->sc_rseek = 0; 355 sc->sc_wseek = 0; 356 357 bzero((char *)&sc->sc_map, sizeof sc->sc_map); 358 /* default to speaker */ 359 sc->sc_map.mr_mmr2 = AMD_MMR2_AINB | AMD_MMR2_LS; 360 361 /* enable interrupts and set parameters established above */ 362 amd = sc->sc_au.au_amd; 363 audio_setmmr2(amd, sc->sc_map.mr_mmr2); 364 ausetrgain(sc, audio_default_level); 365 ausetpgain(sc, audio_default_level); 366 ausetmgain(sc, 0); 367 amd->cr = AMDR_INIT; 368 amd->dr = AMD_INIT_PMS_ACTIVE; 369 370 return (0); 371 } 372 373 static int 374 audio_drain(sc) 375 register struct audio_softc *sc; 376 { 377 register int error; 378 379 while (!AUCB_EMPTY(&sc->sc_au.au_wb)) 380 if ((error = audio_sleep(&sc->sc_au.au_wb, 0)) != 0) 381 return (error); 382 return (0); 383 } 384 385 /* 386 * Close an audio chip. 387 */ 388 /* ARGSUSED */ 389 int 390 AUDIOCLOSE(dev, flags, ifmt, p) 391 { 392 register struct audio_softc *sc = SOFTC(dev); 393 register volatile struct amd7930 *amd; 394 register struct aucb *cb; 395 register int s; 396 397 /* 398 * Block until output drains, but allow ^C interrupt. 399 */ 400 sc->sc_au.au_lowat = 0; /* avoid excessive wakeups */ 401 s = splaudio(); 402 /* 403 * If there is pending output, let it drain (unless 404 * the output is paused). 405 */ 406 cb = &sc->sc_au.au_wb; 407 if (!AUCB_EMPTY(cb) && !cb->cb_pause) 408 (void)audio_drain(sc); 409 /* 410 * Disable interrupts, clear open flag, and done. 411 */ 412 amd = sc->sc_au.au_amd; 413 amd->cr = AMDR_INIT; 414 amd->dr = AMD_INIT_PMS_ACTIVE | AMD_INIT_INT_DISABLE; 415 splx(s); 416 sc->sc_open = 0; 417 return (0); 418 } 419 420 int 421 audio_sleep(cb, thresh) 422 register struct aucb *cb; 423 register int thresh; 424 { 425 register int error; 426 register int s = splaudio(); 427 428 cb->cb_thresh = thresh; 429 error = tsleep((caddr_t)cb, (PZERO + 1) | PCATCH, "audio", 0); 430 splx(s); 431 return (error); 432 } 433 434 int 435 AUDIOREAD(dev, uio, ioflag) 436 { 437 register struct audio_softc *sc = SOFTC(dev); 438 register struct aucb *cb; 439 register int n, head, taildata, error; 440 register int blocksize = sc->sc_au.au_blksize; 441 442 if (uio->uio_resid == 0) 443 return (0); 444 cb = &sc->sc_au.au_rb; 445 error = 0; 446 cb->cb_drops = 0; 447 sc->sc_rseek = sc->sc_au.au_stamp - AUCB_LEN(cb); 448 do { 449 while (AUCB_LEN(cb) < blocksize) { 450 #ifndef SUNOS 451 if (ioflag & IO_NDELAY) { 452 error = EWOULDBLOCK; 453 return (error); 454 } 455 #endif 456 if ((error = audio_sleep(cb, blocksize)) != 0) 457 return (error); 458 } 459 /* 460 * The space calculation can only err on the short 461 * side if an interrupt occurs during processing: 462 * only cb_tail is altered in the interrupt code. 463 */ 464 head = cb->cb_head; 465 if ((n = AUCB_LEN(cb)) > uio->uio_resid) 466 n = uio->uio_resid; 467 taildata = AUCB_SIZE - head; 468 if (n > taildata) { 469 error = UIOMOVE((caddr_t)cb->cb_data + head, 470 taildata, UIO_READ, uio); 471 if (error == 0) 472 error = UIOMOVE((caddr_t)cb->cb_data, 473 n - taildata, UIO_READ, uio); 474 } else 475 error = UIOMOVE((caddr_t)cb->cb_data + head, n, 476 UIO_READ, uio); 477 if (error) 478 break; 479 head = AUCB_MOD(head + n); 480 cb->cb_head = head; 481 } while (uio->uio_resid >= blocksize); 482 483 return (error); 484 } 485 486 int 487 AUDIOWRITE(dev, uio, ioflag) 488 { 489 register struct audio_softc *sc = SOFTC(dev); 490 register struct aucb *cb = &sc->sc_au.au_wb; 491 register int n, tail, tailspace, error, first, watermark, drops; 492 493 error = 0; 494 first = 1; 495 while (uio->uio_resid > 0) { 496 watermark = sc->sc_au.au_hiwat; 497 while (AUCB_LEN(cb) > watermark) { 498 #ifndef SUNOS 499 if (ioflag & IO_NDELAY) { 500 error = EWOULDBLOCK; 501 return (error); 502 } 503 #endif 504 if ((error = audio_sleep(cb, watermark)) != 0) 505 return (error); 506 watermark = sc->sc_au.au_lowat; 507 } 508 /* 509 * The only value that can change on an interrupt is 510 * cb->cb_head. We only pull that out once to decide 511 * how much to write into cb_data; if we lose a race 512 * and cb_head changes, we will merely be overly 513 * conservative. For a legitimate time stamp, 514 * however, we need to synchronize the accesses to 515 * au_stamp and cb_head at a high ipl below. 516 */ 517 tail = cb->cb_tail; 518 if ((n = (AUCB_SIZE - 1) - AUCB_LEN(cb)) > uio->uio_resid) { 519 n = uio->uio_resid; 520 if (cb->cb_head == tail && 521 n <= sc->sc_au.au_blksize && 522 sc->sc_au.au_stamp - sc->sc_wseek > 400) { 523 /* 524 * the write is 'small', the buffer is empty 525 * and we have been silent for at least 50ms 526 * so we might be dealing with an application 527 * that writes frames synchronously with 528 * reading them. If so, we need an output 529 * backlog to cover scheduling delays or 530 * there will be gaps in the sound output. 531 * Also take this opportunity to reset the 532 * buffer pointers in case we ended up on 533 * a bad boundary (odd byte, blksize bytes 534 * from end, etc.). 535 */ 536 register u_int* ip; 537 register int muzero = 0x7f7f7f7f; 538 register int i = splaudio(); 539 cb->cb_head = cb->cb_tail = 0; 540 splx(i); 541 tail = sc->sc_au.au_backlog; 542 ip = (u_int*)cb->cb_data; 543 for (i = tail >> 2; --i >= 0; ) 544 *ip++ = muzero; 545 } 546 } 547 tailspace = AUCB_SIZE - tail; 548 if (n > tailspace) { 549 /* write first part at tail and rest at head */ 550 error = UIOMOVE((caddr_t)cb->cb_data + tail, 551 tailspace, UIO_WRITE, uio); 552 if (error == 0) 553 error = UIOMOVE((caddr_t)cb->cb_data, 554 n - tailspace, UIO_WRITE, uio); 555 } else 556 error = UIOMOVE((caddr_t)cb->cb_data + tail, n, 557 UIO_WRITE, uio); 558 if (error) 559 break; 560 561 tail = AUCB_MOD(tail + n); 562 if (first) { 563 register int s = splaudio(); 564 sc->sc_wseek = AUCB_LEN(cb) + sc->sc_au.au_stamp + 1; 565 /* 566 * To guarantee that a write is contiguous in the 567 * sample space, we clear the drop count the first 568 * time through. If we later get drops, we will 569 * break out of the loop below, before writing 570 * a new frame. 571 */ 572 cb->cb_drops = 0; 573 cb->cb_tail = tail; 574 splx(s); 575 first = 0; 576 } else { 577 if (cb->cb_drops != 0) 578 break; 579 cb->cb_tail = tail; 580 } 581 } 582 return (error); 583 } 584 585 /* Sun audio compatibility */ 586 struct sun_audio_prinfo { 587 u_int sample_rate; 588 u_int channels; 589 u_int precision; 590 u_int encoding; 591 u_int gain; 592 u_int port; 593 u_int reserved0[4]; 594 u_int samples; 595 u_int eof; 596 u_char pause; 597 u_char error; 598 u_char waiting; 599 u_char reserved1[3]; 600 u_char open; 601 u_char active; 602 }; 603 struct sun_audio_info { 604 struct sun_audio_prinfo play; 605 struct sun_audio_prinfo record; 606 u_int monitor_gain; 607 u_int reserved[4]; 608 }; 609 610 #ifndef SUNOS 611 #define SUNAUDIO_GETINFO _IOR('A', 1, struct sun_audio_info) 612 #define SUNAUDIO_SETINFO _IOWR('A', 2, struct sun_audio_info) 613 #else 614 #define SUNAUDIO_GETINFO _IOR(A, 1, struct sun_audio_info) 615 #define SUNAUDIO_SETINFO _IOWR(A, 2, struct sun_audio_info) 616 #endif 617 618 int 619 AUDIOIOCTL(dev, cmd, addr, flag, p) 620 { 621 register struct audio_softc *sc = SOFTC(dev); 622 int error = 0, i, s; 623 624 switch (cmd) { 625 626 case AUDIO_GETMAP: 627 bcopy((caddr_t)&sc->sc_map, addr, sizeof(sc->sc_map)); 628 break; 629 630 case AUDIO_SETMAP: 631 bcopy(addr, (caddr_t)&sc->sc_map, sizeof(sc->sc_map)); 632 sc->sc_map.mr_mmr2 &= 0x7f; 633 audio_setmap(sc->sc_au.au_amd, &sc->sc_map); 634 break; 635 636 case AUDIO_FLUSH: 637 s = splaudio(); 638 AUCB_INIT(&sc->sc_au.au_rb); 639 AUCB_INIT(&sc->sc_au.au_wb); 640 sc->sc_au.au_stamp = 0; 641 splx(s); 642 sc->sc_wseek = 0; 643 sc->sc_rseek = 0; 644 break; 645 646 /* 647 * Number of read samples dropped. We don't know where or 648 * when they were dropped. 649 */ 650 case AUDIO_RERROR: 651 *(int *)addr = sc->sc_au.au_rb.cb_drops != 0; 652 break; 653 654 /* 655 * How many samples will elapse until mike hears the first 656 * sample of what we last wrote? 657 */ 658 case AUDIO_WSEEK: 659 s = splaudio(); 660 *(u_long *)addr = sc->sc_wseek - sc->sc_au.au_stamp 661 + AUCB_LEN(&sc->sc_au.au_rb); 662 splx(s); 663 break; 664 665 case AUDIO_SETINFO: 666 error = audiosetinfo(sc, (struct audio_info *)addr); 667 break; 668 669 case AUDIO_GETINFO: 670 error = audiogetinfo(sc, (struct audio_info *)addr); 671 break; 672 673 case SUNAUDIO_GETINFO: 674 error = sunaudiogetinfo(sc, (struct sun_audio_info *)addr); 675 break; 676 677 case SUNAUDIO_SETINFO: 678 error = sunaudiosetinfo(sc, (struct sun_audio_info *)addr); 679 break; 680 681 case AUDIO_DRAIN: 682 error = audio_drain(sc); 683 break; 684 685 default: 686 error = EINVAL; 687 break; 688 } 689 return (error); 690 } 691 692 int 693 AUDIOSELECT(dev, rw, p) 694 { 695 register struct audio_softc *sc = SOFTC(dev); 696 register struct aucb *cb; 697 register int s = splaudio(); 698 699 switch (rw) { 700 701 case FREAD: 702 cb = &sc->sc_au.au_rb; 703 if (AUCB_LEN(cb) >= sc->sc_au.au_blksize) { 704 splx(s); 705 return (1); 706 } 707 selrecord(p, &sc->sc_rsel); 708 cb->cb_thresh = sc->sc_au.au_blksize; 709 break; 710 711 case FWRITE: 712 cb = &sc->sc_au.au_wb; 713 if (AUCB_LEN(cb) <= sc->sc_au.au_lowat) { 714 splx(s); 715 return (1); 716 } 717 selrecord(p, &sc->sc_wsel); 718 cb->cb_thresh = sc->sc_au.au_lowat; 719 break; 720 } 721 splx(s); 722 return (0); 723 } 724 725 #ifdef AUDIO_C_HANDLER 726 int 727 audiohwintr(au0) 728 void *au0; 729 { 730 #ifdef SUNOS 731 register struct auio *au = audio_au; 732 #else 733 register struct auio *au = au0; 734 #endif 735 register volatile struct amd7930 *amd = au->au_amd; 736 register struct aucb *cb; 737 register int h, t, k; 738 739 k = amd->ir; /* clear interrupt */ 740 ++au->au_stamp; 741 742 /* receive incoming data */ 743 cb = &au->au_rb; 744 h = cb->cb_head; 745 t = cb->cb_tail; 746 k = AUCB_MOD(t + 1); 747 if (h == k) 748 cb->cb_drops++; 749 else if (cb->cb_pause != 0) 750 cb->cb_pdrops++; 751 else { 752 cb->cb_data[t] = amd->bbrb; 753 cb->cb_tail = t = k; 754 } 755 if (AUCB_MOD(t - h) >= cb->cb_thresh) { 756 cb->cb_thresh = AUCB_SIZE; 757 cb->cb_waking = 1; 758 AUDIO_SET_SWINTR; 759 } 760 /* send outgoing data */ 761 cb = &au->au_wb; 762 h = cb->cb_head; 763 t = cb->cb_tail; 764 if (h == t) 765 cb->cb_drops++; 766 else if (cb->cb_pause != 0) 767 cb->cb_pdrops++; 768 else { 769 cb->cb_head = h = AUCB_MOD(h + 1); 770 amd->bbtb = cb->cb_data[h]; 771 } 772 if (AUCB_MOD(t - h) <= cb->cb_thresh) { 773 cb->cb_thresh = -1; 774 cb->cb_waking = 1; 775 AUDIO_SET_SWINTR; 776 } 777 return (1); 778 } 779 #endif 780 781 int 782 audioswintr(sc0) 783 void *sc0; 784 { 785 register struct audio_softc *sc; 786 register int s, ret = 0; 787 #ifdef SUNOS 788 sc = &audio_softc; 789 #else 790 sc = sc0; 791 #endif 792 s = splaudio(); 793 if (sc->sc_au.au_rb.cb_waking != 0) { 794 sc->sc_au.au_rb.cb_waking = 0; 795 splx(s); 796 ret = 1; 797 wakeup((caddr_t)&sc->sc_au.au_rb); 798 SELWAKEUP(&sc->sc_rsel); 799 } 800 if (sc->sc_au.au_wb.cb_waking != 0) { 801 sc->sc_au.au_wb.cb_waking = 0; 802 splx(s); 803 ret = 1; 804 wakeup((caddr_t)&sc->sc_au.au_wb); 805 SELWAKEUP(&sc->sc_wsel); 806 } else 807 splx(s); 808 return (ret); 809 } 810 811 /* Write 16 bits of data from variable v to the data port of the audio chip */ 812 813 #define WAMD16(amd, v) ((amd)->dr = (v), (amd)->dr = (v) >> 8) 814 815 void 816 audio_setmap(amd, map) 817 register volatile struct amd7930 *amd; 818 register struct mapreg *map; 819 { 820 register int i, s, v; 821 822 s = splaudio(); 823 amd->cr = AMDR_MAP_1_10; 824 for (i = 0; i < 8; i++) { 825 v = map->mr_x[i]; 826 WAMD16(amd, v); 827 } 828 for (i = 0; i < 8; ++i) { 829 v = map->mr_r[i]; 830 WAMD16(amd, v); 831 } 832 v = map->mr_gx; WAMD16(amd, v); 833 v = map->mr_gr; WAMD16(amd, v); 834 v = map->mr_ger; WAMD16(amd, v); 835 v = map->mr_stgr; WAMD16(amd, v); 836 v = map->mr_ftgr; WAMD16(amd, v); 837 v = map->mr_atgr; WAMD16(amd, v); 838 amd->dr = map->mr_mmr1; 839 amd->dr = map->mr_mmr2; 840 splx(s); 841 } 842 843 /* 844 * Set the mmr1 register and one other 16 bit register in the audio chip. 845 * The other register is indicated by op and val. 846 */ 847 void 848 audio_setmmr1(amd, mmr1, op, val) 849 register volatile struct amd7930 *amd; 850 register int mmr1; 851 register int op; 852 register int val; 853 { 854 register int s = splaudio(); 855 856 amd->cr = AMDR_MAP_MMR1; 857 amd->dr = mmr1; 858 amd->cr = op; 859 WAMD16(amd, val); 860 splx(s); 861 } 862 863 /* 864 * Set the mmr2 register. 865 */ 866 static void 867 audio_setmmr2(amd, mmr2) 868 register volatile struct amd7930 *amd; 869 register int mmr2; 870 { 871 register int s = splaudio(); 872 873 amd->cr = AMDR_MAP_MMR2; 874 amd->dr = mmr2; 875 splx(s); 876 } 877 878 /* 879 * gx, gr & stg gains. this table must contain 256 elements with 880 * the 0th being "infinity" (the magic value 9008). The remaining 881 * elements match sun's gain curve (but with higher resolution): 882 * -18 to 0dB in .16dB steps then 0 to 12dB in .08dB steps. 883 */ 884 static const u_short gx_coeff[256] = { 885 0x9008, 0x8b7c, 0x8b51, 0x8b45, 0x8b42, 0x8b3b, 0x8b36, 0x8b33, 886 0x8b32, 0x8b2a, 0x8b2b, 0x8b2c, 0x8b25, 0x8b23, 0x8b22, 0x8b22, 887 0x9122, 0x8b1a, 0x8aa3, 0x8aa3, 0x8b1c, 0x8aa6, 0x912d, 0x912b, 888 0x8aab, 0x8b12, 0x8aaa, 0x8ab2, 0x9132, 0x8ab4, 0x913c, 0x8abb, 889 0x9142, 0x9144, 0x9151, 0x8ad5, 0x8aeb, 0x8a79, 0x8a5a, 0x8a4a, 890 0x8b03, 0x91c2, 0x91bb, 0x8a3f, 0x8a33, 0x91b2, 0x9212, 0x9213, 891 0x8a2c, 0x921d, 0x8a23, 0x921a, 0x9222, 0x9223, 0x922d, 0x9231, 892 0x9234, 0x9242, 0x925b, 0x92dd, 0x92c1, 0x92b3, 0x92ab, 0x92a4, 893 0x92a2, 0x932b, 0x9341, 0x93d3, 0x93b2, 0x93a2, 0x943c, 0x94b2, 894 0x953a, 0x9653, 0x9782, 0x9e21, 0x9d23, 0x9cd2, 0x9c23, 0x9baa, 895 0x9bde, 0x9b33, 0x9b22, 0x9b1d, 0x9ab2, 0xa142, 0xa1e5, 0x9a3b, 896 0xa213, 0xa1a2, 0xa231, 0xa2eb, 0xa313, 0xa334, 0xa421, 0xa54b, 897 0xada4, 0xac23, 0xab3b, 0xaaab, 0xaa5c, 0xb1a3, 0xb2ca, 0xb3bd, 898 0xbe24, 0xbb2b, 0xba33, 0xc32b, 0xcb5a, 0xd2a2, 0xe31d, 0x0808, 899 0x72ba, 0x62c2, 0x5c32, 0x52db, 0x513e, 0x4cce, 0x43b2, 0x4243, 900 0x41b4, 0x3b12, 0x3bc3, 0x3df2, 0x34bd, 0x3334, 0x32c2, 0x3224, 901 0x31aa, 0x2a7b, 0x2aaa, 0x2b23, 0x2bba, 0x2c42, 0x2e23, 0x25bb, 902 0x242b, 0x240f, 0x231a, 0x22bb, 0x2241, 0x2223, 0x221f, 0x1a33, 903 0x1a4a, 0x1acd, 0x2132, 0x1b1b, 0x1b2c, 0x1b62, 0x1c12, 0x1c32, 904 0x1d1b, 0x1e71, 0x16b1, 0x1522, 0x1434, 0x1412, 0x1352, 0x1323, 905 0x1315, 0x12bc, 0x127a, 0x1235, 0x1226, 0x11a2, 0x1216, 0x0a2a, 906 0x11bc, 0x11d1, 0x1163, 0x0ac2, 0x0ab2, 0x0aab, 0x0b1b, 0x0b23, 907 0x0b33, 0x0c0f, 0x0bb3, 0x0c1b, 0x0c3e, 0x0cb1, 0x0d4c, 0x0ec1, 908 0x079a, 0x0614, 0x0521, 0x047c, 0x0422, 0x03b1, 0x03e3, 0x0333, 909 0x0322, 0x031c, 0x02aa, 0x02ba, 0x02f2, 0x0242, 0x0232, 0x0227, 910 0x0222, 0x021b, 0x01ad, 0x0212, 0x01b2, 0x01bb, 0x01cb, 0x01f6, 911 0x0152, 0x013a, 0x0133, 0x0131, 0x012c, 0x0123, 0x0122, 0x00a2, 912 0x011b, 0x011e, 0x0114, 0x00b1, 0x00aa, 0x00b3, 0x00bd, 0x00ba, 913 0x00c5, 0x00d3, 0x00f3, 0x0062, 0x0051, 0x0042, 0x003b, 0x0033, 914 0x0032, 0x002a, 0x002c, 0x0025, 0x0023, 0x0022, 0x001a, 0x0021, 915 0x001b, 0x001b, 0x001d, 0x0015, 0x0013, 0x0013, 0x0012, 0x0012, 916 0x000a, 0x000a, 0x0011, 0x0011, 0x000b, 0x000b, 0x000c, 0x000e, 917 }; 918 919 /* 920 * second stage play gain. 921 */ 922 static const u_short ger_coeff[] = { 923 0x431f, /* 5. dB */ 924 0x331f, /* 5.5 dB */ 925 0x40dd, /* 6. dB */ 926 0x11dd, /* 6.5 dB */ 927 0x440f, /* 7. dB */ 928 0x411f, /* 7.5 dB */ 929 0x311f, /* 8. dB */ 930 0x5520, /* 8.5 dB */ 931 0x10dd, /* 9. dB */ 932 0x4211, /* 9.5 dB */ 933 0x410f, /* 10. dB */ 934 0x111f, /* 10.5 dB */ 935 0x600b, /* 11. dB */ 936 0x00dd, /* 11.5 dB */ 937 0x4210, /* 12. dB */ 938 0x110f, /* 13. dB */ 939 0x7200, /* 14. dB */ 940 0x2110, /* 15. dB */ 941 0x2200, /* 15.9 dB */ 942 0x000b, /* 16.9 dB */ 943 0x000f /* 18. dB */ 944 #define NGER (sizeof(ger_coeff) / sizeof(ger_coeff[0])) 945 }; 946 947 static void 948 ausetrgain(sc, level) 949 register struct audio_softc *sc; 950 register int level; 951 { 952 level &= 0xff; 953 sc->sc_rlevel = level; 954 sc->sc_map.mr_mmr1 |= AMD_MMR1_GX; 955 sc->sc_map.mr_gx = gx_coeff[level]; 956 audio_setmmr1(sc->sc_au.au_amd, sc->sc_map.mr_mmr1, 957 AMDR_MAP_GX, sc->sc_map.mr_gx); 958 } 959 960 static void 961 ausetpgain(sc, level) 962 register struct audio_softc *sc; 963 register int level; 964 { 965 register int gi, s; 966 register volatile struct amd7930 *amd; 967 968 level &= 0xff; 969 sc->sc_plevel = level; 970 sc->sc_map.mr_mmr1 |= AMD_MMR1_GER|AMD_MMR1_GR; 971 level *= 256 + NGER; 972 level >>= 8; 973 if (level >= 256) { 974 gi = level - 256; 975 level = 255; 976 } else 977 gi = 0; 978 sc->sc_map.mr_ger = ger_coeff[gi]; 979 sc->sc_map.mr_gr = gx_coeff[level]; 980 981 amd = sc->sc_au.au_amd; 982 s = splaudio(); 983 amd->cr = AMDR_MAP_MMR1; 984 amd->dr = sc->sc_map.mr_mmr1; 985 amd->cr = AMDR_MAP_GR; 986 gi = sc->sc_map.mr_gr; 987 WAMD16(amd, gi); 988 amd->cr = AMDR_MAP_GER; 989 gi = sc->sc_map.mr_ger; 990 WAMD16(amd, gi); 991 splx(s); 992 } 993 994 static void 995 ausetmgain(sc, level) 996 register struct audio_softc *sc; 997 register int level; 998 { 999 level &= 0xff; 1000 sc->sc_mlevel = level; 1001 sc->sc_map.mr_mmr1 |= AMD_MMR1_STG; 1002 sc->sc_map.mr_stgr = gx_coeff[level]; 1003 audio_setmmr1(sc->sc_au.au_amd, sc->sc_map.mr_mmr1, 1004 AMDR_MAP_STG, sc->sc_map.mr_stgr); 1005 } 1006 1007 static int 1008 audiosetinfo(sc, ai) 1009 struct audio_softc *sc; 1010 struct audio_info *ai; 1011 { 1012 struct audio_prinfo *r = &ai->record, *p = &ai->play; 1013 register int s, bsize; 1014 1015 if (p->gain != ~0) 1016 ausetpgain(sc, p->gain); 1017 if (r->gain != ~0) 1018 ausetrgain(sc, r->gain); 1019 if (ai->monitor_gain != ~0) 1020 ausetmgain(sc, ai->monitor_gain); 1021 if (p->port == AUDIO_SPEAKER) { 1022 sc->sc_map.mr_mmr2 |= AMD_MMR2_LS; 1023 audio_setmmr2(sc->sc_au.au_amd, sc->sc_map.mr_mmr2); 1024 } else if (p->port == AUDIO_HEADPHONE) { 1025 sc->sc_map.mr_mmr2 &=~ AMD_MMR2_LS; 1026 audio_setmmr2(sc->sc_au.au_amd, sc->sc_map.mr_mmr2); 1027 } 1028 if (p->pause != (u_char)~0) 1029 sc->sc_au.au_wb.cb_pause = p->pause; 1030 if (r->pause != (u_char)~0) 1031 sc->sc_au.au_rb.cb_pause = r->pause; 1032 1033 if (ai->blocksize != ~0) { 1034 if (ai->blocksize == 0) 1035 bsize = ai->blocksize = DEFBLKSIZE; 1036 else if (ai->blocksize > MAXBLKSIZE) 1037 bsize = ai->blocksize = MAXBLKSIZE; 1038 else 1039 bsize = ai->blocksize; 1040 1041 s = splaudio(); 1042 sc->sc_au.au_blksize = bsize; 1043 /* AUDIO_FLUSH */ 1044 AUCB_INIT(&sc->sc_au.au_rb); 1045 AUCB_INIT(&sc->sc_au.au_wb); 1046 splx(s); 1047 1048 } 1049 if (ai->hiwat != ~0 && (unsigned)ai->hiwat < AUCB_SIZE) 1050 sc->sc_au.au_hiwat = ai->hiwat; 1051 if (ai->lowat != ~0 && ai->lowat < AUCB_SIZE) 1052 sc->sc_au.au_lowat = ai->lowat; 1053 if (ai->backlog != ~0 && ai->backlog < (AUCB_SIZE/2)) 1054 sc->sc_au.au_backlog = ai->backlog; 1055 1056 return (0); 1057 } 1058 1059 static int 1060 sunaudiosetinfo(sc, ai) 1061 struct audio_softc *sc; 1062 struct sun_audio_info *ai; 1063 { 1064 struct sun_audio_prinfo *r = &ai->record, *p = &ai->play; 1065 1066 if (p->gain != ~0) 1067 ausetpgain(sc, p->gain); 1068 if (r->gain != ~0) 1069 ausetrgain(sc, r->gain); 1070 if (ai->monitor_gain != ~0) 1071 ausetmgain(sc, ai->monitor_gain); 1072 if (p->port == AUDIO_SPEAKER) { 1073 sc->sc_map.mr_mmr2 |= AMD_MMR2_LS; 1074 audio_setmmr2(sc->sc_au.au_amd, sc->sc_map.mr_mmr2); 1075 } else if (p->port == AUDIO_HEADPHONE) { 1076 sc->sc_map.mr_mmr2 &=~ AMD_MMR2_LS; 1077 audio_setmmr2(sc->sc_au.au_amd, sc->sc_map.mr_mmr2); 1078 } 1079 /* 1080 * The bsd driver does not distinguish between paused and active. 1081 * (In the sun driver, not active means samples are not ouput 1082 * at all, but paused means the last streams buffer is drained 1083 * and then output stops.) If either are 0, then when stop output. 1084 * Otherwise, if either are non-zero, we resume. 1085 */ 1086 if (p->pause == 0 || p->active == 0) 1087 sc->sc_au.au_wb.cb_pause = 0; 1088 else if (p->pause != (u_char)~0 || p->active != (u_char)~0) 1089 sc->sc_au.au_wb.cb_pause = 1; 1090 if (r->pause == 0 || r->active == 0) 1091 sc->sc_au.au_rb.cb_pause = 0; 1092 else if (r->pause != (u_char)~0 || r->active != (u_char)~0) 1093 sc->sc_au.au_rb.cb_pause = 1; 1094 1095 return (0); 1096 } 1097 1098 static int 1099 audiogetinfo(sc, ai) 1100 struct audio_softc *sc; 1101 struct audio_info *ai; 1102 { 1103 struct audio_prinfo *r = &ai->record, *p = &ai->play; 1104 1105 p->sample_rate = r->sample_rate = 8000; 1106 p->channels = r->channels = 1; 1107 p->precision = r->precision = 8; 1108 p->encoding = r->encoding = AUDIO_ENCODING_ULAW; 1109 1110 ai->monitor_gain = sc->sc_mlevel; 1111 r->gain = sc->sc_rlevel; 1112 p->gain = sc->sc_plevel; 1113 r->port = 1; p->port = (sc->sc_map.mr_mmr2 & AMD_MMR2_LS) ? 1114 AUDIO_SPEAKER : AUDIO_HEADPHONE; 1115 1116 p->pause = sc->sc_au.au_wb.cb_pause; 1117 r->pause = sc->sc_au.au_rb.cb_pause; 1118 p->error = sc->sc_au.au_wb.cb_drops != 0; 1119 r->error = sc->sc_au.au_rb.cb_drops != 0; 1120 1121 p->open = sc->sc_open; 1122 r->open = sc->sc_open; 1123 1124 p->samples = sc->sc_au.au_stamp - sc->sc_au.au_wb.cb_pdrops; 1125 r->samples = sc->sc_au.au_stamp - sc->sc_au.au_rb.cb_pdrops; 1126 1127 p->seek = sc->sc_wseek; 1128 r->seek = sc->sc_rseek; 1129 1130 ai->blocksize = sc->sc_au.au_blksize; 1131 ai->hiwat = sc->sc_au.au_hiwat; 1132 ai->lowat = sc->sc_au.au_lowat; 1133 ai->backlog = sc->sc_au.au_backlog; 1134 1135 return (0); 1136 } 1137 1138 static int 1139 sunaudiogetinfo(sc, ai) 1140 struct audio_softc *sc; 1141 struct sun_audio_info *ai; 1142 { 1143 struct sun_audio_prinfo *r = &ai->record, *p = &ai->play; 1144 1145 p->sample_rate = r->sample_rate = 8000; 1146 p->channels = r->channels = 1; 1147 p->precision = r->precision = 8; 1148 p->encoding = r->encoding = AUDIO_ENCODING_ULAW; 1149 1150 ai->monitor_gain = sc->sc_mlevel; 1151 r->gain = sc->sc_rlevel; 1152 p->gain = sc->sc_plevel; 1153 r->port = 1; p->port = (sc->sc_map.mr_mmr2 & AMD_MMR2_LS) ? 1154 AUDIO_SPEAKER : AUDIO_HEADPHONE; 1155 1156 p->active = p->pause = sc->sc_au.au_wb.cb_pause; 1157 r->active = r->pause = sc->sc_au.au_rb.cb_pause; 1158 p->error = sc->sc_au.au_wb.cb_drops != 0; 1159 r->error = sc->sc_au.au_rb.cb_drops != 0; 1160 1161 p->waiting = 0; 1162 r->waiting = 0; 1163 p->eof = 0; 1164 r->eof = 0; 1165 1166 p->open = sc->sc_open; 1167 r->open = sc->sc_open; 1168 1169 p->samples = sc->sc_au.au_stamp - sc->sc_au.au_wb.cb_pdrops; 1170 r->samples = sc->sc_au.au_stamp - sc->sc_au.au_rb.cb_pdrops; 1171 1172 return (0); 1173 } 1174 #endif 1175