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