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