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