Home | History | Annotate | Line # | Download | only in dev
aucc.c revision 1.9
      1 /*	$NetBSD: aucc.c,v 1.9 1997/07/09 22:37:08 is Exp $	*/
      2 #undef AUDIO_DEBUG
      3 /*
      4  * Copyright (c) 1997 Stephan Thesing
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *      This product includes software developed by Stephan Thesing.
     18  * 4. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include "aucc.h"
     34 #if NAUCC > 0
     35 
     36 #include <sys/param.h>
     37 #include <sys/systm.h>
     38 #include <sys/errno.h>
     39 #include <sys/ioctl.h>
     40 #include <sys/device.h>
     41 #include <sys/proc.h>
     42 #include <machine/cpu.h>
     43 
     44 #include <sys/audioio.h>
     45 #include <dev/audio_if.h>
     46 #include <amiga/amiga/cc.h>
     47 #include <amiga/amiga/custom.h>
     48 #include <amiga/amiga/device.h>
     49 #include <amiga/dev/auccvar.h>
     50 
     51 
     52 #ifdef LEV6_DEFER
     53 #define AUCC_MAXINT 3
     54 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2)
     55 #else
     56 #define AUCC_MAXINT 4
     57 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3)
     58 #endif
     59 /* this unconditionally; we may use AUD3 as slave channel with LEV6_DEFER */
     60 #define AUCC_ALLDMAF (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3)
     61 
     62 #ifdef AUDIO_DEBUG
     63 /*extern printf __P((const char *,...));*/
     64 int     auccdebug = 1;
     65 #define DPRINTF(x)      if (auccdebug) printf x
     66 #else
     67 #define DPRINTF(x)
     68 #endif
     69 
     70 #ifdef splaudio
     71 #undef splaudio
     72 #endif
     73 
     74 #define splaudio() spl4();
     75 
     76 /* clock frequency.. */
     77 extern int eclockfreq;
     78 
     79 
     80 /* hw audio ch */
     81 extern struct audio_channel channel[4];
     82 
     83 
     84 /*
     85  * Software state.
     86  */
     87 struct aucc_softc {
     88 	struct	device sc_dev;		/* base device */
     89 
     90 	int	sc_open;		/* single use device */
     91 	aucc_data_t sc_channel[4];	/* per channel freq, ... */
     92 	u_int	sc_encoding;		/* encoding AUDIO_ENCODING_.*/
     93 	int	sc_channels;		/* # of channels used */
     94 
     95 	int	sc_intrcnt;		/* interrupt count */
     96 	int	sc_channelmask;  	/* which channels are used ? */
     97 };
     98 
     99 /* interrupt interfaces */
    100 void aucc_inthdl __P((int));
    101 
    102 /* forward declarations */
    103 static int init_aucc __P((struct aucc_softc *));
    104 static u_int freqtoper  __P((u_int));
    105 static u_int pertofreq  __P((u_int));
    106 
    107 /* autoconfiguration driver */
    108 void	auccattach __P((struct device *, struct device *, void *));
    109 int	auccmatch __P((struct device *, struct cfdata *, void *));
    110 
    111 struct cfattach aucc_ca = {
    112 	sizeof(struct aucc_softc),
    113 	auccmatch,
    114 	auccattach
    115 };
    116 
    117 struct	cfdriver aucc_cd = {
    118 	NULL, "aucc", DV_DULL, NULL, 0
    119 };
    120 
    121 struct audio_device aucc_device = {
    122 	"Amiga-audio",
    123 	"x",
    124 	"aucc"
    125 };
    126 
    127 
    128 struct aucc_softc *aucc=NULL;
    129 
    130 
    131 unsigned char ulaw_to_lin[] = {
    132 	0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
    133 	0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
    134 	0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf,
    135 	0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf,
    136 	0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
    137 	0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
    138 	0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4,
    139 	0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8,
    140 	0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
    141 	0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
    142 	0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd,
    143 	0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe,
    144 	0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
    145 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    146 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    147 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
    148 	0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61,
    149 	0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, 0x45, 0x41,
    150 	0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30,
    151 	0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20,
    152 	0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17,
    153 	0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f,
    154 	0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b,
    155 	0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07,
    156 	0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05,
    157 	0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
    158 	0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02,
    159 	0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
    160 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    161 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    162 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    163 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    164 };
    165 
    166 /*
    167  * Define our interface to the higher level audio driver.
    168  */
    169 int	aucc_open __P((dev_t, int));
    170 void	aucc_close __P((void *));
    171 int	aucc_set_out_sr __P((void *, u_long));
    172 int	aucc_query_encoding __P((void *, struct audio_encoding *));
    173 int	aucc_get_encoding __P((void *));
    174 int	aucc_get_precision __P((void *));
    175 int	aucc_get_channels __P((void *));
    176 int	aucc_round_blocksize __P((void *, int));
    177 int	aucc_set_out_port __P((void *, int));
    178 int	aucc_get_out_port __P((void *));
    179 int	aucc_set_in_port __P((void *, int));
    180 int	aucc_get_in_port __P((void *));
    181 int	aucc_commit_settings __P((void *));
    182 int	aucc_start_output __P((void *, void *, int, void (*)(void *),
    183 				  void *));
    184 int	aucc_start_input __P((void *, void *, int, void (*)(void *),
    185 				 void *));
    186 int	aucc_halt_output __P((void *));
    187 int	aucc_halt_input __P((void *));
    188 int	aucc_cont_output __P((void *));
    189 int	aucc_cont_input __P((void *));
    190 int	aucc_getdev __P((void *, struct audio_device *));
    191 int	aucc_setfd __P((void *, int));
    192 int	aucc_set_port __P((void *, mixer_ctrl_t *));
    193 int	aucc_get_port __P((void *, mixer_ctrl_t *));
    194 int	aucc_query_devinfo __P((void *, mixer_devinfo_t *));
    195 void	aucc_encode __P((int, int, int, u_char *, u_short **));
    196 int	aucc_set_params __P((void *, int, struct audio_params *,
    197 	    struct audio_params *));
    198 
    199 struct audio_hw_if sa_hw_if = {
    200 	aucc_open,
    201 	aucc_close,
    202 	NULL,
    203 	aucc_query_encoding,
    204 	aucc_set_params,
    205 	aucc_round_blocksize,
    206 	aucc_set_out_port,
    207 	aucc_get_out_port,
    208 	aucc_set_in_port,
    209 	aucc_get_in_port,
    210 	aucc_commit_settings,
    211 	aucc_start_output,
    212 	aucc_start_input,
    213 	aucc_halt_output,
    214 	aucc_halt_input,
    215 	aucc_cont_output,
    216 	aucc_cont_input,
    217 	NULL,
    218 	aucc_getdev,
    219 	aucc_setfd,
    220 	aucc_set_port,
    221 	aucc_get_port,
    222 	aucc_query_devinfo,
    223 	0,
    224 	0
    225 };
    226 
    227 /* autoconfig routines */
    228 
    229 int
    230 auccmatch(pdp, cfp, aux)
    231 	struct device *pdp;
    232 	struct cfdata *cfp;
    233 	void *aux;
    234 {
    235 	if (matchname((char *)aux, "aucc") &&
    236 #ifdef DRACO
    237 	    !is_draco() &&
    238 #endif
    239 	    (cfp->cf_unit == 0))
    240 		return 1;
    241 
    242 	return 0;
    243 }
    244 
    245 /*
    246  * Audio chip found.
    247  */
    248 void
    249 auccattach(parent, self, args)
    250 	struct device *parent, *self;
    251 	void *args;
    252 {
    253 	register struct aucc_softc *sc = (struct aucc_softc *)self;
    254 	register int i;
    255 
    256 	printf("\n");
    257 
    258 	if((i=init_aucc(sc))) {
    259 		printf("audio: no chipmem\n");
    260 		return;
    261 	}
    262 
    263 	if (audio_hardware_attach(&sa_hw_if, sc) != 0)
    264 		printf("audio: could not attach to audio pseudo-device driver\n");
    265 	/* XXX: no way to return error, if init fails */
    266 }
    267 
    268 
    269 static int
    270 init_aucc(sc)
    271 	struct aucc_softc *sc;
    272 {
    273 	register int i, err=0;
    274 
    275 	/* init values per channel */
    276  	for (i=0;i<4;i++) {
    277 		sc->sc_channel[i].nd_freq=8000;
    278 		sc->sc_channel[i].nd_per=freqtoper(8000);
    279 		sc->sc_channel[i].nd_busy=0;
    280 		sc->sc_channel[i].nd_dma=alloc_chipmem(AUDIO_BUF_SIZE*2);
    281 		if (sc->sc_channel[i].nd_dma==NULL)
    282 			err=1;
    283 	 	sc->sc_channel[i].nd_dmalength=0;
    284 		sc->sc_channel[i].nd_volume=64;
    285 		sc->sc_channel[i].nd_intr=NULL;
    286 		sc->sc_channel[i].nd_intrdata=NULL;
    287 		sc->sc_channel[i].nd_doublebuf=0;
    288 		DPRINTF(("dma buffer for channel %d is %p\n", i,
    289 		    sc->sc_channel[i].nd_dma));
    290 
    291 	}
    292 
    293 	if (err) {
    294 		for(i=0;i<4;i++)
    295 			if (sc->sc_channel[i].nd_dma)
    296 				free_chipmem(sc->sc_channel[i].nd_dma);
    297 	}
    298 
    299 	sc->sc_channels=1;
    300 	sc->sc_channelmask=0xf;
    301 
    302 	/* clear interrupts and dma: */
    303 	custom.intena = AUCC_ALLINTF;
    304 	custom.dmacon = AUCC_ALLDMAF;;
    305 
    306 	sc->sc_encoding=AUDIO_ENCODING_ULAW;
    307 
    308 	return err;
    309 
    310 }
    311 
    312 int
    313 aucc_open(dev, flags)
    314 	dev_t dev;
    315 	int flags;
    316 {
    317 	register struct aucc_softc *sc;
    318 	int unit = AUDIOUNIT(dev);
    319 	register int i;
    320 
    321 	DPRINTF(("sa_open: unit %d\n",unit));
    322 
    323 	if (unit >= aucc_cd.cd_ndevs)
    324 		return (ENODEV);
    325 	if ((sc = aucc_cd.cd_devs[unit]) == NULL)
    326 		return (ENXIO);
    327 	if (sc->sc_open)
    328 		return (EBUSY);
    329 	sc->sc_open = 1;
    330 	for (i=0;i<AUCC_MAXINT;i++) {
    331 		sc->sc_channel[i].nd_intr=NULL;
    332 		sc->sc_channel[i].nd_intrdata=NULL;
    333 	}
    334 	aucc=sc;
    335 	sc->sc_channelmask=0xf;
    336 
    337 	DPRINTF(("saopen: ok -> sc=0x%p\n",sc));
    338 
    339 	return (0);
    340 }
    341 
    342 void
    343 aucc_close(addr)
    344 	void *addr;
    345 {
    346 	register struct aucc_softc *sc = addr;
    347 
    348 	DPRINTF(("sa_close: sc=0x%p\n", sc));
    349 	/*
    350 	 * halt i/o, clear open flag, and done.
    351 	 */
    352 	aucc_halt_output(sc);
    353 	sc->sc_open = 0;
    354 
    355 	DPRINTF(("sa_close: closed.\n"));
    356 }
    357 
    358 int
    359 aucc_set_out_sr(addr, sr)
    360 	void *addr;
    361 	u_long sr;
    362 {
    363 	struct aucc_softc *sc=addr;
    364 	u_long per;
    365 	register int i;
    366 
    367 	per=freqtoper(sr);
    368 	if (per>0xffff)
    369 		return EINVAL;
    370 	sr=pertofreq(per);
    371 
    372 	for (i=0;i<4;i++) {
    373 		sc->sc_channel[i].nd_freq=sr;
    374 		sc->sc_channel[i].nd_per=per;
    375 	}
    376 
    377 	return(0);
    378 }
    379 
    380 int
    381 aucc_query_encoding(addr, fp)
    382 	void *addr;
    383 	struct audio_encoding *fp;
    384 {
    385 	switch (fp->index) {
    386 	case 0:
    387 		strcpy(fp->name, AudioElinear);
    388 		fp->encoding = AUDIO_ENCODING_LINEAR;
    389 		fp->precision = 8;
    390 		fp->flags = 0;
    391 		break;
    392 	case 1:
    393 		strcpy(fp->name, AudioEmulaw);
    394 		fp->encoding = AUDIO_ENCODING_ULAW;
    395 		fp->precision = 8;
    396 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    397 		break;
    398 
    399 	case 2:
    400 		strcpy(fp->name, AudioEulinear);
    401 		fp->encoding = AUDIO_ENCODING_ULINEAR;
    402 		fp->precision = 8;
    403 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    404 		break;
    405 
    406 	default:
    407 		return(EINVAL);
    408 		/*NOTREACHED*/
    409 	}
    410 	return(0);
    411 }
    412 
    413 int
    414 aucc_set_params(addr, mode, p, q)
    415 	void *addr;
    416 	int mode;
    417 	struct  audio_params *p, *q;
    418 {
    419 	struct aucc_softc *sc;
    420 
    421 	sc = addr;
    422 
    423 	/* if (mode == AUMODE_RECORD)
    424 		return 0 ENXIO*/;
    425 
    426 #ifdef AUCCDEBUG
    427 	printf("aucc_set_params(mode %x, enc %d, bits %d, chn %d, sr %ld)\n",
    428 	    mode, p->encoding, p->precision, p->channels, p->sample_rate);
    429 #endif
    430 
    431 	switch (p->encoding) {
    432 	case AUDIO_ENCODING_ULAW:
    433 	case AUDIO_ENCODING_LINEAR:
    434 	case AUDIO_ENCODING_LINEAR_BE:
    435 	case AUDIO_ENCODING_LINEAR_LE:
    436 	case AUDIO_ENCODING_ULINEAR_BE:
    437 	case AUDIO_ENCODING_ULINEAR_LE:
    438 		break;
    439 
    440 	default:
    441 		return EINVAL;
    442 		/* NOTREADCHED */
    443 	}
    444 
    445 	if (p->precision != 8)
    446 		return EINVAL;
    447 
    448 	if ((p->channels<1) || (p->channels>4))
    449 		return(EINVAL);
    450 
    451 	sc->sc_channels = p->channels;
    452 	sc->sc_encoding = p->encoding;
    453 
    454 	q->encoding = p->encoding;
    455 	q->precision = p->precision;
    456 	q->channels = p->channels;
    457 	q->sample_rate = p->sample_rate;
    458 
    459 	return aucc_set_out_sr(addr, p->sample_rate);
    460 }
    461 
    462 int
    463 aucc_get_encoding(addr)
    464 	void *addr;
    465 {
    466 	return ((struct aucc_softc *)addr)->sc_encoding;
    467 }
    468 
    469 int
    470 aucc_get_precision(addr)
    471 	void *addr;
    472 {
    473 	return(8);
    474 }
    475 
    476 int
    477 aucc_get_channels(addr)
    478 	void *addr;
    479 {
    480 	return ((struct aucc_softc *)addr)->sc_channels;
    481 }
    482 
    483 int
    484 aucc_round_blocksize(addr, blk)
    485 	void *addr;
    486 	int blk;
    487 {
    488 
    489 
    490 	return blk>AUDIO_BUF_SIZE?AUDIO_BUF_SIZE:blk; /* round up to even size */
    491 }
    492 
    493 int
    494 aucc_set_out_port(addr, port) /* can set channels  */
    495 	void *addr;
    496 	int port;
    497 {
    498 	register struct aucc_softc *sc = addr;
    499 
    500 	/* port is mask for channels 0..3 */
    501 	if ((port<0)||(port>15))
    502 		return EINVAL;
    503 
    504 	sc->sc_channelmask=port;
    505 
    506 	return(0);
    507 }
    508 
    509 int
    510 aucc_get_out_port(addr)
    511 	void *addr;
    512 {
    513 	register struct aucc_softc *sc = addr;
    514 
    515 	return sc->sc_channelmask;
    516 }
    517 
    518 int
    519 aucc_set_in_port(addr, port)
    520 	void *addr;
    521 	int port;
    522 {
    523 	return(EINVAL); /* no input possible */
    524 
    525 }
    526 
    527 int
    528 aucc_get_in_port(addr)
    529 	void *addr;
    530 {
    531 	return(0);
    532 }
    533 
    534 int
    535 aucc_commit_settings(addr)
    536 	void *addr;
    537 {
    538 	register struct aucc_softc *sc = addr;
    539 	register int i;
    540 
    541 	DPRINTF(("sa_commit.\n"));
    542 
    543 	for (i=0;i<4;i++) {
    544 		custom.aud[i].vol=sc->sc_channel[i].nd_volume;
    545 		custom.aud[i].per=sc->sc_channel[i].nd_per;
    546 	}
    547 
    548 	DPRINTF(("commit done\n"));
    549 
    550 	return(0);
    551 }
    552 
    553 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
    554 static int masks2[4] = {1,2,4,8};
    555 
    556 int
    557 aucc_start_output(addr, p, cc, intr, arg)
    558 	void *addr;
    559 	void *p;
    560 	int cc;
    561 	void (*intr) __P((void *));
    562 	void *arg;
    563 {
    564 	struct aucc_softc *sc;
    565 	int mask;
    566 	int i,j,k;
    567 	u_short *dmap[4];
    568 	u_char *pp;
    569 
    570 
    571 	sc = addr;
    572 	mask = sc->sc_channelmask;
    573 
    574 	dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
    575 
    576 	DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
    577 
    578 	mask &=masks[sc->sc_channels-1]; /* we use first sc_channels channels */
    579 	if (mask==0) /* active and used channels are disjoint */
    580 		return EINVAL;
    581 
    582 	for (i=0;i<4;i++) { /* channels available ? */
    583 		if ((masks2[i]&mask)&&(sc->sc_channel[i].nd_busy))
    584 			return EBUSY; /* channel is busy */
    585 		if (channel[i].isaudio==-1)
    586 			return EBUSY; /* system uses them */
    587 	}
    588 
    589 	/* enable interrupt on 1st channel */
    590 	for (i=j=0;i<AUCC_MAXINT;i++) {
    591 		if (masks2[i]&mask) {
    592 			DPRINTF(("first channel is %d\n",i));
    593 			j=i;
    594 			sc->sc_channel[i].nd_intr=intr;
    595 			sc->sc_channel[i].nd_intrdata=arg;
    596 			break;
    597 		}
    598 	}
    599 
    600 	DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
    601 		dmap[2], dmap[3], mask));
    602 
    603 	/* disable ints, dma for channels, until all parameters set */
    604 	/* XXX dont disable DMA! custom.dmacon=mask;*/
    605 	custom.intreq=mask<<INTB_AUD0;
    606 	custom.intena=mask<<INTB_AUD0;
    607 
    608 	/* copy data to dma buffer */
    609 
    610 
    611 	pp=(u_char *)p;
    612 
    613 	if (sc->sc_channels == 1) {
    614 		dmap[0] =
    615 		dmap[1] =
    616 		dmap[2] =
    617 		dmap[3] = sc->sc_channel[j].nd_dma;
    618 	} else {
    619 		for (k=0; k<4; k++) {
    620 			if (masks2[k+j]&mask)
    621 				dmap[k]=sc->sc_channel[k+j].nd_dma;
    622 		}
    623 	}
    624 
    625 	sc->sc_channel[j].nd_doublebuf ^= 1;
    626 	if (sc->sc_channel[j].nd_doublebuf) {
    627 		dmap[0] += AUDIO_BUF_SIZE/sizeof(u_short);
    628 		dmap[1] += AUDIO_BUF_SIZE/sizeof(u_short);
    629 		dmap[2] += AUDIO_BUF_SIZE/sizeof(u_short);
    630 		dmap[3] += AUDIO_BUF_SIZE/sizeof(u_short);
    631 	}
    632 
    633 	aucc_encode(sc->sc_encoding, sc->sc_channels, cc, pp, dmap);
    634 
    635 	/* dma buffers: we use same buffer 4 all channels */
    636 	/* write dma location and length */
    637 	for (i=k=0; i<4; i++) {
    638 		if (masks2[i] & mask) {
    639 			DPRINTF(("turning channel %d on\n",i));
    640 			/*  sc->sc_channel[i].nd_busy=1;*/
    641 			channel[i].isaudio=1;
    642 			channel[i].play_count=1;
    643 			channel[i].handler=NULL;
    644 			custom.aud[i].per=sc->sc_channel[i].nd_per;
    645 			custom.aud[i].vol=sc->sc_channel[i].nd_volume;
    646 			custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
    647 			custom.aud[i].len=cc/(sc->sc_channels*2);
    648 			sc->sc_channel[i].nd_mask=mask;
    649 			DPRINTF(("per is %d, vol is %d, len is %d\n",\
    650 			    sc->sc_channel[i].nd_per,
    651 			    sc->sc_channel[i].nd_volume, cc>>1));
    652 
    653 		}
    654 	}
    655 
    656 	channel[j].handler=aucc_inthdl;
    657 
    658 	/* enable ints */
    659 	custom.intena=INTF_SETCLR|INTF_INTEN| (masks2[j]<<INTB_AUD0);
    660 
    661 	DPRINTF(("enabled ints: 0x%x\n",(masks2[j]<<INTB_AUD0)));
    662 
    663 	/* enable dma */
    664 	custom.dmacon=DMAF_SETCLR|DMAF_MASTER|mask;
    665 
    666 	DPRINTF(("enabled dma, mask=0x%x\n",mask));
    667 
    668 	return(0);
    669 }
    670 
    671 /* ARGSUSED */
    672 int
    673 aucc_start_input(addr, p, cc, intr, arg)
    674 	void *addr;
    675 	void *p;
    676 	int cc;
    677 	void (*intr) __P((void *));
    678 	void *arg;
    679 {
    680 
    681 	return ENXIO; /* no input */
    682 }
    683 
    684 int
    685 aucc_halt_output(addr)
    686 	void *addr;
    687 {
    688 	register struct aucc_softc *sc = addr;
    689 	register int i;
    690 
    691 	/* XXX only halt, if input is also halted ?? */
    692 	/* stop dma, etc */
    693 	custom.intena = AUCC_ALLINTF;
    694 	custom.dmacon = AUCC_ALLDMAF;
    695 	/* mark every busy unit idle */
    696 	for (i=0;i<4;i++) {
    697 		sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0;
    698 		channel[i].isaudio=0;
    699 		channel[i].play_count=0;
    700 	}
    701 
    702 	return(0);
    703 }
    704 
    705 int
    706 aucc_halt_input(addr)
    707 	void *addr;
    708 {
    709 	/* no input */
    710 
    711 	return ENXIO;
    712 }
    713 
    714 int
    715 aucc_cont_output(addr)
    716 	void *addr;
    717 {
    718 	DPRINTF(("aucc_cont_output: never called, what should it do?!\n"));
    719 	/* reenable DMA XXX */
    720 	return ENXIO;
    721 }
    722 
    723 int
    724 aucc_cont_input(addr)
    725 	void *addr;
    726 {
    727 	DPRINTF(("aucc_cont_input: never called, what should it do?!\n"));
    728 	return(0);
    729 }
    730 
    731 int
    732 aucc_getdev(addr, retp)
    733         void *addr;
    734         struct audio_device *retp;
    735 {
    736         *retp = aucc_device;
    737         return 0;
    738 }
    739 
    740 int
    741 aucc_setfd(addr, flag)
    742         void *addr;
    743         int flag;
    744 {
    745         return flag?EINVAL:0; /* Always half-duplex */
    746 }
    747 
    748 int
    749 aucc_set_port(addr, cp)
    750 	void *addr;
    751 	mixer_ctrl_t *cp;
    752 {
    753 	register struct aucc_softc *sc = addr;
    754 	register int i,j;
    755 
    756 	DPRINTF(("aucc_set_port: port=%d", cp->dev));
    757 
    758 	switch (cp->type) {
    759 	case AUDIO_MIXER_SET:
    760 		if (cp->dev!=AUCC_CHANNELS)
    761 			return EINVAL;
    762 		i=cp->un.mask;
    763 		if ((i<1)||(i>15))
    764 			return EINVAL;
    765 		sc->sc_channelmask=i;
    766 		break;
    767 
    768 	case AUDIO_MIXER_VALUE:
    769 		i=cp->un.value.num_channels;
    770 		if ((i<1)||(i>4))
    771 			return EINVAL;
    772 
    773 		if (cp->dev!=AUCC_VOLUME)
    774 			return EINVAL;
    775 
    776 		/* set volume for channel 0..i-1 */
    777 		for (j=0;j<i;j++)
    778 	 		sc->sc_channel[j].nd_volume=cp->un.value.level[j]>>2;
    779 			break;
    780 
    781 	default:
    782 		return EINVAL;
    783 		break;
    784 	}
    785 	return 0;
    786 }
    787 
    788 
    789 int
    790 aucc_get_port(addr, cp)
    791 	void *addr;
    792 	mixer_ctrl_t *cp;
    793 {
    794 	register struct aucc_softc *sc = addr;
    795 	register int i,j;
    796 
    797 	DPRINTF(("aucc_get_port: port=%d", cp->dev));
    798 
    799 	switch (cp->type) {
    800 	case AUDIO_MIXER_SET:
    801 		if (cp->dev!=AUCC_CHANNELS)
    802 			return EINVAL;
    803 		cp->un.mask=sc->sc_channelmask;
    804 		break;
    805 
    806 	case AUDIO_MIXER_VALUE:
    807 		i = cp->un.value.num_channels;
    808 		if ((i<1)||(i>4))
    809 			return EINVAL;
    810 
    811 		for (j=0;j<i;j++)
    812 			cp->un.value.level[j]=sc->sc_channel[j].nd_volume<<2;
    813 		break;
    814 
    815 	default:
    816 		return EINVAL;
    817 	}
    818 	return 0;
    819 }
    820 
    821 
    822 int
    823 aucc_query_devinfo(addr, dip)
    824 	void *addr;
    825 	register mixer_devinfo_t *dip;
    826 {
    827 	register int i;
    828 
    829 	switch(dip->index) {
    830 	case AUCC_CHANNELS:
    831 		dip->type = AUDIO_MIXER_SET;
    832 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    833 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    834                 strcpy(dip->label.name, AudioNspeaker);
    835 		for (i=0;i<16;i++) {
    836 			sprintf(dip->un.s.member[i].label.name,
    837 			    "channelmask%d", i);
    838 			dip->un.s.member[i].mask = i;
    839 		}
    840 		dip->un.s.num_mem = 16;
    841 		break;
    842 
    843 	case AUCC_VOLUME:
    844 		dip->type = AUDIO_MIXER_VALUE;
    845 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    846 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    847 		strcpy(dip->label.name, AudioNspeaker);
    848 		dip->un.v.num_channels = 4;
    849 		strcpy(dip->un.v.units.name, AudioNvolume);
    850 		break;
    851 
    852 	case AUCC_OUTPUT_CLASS:
    853 		dip->type = AUDIO_MIXER_CLASS;
    854 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    855 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    856 		strcpy(dip->label.name, AudioCOutputs);
    857 		break;
    858 	default:
    859 		return ENXIO;
    860 		/*NOTREACHED*/
    861 	}
    862 
    863 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
    864 
    865 	return(0);
    866 }
    867 
    868 
    869 /* audio int handler */
    870 void
    871 aucc_inthdl(int ch)
    872 {
    873 	register int i;
    874 	register int mask=aucc->sc_channel[ch].nd_mask;
    875 
    876 	/* for all channels in this maskgroup:
    877 	   disable dma, int
    878 	   mark idle */
    879 	DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask));
    880 
    881 	custom.intreq=mask<<INTB_AUD0; /* clear request */
    882 	/* XXX: maybe we can leave ints and/or DMA on, if another sample has to be played?*/
    883 	custom.intena=mask<<INTB_AUD0;
    884 	/*
    885 	 * XXX custom.dmacon=mask; NO!!!
    886 	 */
    887 	for (i=0;i<4;i++) {
    888 		if (masks2[i]&&mask) {
    889 			DPRINTF(("marking channel %d idle\n",i));
    890 			aucc->sc_channel[i].nd_busy=0;
    891 			aucc->sc_channel[i].nd_mask=0;
    892 			channel[i].isaudio=channel[i].play_count=0;
    893 		}
    894 	}
    895 
    896 	/* call handler */
    897 	if (aucc->sc_channel[ch].nd_intr) {
    898 		DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
    899 		(*(aucc->sc_channel[ch].nd_intr))(aucc->sc_channel[ch].nd_intrdata);
    900 	}
    901 	else DPRINTF(("zero int handler\n"));
    902 	DPRINTF(("ints done\n"));
    903 }
    904 
    905 
    906 
    907 
    908 /* transform frequency to period, adjust bounds */
    909 static u_int
    910 freqtoper(u_int freq)
    911 {
    912 	u_int per=eclockfreq*5/freq;
    913 
    914 	if (per<124)
    915 		per=124; /* must have at least 124 ticks between samples */
    916 
    917 	return per;
    918 }
    919 
    920 /* transform period to frequency */
    921 static u_int
    922 pertofreq(u_int per)
    923 {
    924 	u_int freq=eclockfreq*5/per;
    925 
    926 
    927 	return freq;
    928 }
    929 
    930 
    931 
    932 void
    933 aucc_encode(enc, channels, i, p, dmap)
    934 	int enc, channels, i;
    935 	u_char *p;
    936 	u_short **dmap;
    937 {
    938 	char *q, *r, *s, *t;
    939 	int off;
    940 	u_char *tab;
    941 
    942 #ifdef AUCCDEBUG
    943 	static int debctl = 6;
    944 #endif
    945 
    946 	off = 0;
    947 	tab = NULL;
    948 
    949 #ifdef AUCCDEBUG
    950 	if (--debctl >= 0)
    951 		printf("Enc: enc %d, chan %d, dmap %p %p %p %p\n",
    952 		    enc, channels, dmap[0], dmap[1], dmap[2], dmap[3]);
    953 #endif
    954 
    955 	switch (enc) {
    956 	case AUDIO_ENCODING_ULAW:
    957 		tab=ulaw_to_lin;
    958 		break;
    959 	case AUDIO_ENCODING_ULINEAR:
    960 	case AUDIO_ENCODING_ULINEAR_BE:
    961 	case AUDIO_ENCODING_ULINEAR_LE:
    962 		off=-128;
    963 		break;
    964 	case AUDIO_ENCODING_LINEAR:
    965 	case AUDIO_ENCODING_LINEAR_BE:
    966 	case AUDIO_ENCODING_LINEAR_LE:
    967 		break;
    968 	default:
    969 		return;
    970 	}
    971 
    972 	q = (char *)dmap[0];
    973 	r = (char *)dmap[1];
    974 	s = (char *)dmap[2];
    975 	t = (char *)dmap[3];
    976 
    977 	if (tab)
    978 		while (i) {
    979 			switch (channels) {
    980 			case 4: *t++ = tab[*p++];
    981 			case 3: *s++ = tab[*p++];
    982 			case 2: *r++ = tab[*p++];
    983 			case 1: *q++ = tab[*p++];
    984 			}
    985 			i -= channels;
    986 		}
    987 	else
    988 		while (i) {
    989 			switch (channels) {
    990 			case 4: *t++ = *p++ + off;
    991 			case 3: *s++ = *p++ + off;
    992 			case 2: *r++ = *p++ + off;
    993 			case 1: *q++ = *p++ + off;
    994 			}
    995 			i -= channels;
    996 		}
    997 
    998 }
    999 
   1000 #endif /* NAUCC > 0 */
   1001