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