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