1 /* $NetBSD: aucc.c,v 1.21 1997/11/24 21:00:50 is Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Stephan Thesing 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Stephan Thesing. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include "aucc.h" 34 #if NAUCC > 0 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/errno.h> 39 #include <sys/ioctl.h> 40 #include <sys/device.h> 41 #include <sys/proc.h> 42 #include <machine/cpu.h> 43 44 #include <sys/audioio.h> 45 #include <dev/audio_if.h> 46 #include <amiga/amiga/cc.h> 47 #include <amiga/amiga/custom.h> 48 #include <amiga/amiga/device.h> 49 #include <amiga/dev/auccvar.h> 50 51 52 #ifdef LEV6_DEFER 53 #define AUCC_MAXINT 3 54 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2) 55 #else 56 #define AUCC_MAXINT 4 57 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3) 58 #endif 59 /* this unconditionally; we may use AUD3 as slave channel with LEV6_DEFER */ 60 #define AUCC_ALLDMAF (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3) 61 62 #ifdef AUDIO_DEBUG 63 /*extern printf __P((const char *,...));*/ 64 int auccdebug = 1; 65 #define DPRINTF(x) if (auccdebug) printf x 66 #else 67 #define DPRINTF(x) 68 #endif 69 70 #ifdef splaudio 71 #undef splaudio 72 #endif 73 74 #define splaudio() spl4(); 75 76 /* clock frequency.. */ 77 extern int eclockfreq; 78 79 80 /* hw audio ch */ 81 extern struct audio_channel channel[4]; 82 83 84 /* 85 * Software state. 86 */ 87 struct aucc_softc { 88 struct device sc_dev; /* base device */ 89 90 int sc_open; /* single use device */ 91 aucc_data_t sc_channel[4]; /* per channel freq, ... */ 92 u_int sc_encoding; /* encoding AUDIO_ENCODING_.*/ 93 int sc_channels; /* # of channels used */ 94 95 int sc_intrcnt; /* interrupt count */ 96 int sc_channelmask; /* which channels are used ? */ 97 }; 98 99 /* interrupt interfaces */ 100 void aucc_inthdl __P((int)); 101 102 /* forward declarations */ 103 static int init_aucc __P((struct aucc_softc *)); 104 static u_int freqtoper __P((u_int)); 105 static u_int pertofreq __P((u_int)); 106 107 /* autoconfiguration driver */ 108 void auccattach __P((struct device *, struct device *, void *)); 109 int auccmatch __P((struct device *, struct cfdata *, void *)); 110 111 struct cfattach aucc_ca = { 112 sizeof(struct aucc_softc), 113 auccmatch, 114 auccattach 115 }; 116 117 struct cfdriver aucc_cd = { 118 NULL, "aucc", DV_DULL, NULL, 0 119 }; 120 121 struct audio_device aucc_device = { 122 "Amiga-audio", 123 "x", 124 "aucc" 125 }; 126 127 128 struct aucc_softc *aucc=NULL; 129 130 131 unsigned char ulaw_to_lin[] = { 132 0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e, 133 0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe, 134 0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf, 135 0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf, 136 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 137 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 138 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4, 139 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8, 140 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 141 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 142 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 143 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 144 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 145 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 146 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 147 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 148 0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61, 149 0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, 0x45, 0x41, 150 0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30, 151 0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20, 152 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 153 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 154 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b, 155 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07, 156 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 157 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 158 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 159 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 160 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 164 }; 165 166 /* 167 * Define our interface to the higher level audio driver. 168 */ 169 int aucc_open __P((void *, int)); 170 void aucc_close __P((void *)); 171 int aucc_set_out_sr __P((void *, u_long)); 172 int aucc_query_encoding __P((void *, struct audio_encoding *)); 173 int aucc_round_blocksize __P((void *, int)); 174 int aucc_commit_settings __P((void *)); 175 int aucc_start_output __P((void *, void *, int, void (*)(void *), 176 void *)); 177 int aucc_start_input __P((void *, void *, int, void (*)(void *), 178 void *)); 179 int aucc_halt_output __P((void *)); 180 int aucc_halt_input __P((void *)); 181 int aucc_getdev __P((void *, struct audio_device *)); 182 int aucc_set_port __P((void *, mixer_ctrl_t *)); 183 int aucc_get_port __P((void *, mixer_ctrl_t *)); 184 int aucc_query_devinfo __P((void *, mixer_devinfo_t *)); 185 void aucc_encode __P((int, int, int, u_char *, u_short **)); 186 int aucc_set_params __P((void *, int, int, 187 struct audio_params *, struct audio_params *)); 188 int aucc_get_props __P((void *)); 189 190 struct audio_hw_if sa_hw_if = { 191 aucc_open, 192 aucc_close, 193 NULL, 194 aucc_query_encoding, 195 aucc_set_params, 196 aucc_round_blocksize, 197 aucc_commit_settings, 198 NULL, 199 NULL, 200 aucc_start_output, 201 aucc_start_input, 202 aucc_halt_output, 203 aucc_halt_input, 204 NULL, 205 aucc_getdev, 206 NULL, 207 aucc_set_port, 208 aucc_get_port, 209 aucc_query_devinfo, 210 NULL, 211 NULL, 212 NULL, 213 NULL, 214 aucc_get_props, 215 }; 216 217 /* autoconfig routines */ 218 219 int 220 auccmatch(pdp, cfp, aux) 221 struct device *pdp; 222 struct cfdata *cfp; 223 void *aux; 224 { 225 if (matchname((char *)aux, "aucc") && 226 #ifdef DRACO 227 !is_draco() && 228 #endif 229 (cfp->cf_unit == 0)) 230 return 1; 231 232 return 0; 233 } 234 235 /* 236 * Audio chip found. 237 */ 238 void 239 auccattach(parent, self, args) 240 struct device *parent, *self; 241 void *args; 242 { 243 register struct aucc_softc *sc = (struct aucc_softc *)self; 244 register int i; 245 246 printf("\n"); 247 248 if((i=init_aucc(sc))) { 249 printf("audio: no chipmem\n"); 250 return; 251 } 252 253 audio_attach_mi(&sa_hw_if, 0, sc, &sc->sc_dev); 254 } 255 256 257 static int 258 init_aucc(sc) 259 struct aucc_softc *sc; 260 { 261 register int i, err=0; 262 263 /* init values per channel */ 264 for (i=0;i<4;i++) { 265 sc->sc_channel[i].nd_freq=8000; 266 sc->sc_channel[i].nd_per=freqtoper(8000); 267 sc->sc_channel[i].nd_busy=0; 268 sc->sc_channel[i].nd_dma=alloc_chipmem(AUDIO_BUF_SIZE*2); 269 if (sc->sc_channel[i].nd_dma==NULL) 270 err=1; 271 sc->sc_channel[i].nd_dmalength=0; 272 sc->sc_channel[i].nd_volume=64; 273 sc->sc_channel[i].nd_intr=NULL; 274 sc->sc_channel[i].nd_intrdata=NULL; 275 sc->sc_channel[i].nd_doublebuf=0; 276 DPRINTF(("dma buffer for channel %d is %p\n", i, 277 sc->sc_channel[i].nd_dma)); 278 279 } 280 281 if (err) { 282 for(i=0;i<4;i++) 283 if (sc->sc_channel[i].nd_dma) 284 free_chipmem(sc->sc_channel[i].nd_dma); 285 } 286 287 sc->sc_channels=1; 288 sc->sc_channelmask=0xf; 289 290 /* clear interrupts and dma: */ 291 custom.intena = AUCC_ALLINTF; 292 custom.dmacon = AUCC_ALLDMAF;; 293 294 sc->sc_encoding=AUDIO_ENCODING_ULAW; 295 296 return err; 297 298 } 299 300 int 301 aucc_open(addr, flags) 302 void *addr; 303 int flags; 304 { 305 struct aucc_softc *sc = addr; 306 int i; 307 308 DPRINTF(("sa_open: unit %p\n",sc)); 309 310 if (sc->sc_open) 311 return (EBUSY); 312 sc->sc_open = 1; 313 for (i=0;i<AUCC_MAXINT;i++) { 314 sc->sc_channel[i].nd_intr=NULL; 315 sc->sc_channel[i].nd_intrdata=NULL; 316 } 317 aucc=sc; 318 sc->sc_channelmask=0xf; 319 320 DPRINTF(("saopen: ok -> sc=0x%p\n",sc)); 321 322 return (0); 323 } 324 325 void 326 aucc_close(addr) 327 void *addr; 328 { 329 register struct aucc_softc *sc = addr; 330 331 DPRINTF(("sa_close: sc=0x%p\n", sc)); 332 /* 333 * halt i/o, clear open flag, and done. 334 */ 335 aucc_halt_output(sc); 336 sc->sc_open = 0; 337 338 DPRINTF(("sa_close: closed.\n")); 339 } 340 341 int 342 aucc_set_out_sr(addr, sr) 343 void *addr; 344 u_long sr; 345 { 346 struct aucc_softc *sc=addr; 347 u_long per; 348 register int i; 349 350 per=freqtoper(sr); 351 if (per>0xffff) 352 return EINVAL; 353 sr=pertofreq(per); 354 355 for (i=0;i<4;i++) { 356 sc->sc_channel[i].nd_freq=sr; 357 sc->sc_channel[i].nd_per=per; 358 } 359 360 return(0); 361 } 362 363 int 364 aucc_query_encoding(addr, fp) 365 void *addr; 366 struct audio_encoding *fp; 367 { 368 switch (fp->index) { 369 case 0: 370 strcpy(fp->name, AudioEslinear); 371 fp->encoding = AUDIO_ENCODING_SLINEAR; 372 fp->precision = 8; 373 fp->flags = 0; 374 break; 375 case 1: 376 strcpy(fp->name, AudioEmulaw); 377 fp->encoding = AUDIO_ENCODING_ULAW; 378 fp->precision = 8; 379 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 380 break; 381 382 case 2: 383 strcpy(fp->name, AudioEulinear); 384 fp->encoding = AUDIO_ENCODING_ULINEAR; 385 fp->precision = 8; 386 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 387 break; 388 389 default: 390 return(EINVAL); 391 /*NOTREACHED*/ 392 } 393 return(0); 394 } 395 396 int 397 aucc_set_params(addr, setmode, usemode, p, r) 398 void *addr; 399 int setmode, usemode; 400 struct audio_params *p, *r; 401 { 402 struct aucc_softc *sc = addr; 403 404 /* if (setmode & AUMODE_RECORD) 405 return 0 ENXIO*/; 406 407 #ifdef AUCCDEBUG 408 printf("aucc_set_params(setmode 0x%x, usemode 0x%x, enc %d, bits %d, chn %d, sr %ld)\n", 409 setmode, usemode, p->encoding, p->precision, p->channels, p->sample_rate); 410 #endif 411 412 switch (p->encoding) { 413 case AUDIO_ENCODING_ULAW: 414 case AUDIO_ENCODING_SLINEAR: 415 case AUDIO_ENCODING_SLINEAR_BE: 416 case AUDIO_ENCODING_SLINEAR_LE: 417 case AUDIO_ENCODING_ULINEAR_BE: 418 case AUDIO_ENCODING_ULINEAR_LE: 419 break; 420 421 default: 422 return EINVAL; 423 /* NOTREADCHED */ 424 } 425 426 if (p->precision != 8) 427 return EINVAL; 428 429 if ((p->channels<1) || (p->channels>4)) 430 return(EINVAL); 431 432 sc->sc_channels = p->channels; 433 sc->sc_encoding = p->encoding; 434 435 return aucc_set_out_sr(addr, p->sample_rate); 436 } 437 438 int 439 aucc_round_blocksize(addr, blk) 440 void *addr; 441 int blk; 442 { 443 444 445 return blk>AUDIO_BUF_SIZE?AUDIO_BUF_SIZE:blk; /* round up to even size */ 446 } 447 448 int 449 aucc_commit_settings(addr) 450 void *addr; 451 { 452 register struct aucc_softc *sc = addr; 453 register int i; 454 455 DPRINTF(("sa_commit.\n")); 456 457 for (i=0;i<4;i++) { 458 custom.aud[i].vol=sc->sc_channel[i].nd_volume; 459 custom.aud[i].per=sc->sc_channel[i].nd_per; 460 } 461 462 DPRINTF(("commit done\n")); 463 464 return(0); 465 } 466 467 static int masks[4] = {1,3,7,15}; /* masks for n first channels */ 468 static int masks2[4] = {1,2,4,8}; 469 470 int 471 aucc_start_output(addr, p, cc, intr, arg) 472 void *addr; 473 void *p; 474 int cc; 475 void (*intr) __P((void *)); 476 void *arg; 477 { 478 struct aucc_softc *sc; 479 int mask; 480 int i,j,k; 481 u_short *dmap[4]; 482 u_char *pp; 483 484 485 sc = addr; 486 mask = sc->sc_channelmask; 487 488 dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL; 489 490 DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg)); 491 492 if (sc->sc_channels > 1) 493 mask &=masks[sc->sc_channels-1]; 494 /* we use first sc_channels channels */ 495 if (mask==0) /* active and used channels are disjoint */ 496 return EINVAL; 497 498 for (i=0;i<4;i++) { /* channels available ? */ 499 if ((masks2[i]&mask)&&(sc->sc_channel[i].nd_busy)) 500 return EBUSY; /* channel is busy */ 501 if (channel[i].isaudio==-1) 502 return EBUSY; /* system uses them */ 503 } 504 505 /* enable interrupt on 1st channel */ 506 for (i=j=0;i<AUCC_MAXINT;i++) { 507 if (masks2[i]&mask) { 508 DPRINTF(("first channel is %d\n",i)); 509 j=i; 510 sc->sc_channel[i].nd_intr=intr; 511 sc->sc_channel[i].nd_intrdata=arg; 512 break; 513 } 514 } 515 516 DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1], 517 dmap[2], dmap[3], mask)); 518 519 /* disable ints, dma for channels, until all parameters set */ 520 /* XXX dont disable DMA! custom.dmacon=mask;*/ 521 custom.intreq=mask<<INTB_AUD0; 522 custom.intena=mask<<INTB_AUD0; 523 524 /* copy data to dma buffer */ 525 526 527 pp=(u_char *)p; 528 529 if (sc->sc_channels == 1) { 530 dmap[0] = 531 dmap[1] = 532 dmap[2] = 533 dmap[3] = sc->sc_channel[j].nd_dma; 534 } else { 535 for (k=0; k<4; k++) { 536 if (masks2[k+j]&mask) 537 dmap[k]=sc->sc_channel[k+j].nd_dma; 538 } 539 } 540 541 sc->sc_channel[j].nd_doublebuf ^= 1; 542 if (sc->sc_channel[j].nd_doublebuf) { 543 dmap[0] += AUDIO_BUF_SIZE/sizeof(u_short); 544 dmap[1] += AUDIO_BUF_SIZE/sizeof(u_short); 545 dmap[2] += AUDIO_BUF_SIZE/sizeof(u_short); 546 dmap[3] += AUDIO_BUF_SIZE/sizeof(u_short); 547 } 548 549 aucc_encode(sc->sc_encoding, sc->sc_channels, cc, pp, dmap); 550 551 /* dma buffers: we use same buffer 4 all channels */ 552 /* write dma location and length */ 553 for (i=k=0; i<4; i++) { 554 if (masks2[i] & mask) { 555 DPRINTF(("turning channel %d on\n",i)); 556 /* sc->sc_channel[i].nd_busy=1;*/ 557 channel[i].isaudio=1; 558 channel[i].play_count=1; 559 channel[i].handler=NULL; 560 custom.aud[i].per=sc->sc_channel[i].nd_per; 561 custom.aud[i].vol=sc->sc_channel[i].nd_volume; 562 custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]); 563 custom.aud[i].len=cc/(sc->sc_channels*2); 564 sc->sc_channel[i].nd_mask=mask; 565 DPRINTF(("per is %d, vol is %d, len is %d\n",\ 566 sc->sc_channel[i].nd_per, 567 sc->sc_channel[i].nd_volume, cc>>1)); 568 569 } 570 } 571 572 channel[j].handler=aucc_inthdl; 573 574 /* enable ints */ 575 custom.intena=INTF_SETCLR|INTF_INTEN| (masks2[j]<<INTB_AUD0); 576 577 DPRINTF(("enabled ints: 0x%x\n",(masks2[j]<<INTB_AUD0))); 578 579 /* enable dma */ 580 custom.dmacon=DMAF_SETCLR|DMAF_MASTER|mask; 581 582 DPRINTF(("enabled dma, mask=0x%x\n",mask)); 583 584 return(0); 585 } 586 587 /* ARGSUSED */ 588 int 589 aucc_start_input(addr, p, cc, intr, arg) 590 void *addr; 591 void *p; 592 int cc; 593 void (*intr) __P((void *)); 594 void *arg; 595 { 596 597 return ENXIO; /* no input */ 598 } 599 600 int 601 aucc_halt_output(addr) 602 void *addr; 603 { 604 register struct aucc_softc *sc = addr; 605 register int i; 606 607 /* XXX only halt, if input is also halted ?? */ 608 /* stop dma, etc */ 609 custom.intena = AUCC_ALLINTF; 610 custom.dmacon = AUCC_ALLDMAF; 611 /* mark every busy unit idle */ 612 for (i=0;i<4;i++) { 613 sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0; 614 channel[i].isaudio=0; 615 channel[i].play_count=0; 616 } 617 618 return(0); 619 } 620 621 int 622 aucc_halt_input(addr) 623 void *addr; 624 { 625 /* no input */ 626 627 return ENXIO; 628 } 629 630 int 631 aucc_getdev(addr, retp) 632 void *addr; 633 struct audio_device *retp; 634 { 635 *retp = aucc_device; 636 return 0; 637 } 638 639 int 640 aucc_set_port(addr, cp) 641 void *addr; 642 mixer_ctrl_t *cp; 643 { 644 register struct aucc_softc *sc = addr; 645 register int i,j; 646 647 DPRINTF(("aucc_set_port: port=%d", cp->dev)); 648 649 switch (cp->type) { 650 case AUDIO_MIXER_SET: 651 if (cp->dev!=AUCC_CHANNELS) 652 return EINVAL; 653 i=cp->un.mask; 654 if ((i<1)||(i>15)) 655 return EINVAL; 656 sc->sc_channelmask=i; 657 break; 658 659 case AUDIO_MIXER_VALUE: 660 i=cp->un.value.num_channels; 661 if ((i<1)||(i>4)) 662 return EINVAL; 663 664 #ifdef __XXXwhatsthat 665 if (cp->dev!=AUCC_VOLUME) 666 return EINVAL; 667 #endif 668 669 /* set volume for channel 0..i-1 */ 670 671 /* evil workaround for xanim bug, IMO */ 672 if ((sc->sc_channels == 1) && (i == 2)) { 673 sc->sc_channel[0].nd_volume = 674 sc->sc_channel[3].nd_volume = 675 cp->un.value.level[0]>>2; 676 sc->sc_channel[1].nd_volume = 677 sc->sc_channel[2].nd_volume = 678 cp->un.value.level[1]>>2; 679 } else if (i>1) { 680 for (j=0;j<i;j++) 681 sc->sc_channel[j].nd_volume = 682 cp->un.value.level[j]>>2; 683 } else if (sc->sc_channels > 1) 684 for (j=0; j<sc->sc_channels; j++) 685 sc->sc_channel[j].nd_volume = 686 cp->un.value.level[0]>>2; 687 else 688 for (j=0; j<4; j++) 689 sc->sc_channel[j].nd_volume = 690 cp->un.value.level[0]>>2; 691 break; 692 693 default: 694 return EINVAL; 695 break; 696 } 697 return 0; 698 } 699 700 701 int 702 aucc_get_port(addr, cp) 703 void *addr; 704 mixer_ctrl_t *cp; 705 { 706 register struct aucc_softc *sc = addr; 707 register int i,j; 708 709 DPRINTF(("aucc_get_port: port=%d", cp->dev)); 710 711 switch (cp->type) { 712 case AUDIO_MIXER_SET: 713 if (cp->dev!=AUCC_CHANNELS) 714 return EINVAL; 715 cp->un.mask=sc->sc_channelmask; 716 break; 717 718 case AUDIO_MIXER_VALUE: 719 i = cp->un.value.num_channels; 720 if ((i<1)||(i>4)) 721 return EINVAL; 722 723 for (j=0;j<i;j++) 724 cp->un.value.level[j] = 725 (sc->sc_channel[j].nd_volume<<2) + 726 (sc->sc_channel[j].nd_volume>>4); 727 break; 728 729 default: 730 return EINVAL; 731 } 732 return 0; 733 } 734 735 736 int 737 aucc_get_props(addr) 738 void *addr; 739 { 740 return 0; 741 } 742 743 int 744 aucc_query_devinfo(addr, dip) 745 void *addr; 746 register mixer_devinfo_t *dip; 747 { 748 register int i; 749 750 switch(dip->index) { 751 case AUCC_CHANNELS: 752 dip->type = AUDIO_MIXER_SET; 753 dip->mixer_class = AUCC_OUTPUT_CLASS; 754 dip->prev = dip->next = AUDIO_MIXER_LAST; 755 strcpy(dip->label.name, AudioNspeaker); 756 for (i=0;i<16;i++) { 757 sprintf(dip->un.s.member[i].label.name, 758 "channelmask%d", i); 759 dip->un.s.member[i].mask = i; 760 } 761 dip->un.s.num_mem = 16; 762 break; 763 764 case AUCC_VOLUME: 765 dip->type = AUDIO_MIXER_VALUE; 766 dip->mixer_class = AUCC_OUTPUT_CLASS; 767 dip->prev = dip->next = AUDIO_MIXER_LAST; 768 strcpy(dip->label.name, AudioNmaster); 769 dip->un.v.num_channels = 4; 770 strcpy(dip->un.v.units.name, AudioNvolume); 771 break; 772 773 case AUCC_OUTPUT_CLASS: 774 dip->type = AUDIO_MIXER_CLASS; 775 dip->mixer_class = AUCC_OUTPUT_CLASS; 776 dip->next = dip->prev = AUDIO_MIXER_LAST; 777 strcpy(dip->label.name, AudioCoutputs); 778 break; 779 780 default: 781 return ENXIO; 782 } 783 784 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); 785 786 return(0); 787 } 788 789 790 /* audio int handler */ 791 void 792 aucc_inthdl(int ch) 793 { 794 register int i; 795 register int mask=aucc->sc_channel[ch].nd_mask; 796 797 /* for all channels in this maskgroup: 798 disable dma, int 799 mark idle */ 800 DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask)); 801 802 custom.intreq=mask<<INTB_AUD0; /* clear request */ 803 /* XXX: maybe we can leave ints and/or DMA on, if another sample has to be played?*/ 804 custom.intena=mask<<INTB_AUD0; 805 /* 806 * XXX custom.dmacon=mask; NO!!! 807 */ 808 for (i=0;i<4;i++) { 809 if (masks2[i]&&mask) { 810 DPRINTF(("marking channel %d idle\n",i)); 811 aucc->sc_channel[i].nd_busy=0; 812 aucc->sc_channel[i].nd_mask=0; 813 channel[i].isaudio=channel[i].play_count=0; 814 } 815 } 816 817 /* call handler */ 818 if (aucc->sc_channel[ch].nd_intr) { 819 DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr)); 820 (*(aucc->sc_channel[ch].nd_intr))(aucc->sc_channel[ch].nd_intrdata); 821 } 822 else DPRINTF(("zero int handler\n")); 823 DPRINTF(("ints done\n")); 824 } 825 826 827 828 829 /* transform frequency to period, adjust bounds */ 830 static u_int 831 freqtoper(u_int freq) 832 { 833 u_int per=eclockfreq*5/freq; 834 835 if (per<124) 836 per=124; /* must have at least 124 ticks between samples */ 837 838 return per; 839 } 840 841 /* transform period to frequency */ 842 static u_int 843 pertofreq(u_int per) 844 { 845 u_int freq=eclockfreq*5/per; 846 847 848 return freq; 849 } 850 851 852 853 void 854 aucc_encode(enc, channels, i, p, dmap) 855 int enc, channels, i; 856 u_char *p; 857 u_short **dmap; 858 { 859 char *q, *r, *s, *t; 860 int off; 861 u_char *tab; 862 863 #ifdef AUCCDEBUG 864 static int debctl = 6; 865 #endif 866 867 off = 0; 868 tab = NULL; 869 870 #ifdef AUCCDEBUG 871 if (--debctl >= 0) 872 printf("Enc: enc %d, chan %d, dmap %p %p %p %p\n", 873 enc, channels, dmap[0], dmap[1], dmap[2], dmap[3]); 874 #endif 875 876 switch (enc) { 877 case AUDIO_ENCODING_ULAW: 878 tab=ulaw_to_lin; 879 break; 880 case AUDIO_ENCODING_ULINEAR_BE: 881 case AUDIO_ENCODING_ULINEAR_LE: 882 off=-128; 883 break; 884 case AUDIO_ENCODING_SLINEAR_BE: 885 case AUDIO_ENCODING_SLINEAR_LE: 886 break; 887 default: 888 return; 889 } 890 891 q = (char *)dmap[0]; 892 r = (char *)dmap[1]; 893 s = (char *)dmap[2]; 894 t = (char *)dmap[3]; 895 896 if (tab) 897 while (i) { 898 switch (channels) { 899 case 4: *t++ = tab[*p++]; 900 case 3: *s++ = tab[*p++]; 901 case 2: *r++ = tab[*p++]; 902 case 1: *q++ = tab[*p++]; 903 } 904 i -= channels; 905 } 906 else 907 while (i) { 908 switch (channels) { 909 case 4: *t++ = *p++ + off; 910 case 3: *s++ = *p++ + off; 911 case 2: *r++ = *p++ + off; 912 case 1: *q++ = *p++ + off; 913 } 914 i -= channels; 915 } 916 917 } 918 919 #endif /* NAUCC > 0 */ 920