Home | History | Annotate | Line # | Download | only in dev
aucc.c revision 1.6
      1 /*	$NetBSD: aucc.c,v 1.6 1997/06/21 22:46:43 kleink 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 #ifdef LEV6_DEFER
     37 #error Not prepared yet for coexistance with LEV6_DEFER.
     38 #endif
     39 
     40 #include <sys/param.h>
     41 #include <sys/systm.h>
     42 #include <sys/errno.h>
     43 #include <sys/ioctl.h>
     44 #include <sys/device.h>
     45 #include <sys/proc.h>
     46 #include <machine/cpu.h>
     47 
     48 #include <sys/audioio.h>
     49 #include <dev/audio_if.h>
     50 #include <amiga/amiga/cc.h>
     51 #include <amiga/amiga/custom.h>
     52 #include <amiga/amiga/device.h>
     53 #include <amiga/dev/auccvar.h>
     54 
     55 #ifdef AUDIO_DEBUG
     56 /*extern printf __P((const char *,...));*/
     57 int     auccdebug = 1;
     58 #define DPRINTF(x)      if (auccdebug) printf x
     59 #else
     60 #define DPRINTF(x)
     61 #endif
     62 
     63 #ifdef splaudio
     64 #undef splaudio
     65 #endif
     66 
     67 #define splaudio() spl4();
     68 
     69 /* clock frequency.. */
     70 extern int eclockfreq;
     71 
     72 
     73 /* hw audio ch */
     74 extern struct audio_channel channel[4];
     75 
     76 
     77 /*
     78  * Software state.
     79  */
     80 struct aucc_softc {
     81 	struct	device sc_dev;		/* base device */
     82 
     83 	int	sc_open;		/* single use device */
     84 	aucc_data_t sc_channel[4];	/* per channel freq, ... */
     85 	u_int	sc_encoding;		/* encoding AUDIO_ENCODING_.*/
     86 	int	sc_channels;		/* # of channels used */
     87 
     88 	int	sc_intrcnt;		/* interrupt count */
     89 	int	sc_channelmask;  	/* which channels are used ? */
     90 };
     91 
     92 /* interrupt interfaces */
     93 void aucc_inthdl __P((int));
     94 
     95 /* forward declarations */
     96 static int init_aucc __P((struct aucc_softc *));
     97 static u_int freqtoper  __P((u_int));
     98 static u_int pertofreq  __P((u_int));
     99 
    100 /* autoconfiguration driver */
    101 void	auccattach __P((struct device *, struct device *, void *));
    102 int	auccmatch __P((struct device *, struct cfdata *, void *));
    103 
    104 struct cfattach aucc_ca = {
    105 	sizeof(struct aucc_softc),
    106 	auccmatch,
    107 	auccattach
    108 };
    109 
    110 struct	cfdriver aucc_cd = {
    111 	NULL, "aucc", DV_DULL, NULL, 0
    112 };
    113 
    114 struct audio_device aucc_device = {
    115 	"Amiga-audio",
    116 	"x",
    117 	"aucc"
    118 };
    119 
    120 
    121 struct aucc_softc *aucc=NULL;
    122 
    123 
    124 unsigned char ulaw_to_lin[] = {
    125 	0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
    126 	0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
    127 	0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf,
    128 	0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf,
    129 	0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
    130 	0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
    131 	0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4,
    132 	0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8,
    133 	0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
    134 	0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
    135 	0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd,
    136 	0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe,
    137 	0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
    138 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    139 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    140 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
    141 	0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61,
    142 	0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, 0x45, 0x41,
    143 	0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30,
    144 	0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20,
    145 	0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17,
    146 	0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f,
    147 	0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b,
    148 	0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07,
    149 	0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05,
    150 	0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
    151 	0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02,
    152 	0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
    153 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    154 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    155 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    156 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    157 };
    158 
    159 /*
    160  * Define our interface to the higher level audio driver.
    161  */
    162 int	aucc_open __P((dev_t, int));
    163 void	aucc_close __P((void *));
    164 int	aucc_set_out_sr __P((void *, u_long));
    165 int	aucc_query_encoding __P((void *, struct audio_encoding *));
    166 int	aucc_set_encoding __P((void *, u_int));
    167 int	aucc_get_encoding __P((void *));
    168 int	aucc_set_precision __P((void *, u_int));
    169 int	aucc_get_precision __P((void *));
    170 int	aucc_set_channels __P((void *, int));
    171 int	aucc_get_channels __P((void *));
    172 int	aucc_round_blocksize __P((void *, int));
    173 int	aucc_set_out_port __P((void *, int));
    174 int	aucc_get_out_port __P((void *));
    175 int	aucc_set_in_port __P((void *, int));
    176 int	aucc_get_in_port __P((void *));
    177 int	aucc_commit_settings __P((void *));
    178 int	aucc_start_output __P((void *, void *, int, void (*)(void *),
    179 				  void *));
    180 int	aucc_start_input __P((void *, void *, int, void (*)(void *),
    181 				 void *));
    182 int	aucc_halt_output __P((void *));
    183 int	aucc_halt_input __P((void *));
    184 int	aucc_cont_output __P((void *));
    185 int	aucc_cont_input __P((void *));
    186 int	aucc_getdev __P((void *, struct audio_device *));
    187 int	aucc_setfd __P((void *, int));
    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, u_char *, char *, int));
    192 int	aucc_set_params __P((void *, int, struct audio_params *,
    193 	    struct audio_params *));
    194 
    195 struct audio_hw_if sa_hw_if = {
    196 	aucc_open,
    197 	aucc_close,
    198 	NULL,
    199 	aucc_query_encoding,
    200 	aucc_set_params,
    201 	aucc_round_blocksize,
    202 	aucc_set_out_port,
    203 	aucc_get_out_port,
    204 	aucc_set_in_port,
    205 	aucc_get_in_port,
    206 	aucc_commit_settings,
    207 	aucc_start_output,
    208 	aucc_start_input,
    209 	aucc_halt_output,
    210 	aucc_halt_input,
    211 	aucc_cont_output,
    212 	aucc_cont_input,
    213 	NULL,
    214 	aucc_getdev,
    215 	aucc_setfd,
    216 	aucc_set_port,
    217 	aucc_get_port,
    218 	aucc_query_devinfo,
    219 	0,
    220 	0
    221 };
    222 
    223 /* autoconfig routines */
    224 
    225 int
    226 auccmatch(pdp, cfp, aux)
    227 	struct device *pdp;
    228 	struct cfdata *cfp;
    229 	void *aux;
    230 {
    231 	if (matchname((char *)aux, "aucc") &&
    232 #ifdef DRACO
    233 	    !is_draco() &&
    234 #endif
    235 	    (cfp->cf_unit == 0))
    236 		return 1;
    237 
    238 	return 0;
    239 }
    240 
    241 /*
    242  * Audio chip found.
    243  */
    244 void
    245 auccattach(parent, self, args)
    246 	struct device *parent, *self;
    247 	void *args;
    248 {
    249 	register struct aucc_softc *sc = (struct aucc_softc *)self;
    250 	register int i;
    251 
    252 	printf("\n");
    253 
    254 	if((i=init_aucc(sc))) {
    255 		printf("audio: no chipmem\n");
    256 		return;
    257 	}
    258 
    259 	if (audio_hardware_attach(&sa_hw_if, sc) != 0)
    260 		printf("audio: could not attach to audio pseudo-device driver\n");
    261 	/* XXX: no way to return error, if init fails */
    262 }
    263 
    264 
    265 static int
    266 init_aucc(sc)
    267 	struct aucc_softc *sc;
    268 {
    269 	register int i, err=0;
    270 
    271 	/* init values per channel */
    272  	for (i=0;i<4;i++) {
    273 		sc->sc_channel[i].nd_freq=8000;
    274 		sc->sc_channel[i].nd_per=freqtoper(8000);
    275 		sc->sc_channel[i].nd_busy=0;
    276 		sc->sc_channel[i].nd_dma=alloc_chipmem(AUDIO_BUF_SIZE*2);
    277 		if (sc->sc_channel[i].nd_dma==NULL)
    278 			err=1;
    279 	 	sc->sc_channel[i].nd_dmalength=0;
    280 		sc->sc_channel[i].nd_volume=64;
    281 		sc->sc_channel[i].nd_intr=NULL;
    282 		sc->sc_channel[i].nd_intrdata=NULL;
    283 		DPRINTF(("dma buffer for channel %d is %p\n", i,
    284 		    sc->sc_channel[i].nd_dma));
    285 
    286 	}
    287 
    288 	if (err) {
    289 		for(i=0;i<4;i++)
    290 			if (sc->sc_channel[i].nd_dma)
    291 				free_chipmem(sc->sc_channel[i].nd_dma);
    292 	}
    293 
    294 	sc->sc_channels=4;
    295 	sc->sc_channelmask=0xf;
    296 
    297 	/* clear interrupts and dma: */
    298 	custom.intena = INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3;
    299 	custom.dmacon = DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3;
    300 
    301 	sc->sc_encoding=AUDIO_ENCODING_ULAW;
    302 
    303 	return err;
    304 
    305 }
    306 
    307 int
    308 aucc_open(dev, flags)
    309 	dev_t dev;
    310 	int flags;
    311 {
    312 	register struct aucc_softc *sc;
    313 	int unit = AUDIOUNIT(dev);
    314 	register int i;
    315 
    316 	DPRINTF(("sa_open: unit %d\n",unit));
    317 
    318 	if (unit >= aucc_cd.cd_ndevs)
    319 		return (ENODEV);
    320 	if ((sc = aucc_cd.cd_devs[unit]) == NULL)
    321 		return (ENXIO);
    322 	if (sc->sc_open)
    323 		return (EBUSY);
    324 	sc->sc_open = 1;
    325 	for (i=0;i<4;i++) {
    326 		sc->sc_channel[i].nd_intr=NULL;
    327 		sc->sc_channel[i].nd_intrdata=NULL;
    328 	}
    329 	aucc=sc;
    330 
    331 	sc->sc_channels=4;
    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_LINEAR;
    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 	if (mode == AUMODE_RECORD)
    417 		return 0 /*ENXIO*/;
    418 
    419 	switch (p->encoding) {
    420 	case AUDIO_ENCODING_ULAW:
    421 	case AUDIO_ENCODING_LINEAR:
    422 	case AUDIO_ENCODING_ULINEAR:
    423 		break;
    424 	default:
    425 		return EINVAL;
    426 		/* NOTREADCHED */
    427 	}
    428 
    429 	if (p->precision != 8)
    430 		return EINVAL;
    431 
    432 	if ((p->channels<1) || (p->channels>4))
    433 		return(EINVAL);
    434 
    435 	q->encoding = p->encoding;
    436 	q->precision = p->precision;
    437 	q->channels = p->channels;
    438 
    439 	aucc_set_out_sr(addr, p->sample_rate);
    440 	return 0;
    441 }
    442 
    443 int
    444 aucc_get_encoding(addr)
    445 	void *addr;
    446 {
    447 	return ((struct aucc_softc *)addr)->sc_encoding;
    448 }
    449 
    450 int
    451 aucc_get_precision(addr)
    452 	void *addr;
    453 {
    454 	return(8);
    455 }
    456 
    457 int
    458 aucc_get_channels(addr)
    459 	void *addr;
    460 {
    461 	return ((struct aucc_softc *)addr)->sc_channels;
    462 }
    463 
    464 int
    465 aucc_round_blocksize(addr, blk)
    466 	void *addr;
    467 	int blk;
    468 {
    469 
    470 
    471 	return blk>AUDIO_BUF_SIZE?AUDIO_BUF_SIZE:blk; /* round up to even size */
    472 }
    473 
    474 int
    475 aucc_set_out_port(addr, port) /* can set channels  */
    476 	void *addr;
    477 	int port;
    478 {
    479 	register struct aucc_softc *sc = addr;
    480 
    481 	/* port is mask for channels 0..3 */
    482 	if ((port<0)||(port>15))
    483 		return EINVAL;
    484 
    485 	sc->sc_channelmask=port;
    486 
    487 	return(0);
    488 }
    489 
    490 int
    491 aucc_get_out_port(addr)
    492 	void *addr;
    493 {
    494 	register struct aucc_softc *sc = addr;
    495 
    496 	return sc->sc_channelmask;
    497 }
    498 
    499 int
    500 aucc_set_in_port(addr, port)
    501 	void *addr;
    502 	int port;
    503 {
    504 	return(EINVAL); /* no input possible */
    505 
    506 }
    507 
    508 int
    509 aucc_get_in_port(addr)
    510 	void *addr;
    511 {
    512 	return(0);
    513 }
    514 
    515 int
    516 aucc_commit_settings(addr)
    517 	void *addr;
    518 {
    519 	register struct aucc_softc *sc = addr;
    520 	register int i;
    521 
    522 	DPRINTF(("sa_commit.\n"));
    523 
    524 	for (i=0;i<4;i++) {
    525 		custom.aud[i].vol=sc->sc_channel[i].nd_volume;
    526 		custom.aud[i].per=sc->sc_channel[i].nd_per;
    527 	}
    528 
    529 	DPRINTF(("commit done\n"));
    530 
    531 	return(0);
    532 }
    533 
    534 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
    535 static int masks2[4] = {1,2,4,8};
    536 
    537 int
    538 aucc_start_output(addr, p, cc, intr, arg)
    539 	void *addr;
    540 	void *p;
    541 	int cc;
    542 	void (*intr) __P((void *));
    543 	void *arg;
    544 {
    545 	register struct aucc_softc *sc = addr;
    546 	register int mask=sc->sc_channelmask;
    547 	register int i,j=0;
    548 	register u_short *dmap;
    549 	register u_char *pp, *to;
    550 
    551 
    552 	dmap=NULL;
    553 
    554 	DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
    555 
    556 	mask &=masks[sc->sc_channels-1]; /* 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=0;i<4;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 			dmap=sc->sc_channel[i].nd_dma;
    575 			break;
    576 		}
    577 	}
    578 
    579 	DPRINTF(("dmap is %p, mask=0x%x\n",dmap,mask));
    580 
    581 	/* copy data to dma buffer */
    582 
    583 
    584 	to=(u_char *)dmap;
    585 	pp=(u_char *)p;
    586 	aucc_encode(sc->sc_encoding, pp, to, cc);
    587 
    588 
    589 	/* disable ints, dma for channels, until all parameters set */
    590 	/* XXX custom.dmacon=mask;*/
    591 	custom.intreq=mask<<7;
    592 	custom.intena=mask<<7;
    593 
    594 
    595 	/* dma buffers: we use same buffer 4 all channels */
    596 	/* write dma location and length */
    597 	for (i=0;i<4;i++) {
    598 		if (masks2[i]&mask) {
    599 			DPRINTF(("turning channel %d on\n",i));
    600 			/*  sc->sc_channel[i].nd_busy=1;*/
    601 			channel[i].isaudio=1;
    602 			channel[i].play_count=1;
    603 			channel[i].handler=NULL;
    604 			custom.aud[i].per=sc->sc_channel[i].nd_per;
    605 			custom.aud[i].vol=sc->sc_channel[i].nd_volume;
    606 			if (custom.aud[i].lc==PREP_DMA_MEM(dmap))
    607 				custom.aud[i].lc =
    608 				    PREP_DMA_MEM(dmap+AUDIO_BUF_SIZE);
    609 			else
    610 				custom.aud[i].lc = PREP_DMA_MEM(dmap);
    611 
    612 			custom.aud[i].len=cc>>1;
    613 			sc->sc_channel[i].nd_mask=mask;
    614 			DPRINTF(("per is %d, vol is %d, len is %d\n",\
    615 sc->sc_channel[i].nd_per, sc->sc_channel[i].nd_volume, cc>>1));
    616 
    617 		}
    618 	}
    619 
    620 	channel[j].handler=aucc_inthdl;
    621 
    622 	/* enable ints */
    623 	custom.intena=INTF_SETCLR|INTF_INTEN| (masks2[j]<<7);
    624 
    625 	DPRINTF(("enabled ints: 0x%x\n",(masks2[j]<<7)));
    626 
    627 	/* enable dma */
    628 	custom.dmacon=DMAF_SETCLR|DMAF_MASTER|mask;
    629 
    630 	DPRINTF(("enabled dma, mask=0x%x\n",mask));
    631 
    632 	return(0);
    633 }
    634 
    635 /* ARGSUSED */
    636 int
    637 aucc_start_input(addr, p, cc, intr, arg)
    638 	void *addr;
    639 	void *p;
    640 	int cc;
    641 	void (*intr) __P((void *));
    642 	void *arg;
    643 {
    644 
    645 	return ENXIO; /* no input */
    646 }
    647 
    648 int
    649 aucc_halt_output(addr)
    650 	void *addr;
    651 {
    652 	register struct aucc_softc *sc = addr;
    653 	register int i;
    654 
    655 	/* XXX only halt, if input is also halted ?? */
    656 	/* stop dma, etc */
    657 	custom.intena=INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3;
    658 	custom.dmacon = DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3;
    659 	/* mark every busy unit idle */
    660 	for (i=0;i<4;i++) {
    661 		sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0;
    662 		channel[i].isaudio=0;
    663 		channel[i].play_count=0;
    664 	}
    665 
    666 	return(0);
    667 }
    668 
    669 int
    670 aucc_halt_input(addr)
    671 	void *addr;
    672 {
    673 	/* no input */
    674 
    675 	return ENXIO;
    676 }
    677 
    678 int
    679 aucc_cont_output(addr)
    680 	void *addr;
    681 {
    682 	DPRINTF(("aucc_cont_output: never called, what should it do?!\n"));
    683 	/* reenable DMA XXX */
    684 	return ENXIO;
    685 }
    686 
    687 int
    688 aucc_cont_input(addr)
    689 	void *addr;
    690 {
    691 	DPRINTF(("aucc_cont_input: never called, what should it do?!\n"));
    692 	return(0);
    693 }
    694 
    695 int
    696 aucc_getdev(addr, retp)
    697         void *addr;
    698         struct audio_device *retp;
    699 {
    700         *retp = aucc_device;
    701         return 0;
    702 }
    703 
    704 int
    705 aucc_setfd(addr, flag)
    706         void *addr;
    707         int flag;
    708 {
    709         return flag?EINVAL:0; /* Always half-duplex */
    710 }
    711 
    712 int
    713 aucc_set_port(addr, cp)
    714 	void *addr;
    715 	mixer_ctrl_t *cp;
    716 {
    717 	register struct aucc_softc *sc = addr;
    718 	register int i,j;
    719 
    720 	DPRINTF(("aucc_set_port: port=%d", cp->dev));
    721 
    722 	switch (cp->type) {
    723 	case AUDIO_MIXER_SET:
    724 		if (cp->dev!=AUCC_CHANNELS)
    725 			return EINVAL;
    726 		i=cp->un.mask;
    727 		if ((i<1)||(i>15))
    728 			return EINVAL;
    729 		sc->sc_channelmask=i;
    730 		break;
    731 
    732 	case AUDIO_MIXER_VALUE:
    733 		i=cp->un.value.num_channels;
    734 		if ((i<1)||(i>4))
    735 			return EINVAL;
    736 
    737 		if (cp->dev!=AUCC_VOLUME)
    738 			return EINVAL;
    739 
    740 		/* set volume for channel 0..i-1 */
    741 		for (j=0;j<i;j++)
    742 	 		sc->sc_channel[j].nd_volume=cp->un.value.level[j]>>2;
    743 			break;
    744 
    745 	default:
    746 		return EINVAL;
    747 		break;
    748 	}
    749 	return 0;
    750 }
    751 
    752 
    753 int
    754 aucc_get_port(addr, cp)
    755 	void *addr;
    756 	mixer_ctrl_t *cp;
    757 {
    758 	register struct aucc_softc *sc = addr;
    759 	register int i,j;
    760 
    761 	DPRINTF(("aucc_get_port: port=%d", cp->dev));
    762 
    763 	switch (cp->type) {
    764 	case AUDIO_MIXER_SET:
    765 		if (cp->dev!=AUCC_CHANNELS)
    766 			return EINVAL;
    767 		cp->un.mask=sc->sc_channelmask;
    768 		break;
    769 
    770 	case AUDIO_MIXER_VALUE:
    771 		i = cp->un.value.num_channels;
    772 		if ((i<1)||(i>4))
    773 			return EINVAL;
    774 
    775 		for (j=0;j<i;j++)
    776 			cp->un.value.level[j]=sc->sc_channel[j].nd_volume<<2;
    777 		break;
    778 
    779 	default:
    780 		return EINVAL;
    781 	}
    782 	return 0;
    783 }
    784 
    785 
    786 int
    787 aucc_query_devinfo(addr, dip)
    788 	void *addr;
    789 	register mixer_devinfo_t *dip;
    790 {
    791 	register int i;
    792 
    793 	switch(dip->index) {
    794 	case AUCC_CHANNELS:
    795 		dip->type = AUDIO_MIXER_SET;
    796 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    797 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    798                 strcpy(dip->label.name, AudioNspeaker);
    799 		for (i=0;i<16;i++) {
    800 			sprintf(dip->un.s.member[i].label.name,
    801 			    "channelmask%d", i);
    802 			dip->un.s.member[i].mask = i;
    803 		}
    804 		dip->un.s.num_mem = 16;
    805 		break;
    806 
    807 	case AUCC_VOLUME:
    808 		dip->type = AUDIO_MIXER_VALUE;
    809 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    810 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    811 		strcpy(dip->label.name, AudioNspeaker);
    812 		dip->un.v.num_channels = 4;
    813 		strcpy(dip->un.v.units.name, AudioNvolume);
    814 		break;
    815 
    816 	case AUCC_OUTPUT_CLASS:
    817 		dip->type = AUDIO_MIXER_CLASS;
    818 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    819 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    820 		strcpy(dip->label.name, AudioCOutputs);
    821 		break;
    822 	default:
    823 		return ENXIO;
    824 		/*NOTREACHED*/
    825 	}
    826 
    827 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
    828 
    829 	return(0);
    830 }
    831 
    832 
    833 /* audio int handler */
    834 void
    835 aucc_inthdl(int ch)
    836 {
    837 	register int i;
    838 	register int mask=aucc->sc_channel[ch].nd_mask;
    839 
    840 	/* for all channels in this maskgroup:
    841 	   disable dma, int
    842 	   mark idle */
    843 	DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask));
    844 
    845 	custom.intreq=mask<<7; /* clear request */
    846 	/* XXX: maybe we can leave ints and/or DMA on, if another sample has to be played?*/
    847 	custom.intena=mask<<7;
    848 	/*
    849 	 * XXX custom.dmacon=mask; NO!!!
    850 	 */
    851 	for (i=0;i<4;i++) {
    852 		if (masks2[i]&&mask) {
    853 			DPRINTF(("marking channel %d idle\n",i));
    854 			aucc->sc_channel[i].nd_busy=0;
    855 			aucc->sc_channel[i].nd_mask=0;
    856 			channel[i].isaudio=channel[i].play_count=0;
    857 		}
    858 	}
    859 
    860 	/* call handler */
    861 	if (aucc->sc_channel[ch].nd_intr) {
    862 		DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
    863 		(*(aucc->sc_channel[ch].nd_intr))(aucc->sc_channel[ch].nd_intrdata);
    864 	}
    865 	else DPRINTF(("zero int handler\n"));
    866 	DPRINTF(("ints done\n"));
    867 }
    868 
    869 
    870 
    871 
    872 /* transform frequency to period, adjust bounds */
    873 static u_int
    874 freqtoper(u_int freq)
    875 {
    876 	u_int per=eclockfreq*5/freq;
    877 
    878 	if (per<124)
    879 		per=124; /* must have at least 124 ticks between samples */
    880 
    881 	return per;
    882 }
    883 
    884 /* transform period to frequency */
    885 static u_int
    886 pertofreq(u_int per)
    887 {
    888 	u_int freq=eclockfreq*5/per;
    889 
    890 
    891 	return freq;
    892 }
    893 
    894 
    895 
    896 void
    897 aucc_encode(enc, p, q, i)
    898 	int enc;
    899 	u_char *p;
    900 	char *q;
    901 	int i;
    902 {
    903 	int off=0;
    904 	u_char *tab=NULL;
    905 
    906 
    907 
    908 	switch (enc) {
    909 	case AUDIO_ENCODING_ULAW:
    910 		tab=ulaw_to_lin;
    911 		break;
    912 	case AUDIO_ENCODING_ULINEAR:
    913 		off=-128;
    914 		/* FALLTHROUGH */
    915 	case AUDIO_ENCODING_LINEAR:
    916 		break;
    917 	default:
    918 		return;
    919 	}
    920 
    921 	if (tab)
    922 		while (i--)
    923 			*q++ = tab[*p++];
    924 	else
    925 		while (i--)
    926 			*q++ = *p++ + off;
    927 
    928 }
    929 
    930 #endif /* NAUCC > 0 */
    931