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