1 /* $NetBSD: aucc.c,v 1.27 2001/05/08 06:09:30 is Exp $ */ 2 3 /* 4 * Copyright (c) 1999 Bernardo Innocenti 5 * All rights reserved. 6 * 7 * Copyright (c) 1997 Stephan Thesing 8 * All rights reserved. 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 Stephan Thesing. 21 * 4. The name of the author may not be used to endorse or promote products 22 * derived from this software without specific prior written permission 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 /* TODO: 37 * 38 * - ulaw -> 14bit conversion 39 * - channel allocation is wrong for 14bit mono 40 * - convert the... err... conversion routines to 68k asm for best performance 41 * XXX: NO. aucc audio is limited by chipmem speed, anyway. You dont 42 * want to make life difficult for amigappc work. 43 * -is 44 * 45 * - rely on auconv.c routines for ulaw/alaw conversions 46 * - perhaps use a calibration table for better 14bit output 47 * - set 31KHz AGA video mode to allow 44.1KHz even if grfcc is missing 48 * in the kernel 49 * - 14bit output requires maximum volume 50 */ 51 52 #include "aucc.h" 53 #if NAUCC > 0 54 55 #include <sys/param.h> 56 #include <sys/systm.h> 57 #include <sys/errno.h> 58 #include <sys/ioctl.h> 59 #include <sys/device.h> 60 #include <sys/proc.h> 61 #include <machine/cpu.h> 62 63 #include <sys/audioio.h> 64 #include <dev/audio_if.h> 65 #include <amiga/amiga/cc.h> 66 #include <amiga/amiga/custom.h> 67 #include <amiga/amiga/device.h> 68 #include <amiga/dev/auccvar.h> 69 70 #include "opt_lev6_defer.h" 71 72 73 #ifdef LEV6_DEFER 74 #define AUCC_MAXINT 3 75 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2) 76 #else 77 #define AUCC_MAXINT 4 78 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3) 79 #endif 80 /* this unconditionally; we may use AUD3 as slave channel with LEV6_DEFER */ 81 #define AUCC_ALLDMAF (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3) 82 83 #ifdef AUDIO_DEBUG 84 /*extern printf __P((const char *,...));*/ 85 int auccdebug = 1; 86 #define DPRINTF(x) if (auccdebug) printf x 87 #else 88 #define DPRINTF(x) 89 #endif 90 91 #ifdef splaudio 92 #undef splaudio 93 #endif 94 95 #define splaudio() spl4(); 96 97 /* clock frequency.. */ 98 extern int eclockfreq; 99 100 101 /* hw audio ch */ 102 extern struct audio_channel channel[4]; 103 104 105 /* 106 * Software state. 107 */ 108 struct aucc_softc { 109 struct device sc_dev; /* base device */ 110 111 int sc_open; /* single use device */ 112 aucc_data_t sc_channel[4]; /* per channel freq, ... */ 113 u_int sc_encoding; /* encoding AUDIO_ENCODING_.*/ 114 int sc_channels; /* # of channels used */ 115 int sc_precision; /* 8 or 16 bits */ 116 int sc_14bit; /* 14bit output enabled */ 117 118 int sc_intrcnt; /* interrupt count */ 119 int sc_channelmask; /* which channels are used ? */ 120 void (*sc_decodefunc) __P((u_char **, u_char *, int)); 121 /* pointer to format conversion routine */ 122 }; 123 124 /* interrupt interfaces */ 125 void aucc_inthdl __P((int)); 126 127 /* forward declarations */ 128 static int init_aucc __P((struct aucc_softc *)); 129 static u_int freqtoper __P((u_int)); 130 static u_int pertofreq __P((u_int)); 131 132 /* autoconfiguration driver */ 133 void auccattach __P((struct device *, struct device *, void *)); 134 int auccmatch __P((struct device *, struct cfdata *, void *)); 135 136 struct cfattach aucc_ca = { 137 sizeof(struct aucc_softc), 138 auccmatch, 139 auccattach 140 }; 141 142 struct audio_device aucc_device = { 143 "Amiga-audio", 144 "2.0", 145 "aucc" 146 }; 147 148 149 struct aucc_softc *aucc=NULL; 150 151 152 unsigned char ulaw_to_lin[] = { 153 0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e, 154 0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe, 155 0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf, 156 0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf, 157 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 158 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 159 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4, 160 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8, 161 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 162 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 163 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 164 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 165 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 166 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 167 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 168 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 169 0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61, 170 0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, 0x45, 0x41, 171 0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30, 172 0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20, 173 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 174 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 175 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b, 176 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07, 177 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 178 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 179 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 180 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 181 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 182 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 183 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 184 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 185 }; 186 187 /* 188 * Define our interface to the higher level audio driver. 189 */ 190 int aucc_open __P((void *, int)); 191 void aucc_close __P((void *)); 192 int aucc_set_out_sr __P((void *, u_long)); 193 int aucc_query_encoding __P((void *, struct audio_encoding *)); 194 int aucc_round_blocksize __P((void *, int)); 195 int aucc_commit_settings __P((void *)); 196 int aucc_start_output __P((void *, void *, int, void (*)(void *), 197 void *)); 198 int aucc_start_input __P((void *, void *, int, void (*)(void *), 199 void *)); 200 int aucc_halt_output __P((void *)); 201 int aucc_halt_input __P((void *)); 202 int aucc_getdev __P((void *, struct audio_device *)); 203 int aucc_set_port __P((void *, mixer_ctrl_t *)); 204 int aucc_get_port __P((void *, mixer_ctrl_t *)); 205 int aucc_query_devinfo __P((void *, mixer_devinfo_t *)); 206 void aucc_encode __P((int, int, int, int, u_char *, u_short **)); 207 int aucc_set_params __P((void *, int, int, 208 struct audio_params *, struct audio_params *)); 209 int aucc_get_props __P((void *)); 210 211 212 static void aucc_decode_slinear8_1ch __P((u_char **, u_char *, int)); 213 static void aucc_decode_slinear8_2ch __P((u_char **, u_char *, int)); 214 static void aucc_decode_slinear8_3ch __P((u_char **, u_char *, int)); 215 static void aucc_decode_slinear8_4ch __P((u_char **, u_char *, int)); 216 217 static void aucc_decode_ulinear8_1ch __P((u_char **, u_char *, int)); 218 static void aucc_decode_ulinear8_2ch __P((u_char **, u_char *, int)); 219 static void aucc_decode_ulinear8_3ch __P((u_char **, u_char *, int)); 220 static void aucc_decode_ulinear8_4ch __P((u_char **, u_char *, int)); 221 222 static void aucc_decode_ulaw_1ch __P((u_char **, u_char *, int)); 223 static void aucc_decode_ulaw_2ch __P((u_char **, u_char *, int)); 224 static void aucc_decode_ulaw_3ch __P((u_char **, u_char *, int)); 225 static void aucc_decode_ulaw_4ch __P((u_char **, u_char *, int)); 226 227 static void aucc_decode_slinear16_1ch __P((u_char **, u_char *, int)); 228 static void aucc_decode_slinear16_2ch __P((u_char **, u_char *, int)); 229 static void aucc_decode_slinear16_3ch __P((u_char **, u_char *, int)); 230 static void aucc_decode_slinear16_4ch __P((u_char **, u_char *, int)); 231 232 static void aucc_decode_slinear16sw_1ch __P((u_char **, u_char *, int)); 233 static void aucc_decode_slinear16sw_2ch __P((u_char **, u_char *, int)); 234 static void aucc_decode_slinear16sw_3ch __P((u_char **, u_char *, int)); 235 static void aucc_decode_slinear16sw_4ch __P((u_char **, u_char *, int)); 236 237 238 239 struct audio_hw_if sa_hw_if = { 240 aucc_open, 241 aucc_close, 242 NULL, 243 aucc_query_encoding, 244 aucc_set_params, 245 aucc_round_blocksize, 246 aucc_commit_settings, 247 NULL, 248 NULL, 249 aucc_start_output, 250 aucc_start_input, 251 aucc_halt_output, 252 aucc_halt_input, 253 NULL, 254 aucc_getdev, 255 NULL, 256 aucc_set_port, 257 aucc_get_port, 258 aucc_query_devinfo, 259 NULL, 260 NULL, 261 NULL, 262 NULL, 263 aucc_get_props, 264 }; 265 266 /* autoconfig routines */ 267 268 int 269 auccmatch(pdp, cfp, aux) 270 struct device *pdp; 271 struct cfdata *cfp; 272 void *aux; 273 { 274 static int aucc_matched = 0; 275 276 if (!matchname((char *)aux, "aucc") || 277 #ifdef DRACO 278 is_draco() || 279 #endif 280 aucc_matched) 281 return 0; 282 283 aucc_matched = 1; 284 return 1; 285 } 286 287 /* 288 * Audio chip found. 289 */ 290 void 291 auccattach(parent, self, args) 292 struct device *parent, *self; 293 void *args; 294 { 295 register struct aucc_softc *sc = (struct aucc_softc *)self; 296 register int i; 297 298 printf("\n"); 299 300 if((i=init_aucc(sc))) { 301 printf("audio: no chipmem\n"); 302 return; 303 } 304 305 audio_attach_mi(&sa_hw_if, sc, &sc->sc_dev); 306 } 307 308 309 static int 310 init_aucc(sc) 311 struct aucc_softc *sc; 312 { 313 register int i, err=0; 314 315 /* init values per channel */ 316 for (i=0;i<4;i++) { 317 sc->sc_channel[i].nd_freq=8000; 318 sc->sc_channel[i].nd_per=freqtoper(8000); 319 sc->sc_channel[i].nd_busy=0; 320 sc->sc_channel[i].nd_dma=alloc_chipmem(AUDIO_BUF_SIZE*2); 321 if (sc->sc_channel[i].nd_dma==NULL) 322 err=1; 323 sc->sc_channel[i].nd_dmalength=0; 324 sc->sc_channel[i].nd_volume=64; 325 sc->sc_channel[i].nd_intr=NULL; 326 sc->sc_channel[i].nd_intrdata=NULL; 327 sc->sc_channel[i].nd_doublebuf=0; 328 DPRINTF(("dma buffer for channel %d is %p\n", i, 329 sc->sc_channel[i].nd_dma)); 330 } 331 332 if (err) { 333 for(i=0;i<4;i++) 334 if (sc->sc_channel[i].nd_dma) 335 free_chipmem(sc->sc_channel[i].nd_dma); 336 } 337 338 sc->sc_channels=1; 339 sc->sc_channelmask=0xf; 340 sc->sc_precision=8; 341 sc->sc_14bit = 0; 342 sc->sc_encoding=AUDIO_ENCODING_ULAW; 343 sc->sc_decodefunc = aucc_decode_ulaw_1ch; 344 345 /* clear interrupts and dma: */ 346 custom.intena = AUCC_ALLINTF; 347 custom.dmacon = AUCC_ALLDMAF; 348 349 return err; 350 } 351 352 int 353 aucc_open(addr, flags) 354 void *addr; 355 int flags; 356 { 357 struct aucc_softc *sc = addr; 358 int i; 359 360 DPRINTF(("sa_open: unit %p\n",sc)); 361 362 if (sc->sc_open) 363 return (EBUSY); 364 sc->sc_open = 1; 365 for (i=0;i<AUCC_MAXINT;i++) { 366 sc->sc_channel[i].nd_intr=NULL; 367 sc->sc_channel[i].nd_intrdata=NULL; 368 } 369 aucc=sc; 370 sc->sc_channelmask=0xf; 371 372 DPRINTF(("saopen: ok -> sc=0x%p\n",sc)); 373 374 return (0); 375 } 376 377 void 378 aucc_close(addr) 379 void *addr; 380 { 381 register struct aucc_softc *sc = addr; 382 383 DPRINTF(("sa_close: sc=0x%p\n", sc)); 384 /* 385 * halt i/o, clear open flag, and done. 386 */ 387 aucc_halt_output(sc); 388 sc->sc_open = 0; 389 390 DPRINTF(("sa_close: closed.\n")); 391 } 392 393 int 394 aucc_set_out_sr(addr, sr) 395 void *addr; 396 u_long sr; 397 { 398 struct aucc_softc *sc=addr; 399 u_long per; 400 register int i; 401 402 per=freqtoper(sr); 403 if (per>0xffff) 404 return EINVAL; 405 sr=pertofreq(per); 406 407 for (i=0;i<4;i++) { 408 sc->sc_channel[i].nd_freq=sr; 409 sc->sc_channel[i].nd_per=per; 410 } 411 412 return(0); 413 } 414 415 int 416 aucc_query_encoding(addr, fp) 417 void *addr; 418 struct audio_encoding *fp; 419 { 420 switch (fp->index) { 421 case 0: 422 strcpy(fp->name, AudioEslinear); 423 fp->encoding = AUDIO_ENCODING_SLINEAR; 424 fp->precision = 8; 425 fp->flags = 0; 426 break; 427 case 1: 428 strcpy(fp->name, AudioEmulaw); 429 fp->encoding = AUDIO_ENCODING_ULAW; 430 fp->precision = 8; 431 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 432 break; 433 434 case 2: 435 strcpy(fp->name, AudioEulinear); 436 fp->encoding = AUDIO_ENCODING_ULINEAR; 437 fp->precision = 8; 438 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 439 break; 440 441 case 3: 442 strcpy(fp->name, AudioEslinear); 443 fp->encoding = AUDIO_ENCODING_SLINEAR; 444 fp->precision = 16; 445 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 446 break; 447 448 case 4: 449 strcpy(fp->name, AudioEslinear_be); 450 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 451 fp->precision = 16; 452 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 453 break; 454 455 case 5: 456 strcpy(fp->name, AudioEslinear_le); 457 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 458 fp->precision = 16; 459 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 460 break; 461 462 default: 463 return(EINVAL); 464 /*NOTREACHED*/ 465 } 466 return(0); 467 } 468 469 int 470 aucc_set_params(addr, setmode, usemode, p, r) 471 void *addr; 472 int setmode, usemode; 473 struct audio_params *p, *r; 474 { 475 struct aucc_softc *sc = addr; 476 477 /* if (setmode & AUMODE_RECORD) 478 return 0 ENXIO*/; 479 480 #ifdef AUCCDEBUG 481 printf("aucc_set_params(setmode 0x%x, usemode 0x%x, " 482 "enc %d, bits %d, chn %d, sr %ld)\n", setmode, usemode, 483 p->encoding, p->precision, p->channels, p->sample_rate); 484 #endif 485 486 switch (p->precision) { 487 case 8: 488 switch (p->encoding) { 489 case AUDIO_ENCODING_ULAW: 490 switch (p->channels) { 491 case 1: 492 sc->sc_decodefunc = aucc_decode_ulaw_1ch; 493 break; 494 case 2: 495 sc->sc_decodefunc = aucc_decode_ulaw_2ch; 496 break; 497 case 3: 498 sc->sc_decodefunc = aucc_decode_ulaw_3ch; 499 break; 500 case 4: 501 sc->sc_decodefunc = aucc_decode_ulaw_4ch; 502 break; 503 default: 504 return EINVAL; 505 } 506 break; 507 508 case AUDIO_ENCODING_SLINEAR: 509 case AUDIO_ENCODING_SLINEAR_BE: 510 case AUDIO_ENCODING_SLINEAR_LE: 511 switch (p->channels) { 512 case 1: 513 sc->sc_decodefunc = aucc_decode_slinear8_1ch; 514 break; 515 case 2: 516 sc->sc_decodefunc = aucc_decode_slinear8_2ch; 517 break; 518 case 3: 519 sc->sc_decodefunc = aucc_decode_slinear8_3ch; 520 break; 521 case 4: 522 sc->sc_decodefunc = aucc_decode_slinear8_4ch; 523 break; 524 default: 525 return EINVAL; 526 } 527 break; 528 529 case AUDIO_ENCODING_ULINEAR: 530 case AUDIO_ENCODING_ULINEAR_BE: 531 case AUDIO_ENCODING_ULINEAR_LE: 532 switch (p->channels) { 533 case 1: 534 sc->sc_decodefunc = aucc_decode_ulinear8_1ch; 535 break; 536 case 2: 537 sc->sc_decodefunc = aucc_decode_ulinear8_2ch; 538 break; 539 case 3: 540 sc->sc_decodefunc = aucc_decode_ulinear8_3ch; 541 break; 542 case 4: 543 sc->sc_decodefunc = aucc_decode_ulinear8_4ch; 544 break; 545 default: 546 return EINVAL; 547 } 548 break; 549 550 default: 551 return EINVAL; 552 } 553 break; 554 555 case 16: 556 switch (p->encoding) { 557 #if BYTE_ORDER == BIG_ENDIAN 558 case AUDIO_ENCODING_SLINEAR: 559 #endif 560 case AUDIO_ENCODING_SLINEAR_BE: 561 switch (p->channels) { 562 case 1: 563 sc->sc_decodefunc = aucc_decode_slinear16_1ch; 564 break; 565 566 case 2: 567 sc->sc_decodefunc = aucc_decode_slinear16_2ch; 568 break; 569 case 3: 570 sc->sc_decodefunc = aucc_decode_slinear16_3ch; 571 break; 572 case 4: 573 sc->sc_decodefunc = aucc_decode_slinear16_4ch; 574 break; 575 default: 576 return EINVAL; 577 } 578 break; 579 580 #if BYTE_ORDER == LITTLE_ENDIAN 581 case AUDIO_ENCODING_SLINEAR: 582 #endif 583 case AUDIO_ENCODING_SLINEAR_LE: 584 switch (p->channels) { 585 case 1: 586 sc->sc_decodefunc = aucc_decode_slinear16sw_1ch; 587 break; 588 case 2: 589 sc->sc_decodefunc = aucc_decode_slinear16sw_2ch; 590 break; 591 case 3: 592 sc->sc_decodefunc = aucc_decode_slinear16sw_3ch; 593 break; 594 case 4: 595 sc->sc_decodefunc = aucc_decode_slinear16sw_4ch; 596 break; 597 default: 598 return EINVAL; 599 } 600 break; 601 602 default: 603 return EINVAL; 604 } 605 break; 606 607 default: 608 return EINVAL; 609 } 610 611 sc->sc_encoding = p->encoding; 612 sc->sc_precision = p->precision; 613 sc->sc_14bit = ((p->precision == 16) && (p->channels <= 2)); 614 sc->sc_channels = sc->sc_14bit ? (p->channels * 2) : p->channels; 615 616 return aucc_set_out_sr(addr, p->sample_rate); 617 } 618 619 int 620 aucc_round_blocksize(addr, blk) 621 void *addr; 622 int blk; 623 { 624 /* round up to even size */ 625 return blk > AUDIO_BUF_SIZE ? AUDIO_BUF_SIZE : blk; 626 } 627 628 int 629 aucc_commit_settings(addr) 630 void *addr; 631 { 632 register struct aucc_softc *sc = addr; 633 register int i; 634 635 DPRINTF(("sa_commit.\n")); 636 637 for (i=0;i<4;i++) { 638 custom.aud[i].vol=sc->sc_channel[i].nd_volume; 639 custom.aud[i].per=sc->sc_channel[i].nd_per; 640 } 641 642 DPRINTF(("commit done\n")); 643 644 return(0); 645 } 646 647 static int masks[4] = {1,3,7,15}; /* masks for n first channels */ 648 static int masks2[4] = {1,2,4,8}; 649 650 int 651 aucc_start_output(addr, p, cc, intr, arg) 652 void *addr; 653 void *p; 654 int cc; 655 void (*intr) __P((void *)); 656 void *arg; 657 { 658 struct aucc_softc *sc; 659 int mask; 660 int i, j, k, len; 661 u_char *dmap[4]; 662 663 664 sc = addr; 665 mask = sc->sc_channelmask; 666 667 dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL; 668 669 DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg)); 670 671 if (sc->sc_channels > 1) 672 mask &= masks[sc->sc_channels - 1]; 673 /* we use first sc_channels channels */ 674 if (mask == 0) /* active and used channels are disjoint */ 675 return EINVAL; 676 677 for (i=0;i<4;i++) { 678 /* channels available ? */ 679 if ((masks2[i] & mask) && (sc->sc_channel[i].nd_busy)) 680 return EBUSY; /* channel is busy */ 681 if (channel[i].isaudio == -1) 682 return EBUSY; /* system uses them */ 683 } 684 685 /* enable interrupt on 1st channel */ 686 for (i = j = 0; i < AUCC_MAXINT; i++) { 687 if (masks2[i] & mask) { 688 DPRINTF(("first channel is %d\n",i)); 689 j=i; 690 sc->sc_channel[i].nd_intr=intr; 691 sc->sc_channel[i].nd_intrdata=arg; 692 break; 693 } 694 } 695 696 DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1], 697 dmap[2], dmap[3], mask)); 698 699 /* disable ints, dma for channels, until all parameters set */ 700 /* XXX dont disable DMA! custom.dmacon=mask;*/ 701 custom.intreq = mask << INTB_AUD0; 702 custom.intena = mask << INTB_AUD0; 703 704 /* copy data to dma buffer */ 705 706 if (sc->sc_channels == 1) { 707 dmap[0] = 708 dmap[1] = 709 dmap[2] = 710 dmap[3] = (u_char *)sc->sc_channel[j].nd_dma; 711 } 712 else { 713 for (k=0; k<4; k++) { 714 if (masks2[k+j] & mask) 715 dmap[k] = (u_char *)sc->sc_channel[k+j].nd_dma; 716 } 717 } 718 719 sc->sc_channel[j].nd_doublebuf ^= 1; 720 if (sc->sc_channel[j].nd_doublebuf) { 721 dmap[0] += AUDIO_BUF_SIZE; 722 dmap[1] += AUDIO_BUF_SIZE; 723 dmap[2] += AUDIO_BUF_SIZE; 724 dmap[3] += AUDIO_BUF_SIZE; 725 } 726 727 /* compute output length in bytes per channel. 728 * divide by two only for 16bit->8bit conversion. 729 */ 730 len = cc / sc->sc_channels; 731 if (!sc->sc_14bit && (sc->sc_precision == 16)) 732 len /= 2; 733 734 /* call audio decoding routine */ 735 sc->sc_decodefunc (dmap, (u_char *)p, len); 736 737 /* dma buffers: we use same buffer 4 all channels 738 * write dma location and length 739 */ 740 for (i = k = 0; i < 4; i++) { 741 if (masks2[i] & mask) { 742 DPRINTF(("turning channel %d on\n",i)); 743 /* sc->sc_channel[i].nd_busy=1; */ 744 channel[i].isaudio = 1; 745 channel[i].play_count = 1; 746 channel[i].handler = NULL; 747 custom.aud[i].per = sc->sc_channel[i].nd_per; 748 if (sc->sc_14bit && (i > 1)) 749 custom.aud[i].vol = 1; 750 else 751 custom.aud[i].vol = sc->sc_channel[i].nd_volume; 752 custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]); 753 custom.aud[i].len = len / 2; 754 sc->sc_channel[i].nd_mask = mask; 755 DPRINTF(("per is %d, vol is %d, len is %d\n",\ 756 sc->sc_channel[i].nd_per, 757 sc->sc_channel[i].nd_volume, len)); 758 } 759 } 760 761 channel[j].handler=aucc_inthdl; 762 763 /* enable ints */ 764 custom.intena = INTF_SETCLR | INTF_INTEN | (masks2[j] << INTB_AUD0); 765 766 DPRINTF(("enabled ints: 0x%x\n", (masks2[j] << INTB_AUD0))); 767 768 /* enable dma */ 769 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | mask; 770 771 DPRINTF(("enabled dma, mask=0x%x\n",mask)); 772 773 return(0); 774 } 775 776 /* ARGSUSED */ 777 int 778 aucc_start_input(addr, p, cc, intr, arg) 779 void *addr; 780 void *p; 781 int cc; 782 void (*intr) __P((void *)); 783 void *arg; 784 { 785 786 return ENXIO; /* no input */ 787 } 788 789 int 790 aucc_halt_output(addr) 791 void *addr; 792 { 793 register struct aucc_softc *sc = addr; 794 register int i; 795 796 /* XXX only halt, if input is also halted ?? */ 797 /* stop dma, etc */ 798 custom.intena = AUCC_ALLINTF; 799 custom.dmacon = AUCC_ALLDMAF; 800 /* mark every busy unit idle */ 801 for (i=0;i<4;i++) { 802 sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0; 803 channel[i].isaudio=0; 804 channel[i].play_count=0; 805 } 806 807 return(0); 808 } 809 810 int 811 aucc_halt_input(addr) 812 void *addr; 813 { 814 /* no input */ 815 816 return ENXIO; 817 } 818 819 int 820 aucc_getdev(addr, retp) 821 void *addr; 822 struct audio_device *retp; 823 { 824 *retp = aucc_device; 825 return 0; 826 } 827 828 int 829 aucc_set_port(addr, cp) 830 void *addr; 831 mixer_ctrl_t *cp; 832 { 833 register struct aucc_softc *sc = addr; 834 register int i,j; 835 836 DPRINTF(("aucc_set_port: port=%d", cp->dev)); 837 838 switch (cp->type) { 839 case AUDIO_MIXER_SET: 840 if (cp->dev!=AUCC_CHANNELS) 841 return EINVAL; 842 i=cp->un.mask; 843 if ((i<1) || (i>15)) 844 return EINVAL; 845 846 sc->sc_channelmask=i; 847 break; 848 849 case AUDIO_MIXER_VALUE: 850 i=cp->un.value.num_channels; 851 if ((i<1) || (i>4)) 852 return EINVAL; 853 854 #ifdef __XXXwhatsthat 855 if (cp->dev!=AUCC_VOLUME) 856 return EINVAL; 857 #endif 858 859 /* set volume for channel 0..i-1 */ 860 861 /* evil workaround for xanim bug, IMO */ 862 if ((sc->sc_channels == 1) && (i == 2)) { 863 sc->sc_channel[0].nd_volume = 864 sc->sc_channel[3].nd_volume = 865 cp->un.value.level[0]>>2; 866 sc->sc_channel[1].nd_volume = 867 sc->sc_channel[2].nd_volume = 868 cp->un.value.level[1]>>2; 869 } else if (i>1) { 870 for (j=0;j<i;j++) 871 sc->sc_channel[j].nd_volume = 872 cp->un.value.level[j]>>2; 873 } else if (sc->sc_channels > 1) 874 for (j=0; j<sc->sc_channels; j++) 875 sc->sc_channel[j].nd_volume = 876 cp->un.value.level[0]>>2; 877 else 878 for (j=0; j<4; j++) 879 sc->sc_channel[j].nd_volume = 880 cp->un.value.level[0]>>2; 881 break; 882 883 default: 884 return EINVAL; 885 break; 886 } 887 return 0; 888 } 889 890 891 int 892 aucc_get_port(addr, cp) 893 void *addr; 894 mixer_ctrl_t *cp; 895 { 896 register struct aucc_softc *sc = addr; 897 register int i,j; 898 899 DPRINTF(("aucc_get_port: port=%d", cp->dev)); 900 901 switch (cp->type) { 902 case AUDIO_MIXER_SET: 903 if (cp->dev!=AUCC_CHANNELS) 904 return EINVAL; 905 cp->un.mask=sc->sc_channelmask; 906 break; 907 908 case AUDIO_MIXER_VALUE: 909 i = cp->un.value.num_channels; 910 if ((i<1)||(i>4)) 911 return EINVAL; 912 913 for (j=0;j<i;j++) 914 cp->un.value.level[j] = 915 (sc->sc_channel[j].nd_volume<<2) + 916 (sc->sc_channel[j].nd_volume>>4); 917 break; 918 919 default: 920 return EINVAL; 921 } 922 return 0; 923 } 924 925 926 int 927 aucc_get_props(addr) 928 void *addr; 929 { 930 return 0; 931 } 932 933 int 934 aucc_query_devinfo(addr, dip) 935 void *addr; 936 register mixer_devinfo_t *dip; 937 { 938 register int i; 939 940 switch(dip->index) { 941 case AUCC_CHANNELS: 942 dip->type = AUDIO_MIXER_SET; 943 dip->mixer_class = AUCC_OUTPUT_CLASS; 944 dip->prev = dip->next = AUDIO_MIXER_LAST; 945 strcpy(dip->label.name, AudioNspeaker); 946 for (i=0;i<16;i++) { 947 sprintf(dip->un.s.member[i].label.name, 948 "channelmask%d", i); 949 dip->un.s.member[i].mask = i; 950 } 951 dip->un.s.num_mem = 16; 952 break; 953 954 case AUCC_VOLUME: 955 dip->type = AUDIO_MIXER_VALUE; 956 dip->mixer_class = AUCC_OUTPUT_CLASS; 957 dip->prev = dip->next = AUDIO_MIXER_LAST; 958 strcpy(dip->label.name, AudioNmaster); 959 dip->un.v.num_channels = 4; 960 strcpy(dip->un.v.units.name, AudioNvolume); 961 break; 962 963 case AUCC_OUTPUT_CLASS: 964 dip->type = AUDIO_MIXER_CLASS; 965 dip->mixer_class = AUCC_OUTPUT_CLASS; 966 dip->next = dip->prev = AUDIO_MIXER_LAST; 967 strcpy(dip->label.name, AudioCoutputs); 968 break; 969 970 default: 971 return ENXIO; 972 } 973 974 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); 975 976 return(0); 977 } 978 979 980 /* audio int handler */ 981 void 982 aucc_inthdl(int ch) 983 { 984 register int i; 985 register int mask=aucc->sc_channel[ch].nd_mask; 986 987 /* for all channels in this maskgroup: 988 disable dma, int 989 mark idle */ 990 DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask)); 991 992 custom.intreq=mask<<INTB_AUD0; /* clear request */ 993 /* 994 * XXX: maybe we can leave ints and/or DMA on, 995 * if another sample has to be played? 996 */ 997 custom.intena=mask<<INTB_AUD0; 998 /* 999 * XXX custom.dmacon=mask; NO!!! 1000 */ 1001 for (i=0; i<4; i++) { 1002 if (masks2[i]&&mask) { 1003 DPRINTF(("marking channel %d idle\n",i)); 1004 aucc->sc_channel[i].nd_busy=0; 1005 aucc->sc_channel[i].nd_mask=0; 1006 channel[i].isaudio=channel[i].play_count=0; 1007 } 1008 } 1009 1010 /* call handler */ 1011 if (aucc->sc_channel[ch].nd_intr) { 1012 DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr)); 1013 (*(aucc->sc_channel[ch].nd_intr)) 1014 (aucc->sc_channel[ch].nd_intrdata); 1015 } 1016 else 1017 DPRINTF(("zero int handler\n")); 1018 DPRINTF(("ints done\n")); 1019 } 1020 1021 1022 1023 1024 /* transform frequency to period, adjust bounds */ 1025 static u_int 1026 freqtoper(u_int freq) { 1027 u_int per=eclockfreq*5/freq; 1028 1029 if (per<124) 1030 per=124; /* must have at least 124 ticks between samples */ 1031 1032 return per; 1033 } 1034 1035 /* transform period to frequency */ 1036 static u_int 1037 pertofreq(u_int per) { 1038 u_int freq=eclockfreq*5/per; 1039 1040 return freq; 1041 } 1042 1043 static void aucc_decode_slinear8_1ch (u_char **dmap, u_char *p, int i) { 1044 memcpy (dmap[0], p, i); 1045 } 1046 1047 static void aucc_decode_slinear8_2ch (u_char **dmap, u_char *p, int i) { 1048 u_char *ch0 = dmap[0]; 1049 u_char *ch1 = dmap[1]; 1050 1051 while (i--) { 1052 *ch0++ = *p++; 1053 *ch1++ = *p++; 1054 } 1055 } 1056 1057 static void aucc_decode_slinear8_3ch (u_char **dmap, u_char *p, int i) { 1058 u_char *ch0 = dmap[0]; 1059 u_char *ch1 = dmap[1]; 1060 u_char *ch2 = dmap[2]; 1061 1062 while (i--) { 1063 *ch0++ = *p++; 1064 *ch1++ = *p++; 1065 *ch2++ = *p++; 1066 } 1067 } 1068 1069 static void aucc_decode_slinear8_4ch (u_char **dmap, u_char *p, int i) { 1070 u_char *ch0 = dmap[0]; 1071 u_char *ch1 = dmap[1]; 1072 u_char *ch2 = dmap[2]; 1073 u_char *ch3 = dmap[3]; 1074 1075 while (i--) { 1076 *ch0++ = *p++; 1077 *ch1++ = *p++; 1078 *ch2++ = *p++; 1079 *ch3++ = *p++; 1080 } 1081 } 1082 1083 static void 1084 aucc_decode_ulinear8_1ch (dmap, p, i) 1085 u_char **dmap; 1086 u_char *p; 1087 int i; 1088 { 1089 u_char *ch0 = dmap[0]; 1090 1091 while (i--) 1092 *ch0++ = *p++ - 128; 1093 } 1094 1095 static void 1096 aucc_decode_ulinear8_2ch(dmap, p, i) 1097 u_char **dmap; 1098 u_char *p; 1099 int i; 1100 { 1101 u_char *ch0 = dmap[0]; 1102 u_char *ch1 = dmap[1]; 1103 1104 while (i--) { 1105 *ch0++ = *p++ - 128; 1106 *ch1++ = *p++ - 128; 1107 } 1108 } 1109 1110 static void 1111 aucc_decode_ulinear8_3ch(dmap, p, i) 1112 u_char **dmap; 1113 u_char *p; 1114 int i; 1115 { 1116 u_char *ch0 = dmap[0]; 1117 u_char *ch1 = dmap[1]; 1118 u_char *ch2 = dmap[2]; 1119 1120 while (i--) { 1121 *ch0++ = *p++ - 128; 1122 *ch1++ = *p++ - 128; 1123 *ch2++ = *p++ - 128; 1124 } 1125 } 1126 1127 static void 1128 aucc_decode_ulinear8_4ch(dmap, p, i) 1129 u_char **dmap; 1130 u_char *p; 1131 int i; 1132 { 1133 u_char *ch0 = dmap[0]; 1134 u_char *ch1 = dmap[1]; 1135 u_char *ch2 = dmap[2]; 1136 u_char *ch3 = dmap[3]; 1137 1138 while (i--) { 1139 *ch0++ = *p++ - 128; 1140 *ch1++ = *p++ - 128; 1141 *ch2++ = *p++ - 128; 1142 *ch3++ = *p++ - 128; 1143 } 1144 } 1145 1146 1147 static void 1148 aucc_decode_ulaw_1ch (dmap, p, i) 1149 u_char **dmap; 1150 u_char *p; 1151 int i; 1152 { 1153 u_char *ch0 = dmap[0]; 1154 1155 while (i--) 1156 *ch0++ = ulaw_to_lin[*p++]; 1157 } 1158 1159 static void 1160 aucc_decode_ulaw_2ch(dmap, p, i) 1161 u_char **dmap; 1162 u_char *p; 1163 int i; 1164 { 1165 u_char *ch0 = dmap[0]; 1166 u_char *ch1 = dmap[1]; 1167 1168 while (i--) { 1169 *ch0++ = ulaw_to_lin[*p++]; 1170 *ch1++ = ulaw_to_lin[*p++]; 1171 } 1172 } 1173 1174 static void 1175 aucc_decode_ulaw_3ch(dmap, p, i) 1176 u_char **dmap; 1177 u_char *p; 1178 int i; 1179 { 1180 u_char *ch0 = dmap[0]; 1181 u_char *ch1 = dmap[1]; 1182 u_char *ch2 = dmap[2]; 1183 1184 while (i--) { 1185 *ch0++ = ulaw_to_lin[*p++]; 1186 *ch1++ = ulaw_to_lin[*p++]; 1187 *ch2++ = ulaw_to_lin[*p++]; 1188 } 1189 } 1190 1191 static void 1192 aucc_decode_ulaw_4ch(dmap, p, i) 1193 u_char **dmap; 1194 u_char *p; 1195 int i; 1196 { 1197 u_char *ch0 = dmap[0]; 1198 u_char *ch1 = dmap[1]; 1199 u_char *ch2 = dmap[2]; 1200 u_char *ch3 = dmap[3]; 1201 1202 while (i--) { 1203 *ch0++ = ulaw_to_lin[*p++]; 1204 *ch1++ = ulaw_to_lin[*p++]; 1205 *ch2++ = ulaw_to_lin[*p++]; 1206 *ch3++ = ulaw_to_lin[*p++]; 1207 } 1208 } 1209 1210 1211 /* 14bit output */ 1212 static void 1213 aucc_decode_slinear16_1ch(dmap, p, i) 1214 u_char **dmap; 1215 u_char *p; 1216 int i; 1217 { 1218 u_char *ch0 = dmap[0]; 1219 u_char *ch3 = dmap[1]; /* XXX should be 3 */ 1220 1221 while (i--) { 1222 *ch0++ = *p++; 1223 *ch3++ = *p++ >> 2; 1224 } 1225 } 1226 1227 /* 14bit stereo output */ 1228 static void 1229 aucc_decode_slinear16_2ch(dmap, p, i) 1230 u_char **dmap; 1231 u_char *p; 1232 int i; 1233 { 1234 u_char *ch0 = dmap[0]; 1235 u_char *ch1 = dmap[1]; 1236 u_char *ch2 = dmap[2]; 1237 u_char *ch3 = dmap[3]; 1238 1239 while (i--) { 1240 *ch0++ = *p++; 1241 *ch3++ = *p++ >> 2; 1242 *ch1++ = *p++; 1243 *ch2++ = *p++ >> 2; 1244 } 1245 } 1246 1247 static void 1248 aucc_decode_slinear16_3ch(dmap, p, i) 1249 u_char **dmap; 1250 u_char *p; 1251 int i; 1252 { 1253 u_char *ch0 = dmap[0]; 1254 u_char *ch1 = dmap[1]; 1255 u_char *ch2 = dmap[2]; 1256 1257 while (i--) { 1258 *ch0++ = *p++; p++; 1259 *ch1++ = *p++; p++; 1260 *ch2++ = *p++; p++; 1261 } 1262 } 1263 1264 static void 1265 aucc_decode_slinear16_4ch (dmap, p, i) 1266 u_char **dmap; 1267 u_char *p; 1268 int i; 1269 { 1270 u_char *ch0 = dmap[0]; 1271 u_char *ch1 = dmap[1]; 1272 u_char *ch2 = dmap[2]; 1273 u_char *ch3 = dmap[3]; 1274 1275 while (i--) { 1276 *ch0++ = *p++; p++; 1277 *ch1++ = *p++; p++; 1278 *ch2++ = *p++; p++; 1279 *ch3++ = *p++; p++; 1280 } 1281 } 1282 1283 /* 14bit output, swap bytes */ 1284 static void 1285 aucc_decode_slinear16sw_1ch(dmap, p, i) 1286 u_char **dmap; 1287 u_char *p; 1288 int i; 1289 { 1290 u_char *ch0 = dmap[0]; 1291 u_char *ch3 = dmap[1]; /* XXX should be 3 */ 1292 1293 while (i--) { 1294 *ch3++ = *p++ >> 2; 1295 *ch0++ = *p++; 1296 } 1297 } 1298 1299 static void 1300 aucc_decode_slinear16sw_2ch(dmap, p, i) 1301 u_char **dmap; 1302 u_char *p; 1303 int i; 1304 { 1305 u_char *ch0 = dmap[0]; 1306 u_char *ch1 = dmap[1]; 1307 u_char *ch2 = dmap[2]; 1308 u_char *ch3 = dmap[3]; 1309 1310 while (i--) { 1311 *ch3++ = *p++ >> 2; 1312 *ch0++ = *p++; 1313 *ch2++ = *p++ >> 2; 1314 *ch1++ = *p++; 1315 } 1316 } 1317 1318 static void 1319 aucc_decode_slinear16sw_3ch(dmap, p, i) 1320 u_char **dmap; 1321 u_char *p; 1322 int i; 1323 { 1324 u_char *ch0 = dmap[0]; 1325 u_char *ch1 = dmap[1]; 1326 u_char *ch2 = dmap[2]; 1327 1328 while (i--) { 1329 p++; *ch0++ = *p++; 1330 p++; *ch1++ = *p++; 1331 p++; *ch2++ = *p++; 1332 } 1333 } 1334 1335 static void 1336 aucc_decode_slinear16sw_4ch(dmap, p, i) 1337 u_char **dmap; 1338 u_char *p; 1339 int i; 1340 { 1341 u_char *ch0 = dmap[0]; 1342 u_char *ch1 = dmap[1]; 1343 u_char *ch2 = dmap[2]; 1344 u_char *ch3 = dmap[3]; 1345 1346 while (i--) { 1347 p++; *ch0++ = *p++; 1348 p++; *ch1++ = *p++; 1349 p++; *ch2++ = *p++; 1350 p++; *ch3++ = *p++; 1351 } 1352 } 1353 1354 1355 #endif /* NAUCC > 0 */ 1356