Home | History | Annotate | Line # | Download | only in dev
      1 /*	$NetBSD: aucc.c,v 1.48 2020/02/29 06:03:55 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.48 2020/02/29 06:03:55 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 	if (blk > AUDIO_BUF_SIZE)
    408 		blk = AUDIO_BUF_SIZE;
    409 
    410 	blk = rounddown(blk, param->channels * param->precision / NBBY);
    411 	return blk;
    412 }
    413 
    414 int
    415 aucc_commit_settings(void *addr)
    416 {
    417 	struct aucc_softc *sc;
    418 	int i;
    419 
    420 	DPRINTF(("sa_commit.\n"));
    421 
    422 	sc = addr;
    423 	for (i = 0; i < 4; i++) {
    424 		custom.aud[i].vol = sc->sc_channel[i].nd_volume;
    425 		custom.aud[i].per = sc->sc_channel[i].nd_per;
    426 	}
    427 
    428 	DPRINTF(("commit done\n"));
    429 
    430 	return 0;
    431 }
    432 
    433 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
    434 static int masks2[4] = {1,2,4,8};
    435 
    436 int
    437 aucc_start_output(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
    438 {
    439 	struct aucc_softc *sc;
    440 	int mask;
    441 	int i, j, k, len;
    442 	u_char *dmap[4];
    443 
    444 
    445 	sc = addr;
    446 	mask = sc->sc_channelmask;
    447 
    448 	dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
    449 
    450 	DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
    451 
    452 	if (sc->sc_channels > 1)
    453 		mask &= masks[sc->sc_channels - 1];
    454 		/* we use first sc_channels channels */
    455 	if (mask == 0) /* active and used channels are disjoint */
    456 		return EINVAL;
    457 
    458 	for (i = 0; i < 4; i++) {
    459 		/* channels available ? */
    460 		if ((masks2[i] & mask) && (sc->sc_channel[i].nd_busy))
    461 			return EBUSY; /* channel is busy */
    462 		if (channel[i].isaudio == -1)
    463 			return EBUSY; /* system uses them */
    464 	}
    465 
    466 	/* enable interrupt on 1st channel */
    467 	for (i = j = 0; i < AUCC_MAXINT; i++) {
    468 		if (masks2[i] & mask) {
    469 			DPRINTF(("first channel is %d\n",i));
    470 			j = i;
    471 			sc->sc_channel[i].nd_intr = intr;
    472 			sc->sc_channel[i].nd_intrdata = arg;
    473 			break;
    474 		}
    475 	}
    476 
    477 	DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
    478 		 dmap[2], dmap[3], mask));
    479 
    480 	/* disable ints, DMA for channels, until all parameters set */
    481 	/* XXX dont disable DMA! custom.dmacon=mask;*/
    482 	custom.intreq = mask << INTB_AUD0;
    483 	custom.intena = mask << INTB_AUD0;
    484 
    485 	/* copy data to DMA buffer */
    486 
    487 	if (sc->sc_channels == 1) {
    488 		dmap[0] =
    489 		dmap[1] =
    490 		dmap[2] =
    491 		dmap[3] = (u_char *)sc->sc_channel[j].nd_dma;
    492 	} else {
    493 		for (k = 0; k < 4; k++) {
    494 			if (masks2[k+j] & mask)
    495 				dmap[k] = (u_char *)sc->sc_channel[k+j].nd_dma;
    496 		}
    497 	}
    498 
    499 	sc->sc_channel[j].nd_doublebuf ^= 1;
    500 	if (sc->sc_channel[j].nd_doublebuf) {
    501 		dmap[0] += AUDIO_BUF_SIZE;
    502 		dmap[1] += AUDIO_BUF_SIZE;
    503 		dmap[2] += AUDIO_BUF_SIZE;
    504 		dmap[3] += AUDIO_BUF_SIZE;
    505 	}
    506 
    507 	/*
    508 	 * compute output length in bytes per channel.
    509 	 * divide by two only for 16bit->8bit conversion.
    510 	 */
    511 	len = cc / sc->sc_channels;
    512 	if (!sc->sc_14bit && (sc->sc_precision == 16))
    513 		len /= 2;
    514 
    515 	/* call audio decoding routine */
    516 	sc->sc_decodefunc (dmap, (u_char *)p, len);
    517 
    518 	/* DMA buffers: we use same buffer 4 all channels
    519 	 * write DMA location and length
    520 	 */
    521 	for (i = k = 0; i < 4; i++) {
    522 		if (masks2[i] & mask) {
    523 			DPRINTF(("turning channel %d on\n",i));
    524 			/* sc->sc_channel[i].nd_busy=1; */
    525 			channel[i].isaudio = 1;
    526 			channel[i].play_count = 1;
    527 			channel[i].handler = NULL;
    528 			custom.aud[i].per = sc->sc_channel[i].nd_per;
    529 			if (sc->sc_14bit && (i > 1))
    530 				custom.aud[i].vol = 1;
    531 			else
    532 				custom.aud[i].vol = sc->sc_channel[i].nd_volume;
    533 			custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
    534 			custom.aud[i].len = len / 2;
    535 			sc->sc_channel[i].nd_mask = mask;
    536 			DPRINTF(("per is %d, vol is %d, len is %d\n",\
    537 			    sc->sc_channel[i].nd_per,
    538 			    sc->sc_channel[i].nd_volume, len));
    539 		}
    540 	}
    541 
    542 	channel[j].handler = aucc_inthdl;
    543 
    544 	/* enable ints */
    545 	custom.intena = INTF_SETCLR | INTF_INTEN | (masks2[j] << INTB_AUD0);
    546 
    547 	DPRINTF(("enabled ints: 0x%x\n", (masks2[j] << INTB_AUD0)));
    548 
    549 	/* enable DMA */
    550 	custom.dmacon = DMAF_SETCLR | DMAF_MASTER | mask;
    551 
    552 	DPRINTF(("enabled DMA, mask=0x%x\n",mask));
    553 
    554 	return 0;
    555 }
    556 
    557 /* ARGSUSED */
    558 int
    559 aucc_start_input(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
    560 {
    561 
    562 	return ENXIO; /* no input */
    563 }
    564 
    565 int
    566 aucc_halt_output(void *addr)
    567 {
    568 	struct aucc_softc *sc;
    569 	int i;
    570 
    571 	/* XXX only halt, if input is also halted ?? */
    572 	sc = addr;
    573 	/* stop DMA, etc */
    574 	custom.intena = AUCC_ALLINTF;
    575 	custom.dmacon = AUCC_ALLDMAF;
    576 	/* mark every busy unit idle */
    577 	for (i = 0; i < 4; i++) {
    578 		sc->sc_channel[i].nd_busy = sc->sc_channel[i].nd_mask = 0;
    579 		channel[i].isaudio = 0;
    580 		channel[i].play_count = 0;
    581 	}
    582 
    583 	return 0;
    584 }
    585 
    586 int
    587 aucc_halt_input(void *addr)
    588 {
    589 
    590 	/* no input */
    591 	return ENXIO;
    592 }
    593 
    594 int
    595 aucc_getdev(void *addr, struct audio_device *retp)
    596 {
    597 
    598 	*retp = aucc_device;
    599 	return 0;
    600 }
    601 
    602 int
    603 aucc_set_port(void *addr, mixer_ctrl_t *cp)
    604 {
    605 	struct aucc_softc *sc;
    606 	int i,j;
    607 
    608 	DPRINTF(("aucc_set_port: port=%d", cp->dev));
    609 	sc = addr;
    610 	switch (cp->type) {
    611 	case AUDIO_MIXER_SET:
    612 		if (cp->dev != AUCC_CHANNELS)
    613 			return EINVAL;
    614 		i = cp->un.mask;
    615 		if ((i < 1) || (i > 15))
    616 			return EINVAL;
    617 
    618 		sc->sc_channelmask = i;
    619 		break;
    620 
    621 	case AUDIO_MIXER_VALUE:
    622 		i = cp->un.value.num_channels;
    623 		if ((i < 1) || (i > 4))
    624 			return EINVAL;
    625 
    626 #ifdef __XXXwhatsthat
    627 		if (cp->dev != AUCC_VOLUME)
    628 			return EINVAL;
    629 #endif
    630 
    631 		/* set volume for channel 0..i-1 */
    632 
    633 		/* evil workaround for xanim bug, IMO */
    634 		if ((sc->sc_channels == 1) && (i == 2)) {
    635 			sc->sc_channel[0].nd_volume =
    636 			    sc->sc_channel[3].nd_volume =
    637 			    cp->un.value.level[0] >> 2;
    638 			sc->sc_channel[1].nd_volume =
    639 			    sc->sc_channel[2].nd_volume =
    640 			    cp->un.value.level[1] >> 2;
    641 		} else if (i > 1) {
    642 			for (j = 0; j < i; j++)
    643 				sc->sc_channel[j].nd_volume =
    644 				    cp->un.value.level[j] >> 2;
    645 		} else if (sc->sc_channels > 1)
    646 			for (j = 0; j < sc->sc_channels; j++)
    647 				sc->sc_channel[j].nd_volume =
    648 				    cp->un.value.level[0] >> 2;
    649 		else
    650 			for (j = 0; j < 4; j++)
    651 				sc->sc_channel[j].nd_volume =
    652 				    cp->un.value.level[0] >> 2;
    653 		break;
    654 
    655 	default:
    656 		return EINVAL;
    657 		break;
    658 	}
    659 	return 0;
    660 }
    661 
    662 
    663 int
    664 aucc_get_port(void *addr, mixer_ctrl_t *cp)
    665 {
    666 	struct aucc_softc *sc;
    667 	int i,j;
    668 
    669 	DPRINTF(("aucc_get_port: port=%d", cp->dev));
    670 	sc = addr;
    671 	switch (cp->type) {
    672 	case AUDIO_MIXER_SET:
    673 		if (cp->dev != AUCC_CHANNELS)
    674 			return EINVAL;
    675 		cp->un.mask = sc->sc_channelmask;
    676 		break;
    677 
    678 	case AUDIO_MIXER_VALUE:
    679 		i = cp->un.value.num_channels;
    680 		if ((i < 1) || (i > 4))
    681 			return EINVAL;
    682 
    683 		for (j = 0; j < i; j++)
    684 			cp->un.value.level[j] =
    685 			    (sc->sc_channel[j].nd_volume << 2) +
    686 			    (sc->sc_channel[j].nd_volume >> 4);
    687 		break;
    688 
    689 	default:
    690 		return EINVAL;
    691 	}
    692 	return 0;
    693 }
    694 
    695 
    696 int
    697 aucc_get_props(void *addr)
    698 {
    699 
    700 	return AUDIO_PROP_PLAYBACK;
    701 }
    702 
    703 
    704 void
    705 aucc_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread)
    706 {
    707 	struct aucc_softc *sc = opaque;
    708 
    709 	*intr = &sc->sc_intr_lock;
    710 	*thread = &sc->sc_lock;
    711 }
    712 
    713 int
    714 aucc_query_devinfo(void *addr, register mixer_devinfo_t *dip)
    715 {
    716 	int i;
    717 
    718 	switch(dip->index) {
    719 	case AUCC_CHANNELS:
    720 		dip->type = AUDIO_MIXER_SET;
    721 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    722 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    723 #define setname(a) strlcpy(dip->label.name, (a), sizeof(dip->label.name))
    724 		setname(AudioNspeaker);
    725 		for (i = 0; i < 16; i++) {
    726 			snprintf(dip->un.s.member[i].label.name,
    727 			    sizeof(dip->un.s.member[i].label.name),
    728 			    "channelmask%d", i);
    729 			dip->un.s.member[i].mask = i;
    730 		}
    731 		dip->un.s.num_mem = 16;
    732 		break;
    733 
    734 	case AUCC_VOLUME:
    735 		dip->type = AUDIO_MIXER_VALUE;
    736 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    737 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    738 		setname(AudioNmaster);
    739 		dip->un.v.num_channels = 4;
    740 		strcpy(dip->un.v.units.name, AudioNvolume);
    741 		break;
    742 
    743 	case AUCC_OUTPUT_CLASS:
    744 		dip->type = AUDIO_MIXER_CLASS;
    745 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    746 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    747 		setname(AudioCoutputs);
    748 		break;
    749 
    750 	default:
    751 		return ENXIO;
    752 	}
    753 
    754 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
    755 
    756 	return 0;
    757 }
    758 
    759 /* audio int handler */
    760 void
    761 aucc_inthdl(int ch)
    762 {
    763 	int i;
    764 	int mask;
    765 
    766 	mutex_spin_enter(&aucc->sc_intr_lock);
    767 	mask = aucc->sc_channel[ch].nd_mask;
    768 	/*
    769 	 * for all channels in this maskgroup:
    770 	 * disable DMA, int
    771 	 * mark idle
    772 	 */
    773 	DPRINTF(("inthandler called, channel %d, mask 0x%x\n", ch, mask));
    774 
    775 	custom.intreq = mask << INTB_AUD0; /* clear request */
    776 	/*
    777 	 * XXX: maybe we can leave ints and/or DMA on,
    778 	 * if another sample has to be played?
    779 	 */
    780 	custom.intena = mask << INTB_AUD0;
    781 	/*
    782 	 * XXX custom.dmacon=mask; NO!!!
    783 	 */
    784 	for (i = 0; i < 4; i++) {
    785 		if (masks2[i] && mask) {
    786 			DPRINTF(("marking channel %d idle\n",i));
    787 			aucc->sc_channel[i].nd_busy = 0;
    788 			aucc->sc_channel[i].nd_mask = 0;
    789 			channel[i].isaudio = channel[i].play_count = 0;
    790 		}
    791 	}
    792 
    793 	/* call handler */
    794 	if (aucc->sc_channel[ch].nd_intr) {
    795 		DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
    796 		(*(aucc->sc_channel[ch].nd_intr))
    797 		    (aucc->sc_channel[ch].nd_intrdata);
    798 	} else
    799 		DPRINTF(("zero int handler\n"));
    800 	mutex_spin_exit(&aucc->sc_intr_lock);
    801 	DPRINTF(("ints done\n"));
    802 }
    803 
    804 /* transform frequency to period, adjust bounds */
    805 static u_int
    806 freqtoper(u_int freq)
    807 {
    808 	u_int per;
    809 
    810 	per = eclockfreq * 5 / freq;
    811 	if (per < 124)
    812 		per = 124;   /* must have at least 124 ticks between samples */
    813 
    814 	return per;
    815 }
    816 
    817 /* transform period to frequency */
    818 static u_int
    819 pertofreq(u_int per)
    820 {
    821 
    822 	return eclockfreq * 5 / per;
    823 }
    824 
    825 
    826 /* 14bit output */
    827 static void
    828 aucc_decode_slinear16_1ch(u_char **dmap, u_char *p, int i)
    829 {
    830 	u_char *ch0;
    831 	u_char *ch3;
    832 
    833 	ch0 = dmap[0];
    834 	ch3 = dmap[1];		/* XXX should be 3 */
    835 	while (i--) {
    836 		*ch0++ = *p++;
    837 		*ch3++ = *p++ >> 2;
    838 	}
    839 }
    840 
    841 /* 14bit stereo output */
    842 static void
    843 aucc_decode_slinear16_2ch(u_char **dmap, u_char *p, int i)
    844 {
    845 	u_char *ch0;
    846 	u_char *ch1;
    847 	u_char *ch2;
    848 	u_char *ch3;
    849 
    850 	ch0 = dmap[0];
    851 	ch1 = dmap[1];
    852 	ch2 = dmap[2];
    853 	ch3 = dmap[3];
    854 	while (i--) {
    855 		*ch0++ = *p++;
    856 		*ch3++ = *p++ >> 2;
    857 		*ch1++ = *p++;
    858 		*ch2++ = *p++ >> 2;
    859 	}
    860 }
    861 
    862 static void
    863 aucc_decode_slinear16_3ch(u_char **dmap, u_char *p, int i)
    864 {
    865 	u_char *ch0;
    866 	u_char *ch1;
    867 	u_char *ch2;
    868 
    869 	ch0 = dmap[0];
    870 	ch1 = dmap[1];
    871 	ch2 = dmap[2];
    872 	while (i--) {
    873 		*ch0++ = *p++; p++;
    874 		*ch1++ = *p++; p++;
    875 		*ch2++ = *p++; p++;
    876 	}
    877 }
    878 
    879 static void
    880 aucc_decode_slinear16_4ch(u_char **dmap, u_char *p, int i)
    881 {
    882 	u_char *ch0;
    883 	u_char *ch1;
    884 	u_char *ch2;
    885 	u_char *ch3;
    886 
    887 	ch0 = dmap[0];
    888 	ch1 = dmap[1];
    889 	ch2 = dmap[2];
    890 	ch3 = dmap[3];
    891 	while (i--) {
    892 		*ch0++ = *p++; p++;
    893 		*ch1++ = *p++; p++;
    894 		*ch2++ = *p++; p++;
    895 		*ch3++ = *p++; p++;
    896 	}
    897 }
    898 
    899 #endif /* NAUCC > 0 */
    900