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