Home | History | Annotate | Line # | Download | only in dev
aucc.c revision 1.44
      1 /*	$NetBSD: aucc.c,v 1.44 2019/03/16 12:09:56 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  * - mu-law -> 14bit conversion
     39  * - channel allocation is wrong for 14bit mono
     40  * - convert the... err... conversion routines to 68k asm for best performance
     41  * 	XXX: NO. aucc audio is limited by chipmem speed, anyway. You dont
     42  *	want to make life difficult for amigappc work.
     43  *		-is
     44  *
     45  * - rely on auconv.c routines for mu-law/A-law conversions
     46  * - perhaps use a calibration table for better 14bit output
     47  * - set 31 kHz AGA video mode to allow 44.1 kHz even if grfcc is missing
     48  *	in the kernel
     49  * - 14bit output requires maximum volume
     50  */
     51 
     52 #include "aucc.h"
     53 #if NAUCC > 0
     54 
     55 #include <sys/cdefs.h>
     56 __KERNEL_RCSID(0, "$NetBSD: aucc.c,v 1.44 2019/03/16 12:09:56 isaki Exp $");
     57 
     58 #include <sys/param.h>
     59 #include <sys/systm.h>
     60 #include <sys/errno.h>
     61 #include <sys/ioctl.h>
     62 #include <sys/device.h>
     63 #include <sys/proc.h>
     64 #include <machine/cpu.h>
     65 
     66 #include <sys/audioio.h>
     67 #include <dev/audio_if.h>
     68 #include <amiga/amiga/cc.h>
     69 #include <amiga/amiga/custom.h>
     70 #include <amiga/amiga/device.h>
     71 #include <amiga/dev/auccvar.h>
     72 
     73 #include "opt_lev6_defer.h"
     74 
     75 
     76 #ifdef LEV6_DEFER
     77 #define AUCC_MAXINT 3
     78 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2)
     79 #else
     80 #define AUCC_MAXINT 4
     81 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3)
     82 #endif
     83 /* this unconditionally; we may use AUD3 as slave channel with LEV6_DEFER */
     84 #define AUCC_ALLDMAF (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3)
     85 
     86 #ifdef AUDIO_DEBUG
     87 /*extern printf(const char *,...);*/
     88 int     auccdebug = 1;
     89 #define DPRINTF(x)      if (auccdebug) printf x
     90 #else
     91 #define DPRINTF(x)
     92 #endif
     93 
     94 /* clock frequency.. */
     95 extern int eclockfreq;
     96 
     97 
     98 /* hw audio ch */
     99 extern struct audio_channel channel[4];
    100 
    101 
    102 /*
    103  * Software state.
    104  */
    105 struct aucc_softc {
    106 	int	sc_open;		/* single use device */
    107 	aucc_data_t sc_channel[4];	/* per channel freq, ... */
    108 	u_int	sc_encoding;		/* encoding AUDIO_ENCODING_.*/
    109 	int	sc_channels;		/* # of channels used */
    110 	int	sc_precision;		/* 8 or 16 bits */
    111 	int	sc_14bit;		/* 14bit output enabled */
    112 
    113 	int	sc_intrcnt;		/* interrupt count */
    114 	int	sc_channelmask;		/* which channels are used ? */
    115 	void (*sc_decodefunc)(u_char **, u_char *, int);
    116 				/* pointer to format conversion routine */
    117 
    118 	kmutex_t sc_lock;
    119 	kmutex_t sc_intr_lock;
    120 };
    121 
    122 /* interrupt interfaces */
    123 void aucc_inthdl(int);
    124 
    125 /* forward declarations */
    126 static int init_aucc(struct aucc_softc *);
    127 static u_int freqtoper(u_int);
    128 static u_int pertofreq(u_int);
    129 
    130 /* autoconfiguration driver */
    131 void	auccattach(device_t, device_t, void *);
    132 int	auccmatch(device_t, cfdata_t, void *);
    133 
    134 CFATTACH_DECL_NEW(aucc, sizeof(struct aucc_softc),
    135     auccmatch, auccattach, NULL, NULL);
    136 
    137 struct audio_device aucc_device = {
    138 	"Amiga-audio",
    139 	"2.0",
    140 	"aucc"
    141 };
    142 
    143 
    144 struct aucc_softc *aucc = NULL;
    145 
    146 
    147 unsigned char mulaw_to_lin[] = {
    148 	0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
    149 	0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
    150 	0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf,
    151 	0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf,
    152 	0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
    153 	0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
    154 	0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4,
    155 	0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8,
    156 	0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
    157 	0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
    158 	0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd,
    159 	0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe,
    160 	0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
    161 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    162 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    163 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
    164 	0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61,
    165 	0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, 0x45, 0x41,
    166 	0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30,
    167 	0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20,
    168 	0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17,
    169 	0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f,
    170 	0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b,
    171 	0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07,
    172 	0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05,
    173 	0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
    174 	0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02,
    175 	0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
    176 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    177 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    178 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    179 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    180 };
    181 
    182 /*
    183  * Define our interface to the higher level audio driver.
    184  */
    185 int	aucc_open(void *, int);
    186 void	aucc_close(void *);
    187 int	aucc_set_out_sr(void *, u_int);
    188 int	aucc_query_encoding(void *, struct audio_encoding *);
    189 int	aucc_round_blocksize(void *, int, int, const audio_params_t *);
    190 int	aucc_commit_settings(void *);
    191 int	aucc_start_output(void *, void *, int, void (*)(void *), void *);
    192 int	aucc_start_input(void *, void *, int, void (*)(void *), void *);
    193 int	aucc_halt_output(void *);
    194 int	aucc_halt_input(void *);
    195 int	aucc_getdev(void *, struct audio_device *);
    196 int	aucc_set_port(void *, mixer_ctrl_t *);
    197 int	aucc_get_port(void *, mixer_ctrl_t *);
    198 int	aucc_query_devinfo(void *, mixer_devinfo_t *);
    199 void	aucc_encode(int, int, int, int, u_char *, u_short **);
    200 int	aucc_set_params(void *, int, int, audio_params_t *, audio_params_t *,
    201 			stream_filter_list_t *, stream_filter_list_t *);
    202 int	aucc_get_props(void *);
    203 void	aucc_get_locks(void *, kmutex_t **, kmutex_t **);
    204 
    205 
    206 static void aucc_decode_slinear8_1ch(u_char **, u_char *, int);
    207 static void aucc_decode_slinear8_2ch(u_char **, u_char *, int);
    208 static void aucc_decode_slinear8_3ch(u_char **, u_char *, int);
    209 static void aucc_decode_slinear8_4ch(u_char **, u_char *, int);
    210 
    211 static void aucc_decode_ulinear8_1ch(u_char **, u_char *, int);
    212 static void aucc_decode_ulinear8_2ch(u_char **, u_char *, int);
    213 static void aucc_decode_ulinear8_3ch(u_char **, u_char *, int);
    214 static void aucc_decode_ulinear8_4ch(u_char **, u_char *, int);
    215 
    216 static void aucc_decode_mulaw_1ch(u_char **, u_char *, int);
    217 static void aucc_decode_mulaw_2ch(u_char **, u_char *, int);
    218 static void aucc_decode_mulaw_3ch(u_char **, u_char *, int);
    219 static void aucc_decode_mulaw_4ch(u_char **, u_char *, int);
    220 
    221 static void aucc_decode_slinear16_1ch(u_char **, u_char *, int);
    222 static void aucc_decode_slinear16_2ch(u_char **, u_char *, int);
    223 static void aucc_decode_slinear16_3ch(u_char **, u_char *, int);
    224 static void aucc_decode_slinear16_4ch(u_char **, u_char *, int);
    225 
    226 static void aucc_decode_slinear16sw_1ch(u_char **, u_char *, int);
    227 static void aucc_decode_slinear16sw_2ch(u_char **, u_char *, int);
    228 static void aucc_decode_slinear16sw_3ch(u_char **, u_char *, int);
    229 static void aucc_decode_slinear16sw_4ch(u_char **, u_char *, int);
    230 
    231 
    232 
    233 const struct audio_hw_if sa_hw_if = {
    234 	.open			= aucc_open,
    235 	.close			= aucc_close,
    236 	.query_encoding		= aucc_query_encoding,
    237 	.set_params		= aucc_set_params,
    238 	.round_blocksize	= aucc_round_blocksize,
    239 	.commit_settings	= aucc_commit_settings,
    240 	.start_output		= aucc_start_output,
    241 	.start_input		= aucc_start_input,
    242 	.halt_output		= aucc_halt_output,
    243 	.halt_input		= aucc_halt_input,
    244 	.getdev			= aucc_getdev,
    245 	.set_port		= aucc_set_port,
    246 	.get_port		= aucc_get_port,
    247 	.query_devinfo		= aucc_query_devinfo,
    248 	.get_props		= aucc_get_props,
    249 	.get_locks		= aucc_get_locks,
    250 };
    251 
    252 /* autoconfig routines */
    253 
    254 int
    255 auccmatch(device_t parent, cfdata_t cf, void *aux)
    256 {
    257 	static int aucc_matched = 0;
    258 
    259 	if (!matchname((char *)aux, "aucc") ||
    260 #ifdef DRACO
    261 	    is_draco() ||
    262 #endif
    263 	    aucc_matched)
    264 		return 0;
    265 
    266 	aucc_matched = 1;
    267 	return 1;
    268 }
    269 
    270 /*
    271  * Audio chip found.
    272  */
    273 void
    274 auccattach(device_t parent, device_t self, void *args)
    275 {
    276 	struct aucc_softc *sc;
    277 	int i;
    278 
    279 	sc = device_private(self);
    280 	printf("\n");
    281 
    282 	if ((i=init_aucc(sc))) {
    283 		printf("audio: no chipmem\n");
    284 		return;
    285 	}
    286 
    287 	audio_attach_mi(&sa_hw_if, sc, self);
    288 }
    289 
    290 
    291 static int
    292 init_aucc(struct aucc_softc *sc)
    293 {
    294 	int i, err;
    295 
    296 	err = 0;
    297 	/* init values per channel */
    298 	for (i = 0; i < 4; i++) {
    299 		sc->sc_channel[i].nd_freq = 8000;
    300 		sc->sc_channel[i].nd_per = freqtoper(8000);
    301 		sc->sc_channel[i].nd_busy = 0;
    302 		sc->sc_channel[i].nd_dma = alloc_chipmem(AUDIO_BUF_SIZE*2);
    303 		if (sc->sc_channel[i].nd_dma == NULL)
    304 			err = 1;
    305 		sc->sc_channel[i].nd_dmalength = 0;
    306 		sc->sc_channel[i].nd_volume = 64;
    307 		sc->sc_channel[i].nd_intr = NULL;
    308 		sc->sc_channel[i].nd_intrdata = NULL;
    309 		sc->sc_channel[i].nd_doublebuf = 0;
    310 		DPRINTF(("DMA buffer for channel %d is %p\n", i,
    311 		    sc->sc_channel[i].nd_dma));
    312 	}
    313 
    314 	if (err) {
    315 		for (i = 0; i < 4; i++)
    316 			if (sc->sc_channel[i].nd_dma)
    317 				free_chipmem(sc->sc_channel[i].nd_dma);
    318 	}
    319 
    320 	sc->sc_channels = 1;
    321 	sc->sc_channelmask = 0xf;
    322 	sc->sc_precision = 8;
    323 	sc->sc_14bit = 0;
    324 	sc->sc_encoding = AUDIO_ENCODING_ULAW;
    325 	sc->sc_decodefunc = aucc_decode_mulaw_1ch;
    326 
    327 	/* clear interrupts and DMA: */
    328 	custom.intena = AUCC_ALLINTF;
    329 	custom.dmacon = AUCC_ALLDMAF;
    330 
    331 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    332 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
    333 
    334 	return err;
    335 }
    336 
    337 int
    338 aucc_open(void *addr, int flags)
    339 {
    340 	struct aucc_softc *sc;
    341 	int i;
    342 
    343 	sc = addr;
    344 	DPRINTF(("sa_open: unit %p\n",sc));
    345 
    346 	if (sc->sc_open)
    347 		return EBUSY;
    348 	sc->sc_open = 1;
    349 	for (i = 0; i < AUCC_MAXINT; i++) {
    350 		sc->sc_channel[i].nd_intr = NULL;
    351 		sc->sc_channel[i].nd_intrdata = NULL;
    352 	}
    353 	aucc = sc;
    354 	sc->sc_channelmask = 0xf;
    355 
    356 	DPRINTF(("saopen: ok -> sc=%p\n",sc));
    357 
    358 	return 0;
    359 }
    360 
    361 void
    362 aucc_close(void *addr)
    363 {
    364 	struct aucc_softc *sc;
    365 
    366 	sc = addr;
    367 	DPRINTF(("sa_close: sc=%p\n", sc));
    368 	/*
    369 	 * halt i/o, clear open flag, and done.
    370 	 */
    371 	aucc_halt_output(sc);
    372 	sc->sc_open = 0;
    373 
    374 	DPRINTF(("sa_close: closed.\n"));
    375 }
    376 
    377 int
    378 aucc_set_out_sr(void *addr, u_int sr)
    379 {
    380 	struct aucc_softc *sc;
    381 	u_long per;
    382 	int i;
    383 
    384 	sc = addr;
    385 	per = freqtoper(sr);
    386 	if (per > 0xffff)
    387 		return EINVAL;
    388 	sr = pertofreq(per);
    389 
    390 	for (i = 0; i < 4; i++) {
    391 		sc->sc_channel[i].nd_freq = sr;
    392 		sc->sc_channel[i].nd_per = per;
    393 	}
    394 
    395 	return 0;
    396 }
    397 
    398 int
    399 aucc_query_encoding(void *addr, struct audio_encoding *fp)
    400 {
    401 
    402 	switch (fp->index) {
    403 	case 0:
    404 		strcpy(fp->name, AudioEslinear);
    405 		fp->encoding = AUDIO_ENCODING_SLINEAR;
    406 		fp->precision = 8;
    407 		fp->flags = 0;
    408 		break;
    409 	case 1:
    410 		strcpy(fp->name, AudioEmulaw);
    411 		fp->encoding = AUDIO_ENCODING_ULAW;
    412 		fp->precision = 8;
    413 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    414 		break;
    415 
    416 	case 2:
    417 		strcpy(fp->name, AudioEulinear);
    418 		fp->encoding = AUDIO_ENCODING_ULINEAR;
    419 		fp->precision = 8;
    420 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    421 		break;
    422 
    423 	case 3:
    424 		strcpy(fp->name, AudioEslinear);
    425 		fp->encoding = AUDIO_ENCODING_SLINEAR;
    426 		fp->precision = 16;
    427 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    428 		break;
    429 
    430 	case 4:
    431 		strcpy(fp->name, AudioEslinear_be);
    432 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
    433 		fp->precision = 16;
    434 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    435 		break;
    436 
    437 	case 5:
    438 		strcpy(fp->name, AudioEslinear_le);
    439 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
    440 		fp->precision = 16;
    441 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    442 		break;
    443 
    444 	default:
    445 		return EINVAL;
    446 		/*NOTREACHED*/
    447 	}
    448 	return 0;
    449 }
    450 
    451 int
    452 aucc_set_params(void *addr, int setmode, int usemode,
    453 		audio_params_t *p, audio_params_t *r,
    454 		stream_filter_list_t *pfil, stream_filter_list_t *rfil)
    455 {
    456 	struct aucc_softc *sc;
    457 
    458 	sc = addr;
    459 	/* if (setmode & AUMODE_RECORD)
    460 		return 0 ENXIO*/;
    461 
    462 #ifdef AUCCDEBUG
    463 	printf("aucc_set_params(setmode 0x%x, usemode 0x%x, "
    464 	       "enc %u, bits %u, chn %u, sr %u)\n", setmode, usemode,
    465 	       p->encoding, p->precision, p->channels, p->sample_rate);
    466 #endif
    467 
    468 	switch (p->precision) {
    469 	case 8:
    470 		switch (p->encoding) {
    471 		case AUDIO_ENCODING_ULAW:
    472 			switch (p->channels) {
    473 			case 1:
    474 				sc->sc_decodefunc = aucc_decode_mulaw_1ch;
    475 				break;
    476 			case 2:
    477 				sc->sc_decodefunc = aucc_decode_mulaw_2ch;
    478 				break;
    479 			case 3:
    480 				sc->sc_decodefunc = aucc_decode_mulaw_3ch;
    481 				break;
    482 			case 4:
    483 				sc->sc_decodefunc = aucc_decode_mulaw_4ch;
    484 				break;
    485 			default:
    486 				return EINVAL;
    487 			}
    488 			break;
    489 
    490 		case AUDIO_ENCODING_SLINEAR:
    491 		case AUDIO_ENCODING_SLINEAR_BE:
    492 		case AUDIO_ENCODING_SLINEAR_LE:
    493 			switch (p->channels) {
    494 			case 1:
    495 				sc->sc_decodefunc = aucc_decode_slinear8_1ch;
    496 				break;
    497 			case 2:
    498 				sc->sc_decodefunc = aucc_decode_slinear8_2ch;
    499 				break;
    500 			case 3:
    501 				sc->sc_decodefunc = aucc_decode_slinear8_3ch;
    502 				break;
    503 			case 4:
    504 				sc->sc_decodefunc = aucc_decode_slinear8_4ch;
    505 				break;
    506 			default:
    507 				return EINVAL;
    508 			}
    509 			break;
    510 
    511 		case AUDIO_ENCODING_ULINEAR:
    512 		case AUDIO_ENCODING_ULINEAR_BE:
    513 		case AUDIO_ENCODING_ULINEAR_LE:
    514 			switch (p->channels) {
    515 			case 1:
    516 				sc->sc_decodefunc = aucc_decode_ulinear8_1ch;
    517 				break;
    518 			case 2:
    519 				sc->sc_decodefunc = aucc_decode_ulinear8_2ch;
    520 				break;
    521 			case 3:
    522 				sc->sc_decodefunc = aucc_decode_ulinear8_3ch;
    523 				break;
    524 			case 4:
    525 				sc->sc_decodefunc = aucc_decode_ulinear8_4ch;
    526 				break;
    527 			default:
    528 				return EINVAL;
    529 			}
    530 			break;
    531 
    532 		default:
    533 			return EINVAL;
    534 		}
    535 		break;
    536 
    537 	case 16:
    538 		switch (p->encoding) {
    539 #if BYTE_ORDER == BIG_ENDIAN
    540 		case AUDIO_ENCODING_SLINEAR:
    541 #endif
    542 		case AUDIO_ENCODING_SLINEAR_BE:
    543 			switch (p->channels) {
    544 			case 1:
    545 				sc->sc_decodefunc = aucc_decode_slinear16_1ch;
    546 				break;
    547 
    548 			case 2:
    549 				sc->sc_decodefunc = aucc_decode_slinear16_2ch;
    550 				break;
    551 			case 3:
    552 				sc->sc_decodefunc = aucc_decode_slinear16_3ch;
    553 				break;
    554 			case 4:
    555 				sc->sc_decodefunc = aucc_decode_slinear16_4ch;
    556 				break;
    557 			default:
    558 				return EINVAL;
    559 			}
    560 			break;
    561 
    562 #if BYTE_ORDER == LITTLE_ENDIAN
    563 		case AUDIO_ENCODING_SLINEAR:
    564 #endif
    565 		case AUDIO_ENCODING_SLINEAR_LE:
    566 			switch (p->channels) {
    567 			case 1:
    568 				sc->sc_decodefunc = aucc_decode_slinear16sw_1ch;
    569 				break;
    570 			case 2:
    571 				sc->sc_decodefunc = aucc_decode_slinear16sw_2ch;
    572 				break;
    573 			case 3:
    574 				sc->sc_decodefunc = aucc_decode_slinear16sw_3ch;
    575 				break;
    576 			case 4:
    577 				sc->sc_decodefunc = aucc_decode_slinear16sw_4ch;
    578 				break;
    579 			default:
    580 				return EINVAL;
    581 			}
    582 			break;
    583 
    584 		default:
    585 			return EINVAL;
    586 		}
    587 		break;
    588 
    589 	default:
    590 		return EINVAL;
    591 	}
    592 
    593 	sc->sc_encoding = p->encoding;
    594 	sc->sc_precision = p->precision;
    595 	sc->sc_14bit = ((p->precision == 16) && (p->channels <= 2));
    596 	sc->sc_channels = sc->sc_14bit ? (p->channels * 2) : p->channels;
    597 
    598 	return aucc_set_out_sr(addr, p->sample_rate);
    599 }
    600 
    601 int
    602 aucc_round_blocksize(void *addr, int blk,
    603 		     int mode, const audio_params_t *param)
    604 {
    605 
    606 	/* round up to even size */
    607 	return blk > AUDIO_BUF_SIZE ? AUDIO_BUF_SIZE : blk;
    608 }
    609 
    610 int
    611 aucc_commit_settings(void *addr)
    612 {
    613 	struct aucc_softc *sc;
    614 	int i;
    615 
    616 	DPRINTF(("sa_commit.\n"));
    617 
    618 	sc = addr;
    619 	for (i = 0; i < 4; i++) {
    620 		custom.aud[i].vol = sc->sc_channel[i].nd_volume;
    621 		custom.aud[i].per = sc->sc_channel[i].nd_per;
    622 	}
    623 
    624 	DPRINTF(("commit done\n"));
    625 
    626 	return 0;
    627 }
    628 
    629 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
    630 static int masks2[4] = {1,2,4,8};
    631 
    632 int
    633 aucc_start_output(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
    634 {
    635 	struct aucc_softc *sc;
    636 	int mask;
    637 	int i, j, k, len;
    638 	u_char *dmap[4];
    639 
    640 
    641 	sc = addr;
    642 	mask = sc->sc_channelmask;
    643 
    644 	dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
    645 
    646 	DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
    647 
    648 	if (sc->sc_channels > 1)
    649 		mask &= masks[sc->sc_channels - 1];
    650 		/* we use first sc_channels channels */
    651 	if (mask == 0) /* active and used channels are disjoint */
    652 		return EINVAL;
    653 
    654 	for (i = 0; i < 4; i++) {
    655 		/* channels available ? */
    656 		if ((masks2[i] & mask) && (sc->sc_channel[i].nd_busy))
    657 			return EBUSY; /* channel is busy */
    658 		if (channel[i].isaudio == -1)
    659 			return EBUSY; /* system uses them */
    660 	}
    661 
    662 	/* enable interrupt on 1st channel */
    663 	for (i = j = 0; i < AUCC_MAXINT; i++) {
    664 		if (masks2[i] & mask) {
    665 			DPRINTF(("first channel is %d\n",i));
    666 			j = i;
    667 			sc->sc_channel[i].nd_intr = intr;
    668 			sc->sc_channel[i].nd_intrdata = arg;
    669 			break;
    670 		}
    671 	}
    672 
    673 	DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
    674 		 dmap[2], dmap[3], mask));
    675 
    676 	/* disable ints, DMA for channels, until all parameters set */
    677 	/* XXX dont disable DMA! custom.dmacon=mask;*/
    678 	custom.intreq = mask << INTB_AUD0;
    679 	custom.intena = mask << INTB_AUD0;
    680 
    681 	/* copy data to DMA buffer */
    682 
    683 	if (sc->sc_channels == 1) {
    684 		dmap[0] =
    685 		dmap[1] =
    686 		dmap[2] =
    687 		dmap[3] = (u_char *)sc->sc_channel[j].nd_dma;
    688 	} else {
    689 		for (k = 0; k < 4; k++) {
    690 			if (masks2[k+j] & mask)
    691 				dmap[k] = (u_char *)sc->sc_channel[k+j].nd_dma;
    692 		}
    693 	}
    694 
    695 	sc->sc_channel[j].nd_doublebuf ^= 1;
    696 	if (sc->sc_channel[j].nd_doublebuf) {
    697 		dmap[0] += AUDIO_BUF_SIZE;
    698 		dmap[1] += AUDIO_BUF_SIZE;
    699 		dmap[2] += AUDIO_BUF_SIZE;
    700 		dmap[3] += AUDIO_BUF_SIZE;
    701 	}
    702 
    703 	/*
    704 	 * compute output length in bytes per channel.
    705 	 * divide by two only for 16bit->8bit conversion.
    706 	 */
    707 	len = cc / sc->sc_channels;
    708 	if (!sc->sc_14bit && (sc->sc_precision == 16))
    709 		len /= 2;
    710 
    711 	/* call audio decoding routine */
    712 	sc->sc_decodefunc (dmap, (u_char *)p, len);
    713 
    714 	/* DMA buffers: we use same buffer 4 all channels
    715 	 * write DMA location and length
    716 	 */
    717 	for (i = k = 0; i < 4; i++) {
    718 		if (masks2[i] & mask) {
    719 			DPRINTF(("turning channel %d on\n",i));
    720 			/* sc->sc_channel[i].nd_busy=1; */
    721 			channel[i].isaudio = 1;
    722 			channel[i].play_count = 1;
    723 			channel[i].handler = NULL;
    724 			custom.aud[i].per = sc->sc_channel[i].nd_per;
    725 			if (sc->sc_14bit && (i > 1))
    726 				custom.aud[i].vol = 1;
    727 			else
    728 				custom.aud[i].vol = sc->sc_channel[i].nd_volume;
    729 			custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
    730 			custom.aud[i].len = len / 2;
    731 			sc->sc_channel[i].nd_mask = mask;
    732 			DPRINTF(("per is %d, vol is %d, len is %d\n",\
    733 			    sc->sc_channel[i].nd_per,
    734 			    sc->sc_channel[i].nd_volume, len));
    735 		}
    736 	}
    737 
    738 	channel[j].handler = aucc_inthdl;
    739 
    740 	/* enable ints */
    741 	custom.intena = INTF_SETCLR | INTF_INTEN | (masks2[j] << INTB_AUD0);
    742 
    743 	DPRINTF(("enabled ints: 0x%x\n", (masks2[j] << INTB_AUD0)));
    744 
    745 	/* enable DMA */
    746 	custom.dmacon = DMAF_SETCLR | DMAF_MASTER | mask;
    747 
    748 	DPRINTF(("enabled DMA, mask=0x%x\n",mask));
    749 
    750 	return 0;
    751 }
    752 
    753 /* ARGSUSED */
    754 int
    755 aucc_start_input(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
    756 {
    757 
    758 	return ENXIO; /* no input */
    759 }
    760 
    761 int
    762 aucc_halt_output(void *addr)
    763 {
    764 	struct aucc_softc *sc;
    765 	int i;
    766 
    767 	/* XXX only halt, if input is also halted ?? */
    768 	sc = addr;
    769 	/* stop DMA, etc */
    770 	custom.intena = AUCC_ALLINTF;
    771 	custom.dmacon = AUCC_ALLDMAF;
    772 	/* mark every busy unit idle */
    773 	for (i = 0; i < 4; i++) {
    774 		sc->sc_channel[i].nd_busy = sc->sc_channel[i].nd_mask = 0;
    775 		channel[i].isaudio = 0;
    776 		channel[i].play_count = 0;
    777 	}
    778 
    779 	return 0;
    780 }
    781 
    782 int
    783 aucc_halt_input(void *addr)
    784 {
    785 
    786 	/* no input */
    787 	return ENXIO;
    788 }
    789 
    790 int
    791 aucc_getdev(void *addr, struct audio_device *retp)
    792 {
    793 
    794 	*retp = aucc_device;
    795 	return 0;
    796 }
    797 
    798 int
    799 aucc_set_port(void *addr, mixer_ctrl_t *cp)
    800 {
    801 	struct aucc_softc *sc;
    802 	int i,j;
    803 
    804 	DPRINTF(("aucc_set_port: port=%d", cp->dev));
    805 	sc = addr;
    806 	switch (cp->type) {
    807 	case AUDIO_MIXER_SET:
    808 		if (cp->dev != AUCC_CHANNELS)
    809 			return EINVAL;
    810 		i = cp->un.mask;
    811 		if ((i < 1) || (i > 15))
    812 			return EINVAL;
    813 
    814 		sc->sc_channelmask = i;
    815 		break;
    816 
    817 	case AUDIO_MIXER_VALUE:
    818 		i = cp->un.value.num_channels;
    819 		if ((i < 1) || (i > 4))
    820 			return EINVAL;
    821 
    822 #ifdef __XXXwhatsthat
    823 		if (cp->dev != AUCC_VOLUME)
    824 			return EINVAL;
    825 #endif
    826 
    827 		/* set volume for channel 0..i-1 */
    828 
    829 		/* evil workaround for xanim bug, IMO */
    830 		if ((sc->sc_channels == 1) && (i == 2)) {
    831 			sc->sc_channel[0].nd_volume =
    832 			    sc->sc_channel[3].nd_volume =
    833 			    cp->un.value.level[0] >> 2;
    834 			sc->sc_channel[1].nd_volume =
    835 			    sc->sc_channel[2].nd_volume =
    836 			    cp->un.value.level[1] >> 2;
    837 		} else if (i > 1) {
    838 			for (j = 0; j < i; j++)
    839 				sc->sc_channel[j].nd_volume =
    840 				    cp->un.value.level[j] >> 2;
    841 		} else if (sc->sc_channels > 1)
    842 			for (j = 0; j < sc->sc_channels; j++)
    843 				sc->sc_channel[j].nd_volume =
    844 				    cp->un.value.level[0] >> 2;
    845 		else
    846 			for (j = 0; j < 4; j++)
    847 				sc->sc_channel[j].nd_volume =
    848 				    cp->un.value.level[0] >> 2;
    849 		break;
    850 
    851 	default:
    852 		return EINVAL;
    853 		break;
    854 	}
    855 	return 0;
    856 }
    857 
    858 
    859 int
    860 aucc_get_port(void *addr, mixer_ctrl_t *cp)
    861 {
    862 	struct aucc_softc *sc;
    863 	int i,j;
    864 
    865 	DPRINTF(("aucc_get_port: port=%d", cp->dev));
    866 	sc = addr;
    867 	switch (cp->type) {
    868 	case AUDIO_MIXER_SET:
    869 		if (cp->dev != AUCC_CHANNELS)
    870 			return EINVAL;
    871 		cp->un.mask = sc->sc_channelmask;
    872 		break;
    873 
    874 	case AUDIO_MIXER_VALUE:
    875 		i = cp->un.value.num_channels;
    876 		if ((i < 1) || (i > 4))
    877 			return EINVAL;
    878 
    879 		for (j = 0; j < i; j++)
    880 			cp->un.value.level[j] =
    881 			    (sc->sc_channel[j].nd_volume << 2) +
    882 			    (sc->sc_channel[j].nd_volume >> 4);
    883 		break;
    884 
    885 	default:
    886 		return EINVAL;
    887 	}
    888 	return 0;
    889 }
    890 
    891 
    892 int
    893 aucc_get_props(void *addr)
    894 {
    895 	return 0;
    896 }
    897 
    898 
    899 void
    900 aucc_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread)
    901 {
    902 	struct aucc_softc *sc = opaque;
    903 
    904 	*intr = &sc->sc_intr_lock;
    905 	*thread = &sc->sc_lock;
    906 }
    907 
    908 int
    909 aucc_query_devinfo(void *addr, register mixer_devinfo_t *dip)
    910 {
    911 	int i;
    912 
    913 	switch(dip->index) {
    914 	case AUCC_CHANNELS:
    915 		dip->type = AUDIO_MIXER_SET;
    916 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    917 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    918 #define setname(a) strlcpy(dip->label.name, (a), sizeof(dip->label.name))
    919 		setname(AudioNspeaker);
    920 		for (i = 0; i < 16; i++) {
    921 			snprintf(dip->un.s.member[i].label.name,
    922 			    sizeof(dip->un.s.member[i].label.name),
    923 			    "channelmask%d", i);
    924 			dip->un.s.member[i].mask = i;
    925 		}
    926 		dip->un.s.num_mem = 16;
    927 		break;
    928 
    929 	case AUCC_VOLUME:
    930 		dip->type = AUDIO_MIXER_VALUE;
    931 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    932 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    933 		setname(AudioNmaster);
    934 		dip->un.v.num_channels = 4;
    935 		strcpy(dip->un.v.units.name, AudioNvolume);
    936 		break;
    937 
    938 	case AUCC_OUTPUT_CLASS:
    939 		dip->type = AUDIO_MIXER_CLASS;
    940 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    941 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    942 		setname(AudioCoutputs);
    943 		break;
    944 
    945 	default:
    946 		return ENXIO;
    947 	}
    948 
    949 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
    950 
    951 	return 0;
    952 }
    953 
    954 /* audio int handler */
    955 void
    956 aucc_inthdl(int ch)
    957 {
    958 	int i;
    959 	int mask;
    960 
    961 	mutex_spin_enter(&aucc->sc_intr_lock);
    962 	mask = aucc->sc_channel[ch].nd_mask;
    963 	/*
    964 	 * for all channels in this maskgroup:
    965 	 * disable DMA, int
    966 	 * mark idle
    967 	 */
    968 	DPRINTF(("inthandler called, channel %d, mask 0x%x\n", ch, mask));
    969 
    970 	custom.intreq = mask << INTB_AUD0; /* clear request */
    971 	/*
    972 	 * XXX: maybe we can leave ints and/or DMA on,
    973 	 * if another sample has to be played?
    974 	 */
    975 	custom.intena = mask << INTB_AUD0;
    976 	/*
    977 	 * XXX custom.dmacon=mask; NO!!!
    978 	 */
    979 	for (i = 0; i < 4; i++) {
    980 		if (masks2[i] && mask) {
    981 			DPRINTF(("marking channel %d idle\n",i));
    982 			aucc->sc_channel[i].nd_busy = 0;
    983 			aucc->sc_channel[i].nd_mask = 0;
    984 			channel[i].isaudio = channel[i].play_count = 0;
    985 		}
    986 	}
    987 
    988 	/* call handler */
    989 	if (aucc->sc_channel[ch].nd_intr) {
    990 		DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
    991 		(*(aucc->sc_channel[ch].nd_intr))
    992 		    (aucc->sc_channel[ch].nd_intrdata);
    993 	} else
    994 		DPRINTF(("zero int handler\n"));
    995 	mutex_spin_exit(&aucc->sc_intr_lock);
    996 	DPRINTF(("ints done\n"));
    997 }
    998 
    999 /* transform frequency to period, adjust bounds */
   1000 static u_int
   1001 freqtoper(u_int freq)
   1002 {
   1003 	u_int per;
   1004 
   1005 	per = eclockfreq * 5 / freq;
   1006 	if (per < 124)
   1007 		per = 124;   /* must have at least 124 ticks between samples */
   1008 
   1009 	return per;
   1010 }
   1011 
   1012 /* transform period to frequency */
   1013 static u_int
   1014 pertofreq(u_int per)
   1015 {
   1016 
   1017 	return eclockfreq * 5 / per;
   1018 }
   1019 
   1020 static void
   1021 aucc_decode_slinear8_1ch(u_char **dmap, u_char *p, int i)
   1022 {
   1023 	memcpy(dmap[0], p, i);
   1024 }
   1025 
   1026 static void
   1027 aucc_decode_slinear8_2ch(u_char **dmap, u_char *p, int i)
   1028 {
   1029 	u_char *ch0;
   1030 	u_char *ch1;
   1031 
   1032 	ch0 = dmap[0];
   1033 	ch1 = dmap[1];
   1034 	while (i--) {
   1035 		*ch0++ = *p++;
   1036 		*ch1++ = *p++;
   1037 	}
   1038 }
   1039 
   1040 static void
   1041 aucc_decode_slinear8_3ch(u_char **dmap, u_char *p, int i)
   1042 {
   1043 	u_char *ch0;
   1044 	u_char *ch1;
   1045 	u_char *ch2;
   1046 
   1047 	ch0 = dmap[0];
   1048 	ch1 = dmap[1];
   1049 	ch2 = dmap[2];
   1050 	while (i--) {
   1051 		*ch0++ = *p++;
   1052 		*ch1++ = *p++;
   1053 		*ch2++ = *p++;
   1054 	}
   1055 }
   1056 
   1057 static void
   1058 aucc_decode_slinear8_4ch(u_char **dmap, u_char *p, int i)
   1059 {
   1060 	u_char *ch0;
   1061 	u_char *ch1;
   1062 	u_char *ch2;
   1063 	u_char *ch3;
   1064 
   1065 	ch0 = dmap[0];
   1066 	ch1 = dmap[1];
   1067 	ch2 = dmap[2];
   1068 	ch3 = dmap[3];
   1069 	while (i--) {
   1070 		*ch0++ = *p++;
   1071 		*ch1++ = *p++;
   1072 		*ch2++ = *p++;
   1073 		*ch3++ = *p++;
   1074 	}
   1075 }
   1076 
   1077 static void
   1078 aucc_decode_ulinear8_1ch(u_char **dmap, u_char *p, int i)
   1079 {
   1080 	u_char *ch0;
   1081 
   1082 	ch0 = dmap[0];
   1083 	while (i--)
   1084 		*ch0++ = *p++ - 128;
   1085 }
   1086 
   1087 static void
   1088 aucc_decode_ulinear8_2ch(u_char **dmap, u_char *p, int i)
   1089 {
   1090 	u_char *ch0;
   1091 	u_char *ch1;
   1092 
   1093 	ch0 = dmap[0];
   1094 	ch1 = dmap[1];
   1095 	while (i--) {
   1096 		*ch0++ = *p++ - 128;
   1097 		*ch1++ = *p++ - 128;
   1098 	}
   1099 }
   1100 
   1101 static void
   1102 aucc_decode_ulinear8_3ch(u_char **dmap, u_char *p, int i)
   1103 {
   1104 	u_char *ch0;
   1105 	u_char *ch1;
   1106 	u_char *ch2;
   1107 
   1108 	ch0 = dmap[0];
   1109 	ch1 = dmap[1];
   1110 	ch2 = dmap[2];
   1111 	while (i--) {
   1112 		*ch0++ = *p++ - 128;
   1113 		*ch1++ = *p++ - 128;
   1114 		*ch2++ = *p++ - 128;
   1115 	}
   1116 }
   1117 
   1118 static void
   1119 aucc_decode_ulinear8_4ch(u_char **dmap, u_char *p, int i)
   1120 {
   1121 	u_char *ch0;
   1122 	u_char *ch1;
   1123 	u_char *ch2;
   1124 	u_char *ch3;
   1125 
   1126 	ch0 = dmap[0];
   1127 	ch1 = dmap[1];
   1128 	ch2 = dmap[2];
   1129 	ch3 = dmap[3];
   1130 	while (i--) {
   1131 		*ch0++ = *p++ - 128;
   1132 		*ch1++ = *p++ - 128;
   1133 		*ch2++ = *p++ - 128;
   1134 		*ch3++ = *p++ - 128;
   1135 	}
   1136 }
   1137 
   1138 
   1139 static void
   1140 aucc_decode_mulaw_1ch(u_char **dmap, u_char *p, int i)
   1141 {
   1142 	u_char *ch0;
   1143 
   1144 	ch0 = dmap[0];
   1145 	while (i--)
   1146 		*ch0++ = mulaw_to_lin[*p++];
   1147 }
   1148 
   1149 static void
   1150 aucc_decode_mulaw_2ch(u_char **dmap, u_char *p, int i)
   1151 {
   1152 	u_char *ch0;
   1153 	u_char *ch1;
   1154 
   1155 	ch0 = dmap[0];
   1156 	ch1 = dmap[1];
   1157 	while (i--) {
   1158 		*ch0++ = mulaw_to_lin[*p++];
   1159 		*ch1++ = mulaw_to_lin[*p++];
   1160 	}
   1161 }
   1162 
   1163 static void
   1164 aucc_decode_mulaw_3ch(u_char **dmap, u_char *p, int i)
   1165 {
   1166 	u_char *ch0;
   1167 	u_char *ch1;
   1168 	u_char *ch2;
   1169 
   1170 	ch0 = dmap[0];
   1171 	ch1 = dmap[1];
   1172 	ch2 = dmap[2];
   1173 	while (i--) {
   1174 		*ch0++ = mulaw_to_lin[*p++];
   1175 		*ch1++ = mulaw_to_lin[*p++];
   1176 		*ch2++ = mulaw_to_lin[*p++];
   1177 	}
   1178 }
   1179 
   1180 static void
   1181 aucc_decode_mulaw_4ch(u_char **dmap, u_char *p, int i)
   1182 {
   1183 	u_char *ch0;
   1184 	u_char *ch1;
   1185 	u_char *ch2;
   1186 	u_char *ch3;
   1187 
   1188 	ch0 = dmap[0];
   1189 	ch1 = dmap[1];
   1190 	ch2 = dmap[2];
   1191 	ch3 = dmap[3];
   1192 	while (i--) {
   1193 		*ch0++ = mulaw_to_lin[*p++];
   1194 		*ch1++ = mulaw_to_lin[*p++];
   1195 		*ch2++ = mulaw_to_lin[*p++];
   1196 		*ch3++ = mulaw_to_lin[*p++];
   1197 	}
   1198 }
   1199 
   1200 
   1201 /* 14bit output */
   1202 static void
   1203 aucc_decode_slinear16_1ch(u_char **dmap, u_char *p, int i)
   1204 {
   1205 	u_char *ch0;
   1206 	u_char *ch3;
   1207 
   1208 	ch0 = dmap[0];
   1209 	ch3 = dmap[1];		/* XXX should be 3 */
   1210 	while (i--) {
   1211 		*ch0++ = *p++;
   1212 		*ch3++ = *p++ >> 2;
   1213 	}
   1214 }
   1215 
   1216 /* 14bit stereo output */
   1217 static void
   1218 aucc_decode_slinear16_2ch(u_char **dmap, u_char *p, int i)
   1219 {
   1220 	u_char *ch0;
   1221 	u_char *ch1;
   1222 	u_char *ch2;
   1223 	u_char *ch3;
   1224 
   1225 	ch0 = dmap[0];
   1226 	ch1 = dmap[1];
   1227 	ch2 = dmap[2];
   1228 	ch3 = dmap[3];
   1229 	while (i--) {
   1230 		*ch0++ = *p++;
   1231 		*ch3++ = *p++ >> 2;
   1232 		*ch1++ = *p++;
   1233 		*ch2++ = *p++ >> 2;
   1234 	}
   1235 }
   1236 
   1237 static void
   1238 aucc_decode_slinear16_3ch(u_char **dmap, u_char *p, int i)
   1239 {
   1240 	u_char *ch0;
   1241 	u_char *ch1;
   1242 	u_char *ch2;
   1243 
   1244 	ch0 = dmap[0];
   1245 	ch1 = dmap[1];
   1246 	ch2 = dmap[2];
   1247 	while (i--) {
   1248 		*ch0++ = *p++; p++;
   1249 		*ch1++ = *p++; p++;
   1250 		*ch2++ = *p++; p++;
   1251 	}
   1252 }
   1253 
   1254 static void
   1255 aucc_decode_slinear16_4ch(u_char **dmap, u_char *p, int i)
   1256 {
   1257 	u_char *ch0;
   1258 	u_char *ch1;
   1259 	u_char *ch2;
   1260 	u_char *ch3;
   1261 
   1262 	ch0 = dmap[0];
   1263 	ch1 = dmap[1];
   1264 	ch2 = dmap[2];
   1265 	ch3 = dmap[3];
   1266 	while (i--) {
   1267 		*ch0++ = *p++; p++;
   1268 		*ch1++ = *p++; p++;
   1269 		*ch2++ = *p++; p++;
   1270 		*ch3++ = *p++; p++;
   1271 	}
   1272 }
   1273 
   1274 /* 14bit output, swap bytes */
   1275 static void
   1276 aucc_decode_slinear16sw_1ch(u_char **dmap, u_char *p, int i)
   1277 {
   1278 	u_char *ch0;
   1279 	u_char *ch3;
   1280 
   1281 	ch0 = dmap[0];
   1282 	ch3 = dmap[1];		/* XXX should be 3 */
   1283 	while (i--) {
   1284 		*ch3++ = *p++ >> 2;
   1285 		*ch0++ = *p++;
   1286 	}
   1287 }
   1288 
   1289 static void
   1290 aucc_decode_slinear16sw_2ch(u_char **dmap, u_char *p, int i)
   1291 {
   1292 	u_char *ch0;
   1293 	u_char *ch1;
   1294 	u_char *ch2;
   1295 	u_char *ch3;
   1296 
   1297 	ch0 = dmap[0];
   1298 	ch1 = dmap[1];
   1299 	ch2 = dmap[2];
   1300 	ch3 = dmap[3];
   1301 	while (i--) {
   1302 		*ch3++ = *p++ >> 2;
   1303 		*ch0++ = *p++;
   1304 		*ch2++ = *p++ >> 2;
   1305 		*ch1++ = *p++;
   1306 	}
   1307 }
   1308 
   1309 static void
   1310 aucc_decode_slinear16sw_3ch(u_char **dmap, u_char *p, int i)
   1311 {
   1312 	u_char *ch0;
   1313 	u_char *ch1;
   1314 	u_char *ch2;
   1315 
   1316 	ch0 = dmap[0];
   1317 	ch1 = dmap[1];
   1318 	ch2 = dmap[2];
   1319 	while (i--) {
   1320 		p++; *ch0++ = *p++;
   1321 		p++; *ch1++ = *p++;
   1322 		p++; *ch2++ = *p++;
   1323 	}
   1324 }
   1325 
   1326 static void
   1327 aucc_decode_slinear16sw_4ch(u_char **dmap, u_char *p, int i)
   1328 {
   1329 	u_char *ch0;
   1330 	u_char *ch1;
   1331 	u_char *ch2;
   1332 	u_char *ch3;
   1333 
   1334 	ch0 = dmap[0];
   1335 	ch1 = dmap[1];
   1336 	ch2 = dmap[2];
   1337 	ch3 = dmap[3];
   1338 	while (i--) {
   1339 		p++; *ch0++ = *p++;
   1340 		p++; *ch1++ = *p++;
   1341 		p++; *ch2++ = *p++;
   1342 		p++; *ch3++ = *p++;
   1343 	}
   1344 }
   1345 
   1346 
   1347 #endif /* NAUCC > 0 */
   1348