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