Home | History | Annotate | Line # | Download | only in dev
aucc.c revision 1.46
      1 /*	$NetBSD: aucc.c,v 1.46 2019/06/08 08:02:36 isaki Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1999 Bernardo Innocenti
      5  * All rights reserved.
      6  *
      7  * Copyright (c) 1997 Stephan Thesing
      8  * All rights reserved.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *      This product includes software developed by Stephan Thesing.
     21  * 4. The name of the author may not be used to endorse or promote products
     22  *    derived from this software without specific prior written permission
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     34  */
     35 
     36 /* TODO:
     37  *
     38  * - channel allocation is wrong for 14bit mono
     39  * - perhaps use a calibration table for better 14bit output
     40  * - set 31 kHz AGA video mode to allow 44.1 kHz even if grfcc is missing
     41  *	in the kernel
     42  * - 14bit output requires maximum volume
     43  */
     44 
     45 #include "aucc.h"
     46 #if NAUCC > 0
     47 
     48 #include <sys/cdefs.h>
     49 __KERNEL_RCSID(0, "$NetBSD: aucc.c,v 1.46 2019/06/08 08:02:36 isaki Exp $");
     50 
     51 #include <sys/param.h>
     52 #include <sys/systm.h>
     53 #include <sys/errno.h>
     54 #include <sys/ioctl.h>
     55 #include <sys/device.h>
     56 #include <sys/proc.h>
     57 #include <machine/cpu.h>
     58 
     59 #include <sys/audioio.h>
     60 #include <dev/audio/audio_if.h>
     61 #include <dev/audio/audiovar.h>	/* for AUDIO_MIN_FREQUENCY */
     62 
     63 #include <amiga/amiga/cc.h>
     64 #include <amiga/amiga/custom.h>
     65 #include <amiga/amiga/device.h>
     66 #include <amiga/dev/auccvar.h>
     67 
     68 #include "opt_lev6_defer.h"
     69 
     70 
     71 #ifdef LEV6_DEFER
     72 #define AUCC_MAXINT 3
     73 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2)
     74 #else
     75 #define AUCC_MAXINT 4
     76 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3)
     77 #endif
     78 /* this unconditionally; we may use AUD3 as slave channel with LEV6_DEFER */
     79 #define AUCC_ALLDMAF (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3)
     80 
     81 #ifdef AUDIO_DEBUG
     82 /*extern printf(const char *,...);*/
     83 int     auccdebug = 1;
     84 #define DPRINTF(x)      if (auccdebug) printf x
     85 #else
     86 #define DPRINTF(x)
     87 #endif
     88 
     89 /* clock frequency.. */
     90 extern int eclockfreq;
     91 
     92 
     93 /* hw audio ch */
     94 extern struct audio_channel channel[4];
     95 
     96 
     97 /*
     98  * Software state.
     99  */
    100 struct aucc_softc {
    101 	aucc_data_t sc_channel[4];	/* per channel freq, ... */
    102 	u_int	sc_encoding;		/* encoding AUDIO_ENCODING_.*/
    103 	int	sc_channels;		/* # of channels used */
    104 	int	sc_precision;		/* 8 or 16 bits */
    105 	int	sc_14bit;		/* 14bit output enabled */
    106 
    107 	int	sc_intrcnt;		/* interrupt count */
    108 	int	sc_channelmask;		/* which channels are used ? */
    109 	void (*sc_decodefunc)(u_char **, u_char *, int);
    110 				/* pointer to format conversion routine */
    111 
    112 	kmutex_t sc_lock;
    113 	kmutex_t sc_intr_lock;
    114 };
    115 
    116 /* interrupt interfaces */
    117 void aucc_inthdl(int);
    118 
    119 /* forward declarations */
    120 static int init_aucc(struct aucc_softc *);
    121 static u_int freqtoper(u_int);
    122 static u_int pertofreq(u_int);
    123 
    124 /* autoconfiguration driver */
    125 void	auccattach(device_t, device_t, void *);
    126 int	auccmatch(device_t, cfdata_t, void *);
    127 
    128 CFATTACH_DECL_NEW(aucc, sizeof(struct aucc_softc),
    129     auccmatch, auccattach, NULL, NULL);
    130 
    131 struct audio_device aucc_device = {
    132 	"Amiga-audio",
    133 	"2.0",
    134 	"aucc"
    135 };
    136 
    137 
    138 struct aucc_softc *aucc = NULL;
    139 
    140 
    141 /*
    142  * Define our interface to the higher level audio driver.
    143  */
    144 int	aucc_open(void *, int);
    145 void	aucc_close(void *);
    146 int	aucc_set_out_sr(void *, u_int);
    147 int	aucc_query_format(void *, audio_format_query_t *);
    148 int	aucc_round_blocksize(void *, int, int, const audio_params_t *);
    149 int	aucc_commit_settings(void *);
    150 int	aucc_start_output(void *, void *, int, void (*)(void *), void *);
    151 int	aucc_start_input(void *, void *, int, void (*)(void *), void *);
    152 int	aucc_halt_output(void *);
    153 int	aucc_halt_input(void *);
    154 int	aucc_getdev(void *, struct audio_device *);
    155 int	aucc_set_port(void *, mixer_ctrl_t *);
    156 int	aucc_get_port(void *, mixer_ctrl_t *);
    157 int	aucc_query_devinfo(void *, mixer_devinfo_t *);
    158 void	aucc_encode(int, int, int, int, u_char *, u_short **);
    159 int	aucc_set_format(void *, int,
    160 			const audio_params_t *, const audio_params_t *,
    161 			audio_filter_reg_t *, audio_filter_reg_t *);
    162 int	aucc_get_props(void *);
    163 void	aucc_get_locks(void *, kmutex_t **, kmutex_t **);
    164 
    165 
    166 static void aucc_decode_slinear16_1ch(u_char **, u_char *, int);
    167 static void aucc_decode_slinear16_2ch(u_char **, u_char *, int);
    168 static void aucc_decode_slinear16_3ch(u_char **, u_char *, int);
    169 static void aucc_decode_slinear16_4ch(u_char **, u_char *, int);
    170 
    171 
    172 const struct audio_hw_if sa_hw_if = {
    173 	.open			= aucc_open,
    174 	.close			= aucc_close,
    175 	.query_format		= aucc_query_format,
    176 	.set_format		= aucc_set_format,
    177 	.round_blocksize	= aucc_round_blocksize,
    178 	.commit_settings	= aucc_commit_settings,
    179 	.start_output		= aucc_start_output,
    180 	.start_input		= aucc_start_input,
    181 	.halt_output		= aucc_halt_output,
    182 	.halt_input		= aucc_halt_input,
    183 	.getdev			= aucc_getdev,
    184 	.set_port		= aucc_set_port,
    185 	.get_port		= aucc_get_port,
    186 	.query_devinfo		= aucc_query_devinfo,
    187 	.get_props		= aucc_get_props,
    188 	.get_locks		= aucc_get_locks,
    189 };
    190 
    191 /*
    192  * XXX *1 How lower limit of frequency should be?  same as audio(4)?
    193  * XXX *2 Should avoid a magic number at the upper limit of frequency.
    194  * XXX *3 In fact, there is a number in this range that have minimal errors.
    195  *        It would be better if there is a mechanism which such frequency
    196  *        is prioritized.
    197  * XXX *4 3/4ch modes use 8bits, 1/2ch modes use 14bits,
    198  *        so I imagined that 1/2ch modes are better.
    199  */
    200 #define AUCC_FORMAT(prio, ch, chmask) \
    201 	{ \
    202 		.mode		= AUMODE_PLAY, \
    203 		.priority	= (prio), \
    204 		.encoding	= AUDIO_ENCODING_SLINEAR_BE, \
    205 		.validbits	= 16, \
    206 		.precision	= 16, \
    207 		.channels	= (ch), \
    208 		.channel_mask	= (chmask), \
    209 		.frequency_type	= 0, \
    210 		.frequency	= { AUDIO_MIN_FREQUENCY, 28867 }, \
    211 	}
    212 static const struct audio_format aucc_formats[] = {
    213 	AUCC_FORMAT(1, 1, AUFMT_MONAURAL),
    214 	AUCC_FORMAT(1, 2, AUFMT_STEREO),
    215 	AUCC_FORMAT(0, 3, AUFMT_UNKNOWN_POSITION),
    216 	AUCC_FORMAT(0, 4, AUFMT_UNKNOWN_POSITION),
    217 };
    218 #define AUCC_NFORMATS __arraycount(aucc_formats)
    219 
    220 /* autoconfig routines */
    221 
    222 int
    223 auccmatch(device_t parent, cfdata_t cf, void *aux)
    224 {
    225 	static int aucc_matched = 0;
    226 
    227 	if (!matchname((char *)aux, "aucc") ||
    228 #ifdef DRACO
    229 	    is_draco() ||
    230 #endif
    231 	    aucc_matched)
    232 		return 0;
    233 
    234 	aucc_matched = 1;
    235 	return 1;
    236 }
    237 
    238 /*
    239  * Audio chip found.
    240  */
    241 void
    242 auccattach(device_t parent, device_t self, void *args)
    243 {
    244 	struct aucc_softc *sc;
    245 	int i;
    246 
    247 	sc = device_private(self);
    248 	printf("\n");
    249 
    250 	if ((i=init_aucc(sc))) {
    251 		printf("audio: no chipmem\n");
    252 		return;
    253 	}
    254 
    255 	audio_attach_mi(&sa_hw_if, sc, self);
    256 }
    257 
    258 
    259 static int
    260 init_aucc(struct aucc_softc *sc)
    261 {
    262 	int i, err;
    263 
    264 	err = 0;
    265 	/* init values per channel */
    266 	for (i = 0; i < 4; i++) {
    267 		sc->sc_channel[i].nd_freq = 8000;
    268 		sc->sc_channel[i].nd_per = freqtoper(8000);
    269 		sc->sc_channel[i].nd_busy = 0;
    270 		sc->sc_channel[i].nd_dma = alloc_chipmem(AUDIO_BUF_SIZE*2);
    271 		if (sc->sc_channel[i].nd_dma == NULL)
    272 			err = 1;
    273 		sc->sc_channel[i].nd_dmalength = 0;
    274 		sc->sc_channel[i].nd_volume = 64;
    275 		sc->sc_channel[i].nd_intr = NULL;
    276 		sc->sc_channel[i].nd_intrdata = NULL;
    277 		sc->sc_channel[i].nd_doublebuf = 0;
    278 		DPRINTF(("DMA buffer for channel %d is %p\n", i,
    279 		    sc->sc_channel[i].nd_dma));
    280 	}
    281 
    282 	if (err) {
    283 		for (i = 0; i < 4; i++)
    284 			if (sc->sc_channel[i].nd_dma)
    285 				free_chipmem(sc->sc_channel[i].nd_dma);
    286 	}
    287 
    288 	sc->sc_channels = 1;
    289 	sc->sc_channelmask = 0xf;
    290 	sc->sc_precision = 16;
    291 	sc->sc_14bit = 1;
    292 	sc->sc_encoding = AUDIO_ENCODING_SLINEAR_BE;
    293 	sc->sc_decodefunc = aucc_decode_slinear16_2ch;
    294 
    295 	/* clear interrupts and DMA: */
    296 	custom.intena = AUCC_ALLINTF;
    297 	custom.dmacon = AUCC_ALLDMAF;
    298 
    299 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    300 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
    301 
    302 	return err;
    303 }
    304 
    305 int
    306 aucc_open(void *addr, int flags)
    307 {
    308 	struct aucc_softc *sc;
    309 	int i;
    310 
    311 	sc = addr;
    312 	DPRINTF(("sa_open: unit %p\n",sc));
    313 
    314 	for (i = 0; i < AUCC_MAXINT; i++) {
    315 		sc->sc_channel[i].nd_intr = NULL;
    316 		sc->sc_channel[i].nd_intrdata = NULL;
    317 	}
    318 	aucc = sc;
    319 	sc->sc_channelmask = 0xf;
    320 
    321 	DPRINTF(("saopen: ok -> sc=%p\n",sc));
    322 
    323 	return 0;
    324 }
    325 
    326 void
    327 aucc_close(void *addr)
    328 {
    329 
    330 	DPRINTF(("sa_close: closed.\n"));
    331 }
    332 
    333 int
    334 aucc_set_out_sr(void *addr, u_int sr)
    335 {
    336 	struct aucc_softc *sc;
    337 	u_long per;
    338 	int i;
    339 
    340 	sc = addr;
    341 	per = freqtoper(sr);
    342 	if (per > 0xffff)
    343 		return EINVAL;
    344 	sr = pertofreq(per);
    345 
    346 	for (i = 0; i < 4; i++) {
    347 		sc->sc_channel[i].nd_freq = sr;
    348 		sc->sc_channel[i].nd_per = per;
    349 	}
    350 
    351 	return 0;
    352 }
    353 
    354 int
    355 aucc_query_format(void *addr, audio_format_query_t *afp)
    356 {
    357 
    358 	return audio_query_format(aucc_formats, AUCC_NFORMATS, afp);
    359 }
    360 
    361 int
    362 aucc_set_format(void *addr, int setmode,
    363 	const audio_params_t *p, const audio_params_t *r,
    364 	audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
    365 {
    366 	struct aucc_softc *sc;
    367 
    368 	sc = addr;
    369 	KASSERT((setmode & AUMODE_RECORD) == 0);
    370 
    371 #ifdef AUCCDEBUG
    372 	printf("%s(setmode 0x%x,"
    373 	    "enc %u bits %u, chn %u, sr %u)\n", setmode,
    374 	    p->encoding, p->precision, p->channels, p->sample_rate);
    375 #endif
    376 
    377 	switch (p->channels) {
    378 	case 1:
    379 		sc->sc_decodefunc = aucc_decode_slinear16_1ch;
    380 		break;
    381 	case 2:
    382 		sc->sc_decodefunc = aucc_decode_slinear16_2ch;
    383 		break;
    384 	case 3:
    385 		sc->sc_decodefunc = aucc_decode_slinear16_3ch;
    386 		break;
    387 	case 4:
    388 		sc->sc_decodefunc = aucc_decode_slinear16_4ch;
    389 		break;
    390 	default:
    391 		return EINVAL;
    392 	}
    393 
    394 	sc->sc_encoding = p->encoding;
    395 	sc->sc_precision = p->precision;
    396 	sc->sc_14bit = ((p->precision == 16) && (p->channels <= 2));
    397 	sc->sc_channels = sc->sc_14bit ? (p->channels * 2) : p->channels;
    398 
    399 	return aucc_set_out_sr(addr, p->sample_rate);
    400 }
    401 
    402 int
    403 aucc_round_blocksize(void *addr, int blk,
    404 		     int mode, const audio_params_t *param)
    405 {
    406 
    407 	/* round up to even size */
    408 	return blk > AUDIO_BUF_SIZE ? AUDIO_BUF_SIZE : blk;
    409 }
    410 
    411 int
    412 aucc_commit_settings(void *addr)
    413 {
    414 	struct aucc_softc *sc;
    415 	int i;
    416 
    417 	DPRINTF(("sa_commit.\n"));
    418 
    419 	sc = addr;
    420 	for (i = 0; i < 4; i++) {
    421 		custom.aud[i].vol = sc->sc_channel[i].nd_volume;
    422 		custom.aud[i].per = sc->sc_channel[i].nd_per;
    423 	}
    424 
    425 	DPRINTF(("commit done\n"));
    426 
    427 	return 0;
    428 }
    429 
    430 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
    431 static int masks2[4] = {1,2,4,8};
    432 
    433 int
    434 aucc_start_output(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
    435 {
    436 	struct aucc_softc *sc;
    437 	int mask;
    438 	int i, j, k, len;
    439 	u_char *dmap[4];
    440 
    441 
    442 	sc = addr;
    443 	mask = sc->sc_channelmask;
    444 
    445 	dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
    446 
    447 	DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
    448 
    449 	if (sc->sc_channels > 1)
    450 		mask &= masks[sc->sc_channels - 1];
    451 		/* we use first sc_channels channels */
    452 	if (mask == 0) /* active and used channels are disjoint */
    453 		return EINVAL;
    454 
    455 	for (i = 0; i < 4; i++) {
    456 		/* channels available ? */
    457 		if ((masks2[i] & mask) && (sc->sc_channel[i].nd_busy))
    458 			return EBUSY; /* channel is busy */
    459 		if (channel[i].isaudio == -1)
    460 			return EBUSY; /* system uses them */
    461 	}
    462 
    463 	/* enable interrupt on 1st channel */
    464 	for (i = j = 0; i < AUCC_MAXINT; i++) {
    465 		if (masks2[i] & mask) {
    466 			DPRINTF(("first channel is %d\n",i));
    467 			j = i;
    468 			sc->sc_channel[i].nd_intr = intr;
    469 			sc->sc_channel[i].nd_intrdata = arg;
    470 			break;
    471 		}
    472 	}
    473 
    474 	DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
    475 		 dmap[2], dmap[3], mask));
    476 
    477 	/* disable ints, DMA for channels, until all parameters set */
    478 	/* XXX dont disable DMA! custom.dmacon=mask;*/
    479 	custom.intreq = mask << INTB_AUD0;
    480 	custom.intena = mask << INTB_AUD0;
    481 
    482 	/* copy data to DMA buffer */
    483 
    484 	if (sc->sc_channels == 1) {
    485 		dmap[0] =
    486 		dmap[1] =
    487 		dmap[2] =
    488 		dmap[3] = (u_char *)sc->sc_channel[j].nd_dma;
    489 	} else {
    490 		for (k = 0; k < 4; k++) {
    491 			if (masks2[k+j] & mask)
    492 				dmap[k] = (u_char *)sc->sc_channel[k+j].nd_dma;
    493 		}
    494 	}
    495 
    496 	sc->sc_channel[j].nd_doublebuf ^= 1;
    497 	if (sc->sc_channel[j].nd_doublebuf) {
    498 		dmap[0] += AUDIO_BUF_SIZE;
    499 		dmap[1] += AUDIO_BUF_SIZE;
    500 		dmap[2] += AUDIO_BUF_SIZE;
    501 		dmap[3] += AUDIO_BUF_SIZE;
    502 	}
    503 
    504 	/*
    505 	 * compute output length in bytes per channel.
    506 	 * divide by two only for 16bit->8bit conversion.
    507 	 */
    508 	len = cc / sc->sc_channels;
    509 	if (!sc->sc_14bit && (sc->sc_precision == 16))
    510 		len /= 2;
    511 
    512 	/* call audio decoding routine */
    513 	sc->sc_decodefunc (dmap, (u_char *)p, len);
    514 
    515 	/* DMA buffers: we use same buffer 4 all channels
    516 	 * write DMA location and length
    517 	 */
    518 	for (i = k = 0; i < 4; i++) {
    519 		if (masks2[i] & mask) {
    520 			DPRINTF(("turning channel %d on\n",i));
    521 			/* sc->sc_channel[i].nd_busy=1; */
    522 			channel[i].isaudio = 1;
    523 			channel[i].play_count = 1;
    524 			channel[i].handler = NULL;
    525 			custom.aud[i].per = sc->sc_channel[i].nd_per;
    526 			if (sc->sc_14bit && (i > 1))
    527 				custom.aud[i].vol = 1;
    528 			else
    529 				custom.aud[i].vol = sc->sc_channel[i].nd_volume;
    530 			custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
    531 			custom.aud[i].len = len / 2;
    532 			sc->sc_channel[i].nd_mask = mask;
    533 			DPRINTF(("per is %d, vol is %d, len is %d\n",\
    534 			    sc->sc_channel[i].nd_per,
    535 			    sc->sc_channel[i].nd_volume, len));
    536 		}
    537 	}
    538 
    539 	channel[j].handler = aucc_inthdl;
    540 
    541 	/* enable ints */
    542 	custom.intena = INTF_SETCLR | INTF_INTEN | (masks2[j] << INTB_AUD0);
    543 
    544 	DPRINTF(("enabled ints: 0x%x\n", (masks2[j] << INTB_AUD0)));
    545 
    546 	/* enable DMA */
    547 	custom.dmacon = DMAF_SETCLR | DMAF_MASTER | mask;
    548 
    549 	DPRINTF(("enabled DMA, mask=0x%x\n",mask));
    550 
    551 	return 0;
    552 }
    553 
    554 /* ARGSUSED */
    555 int
    556 aucc_start_input(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
    557 {
    558 
    559 	return ENXIO; /* no input */
    560 }
    561 
    562 int
    563 aucc_halt_output(void *addr)
    564 {
    565 	struct aucc_softc *sc;
    566 	int i;
    567 
    568 	/* XXX only halt, if input is also halted ?? */
    569 	sc = addr;
    570 	/* stop DMA, etc */
    571 	custom.intena = AUCC_ALLINTF;
    572 	custom.dmacon = AUCC_ALLDMAF;
    573 	/* mark every busy unit idle */
    574 	for (i = 0; i < 4; i++) {
    575 		sc->sc_channel[i].nd_busy = sc->sc_channel[i].nd_mask = 0;
    576 		channel[i].isaudio = 0;
    577 		channel[i].play_count = 0;
    578 	}
    579 
    580 	return 0;
    581 }
    582 
    583 int
    584 aucc_halt_input(void *addr)
    585 {
    586 
    587 	/* no input */
    588 	return ENXIO;
    589 }
    590 
    591 int
    592 aucc_getdev(void *addr, struct audio_device *retp)
    593 {
    594 
    595 	*retp = aucc_device;
    596 	return 0;
    597 }
    598 
    599 int
    600 aucc_set_port(void *addr, mixer_ctrl_t *cp)
    601 {
    602 	struct aucc_softc *sc;
    603 	int i,j;
    604 
    605 	DPRINTF(("aucc_set_port: port=%d", cp->dev));
    606 	sc = addr;
    607 	switch (cp->type) {
    608 	case AUDIO_MIXER_SET:
    609 		if (cp->dev != AUCC_CHANNELS)
    610 			return EINVAL;
    611 		i = cp->un.mask;
    612 		if ((i < 1) || (i > 15))
    613 			return EINVAL;
    614 
    615 		sc->sc_channelmask = i;
    616 		break;
    617 
    618 	case AUDIO_MIXER_VALUE:
    619 		i = cp->un.value.num_channels;
    620 		if ((i < 1) || (i > 4))
    621 			return EINVAL;
    622 
    623 #ifdef __XXXwhatsthat
    624 		if (cp->dev != AUCC_VOLUME)
    625 			return EINVAL;
    626 #endif
    627 
    628 		/* set volume for channel 0..i-1 */
    629 
    630 		/* evil workaround for xanim bug, IMO */
    631 		if ((sc->sc_channels == 1) && (i == 2)) {
    632 			sc->sc_channel[0].nd_volume =
    633 			    sc->sc_channel[3].nd_volume =
    634 			    cp->un.value.level[0] >> 2;
    635 			sc->sc_channel[1].nd_volume =
    636 			    sc->sc_channel[2].nd_volume =
    637 			    cp->un.value.level[1] >> 2;
    638 		} else if (i > 1) {
    639 			for (j = 0; j < i; j++)
    640 				sc->sc_channel[j].nd_volume =
    641 				    cp->un.value.level[j] >> 2;
    642 		} else if (sc->sc_channels > 1)
    643 			for (j = 0; j < sc->sc_channels; j++)
    644 				sc->sc_channel[j].nd_volume =
    645 				    cp->un.value.level[0] >> 2;
    646 		else
    647 			for (j = 0; j < 4; j++)
    648 				sc->sc_channel[j].nd_volume =
    649 				    cp->un.value.level[0] >> 2;
    650 		break;
    651 
    652 	default:
    653 		return EINVAL;
    654 		break;
    655 	}
    656 	return 0;
    657 }
    658 
    659 
    660 int
    661 aucc_get_port(void *addr, mixer_ctrl_t *cp)
    662 {
    663 	struct aucc_softc *sc;
    664 	int i,j;
    665 
    666 	DPRINTF(("aucc_get_port: port=%d", cp->dev));
    667 	sc = addr;
    668 	switch (cp->type) {
    669 	case AUDIO_MIXER_SET:
    670 		if (cp->dev != AUCC_CHANNELS)
    671 			return EINVAL;
    672 		cp->un.mask = sc->sc_channelmask;
    673 		break;
    674 
    675 	case AUDIO_MIXER_VALUE:
    676 		i = cp->un.value.num_channels;
    677 		if ((i < 1) || (i > 4))
    678 			return EINVAL;
    679 
    680 		for (j = 0; j < i; j++)
    681 			cp->un.value.level[j] =
    682 			    (sc->sc_channel[j].nd_volume << 2) +
    683 			    (sc->sc_channel[j].nd_volume >> 4);
    684 		break;
    685 
    686 	default:
    687 		return EINVAL;
    688 	}
    689 	return 0;
    690 }
    691 
    692 
    693 int
    694 aucc_get_props(void *addr)
    695 {
    696 
    697 	return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE;
    698 }
    699 
    700 
    701 void
    702 aucc_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread)
    703 {
    704 	struct aucc_softc *sc = opaque;
    705 
    706 	*intr = &sc->sc_intr_lock;
    707 	*thread = &sc->sc_lock;
    708 }
    709 
    710 int
    711 aucc_query_devinfo(void *addr, register mixer_devinfo_t *dip)
    712 {
    713 	int i;
    714 
    715 	switch(dip->index) {
    716 	case AUCC_CHANNELS:
    717 		dip->type = AUDIO_MIXER_SET;
    718 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    719 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    720 #define setname(a) strlcpy(dip->label.name, (a), sizeof(dip->label.name))
    721 		setname(AudioNspeaker);
    722 		for (i = 0; i < 16; i++) {
    723 			snprintf(dip->un.s.member[i].label.name,
    724 			    sizeof(dip->un.s.member[i].label.name),
    725 			    "channelmask%d", i);
    726 			dip->un.s.member[i].mask = i;
    727 		}
    728 		dip->un.s.num_mem = 16;
    729 		break;
    730 
    731 	case AUCC_VOLUME:
    732 		dip->type = AUDIO_MIXER_VALUE;
    733 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    734 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    735 		setname(AudioNmaster);
    736 		dip->un.v.num_channels = 4;
    737 		strcpy(dip->un.v.units.name, AudioNvolume);
    738 		break;
    739 
    740 	case AUCC_OUTPUT_CLASS:
    741 		dip->type = AUDIO_MIXER_CLASS;
    742 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    743 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    744 		setname(AudioCoutputs);
    745 		break;
    746 
    747 	default:
    748 		return ENXIO;
    749 	}
    750 
    751 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
    752 
    753 	return 0;
    754 }
    755 
    756 /* audio int handler */
    757 void
    758 aucc_inthdl(int ch)
    759 {
    760 	int i;
    761 	int mask;
    762 
    763 	mutex_spin_enter(&aucc->sc_intr_lock);
    764 	mask = aucc->sc_channel[ch].nd_mask;
    765 	/*
    766 	 * for all channels in this maskgroup:
    767 	 * disable DMA, int
    768 	 * mark idle
    769 	 */
    770 	DPRINTF(("inthandler called, channel %d, mask 0x%x\n", ch, mask));
    771 
    772 	custom.intreq = mask << INTB_AUD0; /* clear request */
    773 	/*
    774 	 * XXX: maybe we can leave ints and/or DMA on,
    775 	 * if another sample has to be played?
    776 	 */
    777 	custom.intena = mask << INTB_AUD0;
    778 	/*
    779 	 * XXX custom.dmacon=mask; NO!!!
    780 	 */
    781 	for (i = 0; i < 4; i++) {
    782 		if (masks2[i] && mask) {
    783 			DPRINTF(("marking channel %d idle\n",i));
    784 			aucc->sc_channel[i].nd_busy = 0;
    785 			aucc->sc_channel[i].nd_mask = 0;
    786 			channel[i].isaudio = channel[i].play_count = 0;
    787 		}
    788 	}
    789 
    790 	/* call handler */
    791 	if (aucc->sc_channel[ch].nd_intr) {
    792 		DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
    793 		(*(aucc->sc_channel[ch].nd_intr))
    794 		    (aucc->sc_channel[ch].nd_intrdata);
    795 	} else
    796 		DPRINTF(("zero int handler\n"));
    797 	mutex_spin_exit(&aucc->sc_intr_lock);
    798 	DPRINTF(("ints done\n"));
    799 }
    800 
    801 /* transform frequency to period, adjust bounds */
    802 static u_int
    803 freqtoper(u_int freq)
    804 {
    805 	u_int per;
    806 
    807 	per = eclockfreq * 5 / freq;
    808 	if (per < 124)
    809 		per = 124;   /* must have at least 124 ticks between samples */
    810 
    811 	return per;
    812 }
    813 
    814 /* transform period to frequency */
    815 static u_int
    816 pertofreq(u_int per)
    817 {
    818 
    819 	return eclockfreq * 5 / per;
    820 }
    821 
    822 
    823 /* 14bit output */
    824 static void
    825 aucc_decode_slinear16_1ch(u_char **dmap, u_char *p, int i)
    826 {
    827 	u_char *ch0;
    828 	u_char *ch3;
    829 
    830 	ch0 = dmap[0];
    831 	ch3 = dmap[1];		/* XXX should be 3 */
    832 	while (i--) {
    833 		*ch0++ = *p++;
    834 		*ch3++ = *p++ >> 2;
    835 	}
    836 }
    837 
    838 /* 14bit stereo output */
    839 static void
    840 aucc_decode_slinear16_2ch(u_char **dmap, u_char *p, int i)
    841 {
    842 	u_char *ch0;
    843 	u_char *ch1;
    844 	u_char *ch2;
    845 	u_char *ch3;
    846 
    847 	ch0 = dmap[0];
    848 	ch1 = dmap[1];
    849 	ch2 = dmap[2];
    850 	ch3 = dmap[3];
    851 	while (i--) {
    852 		*ch0++ = *p++;
    853 		*ch3++ = *p++ >> 2;
    854 		*ch1++ = *p++;
    855 		*ch2++ = *p++ >> 2;
    856 	}
    857 }
    858 
    859 static void
    860 aucc_decode_slinear16_3ch(u_char **dmap, u_char *p, int i)
    861 {
    862 	u_char *ch0;
    863 	u_char *ch1;
    864 	u_char *ch2;
    865 
    866 	ch0 = dmap[0];
    867 	ch1 = dmap[1];
    868 	ch2 = dmap[2];
    869 	while (i--) {
    870 		*ch0++ = *p++; p++;
    871 		*ch1++ = *p++; p++;
    872 		*ch2++ = *p++; p++;
    873 	}
    874 }
    875 
    876 static void
    877 aucc_decode_slinear16_4ch(u_char **dmap, u_char *p, int i)
    878 {
    879 	u_char *ch0;
    880 	u_char *ch1;
    881 	u_char *ch2;
    882 	u_char *ch3;
    883 
    884 	ch0 = dmap[0];
    885 	ch1 = dmap[1];
    886 	ch2 = dmap[2];
    887 	ch3 = dmap[3];
    888 	while (i--) {
    889 		*ch0++ = *p++; p++;
    890 		*ch1++ = *p++; p++;
    891 		*ch2++ = *p++; p++;
    892 		*ch3++ = *p++; p++;
    893 	}
    894 }
    895 
    896 #endif /* NAUCC > 0 */
    897