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