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