xref: /netbsd-src/sys/arch/amiga/dev/aucc.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
1 /*	$NetBSD: aucc.c,v 1.43 2014/03/22 01:52:44 christos 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.43 2014/03/22 01:52:44 christos 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 #define setname(a) strlcpy(dip->label.name, (a), sizeof(dip->label.name))
931 		setname(AudioNspeaker);
932 		for (i = 0; i < 16; i++) {
933 			snprintf(dip->un.s.member[i].label.name,
934 			    sizeof(dip->un.s.member[i].label.name),
935 			    "channelmask%d", i);
936 			dip->un.s.member[i].mask = i;
937 		}
938 		dip->un.s.num_mem = 16;
939 		break;
940 
941 	case AUCC_VOLUME:
942 		dip->type = AUDIO_MIXER_VALUE;
943 		dip->mixer_class = AUCC_OUTPUT_CLASS;
944 		dip->prev = dip->next = AUDIO_MIXER_LAST;
945 		setname(AudioNmaster);
946 		dip->un.v.num_channels = 4;
947 		strcpy(dip->un.v.units.name, AudioNvolume);
948 		break;
949 
950 	case AUCC_OUTPUT_CLASS:
951 		dip->type = AUDIO_MIXER_CLASS;
952 		dip->mixer_class = AUCC_OUTPUT_CLASS;
953 		dip->next = dip->prev = AUDIO_MIXER_LAST;
954 		setname(AudioCoutputs);
955 		break;
956 
957 	default:
958 		return ENXIO;
959 	}
960 
961 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
962 
963 	return 0;
964 }
965 
966 /* audio int handler */
967 void
968 aucc_inthdl(int ch)
969 {
970 	int i;
971 	int mask;
972 
973 	mutex_spin_enter(&aucc->sc_intr_lock);
974 	mask = aucc->sc_channel[ch].nd_mask;
975 	/*
976 	 * for all channels in this maskgroup:
977 	 * disable DMA, int
978 	 * mark idle
979 	 */
980 	DPRINTF(("inthandler called, channel %d, mask 0x%x\n", ch, mask));
981 
982 	custom.intreq = mask << INTB_AUD0; /* clear request */
983 	/*
984 	 * XXX: maybe we can leave ints and/or DMA on,
985 	 * if another sample has to be played?
986 	 */
987 	custom.intena = mask << INTB_AUD0;
988 	/*
989 	 * XXX custom.dmacon=mask; NO!!!
990 	 */
991 	for (i = 0; i < 4; i++) {
992 		if (masks2[i] && mask) {
993 			DPRINTF(("marking channel %d idle\n",i));
994 			aucc->sc_channel[i].nd_busy = 0;
995 			aucc->sc_channel[i].nd_mask = 0;
996 			channel[i].isaudio = channel[i].play_count = 0;
997 		}
998 	}
999 
1000 	/* call handler */
1001 	if (aucc->sc_channel[ch].nd_intr) {
1002 		DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
1003 		(*(aucc->sc_channel[ch].nd_intr))
1004 		    (aucc->sc_channel[ch].nd_intrdata);
1005 	} else
1006 		DPRINTF(("zero int handler\n"));
1007 	mutex_spin_exit(&aucc->sc_intr_lock);
1008 	DPRINTF(("ints done\n"));
1009 }
1010 
1011 /* transform frequency to period, adjust bounds */
1012 static u_int
1013 freqtoper(u_int freq)
1014 {
1015 	u_int per;
1016 
1017 	per = eclockfreq * 5 / freq;
1018 	if (per < 124)
1019 		per = 124;   /* must have at least 124 ticks between samples */
1020 
1021 	return per;
1022 }
1023 
1024 /* transform period to frequency */
1025 static u_int
1026 pertofreq(u_int per)
1027 {
1028 
1029 	return eclockfreq * 5 / per;
1030 }
1031 
1032 static void
1033 aucc_decode_slinear8_1ch(u_char **dmap, u_char *p, int i)
1034 {
1035 	memcpy(dmap[0], p, i);
1036 }
1037 
1038 static void
1039 aucc_decode_slinear8_2ch(u_char **dmap, u_char *p, int i)
1040 {
1041 	u_char *ch0;
1042 	u_char *ch1;
1043 
1044 	ch0 = dmap[0];
1045 	ch1 = dmap[1];
1046 	while (i--) {
1047 		*ch0++ = *p++;
1048 		*ch1++ = *p++;
1049 	}
1050 }
1051 
1052 static void
1053 aucc_decode_slinear8_3ch(u_char **dmap, u_char *p, int i)
1054 {
1055 	u_char *ch0;
1056 	u_char *ch1;
1057 	u_char *ch2;
1058 
1059 	ch0 = dmap[0];
1060 	ch1 = dmap[1];
1061 	ch2 = dmap[2];
1062 	while (i--) {
1063 		*ch0++ = *p++;
1064 		*ch1++ = *p++;
1065 		*ch2++ = *p++;
1066 	}
1067 }
1068 
1069 static void
1070 aucc_decode_slinear8_4ch(u_char **dmap, u_char *p, int i)
1071 {
1072 	u_char *ch0;
1073 	u_char *ch1;
1074 	u_char *ch2;
1075 	u_char *ch3;
1076 
1077 	ch0 = dmap[0];
1078 	ch1 = dmap[1];
1079 	ch2 = dmap[2];
1080 	ch3 = dmap[3];
1081 	while (i--) {
1082 		*ch0++ = *p++;
1083 		*ch1++ = *p++;
1084 		*ch2++ = *p++;
1085 		*ch3++ = *p++;
1086 	}
1087 }
1088 
1089 static void
1090 aucc_decode_ulinear8_1ch(u_char **dmap, u_char *p, int i)
1091 {
1092 	u_char *ch0;
1093 
1094 	ch0 = dmap[0];
1095 	while (i--)
1096 		*ch0++ = *p++ - 128;
1097 }
1098 
1099 static void
1100 aucc_decode_ulinear8_2ch(u_char **dmap, u_char *p, int i)
1101 {
1102 	u_char *ch0;
1103 	u_char *ch1;
1104 
1105 	ch0 = dmap[0];
1106 	ch1 = dmap[1];
1107 	while (i--) {
1108 		*ch0++ = *p++ - 128;
1109 		*ch1++ = *p++ - 128;
1110 	}
1111 }
1112 
1113 static void
1114 aucc_decode_ulinear8_3ch(u_char **dmap, u_char *p, int i)
1115 {
1116 	u_char *ch0;
1117 	u_char *ch1;
1118 	u_char *ch2;
1119 
1120 	ch0 = dmap[0];
1121 	ch1 = dmap[1];
1122 	ch2 = dmap[2];
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(u_char **dmap, u_char *p, int i)
1132 {
1133 	u_char *ch0;
1134 	u_char *ch1;
1135 	u_char *ch2;
1136 	u_char *ch3;
1137 
1138 	ch0 = dmap[0];
1139 	ch1 = dmap[1];
1140 	ch2 = dmap[2];
1141 	ch3 = dmap[3];
1142 	while (i--) {
1143 		*ch0++ = *p++ - 128;
1144 		*ch1++ = *p++ - 128;
1145 		*ch2++ = *p++ - 128;
1146 		*ch3++ = *p++ - 128;
1147 	}
1148 }
1149 
1150 
1151 static void
1152 aucc_decode_mulaw_1ch(u_char **dmap, u_char *p, int i)
1153 {
1154 	u_char *ch0;
1155 
1156 	ch0 = dmap[0];
1157 	while (i--)
1158 		*ch0++ = mulaw_to_lin[*p++];
1159 }
1160 
1161 static void
1162 aucc_decode_mulaw_2ch(u_char **dmap, u_char *p, int i)
1163 {
1164 	u_char *ch0;
1165 	u_char *ch1;
1166 
1167 	ch0 = dmap[0];
1168 	ch1 = dmap[1];
1169 	while (i--) {
1170 		*ch0++ = mulaw_to_lin[*p++];
1171 		*ch1++ = mulaw_to_lin[*p++];
1172 	}
1173 }
1174 
1175 static void
1176 aucc_decode_mulaw_3ch(u_char **dmap, u_char *p, int i)
1177 {
1178 	u_char *ch0;
1179 	u_char *ch1;
1180 	u_char *ch2;
1181 
1182 	ch0 = dmap[0];
1183 	ch1 = dmap[1];
1184 	ch2 = dmap[2];
1185 	while (i--) {
1186 		*ch0++ = mulaw_to_lin[*p++];
1187 		*ch1++ = mulaw_to_lin[*p++];
1188 		*ch2++ = mulaw_to_lin[*p++];
1189 	}
1190 }
1191 
1192 static void
1193 aucc_decode_mulaw_4ch(u_char **dmap, u_char *p, int i)
1194 {
1195 	u_char *ch0;
1196 	u_char *ch1;
1197 	u_char *ch2;
1198 	u_char *ch3;
1199 
1200 	ch0 = dmap[0];
1201 	ch1 = dmap[1];
1202 	ch2 = dmap[2];
1203 	ch3 = dmap[3];
1204 	while (i--) {
1205 		*ch0++ = mulaw_to_lin[*p++];
1206 		*ch1++ = mulaw_to_lin[*p++];
1207 		*ch2++ = mulaw_to_lin[*p++];
1208 		*ch3++ = mulaw_to_lin[*p++];
1209 	}
1210 }
1211 
1212 
1213 /* 14bit output */
1214 static void
1215 aucc_decode_slinear16_1ch(u_char **dmap, u_char *p, int i)
1216 {
1217 	u_char *ch0;
1218 	u_char *ch3;
1219 
1220 	ch0 = dmap[0];
1221 	ch3 = dmap[1];		/* XXX should be 3 */
1222 	while (i--) {
1223 		*ch0++ = *p++;
1224 		*ch3++ = *p++ >> 2;
1225 	}
1226 }
1227 
1228 /* 14bit stereo output */
1229 static void
1230 aucc_decode_slinear16_2ch(u_char **dmap, u_char *p, int i)
1231 {
1232 	u_char *ch0;
1233 	u_char *ch1;
1234 	u_char *ch2;
1235 	u_char *ch3;
1236 
1237 	ch0 = dmap[0];
1238 	ch1 = dmap[1];
1239 	ch2 = dmap[2];
1240 	ch3 = dmap[3];
1241 	while (i--) {
1242 		*ch0++ = *p++;
1243 		*ch3++ = *p++ >> 2;
1244 		*ch1++ = *p++;
1245 		*ch2++ = *p++ >> 2;
1246 	}
1247 }
1248 
1249 static void
1250 aucc_decode_slinear16_3ch(u_char **dmap, u_char *p, int i)
1251 {
1252 	u_char *ch0;
1253 	u_char *ch1;
1254 	u_char *ch2;
1255 
1256 	ch0 = dmap[0];
1257 	ch1 = dmap[1];
1258 	ch2 = dmap[2];
1259 	while (i--) {
1260 		*ch0++ = *p++; p++;
1261 		*ch1++ = *p++; p++;
1262 		*ch2++ = *p++; p++;
1263 	}
1264 }
1265 
1266 static void
1267 aucc_decode_slinear16_4ch(u_char **dmap, u_char *p, int i)
1268 {
1269 	u_char *ch0;
1270 	u_char *ch1;
1271 	u_char *ch2;
1272 	u_char *ch3;
1273 
1274 	ch0 = dmap[0];
1275 	ch1 = dmap[1];
1276 	ch2 = dmap[2];
1277 	ch3 = dmap[3];
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(u_char **dmap, u_char *p, int i)
1289 {
1290 	u_char *ch0;
1291 	u_char *ch3;
1292 
1293 	ch0 = dmap[0];
1294 	ch3 = dmap[1];		/* XXX should be 3 */
1295 	while (i--) {
1296 		*ch3++ = *p++ >> 2;
1297 		*ch0++ = *p++;
1298 	}
1299 }
1300 
1301 static void
1302 aucc_decode_slinear16sw_2ch(u_char **dmap, u_char *p, int i)
1303 {
1304 	u_char *ch0;
1305 	u_char *ch1;
1306 	u_char *ch2;
1307 	u_char *ch3;
1308 
1309 	ch0 = dmap[0];
1310 	ch1 = dmap[1];
1311 	ch2 = dmap[2];
1312 	ch3 = dmap[3];
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(u_char **dmap, u_char *p, int i)
1323 {
1324 	u_char *ch0;
1325 	u_char *ch1;
1326 	u_char *ch2;
1327 
1328 	ch0 = dmap[0];
1329 	ch1 = dmap[1];
1330 	ch2 = dmap[2];
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(u_char **dmap, u_char *p, int i)
1340 {
1341 	u_char *ch0;
1342 	u_char *ch1;
1343 	u_char *ch2;
1344 	u_char *ch3;
1345 
1346 	ch0 = dmap[0];
1347 	ch1 = dmap[1];
1348 	ch2 = dmap[2];
1349 	ch3 = dmap[3];
1350 	while (i--) {
1351 		p++; *ch0++ = *p++;
1352 		p++; *ch1++ = *p++;
1353 		p++; *ch2++ = *p++;
1354 		p++; *ch3++ = *p++;
1355 	}
1356 }
1357 
1358 
1359 #endif /* NAUCC > 0 */
1360