xref: /netbsd-src/sys/arch/amiga/dev/aucc.c (revision b757af438b42b93f8c6571f026d8b8ef3eaf5fc9)
1 /*	$NetBSD: aucc.c,v 1.41 2011/11/23 23:07:28 jmcneill 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.41 2011/11/23 23:07:28 jmcneill 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 	struct	device sc_dev;		/* base device */
107 
108 	int	sc_open;		/* single use device */
109 	aucc_data_t sc_channel[4];	/* per channel freq, ... */
110 	u_int	sc_encoding;		/* encoding AUDIO_ENCODING_.*/
111 	int	sc_channels;		/* # of channels used */
112 	int	sc_precision;		/* 8 or 16 bits */
113 	int	sc_14bit;		/* 14bit output enabled */
114 
115 	int	sc_intrcnt;		/* interrupt count */
116 	int	sc_channelmask;		/* which channels are used ? */
117 	void (*sc_decodefunc)(u_char **, u_char *, int);
118 				/* pointer to format conversion routine */
119 
120 	kmutex_t sc_lock;
121 	kmutex_t sc_intr_lock;
122 };
123 
124 /* interrupt interfaces */
125 void aucc_inthdl(int);
126 
127 /* forward declarations */
128 static int init_aucc(struct aucc_softc *);
129 static u_int freqtoper(u_int);
130 static u_int pertofreq(u_int);
131 
132 /* autoconfiguration driver */
133 void	auccattach(struct device *, struct device *, void *);
134 int	auccmatch(struct device *, struct cfdata *, void *);
135 
136 CFATTACH_DECL(aucc, sizeof(struct aucc_softc),
137     auccmatch, auccattach, NULL, NULL);
138 
139 struct audio_device aucc_device = {
140 	"Amiga-audio",
141 	"2.0",
142 	"aucc"
143 };
144 
145 
146 struct aucc_softc *aucc = NULL;
147 
148 
149 unsigned char mulaw_to_lin[] = {
150 	0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
151 	0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
152 	0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf,
153 	0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf,
154 	0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
155 	0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
156 	0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4,
157 	0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8,
158 	0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
159 	0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
160 	0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd,
161 	0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe,
162 	0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
163 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
164 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
165 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
166 	0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61,
167 	0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, 0x45, 0x41,
168 	0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30,
169 	0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20,
170 	0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17,
171 	0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f,
172 	0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b,
173 	0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07,
174 	0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05,
175 	0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
176 	0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02,
177 	0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
178 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
179 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182 };
183 
184 /*
185  * Define our interface to the higher level audio driver.
186  */
187 int	aucc_open(void *, int);
188 void	aucc_close(void *);
189 int	aucc_set_out_sr(void *, u_int);
190 int	aucc_query_encoding(void *, struct audio_encoding *);
191 int	aucc_round_blocksize(void *, int, int, const audio_params_t *);
192 int	aucc_commit_settings(void *);
193 int	aucc_start_output(void *, void *, int, void (*)(void *), void *);
194 int	aucc_start_input(void *, void *, int, void (*)(void *), void *);
195 int	aucc_halt_output(void *);
196 int	aucc_halt_input(void *);
197 int	aucc_getdev(void *, struct audio_device *);
198 int	aucc_set_port(void *, mixer_ctrl_t *);
199 int	aucc_get_port(void *, mixer_ctrl_t *);
200 int	aucc_query_devinfo(void *, mixer_devinfo_t *);
201 void	aucc_encode(int, int, int, int, u_char *, u_short **);
202 int	aucc_set_params(void *, int, int, audio_params_t *, audio_params_t *,
203 			stream_filter_list_t *, stream_filter_list_t *);
204 int	aucc_get_props(void *);
205 void	aucc_get_locks(void *, kmutex_t **, kmutex_t **);
206 
207 
208 static void aucc_decode_slinear8_1ch(u_char **, u_char *, int);
209 static void aucc_decode_slinear8_2ch(u_char **, u_char *, int);
210 static void aucc_decode_slinear8_3ch(u_char **, u_char *, int);
211 static void aucc_decode_slinear8_4ch(u_char **, u_char *, int);
212 
213 static void aucc_decode_ulinear8_1ch(u_char **, u_char *, int);
214 static void aucc_decode_ulinear8_2ch(u_char **, u_char *, int);
215 static void aucc_decode_ulinear8_3ch(u_char **, u_char *, int);
216 static void aucc_decode_ulinear8_4ch(u_char **, u_char *, int);
217 
218 static void aucc_decode_mulaw_1ch(u_char **, u_char *, int);
219 static void aucc_decode_mulaw_2ch(u_char **, u_char *, int);
220 static void aucc_decode_mulaw_3ch(u_char **, u_char *, int);
221 static void aucc_decode_mulaw_4ch(u_char **, u_char *, int);
222 
223 static void aucc_decode_slinear16_1ch(u_char **, u_char *, int);
224 static void aucc_decode_slinear16_2ch(u_char **, u_char *, int);
225 static void aucc_decode_slinear16_3ch(u_char **, u_char *, int);
226 static void aucc_decode_slinear16_4ch(u_char **, u_char *, int);
227 
228 static void aucc_decode_slinear16sw_1ch(u_char **, u_char *, int);
229 static void aucc_decode_slinear16sw_2ch(u_char **, u_char *, int);
230 static void aucc_decode_slinear16sw_3ch(u_char **, u_char *, int);
231 static void aucc_decode_slinear16sw_4ch(u_char **, u_char *, int);
232 
233 
234 
235 const struct audio_hw_if sa_hw_if = {
236 	aucc_open,
237 	aucc_close,
238 	NULL,
239 	aucc_query_encoding,
240 	aucc_set_params,
241 	aucc_round_blocksize,
242 	aucc_commit_settings,
243 	NULL,
244 	NULL,
245 	aucc_start_output,
246 	aucc_start_input,
247 	aucc_halt_output,
248 	aucc_halt_input,
249 	NULL,
250 	aucc_getdev,
251 	NULL,
252 	aucc_set_port,
253 	aucc_get_port,
254 	aucc_query_devinfo,
255 	NULL,
256 	NULL,
257 	NULL,
258 	NULL,
259 	aucc_get_props,
260 	NULL,
261 	NULL,
262 	NULL,
263 	aucc_get_locks,
264 };
265 
266 /* autoconfig routines */
267 
268 int
269 auccmatch(struct device *pdp, struct cfdata *cfp, void *aux)
270 {
271 	static int aucc_matched = 0;
272 
273 	if (!matchname((char *)aux, "aucc") ||
274 #ifdef DRACO
275 	    is_draco() ||
276 #endif
277 	    aucc_matched)
278 		return 0;
279 
280 	aucc_matched = 1;
281 	return 1;
282 }
283 
284 /*
285  * Audio chip found.
286  */
287 void
288 auccattach(struct device *parent, struct device *self, void *args)
289 {
290 	struct aucc_softc *sc;
291 	int i;
292 
293 	sc = (struct aucc_softc *)self;
294 	printf("\n");
295 
296 	if ((i=init_aucc(sc))) {
297 		printf("audio: no chipmem\n");
298 		return;
299 	}
300 
301 	audio_attach_mi(&sa_hw_if, sc, &sc->sc_dev);
302 }
303 
304 
305 static int
306 init_aucc(struct aucc_softc *sc)
307 {
308 	int i, err;
309 
310 	err = 0;
311 	/* init values per channel */
312 	for (i = 0; i < 4; i++) {
313 		sc->sc_channel[i].nd_freq = 8000;
314 		sc->sc_channel[i].nd_per = freqtoper(8000);
315 		sc->sc_channel[i].nd_busy = 0;
316 		sc->sc_channel[i].nd_dma = alloc_chipmem(AUDIO_BUF_SIZE*2);
317 		if (sc->sc_channel[i].nd_dma == NULL)
318 			err = 1;
319 		sc->sc_channel[i].nd_dmalength = 0;
320 		sc->sc_channel[i].nd_volume = 64;
321 		sc->sc_channel[i].nd_intr = NULL;
322 		sc->sc_channel[i].nd_intrdata = NULL;
323 		sc->sc_channel[i].nd_doublebuf = 0;
324 		DPRINTF(("DMA buffer for channel %d is %p\n", i,
325 		    sc->sc_channel[i].nd_dma));
326 	}
327 
328 	if (err) {
329 		for (i = 0; i < 4; i++)
330 			if (sc->sc_channel[i].nd_dma)
331 				free_chipmem(sc->sc_channel[i].nd_dma);
332 	}
333 
334 	sc->sc_channels = 1;
335 	sc->sc_channelmask = 0xf;
336 	sc->sc_precision = 8;
337 	sc->sc_14bit = 0;
338 	sc->sc_encoding = AUDIO_ENCODING_ULAW;
339 	sc->sc_decodefunc = aucc_decode_mulaw_1ch;
340 
341 	/* clear interrupts and DMA: */
342 	custom.intena = AUCC_ALLINTF;
343 	custom.dmacon = AUCC_ALLDMAF;
344 
345 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
346 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
347 
348 	return err;
349 }
350 
351 int
352 aucc_open(void *addr, int flags)
353 {
354 	struct aucc_softc *sc;
355 	int i;
356 
357 	sc = addr;
358 	DPRINTF(("sa_open: unit %p\n",sc));
359 
360 	if (sc->sc_open)
361 		return EBUSY;
362 	sc->sc_open = 1;
363 	for (i = 0; i < AUCC_MAXINT; i++) {
364 		sc->sc_channel[i].nd_intr = NULL;
365 		sc->sc_channel[i].nd_intrdata = NULL;
366 	}
367 	aucc = sc;
368 	sc->sc_channelmask = 0xf;
369 
370 	DPRINTF(("saopen: ok -> sc=%p\n",sc));
371 
372 	return 0;
373 }
374 
375 void
376 aucc_close(void *addr)
377 {
378 	struct aucc_softc *sc;
379 
380 	sc = addr;
381 	DPRINTF(("sa_close: sc=%p\n", sc));
382 	/*
383 	 * halt i/o, clear open flag, and done.
384 	 */
385 	aucc_halt_output(sc);
386 	sc->sc_open = 0;
387 
388 	DPRINTF(("sa_close: closed.\n"));
389 }
390 
391 int
392 aucc_set_out_sr(void *addr, u_int sr)
393 {
394 	struct aucc_softc *sc;
395 	u_long per;
396 	int i;
397 
398 	sc = addr;
399 	per = freqtoper(sr);
400 	if (per > 0xffff)
401 		return EINVAL;
402 	sr = pertofreq(per);
403 
404 	for (i = 0; i < 4; i++) {
405 		sc->sc_channel[i].nd_freq = sr;
406 		sc->sc_channel[i].nd_per = per;
407 	}
408 
409 	return 0;
410 }
411 
412 int
413 aucc_query_encoding(void *addr, struct audio_encoding *fp)
414 {
415 
416 	switch (fp->index) {
417 	case 0:
418 		strcpy(fp->name, AudioEslinear);
419 		fp->encoding = AUDIO_ENCODING_SLINEAR;
420 		fp->precision = 8;
421 		fp->flags = 0;
422 		break;
423 	case 1:
424 		strcpy(fp->name, AudioEmulaw);
425 		fp->encoding = AUDIO_ENCODING_ULAW;
426 		fp->precision = 8;
427 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
428 		break;
429 
430 	case 2:
431 		strcpy(fp->name, AudioEulinear);
432 		fp->encoding = AUDIO_ENCODING_ULINEAR;
433 		fp->precision = 8;
434 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
435 		break;
436 
437 	case 3:
438 		strcpy(fp->name, AudioEslinear);
439 		fp->encoding = AUDIO_ENCODING_SLINEAR;
440 		fp->precision = 16;
441 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
442 		break;
443 
444 	case 4:
445 		strcpy(fp->name, AudioEslinear_be);
446 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
447 		fp->precision = 16;
448 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
449 		break;
450 
451 	case 5:
452 		strcpy(fp->name, AudioEslinear_le);
453 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
454 		fp->precision = 16;
455 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
456 		break;
457 
458 	default:
459 		return EINVAL;
460 		/*NOTREACHED*/
461 	}
462 	return 0;
463 }
464 
465 int
466 aucc_set_params(void *addr, int setmode, int usemode,
467 		audio_params_t *p, audio_params_t *r,
468 		stream_filter_list_t *pfil, stream_filter_list_t *rfil)
469 {
470 	struct aucc_softc *sc;
471 
472 	sc = addr;
473 	/* if (setmode & AUMODE_RECORD)
474 		return 0 ENXIO*/;
475 
476 #ifdef AUCCDEBUG
477 	printf("aucc_set_params(setmode 0x%x, usemode 0x%x, "
478 	       "enc %u, bits %u, chn %u, sr %u)\n", setmode, usemode,
479 	       p->encoding, p->precision, p->channels, p->sample_rate);
480 #endif
481 
482 	switch (p->precision) {
483 	case 8:
484 		switch (p->encoding) {
485 		case AUDIO_ENCODING_ULAW:
486 			switch (p->channels) {
487 			case 1:
488 				sc->sc_decodefunc = aucc_decode_mulaw_1ch;
489 				break;
490 			case 2:
491 				sc->sc_decodefunc = aucc_decode_mulaw_2ch;
492 				break;
493 			case 3:
494 				sc->sc_decodefunc = aucc_decode_mulaw_3ch;
495 				break;
496 			case 4:
497 				sc->sc_decodefunc = aucc_decode_mulaw_4ch;
498 				break;
499 			default:
500 				return EINVAL;
501 			}
502 			break;
503 
504 		case AUDIO_ENCODING_SLINEAR:
505 		case AUDIO_ENCODING_SLINEAR_BE:
506 		case AUDIO_ENCODING_SLINEAR_LE:
507 			switch (p->channels) {
508 			case 1:
509 				sc->sc_decodefunc = aucc_decode_slinear8_1ch;
510 				break;
511 			case 2:
512 				sc->sc_decodefunc = aucc_decode_slinear8_2ch;
513 				break;
514 			case 3:
515 				sc->sc_decodefunc = aucc_decode_slinear8_3ch;
516 				break;
517 			case 4:
518 				sc->sc_decodefunc = aucc_decode_slinear8_4ch;
519 				break;
520 			default:
521 				return EINVAL;
522 			}
523 			break;
524 
525 		case AUDIO_ENCODING_ULINEAR:
526 		case AUDIO_ENCODING_ULINEAR_BE:
527 		case AUDIO_ENCODING_ULINEAR_LE:
528 			switch (p->channels) {
529 			case 1:
530 				sc->sc_decodefunc = aucc_decode_ulinear8_1ch;
531 				break;
532 			case 2:
533 				sc->sc_decodefunc = aucc_decode_ulinear8_2ch;
534 				break;
535 			case 3:
536 				sc->sc_decodefunc = aucc_decode_ulinear8_3ch;
537 				break;
538 			case 4:
539 				sc->sc_decodefunc = aucc_decode_ulinear8_4ch;
540 				break;
541 			default:
542 				return EINVAL;
543 			}
544 			break;
545 
546 		default:
547 			return EINVAL;
548 		}
549 		break;
550 
551 	case 16:
552 		switch (p->encoding) {
553 #if BYTE_ORDER == BIG_ENDIAN
554 		case AUDIO_ENCODING_SLINEAR:
555 #endif
556 		case AUDIO_ENCODING_SLINEAR_BE:
557 			switch (p->channels) {
558 			case 1:
559 				sc->sc_decodefunc = aucc_decode_slinear16_1ch;
560 				break;
561 
562 			case 2:
563 				sc->sc_decodefunc = aucc_decode_slinear16_2ch;
564 				break;
565 			case 3:
566 				sc->sc_decodefunc = aucc_decode_slinear16_3ch;
567 				break;
568 			case 4:
569 				sc->sc_decodefunc = aucc_decode_slinear16_4ch;
570 				break;
571 			default:
572 				return EINVAL;
573 			}
574 			break;
575 
576 #if BYTE_ORDER == LITTLE_ENDIAN
577 		case AUDIO_ENCODING_SLINEAR:
578 #endif
579 		case AUDIO_ENCODING_SLINEAR_LE:
580 			switch (p->channels) {
581 			case 1:
582 				sc->sc_decodefunc = aucc_decode_slinear16sw_1ch;
583 				break;
584 			case 2:
585 				sc->sc_decodefunc = aucc_decode_slinear16sw_2ch;
586 				break;
587 			case 3:
588 				sc->sc_decodefunc = aucc_decode_slinear16sw_3ch;
589 				break;
590 			case 4:
591 				sc->sc_decodefunc = aucc_decode_slinear16sw_4ch;
592 				break;
593 			default:
594 				return EINVAL;
595 			}
596 			break;
597 
598 		default:
599 			return EINVAL;
600 		}
601 		break;
602 
603 	default:
604 		return EINVAL;
605 	}
606 
607 	sc->sc_encoding = p->encoding;
608 	sc->sc_precision = p->precision;
609 	sc->sc_14bit = ((p->precision == 16) && (p->channels <= 2));
610 	sc->sc_channels = sc->sc_14bit ? (p->channels * 2) : p->channels;
611 
612 	return aucc_set_out_sr(addr, p->sample_rate);
613 }
614 
615 int
616 aucc_round_blocksize(void *addr, int blk,
617 		     int mode, const audio_params_t *param)
618 {
619 
620 	/* round up to even size */
621 	return blk > AUDIO_BUF_SIZE ? AUDIO_BUF_SIZE : blk;
622 }
623 
624 int
625 aucc_commit_settings(void *addr)
626 {
627 	struct aucc_softc *sc;
628 	int i;
629 
630 	DPRINTF(("sa_commit.\n"));
631 
632 	sc = addr;
633 	for (i = 0; i < 4; i++) {
634 		custom.aud[i].vol = sc->sc_channel[i].nd_volume;
635 		custom.aud[i].per = sc->sc_channel[i].nd_per;
636 	}
637 
638 	DPRINTF(("commit done\n"));
639 
640 	return 0;
641 }
642 
643 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
644 static int masks2[4] = {1,2,4,8};
645 
646 int
647 aucc_start_output(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
648 {
649 	struct aucc_softc *sc;
650 	int mask;
651 	int i, j, k, len;
652 	u_char *dmap[4];
653 
654 
655 	sc = addr;
656 	mask = sc->sc_channelmask;
657 
658 	dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
659 
660 	DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
661 
662 	if (sc->sc_channels > 1)
663 		mask &= masks[sc->sc_channels - 1];
664 		/* we use first sc_channels channels */
665 	if (mask == 0) /* active and used channels are disjoint */
666 		return EINVAL;
667 
668 	for (i = 0; i < 4; i++) {
669 		/* channels available ? */
670 		if ((masks2[i] & mask) && (sc->sc_channel[i].nd_busy))
671 			return EBUSY; /* channel is busy */
672 		if (channel[i].isaudio == -1)
673 			return EBUSY; /* system uses them */
674 	}
675 
676 	/* enable interrupt on 1st channel */
677 	for (i = j = 0; i < AUCC_MAXINT; i++) {
678 		if (masks2[i] & mask) {
679 			DPRINTF(("first channel is %d\n",i));
680 			j = i;
681 			sc->sc_channel[i].nd_intr = intr;
682 			sc->sc_channel[i].nd_intrdata = arg;
683 			break;
684 		}
685 	}
686 
687 	DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
688 		 dmap[2], dmap[3], mask));
689 
690 	/* disable ints, DMA for channels, until all parameters set */
691 	/* XXX dont disable DMA! custom.dmacon=mask;*/
692 	custom.intreq = mask << INTB_AUD0;
693 	custom.intena = mask << INTB_AUD0;
694 
695 	/* copy data to DMA buffer */
696 
697 	if (sc->sc_channels == 1) {
698 		dmap[0] =
699 		dmap[1] =
700 		dmap[2] =
701 		dmap[3] = (u_char *)sc->sc_channel[j].nd_dma;
702 	} else {
703 		for (k = 0; k < 4; k++) {
704 			if (masks2[k+j] & mask)
705 				dmap[k] = (u_char *)sc->sc_channel[k+j].nd_dma;
706 		}
707 	}
708 
709 	sc->sc_channel[j].nd_doublebuf ^= 1;
710 	if (sc->sc_channel[j].nd_doublebuf) {
711 		dmap[0] += AUDIO_BUF_SIZE;
712 		dmap[1] += AUDIO_BUF_SIZE;
713 		dmap[2] += AUDIO_BUF_SIZE;
714 		dmap[3] += AUDIO_BUF_SIZE;
715 	}
716 
717 	/*
718 	 * compute output length in bytes per channel.
719 	 * divide by two only for 16bit->8bit conversion.
720 	 */
721 	len = cc / sc->sc_channels;
722 	if (!sc->sc_14bit && (sc->sc_precision == 16))
723 		len /= 2;
724 
725 	/* call audio decoding routine */
726 	sc->sc_decodefunc (dmap, (u_char *)p, len);
727 
728 	/* DMA buffers: we use same buffer 4 all channels
729 	 * write DMA location and length
730 	 */
731 	for (i = k = 0; i < 4; i++) {
732 		if (masks2[i] & mask) {
733 			DPRINTF(("turning channel %d on\n",i));
734 			/* sc->sc_channel[i].nd_busy=1; */
735 			channel[i].isaudio = 1;
736 			channel[i].play_count = 1;
737 			channel[i].handler = NULL;
738 			custom.aud[i].per = sc->sc_channel[i].nd_per;
739 			if (sc->sc_14bit && (i > 1))
740 				custom.aud[i].vol = 1;
741 			else
742 				custom.aud[i].vol = sc->sc_channel[i].nd_volume;
743 			custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
744 			custom.aud[i].len = len / 2;
745 			sc->sc_channel[i].nd_mask = mask;
746 			DPRINTF(("per is %d, vol is %d, len is %d\n",\
747 			    sc->sc_channel[i].nd_per,
748 			    sc->sc_channel[i].nd_volume, len));
749 		}
750 	}
751 
752 	channel[j].handler = aucc_inthdl;
753 
754 	/* enable ints */
755 	custom.intena = INTF_SETCLR | INTF_INTEN | (masks2[j] << INTB_AUD0);
756 
757 	DPRINTF(("enabled ints: 0x%x\n", (masks2[j] << INTB_AUD0)));
758 
759 	/* enable DMA */
760 	custom.dmacon = DMAF_SETCLR | DMAF_MASTER | mask;
761 
762 	DPRINTF(("enabled DMA, mask=0x%x\n",mask));
763 
764 	return 0;
765 }
766 
767 /* ARGSUSED */
768 int
769 aucc_start_input(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
770 {
771 
772 	return ENXIO; /* no input */
773 }
774 
775 int
776 aucc_halt_output(void *addr)
777 {
778 	struct aucc_softc *sc;
779 	int i;
780 
781 	/* XXX only halt, if input is also halted ?? */
782 	sc = addr;
783 	/* stop DMA, etc */
784 	custom.intena = AUCC_ALLINTF;
785 	custom.dmacon = AUCC_ALLDMAF;
786 	/* mark every busy unit idle */
787 	for (i = 0; i < 4; i++) {
788 		sc->sc_channel[i].nd_busy = sc->sc_channel[i].nd_mask = 0;
789 		channel[i].isaudio = 0;
790 		channel[i].play_count = 0;
791 	}
792 
793 	return 0;
794 }
795 
796 int
797 aucc_halt_input(void *addr)
798 {
799 
800 	/* no input */
801 	return ENXIO;
802 }
803 
804 int
805 aucc_getdev(void *addr, struct audio_device *retp)
806 {
807 
808 	*retp = aucc_device;
809 	return 0;
810 }
811 
812 int
813 aucc_set_port(void *addr, mixer_ctrl_t *cp)
814 {
815 	struct aucc_softc *sc;
816 	int i,j;
817 
818 	DPRINTF(("aucc_set_port: port=%d", cp->dev));
819 	sc = addr;
820 	switch (cp->type) {
821 	case AUDIO_MIXER_SET:
822 		if (cp->dev != AUCC_CHANNELS)
823 			return EINVAL;
824 		i = cp->un.mask;
825 		if ((i < 1) || (i > 15))
826 			return EINVAL;
827 
828 		sc->sc_channelmask = i;
829 		break;
830 
831 	case AUDIO_MIXER_VALUE:
832 		i = cp->un.value.num_channels;
833 		if ((i < 1) || (i > 4))
834 			return EINVAL;
835 
836 #ifdef __XXXwhatsthat
837 		if (cp->dev != AUCC_VOLUME)
838 			return EINVAL;
839 #endif
840 
841 		/* set volume for channel 0..i-1 */
842 
843 		/* evil workaround for xanim bug, IMO */
844 		if ((sc->sc_channels == 1) && (i == 2)) {
845 			sc->sc_channel[0].nd_volume =
846 			    sc->sc_channel[3].nd_volume =
847 			    cp->un.value.level[0] >> 2;
848 			sc->sc_channel[1].nd_volume =
849 			    sc->sc_channel[2].nd_volume =
850 			    cp->un.value.level[1] >> 2;
851 		} else if (i > 1) {
852 			for (j = 0; j < i; j++)
853 				sc->sc_channel[j].nd_volume =
854 				    cp->un.value.level[j] >> 2;
855 		} else if (sc->sc_channels > 1)
856 			for (j = 0; j < sc->sc_channels; j++)
857 				sc->sc_channel[j].nd_volume =
858 				    cp->un.value.level[0] >> 2;
859 		else
860 			for (j = 0; j < 4; j++)
861 				sc->sc_channel[j].nd_volume =
862 				    cp->un.value.level[0] >> 2;
863 		break;
864 
865 	default:
866 		return EINVAL;
867 		break;
868 	}
869 	return 0;
870 }
871 
872 
873 int
874 aucc_get_port(void *addr, mixer_ctrl_t *cp)
875 {
876 	struct aucc_softc *sc;
877 	int i,j;
878 
879 	DPRINTF(("aucc_get_port: port=%d", cp->dev));
880 	sc = addr;
881 	switch (cp->type) {
882 	case AUDIO_MIXER_SET:
883 		if (cp->dev != AUCC_CHANNELS)
884 			return EINVAL;
885 		cp->un.mask = sc->sc_channelmask;
886 		break;
887 
888 	case AUDIO_MIXER_VALUE:
889 		i = cp->un.value.num_channels;
890 		if ((i < 1) || (i > 4))
891 			return EINVAL;
892 
893 		for (j = 0; j < i; j++)
894 			cp->un.value.level[j] =
895 			    (sc->sc_channel[j].nd_volume << 2) +
896 			    (sc->sc_channel[j].nd_volume >> 4);
897 		break;
898 
899 	default:
900 		return EINVAL;
901 	}
902 	return 0;
903 }
904 
905 
906 int
907 aucc_get_props(void *addr)
908 {
909 	return 0;
910 }
911 
912 
913 void
914 aucc_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread)
915 {
916 	struct aucc_softc *sc = opaque;
917 
918 	*intr = &sc->sc_intr_lock;
919 	*thread = &sc->sc_lock;
920 }
921 
922 int
923 aucc_query_devinfo(void *addr, register mixer_devinfo_t *dip)
924 {
925 	int i;
926 
927 	switch(dip->index) {
928 	case AUCC_CHANNELS:
929 		dip->type = AUDIO_MIXER_SET;
930 		dip->mixer_class = AUCC_OUTPUT_CLASS;
931 		dip->prev = dip->next = AUDIO_MIXER_LAST;
932 		strcpy(dip->label.name, AudioNspeaker);
933 		for (i = 0; i < 16; i++) {
934 			sprintf(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 		strcpy(dip->label.name, 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 		strcpy(dip->label.name, 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