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