xref: /netbsd-src/sys/arch/amiga/dev/aucc.c (revision a4ddc2c8fb9af816efe3b1c375a5530aef0e89e9)
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