Home | History | Annotate | Line # | Download | only in dev
aucc.c revision 1.22
      1 /*	$NetBSD: aucc.c,v 1.22 1998/01/12 10:39:10 thorpej Exp $	*/
      2 
      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 audio_device aucc_device = {
    118 	"Amiga-audio",
    119 	"x",
    120 	"aucc"
    121 };
    122 
    123 
    124 struct aucc_softc *aucc=NULL;
    125 
    126 
    127 unsigned char ulaw_to_lin[] = {
    128 	0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
    129 	0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
    130 	0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf,
    131 	0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf,
    132 	0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
    133 	0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
    134 	0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4,
    135 	0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8,
    136 	0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
    137 	0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
    138 	0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd,
    139 	0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe,
    140 	0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
    141 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    142 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    143 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
    144 	0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61,
    145 	0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, 0x45, 0x41,
    146 	0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30,
    147 	0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20,
    148 	0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17,
    149 	0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f,
    150 	0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b,
    151 	0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07,
    152 	0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05,
    153 	0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
    154 	0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02,
    155 	0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
    156 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    157 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    158 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    159 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    160 };
    161 
    162 /*
    163  * Define our interface to the higher level audio driver.
    164  */
    165 int	aucc_open __P((void *, int));
    166 void	aucc_close __P((void *));
    167 int	aucc_set_out_sr __P((void *, u_long));
    168 int	aucc_query_encoding __P((void *, struct audio_encoding *));
    169 int	aucc_round_blocksize __P((void *, int));
    170 int	aucc_commit_settings __P((void *));
    171 int	aucc_start_output __P((void *, void *, int, void (*)(void *),
    172 				  void *));
    173 int	aucc_start_input __P((void *, void *, int, void (*)(void *),
    174 				 void *));
    175 int	aucc_halt_output __P((void *));
    176 int	aucc_halt_input __P((void *));
    177 int	aucc_getdev __P((void *, struct audio_device *));
    178 int	aucc_set_port __P((void *, mixer_ctrl_t *));
    179 int	aucc_get_port __P((void *, mixer_ctrl_t *));
    180 int	aucc_query_devinfo __P((void *, mixer_devinfo_t *));
    181 void	aucc_encode __P((int, int, int, u_char *, u_short **));
    182 int	aucc_set_params __P((void *, int, int,
    183 	    struct audio_params *, struct audio_params *));
    184 int	aucc_get_props __P((void *));
    185 
    186 struct audio_hw_if sa_hw_if = {
    187 	aucc_open,
    188 	aucc_close,
    189 	NULL,
    190 	aucc_query_encoding,
    191 	aucc_set_params,
    192 	aucc_round_blocksize,
    193 	aucc_commit_settings,
    194 	NULL,
    195 	NULL,
    196 	aucc_start_output,
    197 	aucc_start_input,
    198 	aucc_halt_output,
    199 	aucc_halt_input,
    200 	NULL,
    201 	aucc_getdev,
    202 	NULL,
    203 	aucc_set_port,
    204 	aucc_get_port,
    205 	aucc_query_devinfo,
    206 	NULL,
    207 	NULL,
    208 	NULL,
    209 	NULL,
    210 	aucc_get_props,
    211 };
    212 
    213 /* autoconfig routines */
    214 
    215 int
    216 auccmatch(pdp, cfp, aux)
    217 	struct device *pdp;
    218 	struct cfdata *cfp;
    219 	void *aux;
    220 {
    221 	if (matchname((char *)aux, "aucc") &&
    222 #ifdef DRACO
    223 	    !is_draco() &&
    224 #endif
    225 	    (cfp->cf_unit == 0))
    226 		return 1;
    227 
    228 	return 0;
    229 }
    230 
    231 /*
    232  * Audio chip found.
    233  */
    234 void
    235 auccattach(parent, self, args)
    236 	struct device *parent, *self;
    237 	void *args;
    238 {
    239 	register struct aucc_softc *sc = (struct aucc_softc *)self;
    240 	register int i;
    241 
    242 	printf("\n");
    243 
    244 	if((i=init_aucc(sc))) {
    245 		printf("audio: no chipmem\n");
    246 		return;
    247 	}
    248 
    249 	audio_attach_mi(&sa_hw_if, 0, sc, &sc->sc_dev);
    250 }
    251 
    252 
    253 static int
    254 init_aucc(sc)
    255 	struct aucc_softc *sc;
    256 {
    257 	register int i, err=0;
    258 
    259 	/* init values per channel */
    260  	for (i=0;i<4;i++) {
    261 		sc->sc_channel[i].nd_freq=8000;
    262 		sc->sc_channel[i].nd_per=freqtoper(8000);
    263 		sc->sc_channel[i].nd_busy=0;
    264 		sc->sc_channel[i].nd_dma=alloc_chipmem(AUDIO_BUF_SIZE*2);
    265 		if (sc->sc_channel[i].nd_dma==NULL)
    266 			err=1;
    267 	 	sc->sc_channel[i].nd_dmalength=0;
    268 		sc->sc_channel[i].nd_volume=64;
    269 		sc->sc_channel[i].nd_intr=NULL;
    270 		sc->sc_channel[i].nd_intrdata=NULL;
    271 		sc->sc_channel[i].nd_doublebuf=0;
    272 		DPRINTF(("dma buffer for channel %d is %p\n", i,
    273 		    sc->sc_channel[i].nd_dma));
    274 
    275 	}
    276 
    277 	if (err) {
    278 		for(i=0;i<4;i++)
    279 			if (sc->sc_channel[i].nd_dma)
    280 				free_chipmem(sc->sc_channel[i].nd_dma);
    281 	}
    282 
    283 	sc->sc_channels=1;
    284 	sc->sc_channelmask=0xf;
    285 
    286 	/* clear interrupts and dma: */
    287 	custom.intena = AUCC_ALLINTF;
    288 	custom.dmacon = AUCC_ALLDMAF;;
    289 
    290 	sc->sc_encoding=AUDIO_ENCODING_ULAW;
    291 
    292 	return err;
    293 
    294 }
    295 
    296 int
    297 aucc_open(addr, flags)
    298 	void *addr;
    299 	int flags;
    300 {
    301 	struct aucc_softc *sc = addr;
    302 	int i;
    303 
    304 	DPRINTF(("sa_open: unit %p\n",sc));
    305 
    306 	if (sc->sc_open)
    307 		return (EBUSY);
    308 	sc->sc_open = 1;
    309 	for (i=0;i<AUCC_MAXINT;i++) {
    310 		sc->sc_channel[i].nd_intr=NULL;
    311 		sc->sc_channel[i].nd_intrdata=NULL;
    312 	}
    313 	aucc=sc;
    314 	sc->sc_channelmask=0xf;
    315 
    316 	DPRINTF(("saopen: ok -> sc=0x%p\n",sc));
    317 
    318 	return (0);
    319 }
    320 
    321 void
    322 aucc_close(addr)
    323 	void *addr;
    324 {
    325 	register struct aucc_softc *sc = addr;
    326 
    327 	DPRINTF(("sa_close: sc=0x%p\n", sc));
    328 	/*
    329 	 * halt i/o, clear open flag, and done.
    330 	 */
    331 	aucc_halt_output(sc);
    332 	sc->sc_open = 0;
    333 
    334 	DPRINTF(("sa_close: closed.\n"));
    335 }
    336 
    337 int
    338 aucc_set_out_sr(addr, sr)
    339 	void *addr;
    340 	u_long sr;
    341 {
    342 	struct aucc_softc *sc=addr;
    343 	u_long per;
    344 	register int i;
    345 
    346 	per=freqtoper(sr);
    347 	if (per>0xffff)
    348 		return EINVAL;
    349 	sr=pertofreq(per);
    350 
    351 	for (i=0;i<4;i++) {
    352 		sc->sc_channel[i].nd_freq=sr;
    353 		sc->sc_channel[i].nd_per=per;
    354 	}
    355 
    356 	return(0);
    357 }
    358 
    359 int
    360 aucc_query_encoding(addr, fp)
    361 	void *addr;
    362 	struct audio_encoding *fp;
    363 {
    364 	switch (fp->index) {
    365 	case 0:
    366 		strcpy(fp->name, AudioEslinear);
    367 		fp->encoding = AUDIO_ENCODING_SLINEAR;
    368 		fp->precision = 8;
    369 		fp->flags = 0;
    370 		break;
    371 	case 1:
    372 		strcpy(fp->name, AudioEmulaw);
    373 		fp->encoding = AUDIO_ENCODING_ULAW;
    374 		fp->precision = 8;
    375 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    376 		break;
    377 
    378 	case 2:
    379 		strcpy(fp->name, AudioEulinear);
    380 		fp->encoding = AUDIO_ENCODING_ULINEAR;
    381 		fp->precision = 8;
    382 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    383 		break;
    384 
    385 	default:
    386 		return(EINVAL);
    387 		/*NOTREACHED*/
    388 	}
    389 	return(0);
    390 }
    391 
    392 int
    393 aucc_set_params(addr, setmode, usemode, p, r)
    394 	void *addr;
    395 	int setmode, usemode;
    396 	struct  audio_params *p, *r;
    397 {
    398 	struct aucc_softc *sc = addr;
    399 
    400 	/* if (setmode & AUMODE_RECORD)
    401 		return 0 ENXIO*/;
    402 
    403 #ifdef AUCCDEBUG
    404 	printf("aucc_set_params(setmode 0x%x, usemode 0x%x, enc %d, bits %d, chn %d, sr %ld)\n",
    405 	    setmode, usemode, p->encoding, p->precision, p->channels, p->sample_rate);
    406 #endif
    407 
    408 	switch (p->encoding) {
    409 	case AUDIO_ENCODING_ULAW:
    410 	case AUDIO_ENCODING_SLINEAR:
    411 	case AUDIO_ENCODING_SLINEAR_BE:
    412 	case AUDIO_ENCODING_SLINEAR_LE:
    413 	case AUDIO_ENCODING_ULINEAR_BE:
    414 	case AUDIO_ENCODING_ULINEAR_LE:
    415 		break;
    416 
    417 	default:
    418 		return EINVAL;
    419 		/* NOTREADCHED */
    420 	}
    421 
    422 	if (p->precision != 8)
    423 		return EINVAL;
    424 
    425 	if ((p->channels<1) || (p->channels>4))
    426 		return(EINVAL);
    427 
    428 	sc->sc_channels = p->channels;
    429 	sc->sc_encoding = p->encoding;
    430 
    431 	return aucc_set_out_sr(addr, p->sample_rate);
    432 }
    433 
    434 int
    435 aucc_round_blocksize(addr, blk)
    436 	void *addr;
    437 	int blk;
    438 {
    439 
    440 
    441 	return blk>AUDIO_BUF_SIZE?AUDIO_BUF_SIZE:blk; /* round up to even size */
    442 }
    443 
    444 int
    445 aucc_commit_settings(addr)
    446 	void *addr;
    447 {
    448 	register struct aucc_softc *sc = addr;
    449 	register int i;
    450 
    451 	DPRINTF(("sa_commit.\n"));
    452 
    453 	for (i=0;i<4;i++) {
    454 		custom.aud[i].vol=sc->sc_channel[i].nd_volume;
    455 		custom.aud[i].per=sc->sc_channel[i].nd_per;
    456 	}
    457 
    458 	DPRINTF(("commit done\n"));
    459 
    460 	return(0);
    461 }
    462 
    463 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
    464 static int masks2[4] = {1,2,4,8};
    465 
    466 int
    467 aucc_start_output(addr, p, cc, intr, arg)
    468 	void *addr;
    469 	void *p;
    470 	int cc;
    471 	void (*intr) __P((void *));
    472 	void *arg;
    473 {
    474 	struct aucc_softc *sc;
    475 	int mask;
    476 	int i,j,k;
    477 	u_short *dmap[4];
    478 	u_char *pp;
    479 
    480 
    481 	sc = addr;
    482 	mask = sc->sc_channelmask;
    483 
    484 	dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
    485 
    486 	DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
    487 
    488 	if (sc->sc_channels > 1)
    489 		mask &=masks[sc->sc_channels-1];
    490 		/* we use first sc_channels channels */
    491 	if (mask==0) /* active and used channels are disjoint */
    492 		return EINVAL;
    493 
    494 	for (i=0;i<4;i++) { /* channels available ? */
    495 		if ((masks2[i]&mask)&&(sc->sc_channel[i].nd_busy))
    496 			return EBUSY; /* channel is busy */
    497 		if (channel[i].isaudio==-1)
    498 			return EBUSY; /* system uses them */
    499 	}
    500 
    501 	/* enable interrupt on 1st channel */
    502 	for (i=j=0;i<AUCC_MAXINT;i++) {
    503 		if (masks2[i]&mask) {
    504 			DPRINTF(("first channel is %d\n",i));
    505 			j=i;
    506 			sc->sc_channel[i].nd_intr=intr;
    507 			sc->sc_channel[i].nd_intrdata=arg;
    508 			break;
    509 		}
    510 	}
    511 
    512 	DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
    513 		dmap[2], dmap[3], mask));
    514 
    515 	/* disable ints, dma for channels, until all parameters set */
    516 	/* XXX dont disable DMA! custom.dmacon=mask;*/
    517 	custom.intreq=mask<<INTB_AUD0;
    518 	custom.intena=mask<<INTB_AUD0;
    519 
    520 	/* copy data to dma buffer */
    521 
    522 
    523 	pp=(u_char *)p;
    524 
    525 	if (sc->sc_channels == 1) {
    526 		dmap[0] =
    527 		dmap[1] =
    528 		dmap[2] =
    529 		dmap[3] = sc->sc_channel[j].nd_dma;
    530 	} else {
    531 		for (k=0; k<4; k++) {
    532 			if (masks2[k+j]&mask)
    533 				dmap[k]=sc->sc_channel[k+j].nd_dma;
    534 		}
    535 	}
    536 
    537 	sc->sc_channel[j].nd_doublebuf ^= 1;
    538 	if (sc->sc_channel[j].nd_doublebuf) {
    539 		dmap[0] += AUDIO_BUF_SIZE/sizeof(u_short);
    540 		dmap[1] += AUDIO_BUF_SIZE/sizeof(u_short);
    541 		dmap[2] += AUDIO_BUF_SIZE/sizeof(u_short);
    542 		dmap[3] += AUDIO_BUF_SIZE/sizeof(u_short);
    543 	}
    544 
    545 	aucc_encode(sc->sc_encoding, sc->sc_channels, cc, pp, dmap);
    546 
    547 	/* dma buffers: we use same buffer 4 all channels */
    548 	/* write dma location and length */
    549 	for (i=k=0; i<4; i++) {
    550 		if (masks2[i] & mask) {
    551 			DPRINTF(("turning channel %d on\n",i));
    552 			/*  sc->sc_channel[i].nd_busy=1;*/
    553 			channel[i].isaudio=1;
    554 			channel[i].play_count=1;
    555 			channel[i].handler=NULL;
    556 			custom.aud[i].per=sc->sc_channel[i].nd_per;
    557 			custom.aud[i].vol=sc->sc_channel[i].nd_volume;
    558 			custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
    559 			custom.aud[i].len=cc/(sc->sc_channels*2);
    560 			sc->sc_channel[i].nd_mask=mask;
    561 			DPRINTF(("per is %d, vol is %d, len is %d\n",\
    562 			    sc->sc_channel[i].nd_per,
    563 			    sc->sc_channel[i].nd_volume, cc>>1));
    564 
    565 		}
    566 	}
    567 
    568 	channel[j].handler=aucc_inthdl;
    569 
    570 	/* enable ints */
    571 	custom.intena=INTF_SETCLR|INTF_INTEN| (masks2[j]<<INTB_AUD0);
    572 
    573 	DPRINTF(("enabled ints: 0x%x\n",(masks2[j]<<INTB_AUD0)));
    574 
    575 	/* enable dma */
    576 	custom.dmacon=DMAF_SETCLR|DMAF_MASTER|mask;
    577 
    578 	DPRINTF(("enabled dma, mask=0x%x\n",mask));
    579 
    580 	return(0);
    581 }
    582 
    583 /* ARGSUSED */
    584 int
    585 aucc_start_input(addr, p, cc, intr, arg)
    586 	void *addr;
    587 	void *p;
    588 	int cc;
    589 	void (*intr) __P((void *));
    590 	void *arg;
    591 {
    592 
    593 	return ENXIO; /* no input */
    594 }
    595 
    596 int
    597 aucc_halt_output(addr)
    598 	void *addr;
    599 {
    600 	register struct aucc_softc *sc = addr;
    601 	register int i;
    602 
    603 	/* XXX only halt, if input is also halted ?? */
    604 	/* stop dma, etc */
    605 	custom.intena = AUCC_ALLINTF;
    606 	custom.dmacon = AUCC_ALLDMAF;
    607 	/* mark every busy unit idle */
    608 	for (i=0;i<4;i++) {
    609 		sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0;
    610 		channel[i].isaudio=0;
    611 		channel[i].play_count=0;
    612 	}
    613 
    614 	return(0);
    615 }
    616 
    617 int
    618 aucc_halt_input(addr)
    619 	void *addr;
    620 {
    621 	/* no input */
    622 
    623 	return ENXIO;
    624 }
    625 
    626 int
    627 aucc_getdev(addr, retp)
    628         void *addr;
    629         struct audio_device *retp;
    630 {
    631         *retp = aucc_device;
    632         return 0;
    633 }
    634 
    635 int
    636 aucc_set_port(addr, cp)
    637 	void *addr;
    638 	mixer_ctrl_t *cp;
    639 {
    640 	register struct aucc_softc *sc = addr;
    641 	register int i,j;
    642 
    643 	DPRINTF(("aucc_set_port: port=%d", cp->dev));
    644 
    645 	switch (cp->type) {
    646 	case AUDIO_MIXER_SET:
    647 		if (cp->dev!=AUCC_CHANNELS)
    648 			return EINVAL;
    649 		i=cp->un.mask;
    650 		if ((i<1)||(i>15))
    651 			return EINVAL;
    652 		sc->sc_channelmask=i;
    653 		break;
    654 
    655 	case AUDIO_MIXER_VALUE:
    656 		i=cp->un.value.num_channels;
    657 		if ((i<1)||(i>4))
    658 			return EINVAL;
    659 
    660 #ifdef __XXXwhatsthat
    661 		if (cp->dev!=AUCC_VOLUME)
    662 			return EINVAL;
    663 #endif
    664 
    665 		/* set volume for channel 0..i-1 */
    666 
    667 		/* evil workaround for xanim bug, IMO */
    668 		if ((sc->sc_channels == 1) && (i == 2)) {
    669 			sc->sc_channel[0].nd_volume =
    670 			    sc->sc_channel[3].nd_volume =
    671 			    cp->un.value.level[0]>>2;
    672 			sc->sc_channel[1].nd_volume =
    673 			    sc->sc_channel[2].nd_volume =
    674 			    cp->un.value.level[1]>>2;
    675 		} else if (i>1) {
    676 			for (j=0;j<i;j++)
    677 	 			sc->sc_channel[j].nd_volume =
    678 				    cp->un.value.level[j]>>2;
    679 		} else if (sc->sc_channels > 1)
    680 			for (j=0; j<sc->sc_channels; j++)
    681 	 			sc->sc_channel[j].nd_volume =
    682 				    cp->un.value.level[0]>>2;
    683 		else
    684 			for (j=0; j<4; j++)
    685 	 			sc->sc_channel[j].nd_volume =
    686 				    cp->un.value.level[0]>>2;
    687 		break;
    688 
    689 	default:
    690 		return EINVAL;
    691 		break;
    692 	}
    693 	return 0;
    694 }
    695 
    696 
    697 int
    698 aucc_get_port(addr, cp)
    699 	void *addr;
    700 	mixer_ctrl_t *cp;
    701 {
    702 	register struct aucc_softc *sc = addr;
    703 	register int i,j;
    704 
    705 	DPRINTF(("aucc_get_port: port=%d", cp->dev));
    706 
    707 	switch (cp->type) {
    708 	case AUDIO_MIXER_SET:
    709 		if (cp->dev!=AUCC_CHANNELS)
    710 			return EINVAL;
    711 		cp->un.mask=sc->sc_channelmask;
    712 		break;
    713 
    714 	case AUDIO_MIXER_VALUE:
    715 		i = cp->un.value.num_channels;
    716 		if ((i<1)||(i>4))
    717 			return EINVAL;
    718 
    719 		for (j=0;j<i;j++)
    720 			cp->un.value.level[j] =
    721 			    (sc->sc_channel[j].nd_volume<<2) +
    722 			    (sc->sc_channel[j].nd_volume>>4);
    723 		break;
    724 
    725 	default:
    726 		return EINVAL;
    727 	}
    728 	return 0;
    729 }
    730 
    731 
    732 int
    733 aucc_get_props(addr)
    734 	void *addr;
    735 {
    736 	return 0;
    737 }
    738 
    739 int
    740 aucc_query_devinfo(addr, dip)
    741 	void *addr;
    742 	register mixer_devinfo_t *dip;
    743 {
    744 	register int i;
    745 
    746 	switch(dip->index) {
    747 	case AUCC_CHANNELS:
    748 		dip->type = AUDIO_MIXER_SET;
    749 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    750 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    751                 strcpy(dip->label.name, AudioNspeaker);
    752 		for (i=0;i<16;i++) {
    753 			sprintf(dip->un.s.member[i].label.name,
    754 			    "channelmask%d", i);
    755 			dip->un.s.member[i].mask = i;
    756 		}
    757 		dip->un.s.num_mem = 16;
    758 		break;
    759 
    760 	case AUCC_VOLUME:
    761 		dip->type = AUDIO_MIXER_VALUE;
    762 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    763 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    764 		strcpy(dip->label.name, AudioNmaster);
    765 		dip->un.v.num_channels = 4;
    766 		strcpy(dip->un.v.units.name, AudioNvolume);
    767 		break;
    768 
    769 	case AUCC_OUTPUT_CLASS:
    770 		dip->type = AUDIO_MIXER_CLASS;
    771 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    772 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    773 		strcpy(dip->label.name, AudioCoutputs);
    774 		break;
    775 
    776 	default:
    777 		return ENXIO;
    778 	}
    779 
    780 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
    781 
    782 	return(0);
    783 }
    784 
    785 
    786 /* audio int handler */
    787 void
    788 aucc_inthdl(int ch)
    789 {
    790 	register int i;
    791 	register int mask=aucc->sc_channel[ch].nd_mask;
    792 
    793 	/* for all channels in this maskgroup:
    794 	   disable dma, int
    795 	   mark idle */
    796 	DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask));
    797 
    798 	custom.intreq=mask<<INTB_AUD0; /* clear request */
    799 	/* XXX: maybe we can leave ints and/or DMA on, if another sample has to be played?*/
    800 	custom.intena=mask<<INTB_AUD0;
    801 	/*
    802 	 * XXX custom.dmacon=mask; NO!!!
    803 	 */
    804 	for (i=0;i<4;i++) {
    805 		if (masks2[i]&&mask) {
    806 			DPRINTF(("marking channel %d idle\n",i));
    807 			aucc->sc_channel[i].nd_busy=0;
    808 			aucc->sc_channel[i].nd_mask=0;
    809 			channel[i].isaudio=channel[i].play_count=0;
    810 		}
    811 	}
    812 
    813 	/* call handler */
    814 	if (aucc->sc_channel[ch].nd_intr) {
    815 		DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
    816 		(*(aucc->sc_channel[ch].nd_intr))(aucc->sc_channel[ch].nd_intrdata);
    817 	}
    818 	else DPRINTF(("zero int handler\n"));
    819 	DPRINTF(("ints done\n"));
    820 }
    821 
    822 
    823 
    824 
    825 /* transform frequency to period, adjust bounds */
    826 static u_int
    827 freqtoper(u_int freq)
    828 {
    829 	u_int per=eclockfreq*5/freq;
    830 
    831 	if (per<124)
    832 		per=124; /* must have at least 124 ticks between samples */
    833 
    834 	return per;
    835 }
    836 
    837 /* transform period to frequency */
    838 static u_int
    839 pertofreq(u_int per)
    840 {
    841 	u_int freq=eclockfreq*5/per;
    842 
    843 
    844 	return freq;
    845 }
    846 
    847 
    848 
    849 void
    850 aucc_encode(enc, channels, i, p, dmap)
    851 	int enc, channels, i;
    852 	u_char *p;
    853 	u_short **dmap;
    854 {
    855 	char *q, *r, *s, *t;
    856 	int off;
    857 	u_char *tab;
    858 
    859 #ifdef AUCCDEBUG
    860 	static int debctl = 6;
    861 #endif
    862 
    863 	off = 0;
    864 	tab = NULL;
    865 
    866 #ifdef AUCCDEBUG
    867 	if (--debctl >= 0)
    868 		printf("Enc: enc %d, chan %d, dmap %p %p %p %p\n",
    869 		    enc, channels, dmap[0], dmap[1], dmap[2], dmap[3]);
    870 #endif
    871 
    872 	switch (enc) {
    873 	case AUDIO_ENCODING_ULAW:
    874 		tab=ulaw_to_lin;
    875 		break;
    876 	case AUDIO_ENCODING_ULINEAR_BE:
    877 	case AUDIO_ENCODING_ULINEAR_LE:
    878 		off=-128;
    879 		break;
    880 	case AUDIO_ENCODING_SLINEAR_BE:
    881 	case AUDIO_ENCODING_SLINEAR_LE:
    882 		break;
    883 	default:
    884 		return;
    885 	}
    886 
    887 	q = (char *)dmap[0];
    888 	r = (char *)dmap[1];
    889 	s = (char *)dmap[2];
    890 	t = (char *)dmap[3];
    891 
    892 	if (tab)
    893 		while (i) {
    894 			switch (channels) {
    895 			case 4: *t++ = tab[*p++];
    896 			case 3: *s++ = tab[*p++];
    897 			case 2: *r++ = tab[*p++];
    898 			case 1: *q++ = tab[*p++];
    899 			}
    900 			i -= channels;
    901 		}
    902 	else
    903 		while (i) {
    904 			switch (channels) {
    905 			case 4: *t++ = *p++ + off;
    906 			case 3: *s++ = *p++ + off;
    907 			case 2: *r++ = *p++ + off;
    908 			case 1: *q++ = *p++ + off;
    909 			}
    910 			i -= channels;
    911 		}
    912 
    913 }
    914 
    915 #endif /* NAUCC > 0 */
    916