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