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