Home | History | Annotate | Line # | Download | only in dev
aucc.c revision 1.11
      1 /*	$NetBSD: aucc.c,v 1.11 1997/07/15 07:46: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_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_SLINEAR;
    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_SLINEAR:
    434 	case AUDIO_ENCODING_SLINEAR_BE:
    435 	case AUDIO_ENCODING_SLINEAR_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 	if (sc->sc_channels > 1)
    579 		mask &=masks[sc->sc_channels-1];
    580 		/* we use first sc_channels channels */
    581 	if (mask==0) /* active and used channels are disjoint */
    582 		return EINVAL;
    583 
    584 	for (i=0;i<4;i++) { /* channels available ? */
    585 		if ((masks2[i]&mask)&&(sc->sc_channel[i].nd_busy))
    586 			return EBUSY; /* channel is busy */
    587 		if (channel[i].isaudio==-1)
    588 			return EBUSY; /* system uses them */
    589 	}
    590 
    591 	/* enable interrupt on 1st channel */
    592 	for (i=j=0;i<AUCC_MAXINT;i++) {
    593 		if (masks2[i]&mask) {
    594 			DPRINTF(("first channel is %d\n",i));
    595 			j=i;
    596 			sc->sc_channel[i].nd_intr=intr;
    597 			sc->sc_channel[i].nd_intrdata=arg;
    598 			break;
    599 		}
    600 	}
    601 
    602 	DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
    603 		dmap[2], dmap[3], mask));
    604 
    605 	/* disable ints, dma for channels, until all parameters set */
    606 	/* XXX dont disable DMA! custom.dmacon=mask;*/
    607 	custom.intreq=mask<<INTB_AUD0;
    608 	custom.intena=mask<<INTB_AUD0;
    609 
    610 	/* copy data to dma buffer */
    611 
    612 
    613 	pp=(u_char *)p;
    614 
    615 	if (sc->sc_channels == 1) {
    616 		dmap[0] =
    617 		dmap[1] =
    618 		dmap[2] =
    619 		dmap[3] = sc->sc_channel[j].nd_dma;
    620 	} else {
    621 		for (k=0; k<4; k++) {
    622 			if (masks2[k+j]&mask)
    623 				dmap[k]=sc->sc_channel[k+j].nd_dma;
    624 		}
    625 	}
    626 
    627 	sc->sc_channel[j].nd_doublebuf ^= 1;
    628 	if (sc->sc_channel[j].nd_doublebuf) {
    629 		dmap[0] += AUDIO_BUF_SIZE/sizeof(u_short);
    630 		dmap[1] += AUDIO_BUF_SIZE/sizeof(u_short);
    631 		dmap[2] += AUDIO_BUF_SIZE/sizeof(u_short);
    632 		dmap[3] += AUDIO_BUF_SIZE/sizeof(u_short);
    633 	}
    634 
    635 	aucc_encode(sc->sc_encoding, sc->sc_channels, cc, pp, dmap);
    636 
    637 	/* dma buffers: we use same buffer 4 all channels */
    638 	/* write dma location and length */
    639 	for (i=k=0; i<4; i++) {
    640 		if (masks2[i] & mask) {
    641 			DPRINTF(("turning channel %d on\n",i));
    642 			/*  sc->sc_channel[i].nd_busy=1;*/
    643 			channel[i].isaudio=1;
    644 			channel[i].play_count=1;
    645 			channel[i].handler=NULL;
    646 			custom.aud[i].per=sc->sc_channel[i].nd_per;
    647 			custom.aud[i].vol=sc->sc_channel[i].nd_volume;
    648 			custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
    649 			custom.aud[i].len=cc/(sc->sc_channels*2);
    650 			sc->sc_channel[i].nd_mask=mask;
    651 			DPRINTF(("per is %d, vol is %d, len is %d\n",\
    652 			    sc->sc_channel[i].nd_per,
    653 			    sc->sc_channel[i].nd_volume, cc>>1));
    654 
    655 		}
    656 	}
    657 
    658 	channel[j].handler=aucc_inthdl;
    659 
    660 	/* enable ints */
    661 	custom.intena=INTF_SETCLR|INTF_INTEN| (masks2[j]<<INTB_AUD0);
    662 
    663 	DPRINTF(("enabled ints: 0x%x\n",(masks2[j]<<INTB_AUD0)));
    664 
    665 	/* enable dma */
    666 	custom.dmacon=DMAF_SETCLR|DMAF_MASTER|mask;
    667 
    668 	DPRINTF(("enabled dma, mask=0x%x\n",mask));
    669 
    670 	return(0);
    671 }
    672 
    673 /* ARGSUSED */
    674 int
    675 aucc_start_input(addr, p, cc, intr, arg)
    676 	void *addr;
    677 	void *p;
    678 	int cc;
    679 	void (*intr) __P((void *));
    680 	void *arg;
    681 {
    682 
    683 	return ENXIO; /* no input */
    684 }
    685 
    686 int
    687 aucc_halt_output(addr)
    688 	void *addr;
    689 {
    690 	register struct aucc_softc *sc = addr;
    691 	register int i;
    692 
    693 	/* XXX only halt, if input is also halted ?? */
    694 	/* stop dma, etc */
    695 	custom.intena = AUCC_ALLINTF;
    696 	custom.dmacon = AUCC_ALLDMAF;
    697 	/* mark every busy unit idle */
    698 	for (i=0;i<4;i++) {
    699 		sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0;
    700 		channel[i].isaudio=0;
    701 		channel[i].play_count=0;
    702 	}
    703 
    704 	return(0);
    705 }
    706 
    707 int
    708 aucc_halt_input(addr)
    709 	void *addr;
    710 {
    711 	/* no input */
    712 
    713 	return ENXIO;
    714 }
    715 
    716 int
    717 aucc_cont_output(addr)
    718 	void *addr;
    719 {
    720 	DPRINTF(("aucc_cont_output: never called, what should it do?!\n"));
    721 	/* reenable DMA XXX */
    722 	return ENXIO;
    723 }
    724 
    725 int
    726 aucc_cont_input(addr)
    727 	void *addr;
    728 {
    729 	DPRINTF(("aucc_cont_input: never called, what should it do?!\n"));
    730 	return(0);
    731 }
    732 
    733 int
    734 aucc_getdev(addr, retp)
    735         void *addr;
    736         struct audio_device *retp;
    737 {
    738         *retp = aucc_device;
    739         return 0;
    740 }
    741 
    742 int
    743 aucc_setfd(addr, flag)
    744         void *addr;
    745         int flag;
    746 {
    747         return flag?EINVAL:0; /* Always half-duplex */
    748 }
    749 
    750 int
    751 aucc_set_port(addr, cp)
    752 	void *addr;
    753 	mixer_ctrl_t *cp;
    754 {
    755 	register struct aucc_softc *sc = addr;
    756 	register int i,j;
    757 
    758 	DPRINTF(("aucc_set_port: port=%d", cp->dev));
    759 
    760 	switch (cp->type) {
    761 	case AUDIO_MIXER_SET:
    762 		if (cp->dev!=AUCC_CHANNELS)
    763 			return EINVAL;
    764 		i=cp->un.mask;
    765 		if ((i<1)||(i>15))
    766 			return EINVAL;
    767 		sc->sc_channelmask=i;
    768 		break;
    769 
    770 	case AUDIO_MIXER_VALUE:
    771 		i=cp->un.value.num_channels;
    772 		if ((i<1)||(i>4))
    773 			return EINVAL;
    774 
    775 #ifdef __XXXwhatsthat
    776 		if (cp->dev!=AUCC_VOLUME)
    777 			return EINVAL;
    778 #endif
    779 
    780 		/* set volume for channel 0..i-1 */
    781 		if (i>1)
    782 			for (j=0;j<i;j++)
    783 	 			sc->sc_channel[j].nd_volume =
    784 				    cp->un.value.level[j]>>2;
    785 		else if (sc->sc_channels > 1)
    786 			for (j=0; j<sc->sc_channels; j++)
    787 	 			sc->sc_channel[j].nd_volume =
    788 				    cp->un.value.level[0]>>2;
    789 		else
    790 			for (j=0; j<4; j++)
    791 	 			sc->sc_channel[j].nd_volume =
    792 				    cp->un.value.level[0]>>2;
    793 		break;
    794 
    795 	default:
    796 		return EINVAL;
    797 		break;
    798 	}
    799 	return 0;
    800 }
    801 
    802 
    803 int
    804 aucc_get_port(addr, cp)
    805 	void *addr;
    806 	mixer_ctrl_t *cp;
    807 {
    808 	register struct aucc_softc *sc = addr;
    809 	register int i,j;
    810 
    811 	DPRINTF(("aucc_get_port: port=%d", cp->dev));
    812 
    813 	switch (cp->type) {
    814 	case AUDIO_MIXER_SET:
    815 		if (cp->dev!=AUCC_CHANNELS)
    816 			return EINVAL;
    817 		cp->un.mask=sc->sc_channelmask;
    818 		break;
    819 
    820 	case AUDIO_MIXER_VALUE:
    821 		i = cp->un.value.num_channels;
    822 		if ((i<1)||(i>4))
    823 			return EINVAL;
    824 
    825 		for (j=0;j<i;j++)
    826 			cp->un.value.level[j] =
    827 			    (sc->sc_channel[j].nd_volume<<2) +
    828 			    (sc->sc_channel[j].nd_volume>>4);
    829 		break;
    830 
    831 	default:
    832 		return EINVAL;
    833 	}
    834 	return 0;
    835 }
    836 
    837 
    838 int
    839 aucc_query_devinfo(addr, dip)
    840 	void *addr;
    841 	register mixer_devinfo_t *dip;
    842 {
    843 	register int i;
    844 
    845 	switch(dip->index) {
    846 	case AUCC_CHANNELS:
    847 		dip->type = AUDIO_MIXER_SET;
    848 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    849 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    850                 strcpy(dip->label.name, AudioNspeaker);
    851 		for (i=0;i<16;i++) {
    852 			sprintf(dip->un.s.member[i].label.name,
    853 			    "channelmask%d", i);
    854 			dip->un.s.member[i].mask = i;
    855 		}
    856 		dip->un.s.num_mem = 16;
    857 		break;
    858 
    859 	case AUCC_VOLUME:
    860 		dip->type = AUDIO_MIXER_VALUE;
    861 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    862 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    863 		strcpy(dip->label.name, AudioNspeaker);
    864 		dip->un.v.num_channels = 4;
    865 		strcpy(dip->un.v.units.name, AudioNvolume);
    866 		break;
    867 
    868 	case AUCC_OUTPUT_CLASS:
    869 		dip->type = AUDIO_MIXER_CLASS;
    870 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    871 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    872 		strcpy(dip->label.name, AudioCOutputs);
    873 		break;
    874 	default:
    875 		return ENXIO;
    876 		/*NOTREACHED*/
    877 	}
    878 
    879 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
    880 
    881 	return(0);
    882 }
    883 
    884 
    885 /* audio int handler */
    886 void
    887 aucc_inthdl(int ch)
    888 {
    889 	register int i;
    890 	register int mask=aucc->sc_channel[ch].nd_mask;
    891 
    892 	/* for all channels in this maskgroup:
    893 	   disable dma, int
    894 	   mark idle */
    895 	DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask));
    896 
    897 	custom.intreq=mask<<INTB_AUD0; /* clear request */
    898 	/* XXX: maybe we can leave ints and/or DMA on, if another sample has to be played?*/
    899 	custom.intena=mask<<INTB_AUD0;
    900 	/*
    901 	 * XXX custom.dmacon=mask; NO!!!
    902 	 */
    903 	for (i=0;i<4;i++) {
    904 		if (masks2[i]&&mask) {
    905 			DPRINTF(("marking channel %d idle\n",i));
    906 			aucc->sc_channel[i].nd_busy=0;
    907 			aucc->sc_channel[i].nd_mask=0;
    908 			channel[i].isaudio=channel[i].play_count=0;
    909 		}
    910 	}
    911 
    912 	/* call handler */
    913 	if (aucc->sc_channel[ch].nd_intr) {
    914 		DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
    915 		(*(aucc->sc_channel[ch].nd_intr))(aucc->sc_channel[ch].nd_intrdata);
    916 	}
    917 	else DPRINTF(("zero int handler\n"));
    918 	DPRINTF(("ints done\n"));
    919 }
    920 
    921 
    922 
    923 
    924 /* transform frequency to period, adjust bounds */
    925 static u_int
    926 freqtoper(u_int freq)
    927 {
    928 	u_int per=eclockfreq*5/freq;
    929 
    930 	if (per<124)
    931 		per=124; /* must have at least 124 ticks between samples */
    932 
    933 	return per;
    934 }
    935 
    936 /* transform period to frequency */
    937 static u_int
    938 pertofreq(u_int per)
    939 {
    940 	u_int freq=eclockfreq*5/per;
    941 
    942 
    943 	return freq;
    944 }
    945 
    946 
    947 
    948 void
    949 aucc_encode(enc, channels, i, p, dmap)
    950 	int enc, channels, i;
    951 	u_char *p;
    952 	u_short **dmap;
    953 {
    954 	char *q, *r, *s, *t;
    955 	int off;
    956 	u_char *tab;
    957 
    958 #ifdef AUCCDEBUG
    959 	static int debctl = 6;
    960 #endif
    961 
    962 	off = 0;
    963 	tab = NULL;
    964 
    965 #ifdef AUCCDEBUG
    966 	if (--debctl >= 0)
    967 		printf("Enc: enc %d, chan %d, dmap %p %p %p %p\n",
    968 		    enc, channels, dmap[0], dmap[1], dmap[2], dmap[3]);
    969 #endif
    970 
    971 	switch (enc) {
    972 	case AUDIO_ENCODING_ULAW:
    973 		tab=ulaw_to_lin;
    974 		break;
    975 	case AUDIO_ENCODING_ULINEAR:
    976 	case AUDIO_ENCODING_ULINEAR_BE:
    977 	case AUDIO_ENCODING_ULINEAR_LE:
    978 		off=-128;
    979 		break;
    980 	case AUDIO_ENCODING_SLINEAR:
    981 	case AUDIO_ENCODING_SLINEAR_BE:
    982 	case AUDIO_ENCODING_SLINEAR_LE:
    983 		break;
    984 	default:
    985 		return;
    986 	}
    987 
    988 	q = (char *)dmap[0];
    989 	r = (char *)dmap[1];
    990 	s = (char *)dmap[2];
    991 	t = (char *)dmap[3];
    992 
    993 	if (tab)
    994 		while (i) {
    995 			switch (channels) {
    996 			case 4: *t++ = tab[*p++];
    997 			case 3: *s++ = tab[*p++];
    998 			case 2: *r++ = tab[*p++];
    999 			case 1: *q++ = tab[*p++];
   1000 			}
   1001 			i -= channels;
   1002 		}
   1003 	else
   1004 		while (i) {
   1005 			switch (channels) {
   1006 			case 4: *t++ = *p++ + off;
   1007 			case 3: *s++ = *p++ + off;
   1008 			case 2: *r++ = *p++ + off;
   1009 			case 1: *q++ = *p++ + off;
   1010 			}
   1011 			i -= channels;
   1012 		}
   1013 
   1014 }
   1015 
   1016 #endif /* NAUCC > 0 */
   1017