Home | History | Annotate | Line # | Download | only in dev
aucc.c revision 1.16
      1 /*	$NetBSD: aucc.c,v 1.16 1997/07/31 22:33:08 augustss Exp $	*/
      2 #undef AUDIO_DEBUG
      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_set_out_port __P((void *, int));
    175 int	aucc_get_out_port __P((void *));
    176 int	aucc_set_in_port __P((void *, int));
    177 int	aucc_get_in_port __P((void *));
    178 int	aucc_commit_settings __P((void *));
    179 int	aucc_start_output __P((void *, void *, int, void (*)(void *),
    180 				  void *));
    181 int	aucc_start_input __P((void *, void *, int, void (*)(void *),
    182 				 void *));
    183 int	aucc_halt_output __P((void *));
    184 int	aucc_halt_input __P((void *));
    185 int	aucc_cont_output __P((void *));
    186 int	aucc_cont_input __P((void *));
    187 int	aucc_getdev __P((void *, struct audio_device *));
    188 int	aucc_set_port __P((void *, mixer_ctrl_t *));
    189 int	aucc_get_port __P((void *, mixer_ctrl_t *));
    190 int	aucc_query_devinfo __P((void *, mixer_devinfo_t *));
    191 void	aucc_encode __P((int, int, int, u_char *, u_short **));
    192 int	aucc_set_params __P((void *, int, struct audio_params *,
    193 	    struct audio_params *));
    194 int	aucc_get_props __P((void *));
    195 
    196 struct audio_hw_if sa_hw_if = {
    197 	aucc_open,
    198 	aucc_close,
    199 	NULL,
    200 	aucc_query_encoding,
    201 	aucc_set_params,
    202 	aucc_round_blocksize,
    203 	aucc_set_out_port,
    204 	aucc_get_out_port,
    205 	aucc_set_in_port,
    206 	aucc_get_in_port,
    207 	aucc_commit_settings,
    208 	NULL,
    209 	NULL,
    210 	aucc_start_output,
    211 	aucc_start_input,
    212 	aucc_halt_output,
    213 	aucc_halt_input,
    214 	aucc_cont_output,
    215 	aucc_cont_input,
    216 	NULL,
    217 	aucc_getdev,
    218 	NULL,
    219 	aucc_set_port,
    220 	aucc_get_port,
    221 	aucc_query_devinfo,
    222 	NULL,
    223 	NULL,
    224 	NULL,
    225 	NULL,
    226 	aucc_get_props,
    227 };
    228 
    229 /* autoconfig routines */
    230 
    231 int
    232 auccmatch(pdp, cfp, aux)
    233 	struct device *pdp;
    234 	struct cfdata *cfp;
    235 	void *aux;
    236 {
    237 	if (matchname((char *)aux, "aucc") &&
    238 #ifdef DRACO
    239 	    !is_draco() &&
    240 #endif
    241 	    (cfp->cf_unit == 0))
    242 		return 1;
    243 
    244 	return 0;
    245 }
    246 
    247 /*
    248  * Audio chip found.
    249  */
    250 void
    251 auccattach(parent, self, args)
    252 	struct device *parent, *self;
    253 	void *args;
    254 {
    255 	register struct aucc_softc *sc = (struct aucc_softc *)self;
    256 	register int i;
    257 
    258 	printf("\n");
    259 
    260 	if((i=init_aucc(sc))) {
    261 		printf("audio: no chipmem\n");
    262 		return;
    263 	}
    264 
    265 	if (audio_hardware_attach(&sa_hw_if, sc, &sc->sc_dev) != 0)
    266 		printf("audio: could not attach to audio pseudo-device driver\n");
    267 	/* XXX: no way to return error, if init fails */
    268 }
    269 
    270 
    271 static int
    272 init_aucc(sc)
    273 	struct aucc_softc *sc;
    274 {
    275 	register int i, err=0;
    276 
    277 	/* init values per channel */
    278  	for (i=0;i<4;i++) {
    279 		sc->sc_channel[i].nd_freq=8000;
    280 		sc->sc_channel[i].nd_per=freqtoper(8000);
    281 		sc->sc_channel[i].nd_busy=0;
    282 		sc->sc_channel[i].nd_dma=alloc_chipmem(AUDIO_BUF_SIZE*2);
    283 		if (sc->sc_channel[i].nd_dma==NULL)
    284 			err=1;
    285 	 	sc->sc_channel[i].nd_dmalength=0;
    286 		sc->sc_channel[i].nd_volume=64;
    287 		sc->sc_channel[i].nd_intr=NULL;
    288 		sc->sc_channel[i].nd_intrdata=NULL;
    289 		sc->sc_channel[i].nd_doublebuf=0;
    290 		DPRINTF(("dma buffer for channel %d is %p\n", i,
    291 		    sc->sc_channel[i].nd_dma));
    292 
    293 	}
    294 
    295 	if (err) {
    296 		for(i=0;i<4;i++)
    297 			if (sc->sc_channel[i].nd_dma)
    298 				free_chipmem(sc->sc_channel[i].nd_dma);
    299 	}
    300 
    301 	sc->sc_channels=1;
    302 	sc->sc_channelmask=0xf;
    303 
    304 	/* clear interrupts and dma: */
    305 	custom.intena = AUCC_ALLINTF;
    306 	custom.dmacon = AUCC_ALLDMAF;;
    307 
    308 	sc->sc_encoding=AUDIO_ENCODING_ULAW;
    309 
    310 	return err;
    311 
    312 }
    313 
    314 int
    315 aucc_open(addr, flags)
    316 	void *addr;
    317 	int flags;
    318 {
    319 	struct aucc_softc *sc = addr;
    320 	int i;
    321 
    322 	DPRINTF(("sa_open: unit %p\n",sc));
    323 
    324 	if (sc->sc_open)
    325 		return (EBUSY);
    326 	sc->sc_open = 1;
    327 	for (i=0;i<AUCC_MAXINT;i++) {
    328 		sc->sc_channel[i].nd_intr=NULL;
    329 		sc->sc_channel[i].nd_intrdata=NULL;
    330 	}
    331 	aucc=sc;
    332 	sc->sc_channelmask=0xf;
    333 
    334 	DPRINTF(("saopen: ok -> sc=0x%p\n",sc));
    335 
    336 	return (0);
    337 }
    338 
    339 void
    340 aucc_close(addr)
    341 	void *addr;
    342 {
    343 	register struct aucc_softc *sc = addr;
    344 
    345 	DPRINTF(("sa_close: sc=0x%p\n", sc));
    346 	/*
    347 	 * halt i/o, clear open flag, and done.
    348 	 */
    349 	aucc_halt_output(sc);
    350 	sc->sc_open = 0;
    351 
    352 	DPRINTF(("sa_close: closed.\n"));
    353 }
    354 
    355 int
    356 aucc_set_out_sr(addr, sr)
    357 	void *addr;
    358 	u_long sr;
    359 {
    360 	struct aucc_softc *sc=addr;
    361 	u_long per;
    362 	register int i;
    363 
    364 	per=freqtoper(sr);
    365 	if (per>0xffff)
    366 		return EINVAL;
    367 	sr=pertofreq(per);
    368 
    369 	for (i=0;i<4;i++) {
    370 		sc->sc_channel[i].nd_freq=sr;
    371 		sc->sc_channel[i].nd_per=per;
    372 	}
    373 
    374 	return(0);
    375 }
    376 
    377 int
    378 aucc_query_encoding(addr, fp)
    379 	void *addr;
    380 	struct audio_encoding *fp;
    381 {
    382 	switch (fp->index) {
    383 	case 0:
    384 		strcpy(fp->name, AudioElinear);
    385 		fp->encoding = AUDIO_ENCODING_SLINEAR;
    386 		fp->precision = 8;
    387 		fp->flags = 0;
    388 		break;
    389 	case 1:
    390 		strcpy(fp->name, AudioEmulaw);
    391 		fp->encoding = AUDIO_ENCODING_ULAW;
    392 		fp->precision = 8;
    393 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    394 		break;
    395 
    396 	case 2:
    397 		strcpy(fp->name, AudioEulinear);
    398 		fp->encoding = AUDIO_ENCODING_ULINEAR;
    399 		fp->precision = 8;
    400 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    401 		break;
    402 
    403 	default:
    404 		return(EINVAL);
    405 		/*NOTREACHED*/
    406 	}
    407 	return(0);
    408 }
    409 
    410 int
    411 aucc_set_params(addr, mode, p, q)
    412 	void *addr;
    413 	int mode;
    414 	struct  audio_params *p, *q;
    415 {
    416 	struct aucc_softc *sc;
    417 
    418 	sc = addr;
    419 
    420 	/* if (mode == AUMODE_RECORD)
    421 		return 0 ENXIO*/;
    422 
    423 #ifdef AUCCDEBUG
    424 	printf("aucc_set_params(mode %x, enc %d, bits %d, chn %d, sr %ld)\n",
    425 	    mode, p->encoding, p->precision, p->channels, p->sample_rate);
    426 #endif
    427 
    428 	switch (p->encoding) {
    429 	case AUDIO_ENCODING_ULAW:
    430 	case AUDIO_ENCODING_SLINEAR:
    431 	case AUDIO_ENCODING_SLINEAR_BE:
    432 	case AUDIO_ENCODING_SLINEAR_LE:
    433 	case AUDIO_ENCODING_ULINEAR_BE:
    434 	case AUDIO_ENCODING_ULINEAR_LE:
    435 		break;
    436 
    437 	default:
    438 		return EINVAL;
    439 		/* NOTREADCHED */
    440 	}
    441 
    442 	if (p->precision != 8)
    443 		return EINVAL;
    444 
    445 	if ((p->channels<1) || (p->channels>4))
    446 		return(EINVAL);
    447 
    448 	sc->sc_channels = p->channels;
    449 	sc->sc_encoding = p->encoding;
    450 
    451 	q->encoding = p->encoding;
    452 	q->precision = p->precision;
    453 	q->channels = p->channels;
    454 	q->sample_rate = p->sample_rate;
    455 
    456 	return aucc_set_out_sr(addr, p->sample_rate);
    457 }
    458 
    459 int
    460 aucc_round_blocksize(addr, blk)
    461 	void *addr;
    462 	int blk;
    463 {
    464 
    465 
    466 	return blk>AUDIO_BUF_SIZE?AUDIO_BUF_SIZE:blk; /* round up to even size */
    467 }
    468 
    469 int
    470 aucc_set_out_port(addr, port) /* can set channels  */
    471 	void *addr;
    472 	int port;
    473 {
    474 	register struct aucc_softc *sc = addr;
    475 
    476 	/* port is mask for channels 0..3 */
    477 	if ((port<0)||(port>15))
    478 		return EINVAL;
    479 
    480 	sc->sc_channelmask=port;
    481 
    482 	return(0);
    483 }
    484 
    485 int
    486 aucc_get_out_port(addr)
    487 	void *addr;
    488 {
    489 	register struct aucc_softc *sc = addr;
    490 
    491 	return sc->sc_channelmask;
    492 }
    493 
    494 int
    495 aucc_set_in_port(addr, port)
    496 	void *addr;
    497 	int port;
    498 {
    499 	return(EINVAL); /* no input possible */
    500 
    501 }
    502 
    503 int
    504 aucc_get_in_port(addr)
    505 	void *addr;
    506 {
    507 	return(0);
    508 }
    509 
    510 int
    511 aucc_commit_settings(addr)
    512 	void *addr;
    513 {
    514 	register struct aucc_softc *sc = addr;
    515 	register int i;
    516 
    517 	DPRINTF(("sa_commit.\n"));
    518 
    519 	for (i=0;i<4;i++) {
    520 		custom.aud[i].vol=sc->sc_channel[i].nd_volume;
    521 		custom.aud[i].per=sc->sc_channel[i].nd_per;
    522 	}
    523 
    524 	DPRINTF(("commit done\n"));
    525 
    526 	return(0);
    527 }
    528 
    529 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
    530 static int masks2[4] = {1,2,4,8};
    531 
    532 int
    533 aucc_start_output(addr, p, cc, intr, arg)
    534 	void *addr;
    535 	void *p;
    536 	int cc;
    537 	void (*intr) __P((void *));
    538 	void *arg;
    539 {
    540 	struct aucc_softc *sc;
    541 	int mask;
    542 	int i,j,k;
    543 	u_short *dmap[4];
    544 	u_char *pp;
    545 
    546 
    547 	sc = addr;
    548 	mask = sc->sc_channelmask;
    549 
    550 	dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
    551 
    552 	DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
    553 
    554 	if (sc->sc_channels > 1)
    555 		mask &=masks[sc->sc_channels-1];
    556 		/* we use first sc_channels channels */
    557 	if (mask==0) /* active and used channels are disjoint */
    558 		return EINVAL;
    559 
    560 	for (i=0;i<4;i++) { /* channels available ? */
    561 		if ((masks2[i]&mask)&&(sc->sc_channel[i].nd_busy))
    562 			return EBUSY; /* channel is busy */
    563 		if (channel[i].isaudio==-1)
    564 			return EBUSY; /* system uses them */
    565 	}
    566 
    567 	/* enable interrupt on 1st channel */
    568 	for (i=j=0;i<AUCC_MAXINT;i++) {
    569 		if (masks2[i]&mask) {
    570 			DPRINTF(("first channel is %d\n",i));
    571 			j=i;
    572 			sc->sc_channel[i].nd_intr=intr;
    573 			sc->sc_channel[i].nd_intrdata=arg;
    574 			break;
    575 		}
    576 	}
    577 
    578 	DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
    579 		dmap[2], dmap[3], mask));
    580 
    581 	/* disable ints, dma for channels, until all parameters set */
    582 	/* XXX dont disable DMA! custom.dmacon=mask;*/
    583 	custom.intreq=mask<<INTB_AUD0;
    584 	custom.intena=mask<<INTB_AUD0;
    585 
    586 	/* copy data to dma buffer */
    587 
    588 
    589 	pp=(u_char *)p;
    590 
    591 	if (sc->sc_channels == 1) {
    592 		dmap[0] =
    593 		dmap[1] =
    594 		dmap[2] =
    595 		dmap[3] = sc->sc_channel[j].nd_dma;
    596 	} else {
    597 		for (k=0; k<4; k++) {
    598 			if (masks2[k+j]&mask)
    599 				dmap[k]=sc->sc_channel[k+j].nd_dma;
    600 		}
    601 	}
    602 
    603 	sc->sc_channel[j].nd_doublebuf ^= 1;
    604 	if (sc->sc_channel[j].nd_doublebuf) {
    605 		dmap[0] += AUDIO_BUF_SIZE/sizeof(u_short);
    606 		dmap[1] += AUDIO_BUF_SIZE/sizeof(u_short);
    607 		dmap[2] += AUDIO_BUF_SIZE/sizeof(u_short);
    608 		dmap[3] += AUDIO_BUF_SIZE/sizeof(u_short);
    609 	}
    610 
    611 	aucc_encode(sc->sc_encoding, sc->sc_channels, cc, pp, dmap);
    612 
    613 	/* dma buffers: we use same buffer 4 all channels */
    614 	/* write dma location and length */
    615 	for (i=k=0; i<4; i++) {
    616 		if (masks2[i] & mask) {
    617 			DPRINTF(("turning channel %d on\n",i));
    618 			/*  sc->sc_channel[i].nd_busy=1;*/
    619 			channel[i].isaudio=1;
    620 			channel[i].play_count=1;
    621 			channel[i].handler=NULL;
    622 			custom.aud[i].per=sc->sc_channel[i].nd_per;
    623 			custom.aud[i].vol=sc->sc_channel[i].nd_volume;
    624 			custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
    625 			custom.aud[i].len=cc/(sc->sc_channels*2);
    626 			sc->sc_channel[i].nd_mask=mask;
    627 			DPRINTF(("per is %d, vol is %d, len is %d\n",\
    628 			    sc->sc_channel[i].nd_per,
    629 			    sc->sc_channel[i].nd_volume, cc>>1));
    630 
    631 		}
    632 	}
    633 
    634 	channel[j].handler=aucc_inthdl;
    635 
    636 	/* enable ints */
    637 	custom.intena=INTF_SETCLR|INTF_INTEN| (masks2[j]<<INTB_AUD0);
    638 
    639 	DPRINTF(("enabled ints: 0x%x\n",(masks2[j]<<INTB_AUD0)));
    640 
    641 	/* enable dma */
    642 	custom.dmacon=DMAF_SETCLR|DMAF_MASTER|mask;
    643 
    644 	DPRINTF(("enabled dma, mask=0x%x\n",mask));
    645 
    646 	return(0);
    647 }
    648 
    649 /* ARGSUSED */
    650 int
    651 aucc_start_input(addr, p, cc, intr, arg)
    652 	void *addr;
    653 	void *p;
    654 	int cc;
    655 	void (*intr) __P((void *));
    656 	void *arg;
    657 {
    658 
    659 	return ENXIO; /* no input */
    660 }
    661 
    662 int
    663 aucc_halt_output(addr)
    664 	void *addr;
    665 {
    666 	register struct aucc_softc *sc = addr;
    667 	register int i;
    668 
    669 	/* XXX only halt, if input is also halted ?? */
    670 	/* stop dma, etc */
    671 	custom.intena = AUCC_ALLINTF;
    672 	custom.dmacon = AUCC_ALLDMAF;
    673 	/* mark every busy unit idle */
    674 	for (i=0;i<4;i++) {
    675 		sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0;
    676 		channel[i].isaudio=0;
    677 		channel[i].play_count=0;
    678 	}
    679 
    680 	return(0);
    681 }
    682 
    683 int
    684 aucc_halt_input(addr)
    685 	void *addr;
    686 {
    687 	/* no input */
    688 
    689 	return ENXIO;
    690 }
    691 
    692 int
    693 aucc_cont_output(addr)
    694 	void *addr;
    695 {
    696 	DPRINTF(("aucc_cont_output: never called, what should it do?!\n"));
    697 	/* reenable DMA XXX */
    698 	return ENXIO;
    699 }
    700 
    701 int
    702 aucc_cont_input(addr)
    703 	void *addr;
    704 {
    705 	DPRINTF(("aucc_cont_input: never called, what should it do?!\n"));
    706 	return(0);
    707 }
    708 
    709 int
    710 aucc_getdev(addr, retp)
    711         void *addr;
    712         struct audio_device *retp;
    713 {
    714         *retp = aucc_device;
    715         return 0;
    716 }
    717 
    718 int
    719 aucc_set_port(addr, cp)
    720 	void *addr;
    721 	mixer_ctrl_t *cp;
    722 {
    723 	register struct aucc_softc *sc = addr;
    724 	register int i,j;
    725 
    726 	DPRINTF(("aucc_set_port: port=%d", cp->dev));
    727 
    728 	switch (cp->type) {
    729 	case AUDIO_MIXER_SET:
    730 		if (cp->dev!=AUCC_CHANNELS)
    731 			return EINVAL;
    732 		i=cp->un.mask;
    733 		if ((i<1)||(i>15))
    734 			return EINVAL;
    735 		sc->sc_channelmask=i;
    736 		break;
    737 
    738 	case AUDIO_MIXER_VALUE:
    739 		i=cp->un.value.num_channels;
    740 		if ((i<1)||(i>4))
    741 			return EINVAL;
    742 
    743 #ifdef __XXXwhatsthat
    744 		if (cp->dev!=AUCC_VOLUME)
    745 			return EINVAL;
    746 #endif
    747 
    748 		/* set volume for channel 0..i-1 */
    749 		if (i>1)
    750 			for (j=0;j<i;j++)
    751 	 			sc->sc_channel[j].nd_volume =
    752 				    cp->un.value.level[j]>>2;
    753 		else if (sc->sc_channels > 1)
    754 			for (j=0; j<sc->sc_channels; j++)
    755 	 			sc->sc_channel[j].nd_volume =
    756 				    cp->un.value.level[0]>>2;
    757 		else
    758 			for (j=0; j<4; j++)
    759 	 			sc->sc_channel[j].nd_volume =
    760 				    cp->un.value.level[0]>>2;
    761 		break;
    762 
    763 	default:
    764 		return EINVAL;
    765 		break;
    766 	}
    767 	return 0;
    768 }
    769 
    770 
    771 int
    772 aucc_get_port(addr, cp)
    773 	void *addr;
    774 	mixer_ctrl_t *cp;
    775 {
    776 	register struct aucc_softc *sc = addr;
    777 	register int i,j;
    778 
    779 	DPRINTF(("aucc_get_port: port=%d", cp->dev));
    780 
    781 	switch (cp->type) {
    782 	case AUDIO_MIXER_SET:
    783 		if (cp->dev!=AUCC_CHANNELS)
    784 			return EINVAL;
    785 		cp->un.mask=sc->sc_channelmask;
    786 		break;
    787 
    788 	case AUDIO_MIXER_VALUE:
    789 		i = cp->un.value.num_channels;
    790 		if ((i<1)||(i>4))
    791 			return EINVAL;
    792 
    793 		for (j=0;j<i;j++)
    794 			cp->un.value.level[j] =
    795 			    (sc->sc_channel[j].nd_volume<<2) +
    796 			    (sc->sc_channel[j].nd_volume>>4);
    797 		break;
    798 
    799 	default:
    800 		return EINVAL;
    801 	}
    802 	return 0;
    803 }
    804 
    805 
    806 int
    807 aucc_get_props(addr)
    808 	void *addr;
    809 {
    810 	return 0;
    811 }
    812 
    813 int
    814 aucc_query_devinfo(addr, dip)
    815 	void *addr;
    816 	register mixer_devinfo_t *dip;
    817 {
    818 	register int i;
    819 
    820 	switch(dip->index) {
    821 	case AUCC_CHANNELS:
    822 		dip->type = AUDIO_MIXER_SET;
    823 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    824 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    825                 strcpy(dip->label.name, AudioNspeaker);
    826 		for (i=0;i<16;i++) {
    827 			sprintf(dip->un.s.member[i].label.name,
    828 			    "channelmask%d", i);
    829 			dip->un.s.member[i].mask = i;
    830 		}
    831 		dip->un.s.num_mem = 16;
    832 		break;
    833 
    834 	case AUCC_VOLUME:
    835 		dip->type = AUDIO_MIXER_VALUE;
    836 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    837 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    838 		strcpy(dip->label.name, AudioNspeaker);
    839 		dip->un.v.num_channels = 4;
    840 		strcpy(dip->un.v.units.name, AudioNvolume);
    841 		break;
    842 
    843 	case AUCC_OUTPUT_CLASS:
    844 		dip->type = AUDIO_MIXER_CLASS;
    845 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    846 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    847 		strcpy(dip->label.name, AudioCOutputs);
    848 		break;
    849 	default:
    850 		return ENXIO;
    851 		/*NOTREACHED*/
    852 	}
    853 
    854 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
    855 
    856 	return(0);
    857 }
    858 
    859 
    860 /* audio int handler */
    861 void
    862 aucc_inthdl(int ch)
    863 {
    864 	register int i;
    865 	register int mask=aucc->sc_channel[ch].nd_mask;
    866 
    867 	/* for all channels in this maskgroup:
    868 	   disable dma, int
    869 	   mark idle */
    870 	DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask));
    871 
    872 	custom.intreq=mask<<INTB_AUD0; /* clear request */
    873 	/* XXX: maybe we can leave ints and/or DMA on, if another sample has to be played?*/
    874 	custom.intena=mask<<INTB_AUD0;
    875 	/*
    876 	 * XXX custom.dmacon=mask; NO!!!
    877 	 */
    878 	for (i=0;i<4;i++) {
    879 		if (masks2[i]&&mask) {
    880 			DPRINTF(("marking channel %d idle\n",i));
    881 			aucc->sc_channel[i].nd_busy=0;
    882 			aucc->sc_channel[i].nd_mask=0;
    883 			channel[i].isaudio=channel[i].play_count=0;
    884 		}
    885 	}
    886 
    887 	/* call handler */
    888 	if (aucc->sc_channel[ch].nd_intr) {
    889 		DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
    890 		(*(aucc->sc_channel[ch].nd_intr))(aucc->sc_channel[ch].nd_intrdata);
    891 	}
    892 	else DPRINTF(("zero int handler\n"));
    893 	DPRINTF(("ints done\n"));
    894 }
    895 
    896 
    897 
    898 
    899 /* transform frequency to period, adjust bounds */
    900 static u_int
    901 freqtoper(u_int freq)
    902 {
    903 	u_int per=eclockfreq*5/freq;
    904 
    905 	if (per<124)
    906 		per=124; /* must have at least 124 ticks between samples */
    907 
    908 	return per;
    909 }
    910 
    911 /* transform period to frequency */
    912 static u_int
    913 pertofreq(u_int per)
    914 {
    915 	u_int freq=eclockfreq*5/per;
    916 
    917 
    918 	return freq;
    919 }
    920 
    921 
    922 
    923 void
    924 aucc_encode(enc, channels, i, p, dmap)
    925 	int enc, channels, i;
    926 	u_char *p;
    927 	u_short **dmap;
    928 {
    929 	char *q, *r, *s, *t;
    930 	int off;
    931 	u_char *tab;
    932 
    933 #ifdef AUCCDEBUG
    934 	static int debctl = 6;
    935 #endif
    936 
    937 	off = 0;
    938 	tab = NULL;
    939 
    940 #ifdef AUCCDEBUG
    941 	if (--debctl >= 0)
    942 		printf("Enc: enc %d, chan %d, dmap %p %p %p %p\n",
    943 		    enc, channels, dmap[0], dmap[1], dmap[2], dmap[3]);
    944 #endif
    945 
    946 	switch (enc) {
    947 	case AUDIO_ENCODING_ULAW:
    948 		tab=ulaw_to_lin;
    949 		break;
    950 	case AUDIO_ENCODING_ULINEAR_BE:
    951 	case AUDIO_ENCODING_ULINEAR_LE:
    952 		off=-128;
    953 		break;
    954 	case AUDIO_ENCODING_SLINEAR_BE:
    955 	case AUDIO_ENCODING_SLINEAR_LE:
    956 		break;
    957 	default:
    958 		return;
    959 	}
    960 
    961 	q = (char *)dmap[0];
    962 	r = (char *)dmap[1];
    963 	s = (char *)dmap[2];
    964 	t = (char *)dmap[3];
    965 
    966 	if (tab)
    967 		while (i) {
    968 			switch (channels) {
    969 			case 4: *t++ = tab[*p++];
    970 			case 3: *s++ = tab[*p++];
    971 			case 2: *r++ = tab[*p++];
    972 			case 1: *q++ = tab[*p++];
    973 			}
    974 			i -= channels;
    975 		}
    976 	else
    977 		while (i) {
    978 			switch (channels) {
    979 			case 4: *t++ = *p++ + off;
    980 			case 3: *s++ = *p++ + off;
    981 			case 2: *r++ = *p++ + off;
    982 			case 1: *q++ = *p++ + off;
    983 			}
    984 			i -= channels;
    985 		}
    986 
    987 }
    988 
    989 #endif /* NAUCC > 0 */
    990