Home | History | Annotate | Line # | Download | only in dev
aucc.c revision 1.19
      1 /*	$NetBSD: aucc.c,v 1.19 1997/10/11 12:43:51 mycroft 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, int,
    193 	    struct audio_params *, 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, AudioEslinear);
    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, setmode, usemode, p, r)
    410 	void *addr;
    411 	int setmode, usemode;
    412 	struct  audio_params *p, *r;
    413 {
    414 	struct aucc_softc *sc = addr;
    415 
    416 	/* if (setmode & AUMODE_RECORD)
    417 		return 0 ENXIO*/;
    418 
    419 #ifdef AUCCDEBUG
    420 	printf("aucc_set_params(setmode 0x%x, usemode 0x%x, enc %d, bits %d, chn %d, sr %ld)\n",
    421 	    setmode, usemode, p->encoding, p->precision, p->channels, p->sample_rate);
    422 #endif
    423 
    424 	switch (p->encoding) {
    425 	case AUDIO_ENCODING_ULAW:
    426 	case AUDIO_ENCODING_SLINEAR:
    427 	case AUDIO_ENCODING_SLINEAR_BE:
    428 	case AUDIO_ENCODING_SLINEAR_LE:
    429 	case AUDIO_ENCODING_ULINEAR_BE:
    430 	case AUDIO_ENCODING_ULINEAR_LE:
    431 		break;
    432 
    433 	default:
    434 		return EINVAL;
    435 		/* NOTREADCHED */
    436 	}
    437 
    438 	if (p->precision != 8)
    439 		return EINVAL;
    440 
    441 	if ((p->channels<1) || (p->channels>4))
    442 		return(EINVAL);
    443 
    444 	sc->sc_channels = p->channels;
    445 	sc->sc_encoding = p->encoding;
    446 
    447 	return aucc_set_out_sr(addr, p->sample_rate);
    448 }
    449 
    450 int
    451 aucc_round_blocksize(addr, blk)
    452 	void *addr;
    453 	int blk;
    454 {
    455 
    456 
    457 	return blk>AUDIO_BUF_SIZE?AUDIO_BUF_SIZE:blk; /* round up to even size */
    458 }
    459 
    460 int
    461 aucc_set_out_port(addr, port) /* can set channels  */
    462 	void *addr;
    463 	int port;
    464 {
    465 	register struct aucc_softc *sc = addr;
    466 
    467 	/* port is mask for channels 0..3 */
    468 	if ((port<0)||(port>15))
    469 		return EINVAL;
    470 
    471 	sc->sc_channelmask=port;
    472 
    473 	return(0);
    474 }
    475 
    476 int
    477 aucc_get_out_port(addr)
    478 	void *addr;
    479 {
    480 	register struct aucc_softc *sc = addr;
    481 
    482 	return sc->sc_channelmask;
    483 }
    484 
    485 int
    486 aucc_set_in_port(addr, port)
    487 	void *addr;
    488 	int port;
    489 {
    490 	return(EINVAL); /* no input possible */
    491 
    492 }
    493 
    494 int
    495 aucc_get_in_port(addr)
    496 	void *addr;
    497 {
    498 	return(0);
    499 }
    500 
    501 int
    502 aucc_commit_settings(addr)
    503 	void *addr;
    504 {
    505 	register struct aucc_softc *sc = addr;
    506 	register int i;
    507 
    508 	DPRINTF(("sa_commit.\n"));
    509 
    510 	for (i=0;i<4;i++) {
    511 		custom.aud[i].vol=sc->sc_channel[i].nd_volume;
    512 		custom.aud[i].per=sc->sc_channel[i].nd_per;
    513 	}
    514 
    515 	DPRINTF(("commit done\n"));
    516 
    517 	return(0);
    518 }
    519 
    520 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
    521 static int masks2[4] = {1,2,4,8};
    522 
    523 int
    524 aucc_start_output(addr, p, cc, intr, arg)
    525 	void *addr;
    526 	void *p;
    527 	int cc;
    528 	void (*intr) __P((void *));
    529 	void *arg;
    530 {
    531 	struct aucc_softc *sc;
    532 	int mask;
    533 	int i,j,k;
    534 	u_short *dmap[4];
    535 	u_char *pp;
    536 
    537 
    538 	sc = addr;
    539 	mask = sc->sc_channelmask;
    540 
    541 	dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
    542 
    543 	DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
    544 
    545 	if (sc->sc_channels > 1)
    546 		mask &=masks[sc->sc_channels-1];
    547 		/* we use first sc_channels channels */
    548 	if (mask==0) /* active and used channels are disjoint */
    549 		return EINVAL;
    550 
    551 	for (i=0;i<4;i++) { /* channels available ? */
    552 		if ((masks2[i]&mask)&&(sc->sc_channel[i].nd_busy))
    553 			return EBUSY; /* channel is busy */
    554 		if (channel[i].isaudio==-1)
    555 			return EBUSY; /* system uses them */
    556 	}
    557 
    558 	/* enable interrupt on 1st channel */
    559 	for (i=j=0;i<AUCC_MAXINT;i++) {
    560 		if (masks2[i]&mask) {
    561 			DPRINTF(("first channel is %d\n",i));
    562 			j=i;
    563 			sc->sc_channel[i].nd_intr=intr;
    564 			sc->sc_channel[i].nd_intrdata=arg;
    565 			break;
    566 		}
    567 	}
    568 
    569 	DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
    570 		dmap[2], dmap[3], mask));
    571 
    572 	/* disable ints, dma for channels, until all parameters set */
    573 	/* XXX dont disable DMA! custom.dmacon=mask;*/
    574 	custom.intreq=mask<<INTB_AUD0;
    575 	custom.intena=mask<<INTB_AUD0;
    576 
    577 	/* copy data to dma buffer */
    578 
    579 
    580 	pp=(u_char *)p;
    581 
    582 	if (sc->sc_channels == 1) {
    583 		dmap[0] =
    584 		dmap[1] =
    585 		dmap[2] =
    586 		dmap[3] = sc->sc_channel[j].nd_dma;
    587 	} else {
    588 		for (k=0; k<4; k++) {
    589 			if (masks2[k+j]&mask)
    590 				dmap[k]=sc->sc_channel[k+j].nd_dma;
    591 		}
    592 	}
    593 
    594 	sc->sc_channel[j].nd_doublebuf ^= 1;
    595 	if (sc->sc_channel[j].nd_doublebuf) {
    596 		dmap[0] += AUDIO_BUF_SIZE/sizeof(u_short);
    597 		dmap[1] += AUDIO_BUF_SIZE/sizeof(u_short);
    598 		dmap[2] += AUDIO_BUF_SIZE/sizeof(u_short);
    599 		dmap[3] += AUDIO_BUF_SIZE/sizeof(u_short);
    600 	}
    601 
    602 	aucc_encode(sc->sc_encoding, sc->sc_channels, cc, pp, dmap);
    603 
    604 	/* dma buffers: we use same buffer 4 all channels */
    605 	/* write dma location and length */
    606 	for (i=k=0; i<4; i++) {
    607 		if (masks2[i] & mask) {
    608 			DPRINTF(("turning channel %d on\n",i));
    609 			/*  sc->sc_channel[i].nd_busy=1;*/
    610 			channel[i].isaudio=1;
    611 			channel[i].play_count=1;
    612 			channel[i].handler=NULL;
    613 			custom.aud[i].per=sc->sc_channel[i].nd_per;
    614 			custom.aud[i].vol=sc->sc_channel[i].nd_volume;
    615 			custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
    616 			custom.aud[i].len=cc/(sc->sc_channels*2);
    617 			sc->sc_channel[i].nd_mask=mask;
    618 			DPRINTF(("per is %d, vol is %d, len is %d\n",\
    619 			    sc->sc_channel[i].nd_per,
    620 			    sc->sc_channel[i].nd_volume, cc>>1));
    621 
    622 		}
    623 	}
    624 
    625 	channel[j].handler=aucc_inthdl;
    626 
    627 	/* enable ints */
    628 	custom.intena=INTF_SETCLR|INTF_INTEN| (masks2[j]<<INTB_AUD0);
    629 
    630 	DPRINTF(("enabled ints: 0x%x\n",(masks2[j]<<INTB_AUD0)));
    631 
    632 	/* enable dma */
    633 	custom.dmacon=DMAF_SETCLR|DMAF_MASTER|mask;
    634 
    635 	DPRINTF(("enabled dma, mask=0x%x\n",mask));
    636 
    637 	return(0);
    638 }
    639 
    640 /* ARGSUSED */
    641 int
    642 aucc_start_input(addr, p, cc, intr, arg)
    643 	void *addr;
    644 	void *p;
    645 	int cc;
    646 	void (*intr) __P((void *));
    647 	void *arg;
    648 {
    649 
    650 	return ENXIO; /* no input */
    651 }
    652 
    653 int
    654 aucc_halt_output(addr)
    655 	void *addr;
    656 {
    657 	register struct aucc_softc *sc = addr;
    658 	register int i;
    659 
    660 	/* XXX only halt, if input is also halted ?? */
    661 	/* stop dma, etc */
    662 	custom.intena = AUCC_ALLINTF;
    663 	custom.dmacon = AUCC_ALLDMAF;
    664 	/* mark every busy unit idle */
    665 	for (i=0;i<4;i++) {
    666 		sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0;
    667 		channel[i].isaudio=0;
    668 		channel[i].play_count=0;
    669 	}
    670 
    671 	return(0);
    672 }
    673 
    674 int
    675 aucc_halt_input(addr)
    676 	void *addr;
    677 {
    678 	/* no input */
    679 
    680 	return ENXIO;
    681 }
    682 
    683 int
    684 aucc_cont_output(addr)
    685 	void *addr;
    686 {
    687 	DPRINTF(("aucc_cont_output: never called, what should it do?!\n"));
    688 	/* reenable DMA XXX */
    689 	return ENXIO;
    690 }
    691 
    692 int
    693 aucc_cont_input(addr)
    694 	void *addr;
    695 {
    696 	DPRINTF(("aucc_cont_input: never called, what should it do?!\n"));
    697 	return(0);
    698 }
    699 
    700 int
    701 aucc_getdev(addr, retp)
    702         void *addr;
    703         struct audio_device *retp;
    704 {
    705         *retp = aucc_device;
    706         return 0;
    707 }
    708 
    709 int
    710 aucc_set_port(addr, cp)
    711 	void *addr;
    712 	mixer_ctrl_t *cp;
    713 {
    714 	register struct aucc_softc *sc = addr;
    715 	register int i,j;
    716 
    717 	DPRINTF(("aucc_set_port: port=%d", cp->dev));
    718 
    719 	switch (cp->type) {
    720 	case AUDIO_MIXER_SET:
    721 		if (cp->dev!=AUCC_CHANNELS)
    722 			return EINVAL;
    723 		i=cp->un.mask;
    724 		if ((i<1)||(i>15))
    725 			return EINVAL;
    726 		sc->sc_channelmask=i;
    727 		break;
    728 
    729 	case AUDIO_MIXER_VALUE:
    730 		i=cp->un.value.num_channels;
    731 		if ((i<1)||(i>4))
    732 			return EINVAL;
    733 
    734 #ifdef __XXXwhatsthat
    735 		if (cp->dev!=AUCC_VOLUME)
    736 			return EINVAL;
    737 #endif
    738 
    739 		/* set volume for channel 0..i-1 */
    740 		if (i>1)
    741 			for (j=0;j<i;j++)
    742 	 			sc->sc_channel[j].nd_volume =
    743 				    cp->un.value.level[j]>>2;
    744 		else if (sc->sc_channels > 1)
    745 			for (j=0; j<sc->sc_channels; j++)
    746 	 			sc->sc_channel[j].nd_volume =
    747 				    cp->un.value.level[0]>>2;
    748 		else
    749 			for (j=0; j<4; j++)
    750 	 			sc->sc_channel[j].nd_volume =
    751 				    cp->un.value.level[0]>>2;
    752 		break;
    753 
    754 	default:
    755 		return EINVAL;
    756 		break;
    757 	}
    758 	return 0;
    759 }
    760 
    761 
    762 int
    763 aucc_get_port(addr, cp)
    764 	void *addr;
    765 	mixer_ctrl_t *cp;
    766 {
    767 	register struct aucc_softc *sc = addr;
    768 	register int i,j;
    769 
    770 	DPRINTF(("aucc_get_port: port=%d", cp->dev));
    771 
    772 	switch (cp->type) {
    773 	case AUDIO_MIXER_SET:
    774 		if (cp->dev!=AUCC_CHANNELS)
    775 			return EINVAL;
    776 		cp->un.mask=sc->sc_channelmask;
    777 		break;
    778 
    779 	case AUDIO_MIXER_VALUE:
    780 		i = cp->un.value.num_channels;
    781 		if ((i<1)||(i>4))
    782 			return EINVAL;
    783 
    784 		for (j=0;j<i;j++)
    785 			cp->un.value.level[j] =
    786 			    (sc->sc_channel[j].nd_volume<<2) +
    787 			    (sc->sc_channel[j].nd_volume>>4);
    788 		break;
    789 
    790 	default:
    791 		return EINVAL;
    792 	}
    793 	return 0;
    794 }
    795 
    796 
    797 int
    798 aucc_get_props(addr)
    799 	void *addr;
    800 {
    801 	return 0;
    802 }
    803 
    804 int
    805 aucc_query_devinfo(addr, dip)
    806 	void *addr;
    807 	register mixer_devinfo_t *dip;
    808 {
    809 	register int i;
    810 
    811 	switch(dip->index) {
    812 	case AUCC_CHANNELS:
    813 		dip->type = AUDIO_MIXER_SET;
    814 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    815 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    816                 strcpy(dip->label.name, AudioNspeaker);
    817 		for (i=0;i<16;i++) {
    818 			sprintf(dip->un.s.member[i].label.name,
    819 			    "channelmask%d", i);
    820 			dip->un.s.member[i].mask = i;
    821 		}
    822 		dip->un.s.num_mem = 16;
    823 		break;
    824 
    825 	case AUCC_VOLUME:
    826 		dip->type = AUDIO_MIXER_VALUE;
    827 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    828 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    829 		strcpy(dip->label.name, AudioNspeaker);
    830 		dip->un.v.num_channels = 4;
    831 		strcpy(dip->un.v.units.name, AudioNvolume);
    832 		break;
    833 
    834 	case AUCC_OUTPUT_CLASS:
    835 		dip->type = AUDIO_MIXER_CLASS;
    836 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    837 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    838 		strcpy(dip->label.name, AudioCoutputs);
    839 		break;
    840 	default:
    841 		return ENXIO;
    842 		/*NOTREACHED*/
    843 	}
    844 
    845 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
    846 
    847 	return(0);
    848 }
    849 
    850 
    851 /* audio int handler */
    852 void
    853 aucc_inthdl(int ch)
    854 {
    855 	register int i;
    856 	register int mask=aucc->sc_channel[ch].nd_mask;
    857 
    858 	/* for all channels in this maskgroup:
    859 	   disable dma, int
    860 	   mark idle */
    861 	DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask));
    862 
    863 	custom.intreq=mask<<INTB_AUD0; /* clear request */
    864 	/* XXX: maybe we can leave ints and/or DMA on, if another sample has to be played?*/
    865 	custom.intena=mask<<INTB_AUD0;
    866 	/*
    867 	 * XXX custom.dmacon=mask; NO!!!
    868 	 */
    869 	for (i=0;i<4;i++) {
    870 		if (masks2[i]&&mask) {
    871 			DPRINTF(("marking channel %d idle\n",i));
    872 			aucc->sc_channel[i].nd_busy=0;
    873 			aucc->sc_channel[i].nd_mask=0;
    874 			channel[i].isaudio=channel[i].play_count=0;
    875 		}
    876 	}
    877 
    878 	/* call handler */
    879 	if (aucc->sc_channel[ch].nd_intr) {
    880 		DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
    881 		(*(aucc->sc_channel[ch].nd_intr))(aucc->sc_channel[ch].nd_intrdata);
    882 	}
    883 	else DPRINTF(("zero int handler\n"));
    884 	DPRINTF(("ints done\n"));
    885 }
    886 
    887 
    888 
    889 
    890 /* transform frequency to period, adjust bounds */
    891 static u_int
    892 freqtoper(u_int freq)
    893 {
    894 	u_int per=eclockfreq*5/freq;
    895 
    896 	if (per<124)
    897 		per=124; /* must have at least 124 ticks between samples */
    898 
    899 	return per;
    900 }
    901 
    902 /* transform period to frequency */
    903 static u_int
    904 pertofreq(u_int per)
    905 {
    906 	u_int freq=eclockfreq*5/per;
    907 
    908 
    909 	return freq;
    910 }
    911 
    912 
    913 
    914 void
    915 aucc_encode(enc, channels, i, p, dmap)
    916 	int enc, channels, i;
    917 	u_char *p;
    918 	u_short **dmap;
    919 {
    920 	char *q, *r, *s, *t;
    921 	int off;
    922 	u_char *tab;
    923 
    924 #ifdef AUCCDEBUG
    925 	static int debctl = 6;
    926 #endif
    927 
    928 	off = 0;
    929 	tab = NULL;
    930 
    931 #ifdef AUCCDEBUG
    932 	if (--debctl >= 0)
    933 		printf("Enc: enc %d, chan %d, dmap %p %p %p %p\n",
    934 		    enc, channels, dmap[0], dmap[1], dmap[2], dmap[3]);
    935 #endif
    936 
    937 	switch (enc) {
    938 	case AUDIO_ENCODING_ULAW:
    939 		tab=ulaw_to_lin;
    940 		break;
    941 	case AUDIO_ENCODING_ULINEAR_BE:
    942 	case AUDIO_ENCODING_ULINEAR_LE:
    943 		off=-128;
    944 		break;
    945 	case AUDIO_ENCODING_SLINEAR_BE:
    946 	case AUDIO_ENCODING_SLINEAR_LE:
    947 		break;
    948 	default:
    949 		return;
    950 	}
    951 
    952 	q = (char *)dmap[0];
    953 	r = (char *)dmap[1];
    954 	s = (char *)dmap[2];
    955 	t = (char *)dmap[3];
    956 
    957 	if (tab)
    958 		while (i) {
    959 			switch (channels) {
    960 			case 4: *t++ = tab[*p++];
    961 			case 3: *s++ = tab[*p++];
    962 			case 2: *r++ = tab[*p++];
    963 			case 1: *q++ = tab[*p++];
    964 			}
    965 			i -= channels;
    966 		}
    967 	else
    968 		while (i) {
    969 			switch (channels) {
    970 			case 4: *t++ = *p++ + off;
    971 			case 3: *s++ = *p++ + off;
    972 			case 2: *r++ = *p++ + off;
    973 			case 1: *q++ = *p++ + off;
    974 			}
    975 			i -= channels;
    976 		}
    977 
    978 }
    979 
    980 #endif /* NAUCC > 0 */
    981