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