xref: /netbsd-src/sys/arch/amiga/dev/aucc.c (revision 481fca6e59249d8ffcf24fef7cfbe7b131bfb080)
1 /*	$NetBSD: aucc.c,v 1.25 2000/03/16 16:37:20 kleink Exp $	*/
2 
3 /*
4  * Copyright (c) 1999 Bernardo Innocenti
5  * All rights reserved.
6  *
7  * Copyright (c) 1997 Stephan Thesing
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by Stephan Thesing.
21  * 4. The name of the author may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 /* TODO:
37  *
38  * - ulaw -> 14bit conversion
39  * - channel allocation is wrong for 14bit mono
40  * - convert the... err... conversion routines to 68k asm for best performance
41  * 	XXX: NO. aucc audio is limited by chipmem speed, anyway. You dont
42  *	want to make life difficult for amigappc work.
43  *		-is
44  *
45  * - rely on auconv.c routines for ulaw/alaw conversions
46  * - perhaps use a calibration table for better 14bit output
47  * - set 31KHz AGA video mode to allow 44.1KHz even if grfcc is missing
48  *	in the kernel
49  * - 14bit output requires maximum volume
50  */
51 
52 #include "aucc.h"
53 #if NAUCC > 0
54 
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/errno.h>
58 #include <sys/ioctl.h>
59 #include <sys/device.h>
60 #include <sys/proc.h>
61 #include <machine/cpu.h>
62 
63 #include <sys/audioio.h>
64 #include <dev/audio_if.h>
65 #include <amiga/amiga/cc.h>
66 #include <amiga/amiga/custom.h>
67 #include <amiga/amiga/device.h>
68 #include <amiga/dev/auccvar.h>
69 
70 
71 #ifdef LEV6_DEFER
72 #define AUCC_MAXINT 3
73 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2)
74 #else
75 #define AUCC_MAXINT 4
76 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3)
77 #endif
78 /* this unconditionally; we may use AUD3 as slave channel with LEV6_DEFER */
79 #define AUCC_ALLDMAF (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3)
80 
81 #ifdef AUDIO_DEBUG
82 /*extern printf __P((const char *,...));*/
83 int     auccdebug = 1;
84 #define DPRINTF(x)      if (auccdebug) printf x
85 #else
86 #define DPRINTF(x)
87 #endif
88 
89 #ifdef splaudio
90 #undef splaudio
91 #endif
92 
93 #define splaudio() spl4();
94 
95 /* clock frequency.. */
96 extern int eclockfreq;
97 
98 
99 /* hw audio ch */
100 extern struct audio_channel channel[4];
101 
102 
103 /*
104  * Software state.
105  */
106 struct aucc_softc {
107 	struct	device sc_dev;		/* base device */
108 
109 	int	sc_open;		/* single use device */
110 	aucc_data_t sc_channel[4];	/* per channel freq, ... */
111 	u_int	sc_encoding;		/* encoding AUDIO_ENCODING_.*/
112 	int	sc_channels;		/* # of channels used */
113 	int	sc_precision;		/* 8 or 16 bits */
114 	int	sc_14bit;		/* 14bit output enabled */
115 
116 	int	sc_intrcnt;		/* interrupt count */
117 	int	sc_channelmask;  	/* which channels are used ? */
118 	void (*sc_decodefunc) __P((u_char **, u_char *, int));
119 				/* pointer to format conversion routine */
120 };
121 
122 /* interrupt interfaces */
123 void aucc_inthdl __P((int));
124 
125 /* forward declarations */
126 static int init_aucc __P((struct aucc_softc *));
127 static u_int freqtoper  __P((u_int));
128 static u_int pertofreq  __P((u_int));
129 
130 /* autoconfiguration driver */
131 void	auccattach __P((struct device *, struct device *, void *));
132 int	auccmatch __P((struct device *, struct cfdata *, void *));
133 
134 struct cfattach aucc_ca = {
135 	sizeof(struct aucc_softc),
136 	auccmatch,
137 	auccattach
138 };
139 
140 struct audio_device aucc_device = {
141 	"Amiga-audio",
142 	"2.0",
143 	"aucc"
144 };
145 
146 
147 struct aucc_softc *aucc=NULL;
148 
149 
150 unsigned char ulaw_to_lin[] = {
151 	0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
152 	0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
153 	0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf,
154 	0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf,
155 	0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
156 	0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
157 	0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4,
158 	0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8,
159 	0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
160 	0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
161 	0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd,
162 	0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe,
163 	0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
164 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
165 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
166 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
167 	0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61,
168 	0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, 0x45, 0x41,
169 	0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30,
170 	0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20,
171 	0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17,
172 	0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f,
173 	0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b,
174 	0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07,
175 	0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05,
176 	0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
177 	0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02,
178 	0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
179 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
180 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 };
184 
185 /*
186  * Define our interface to the higher level audio driver.
187  */
188 int	aucc_open __P((void *, int));
189 void	aucc_close __P((void *));
190 int	aucc_set_out_sr __P((void *, u_long));
191 int	aucc_query_encoding __P((void *, struct audio_encoding *));
192 int	aucc_round_blocksize __P((void *, int));
193 int	aucc_commit_settings __P((void *));
194 int	aucc_start_output __P((void *, void *, int, void (*)(void *),
195 				  void *));
196 int	aucc_start_input __P((void *, void *, int, void (*)(void *),
197 				 void *));
198 int	aucc_halt_output __P((void *));
199 int	aucc_halt_input __P((void *));
200 int	aucc_getdev __P((void *, struct audio_device *));
201 int	aucc_set_port __P((void *, mixer_ctrl_t *));
202 int	aucc_get_port __P((void *, mixer_ctrl_t *));
203 int	aucc_query_devinfo __P((void *, mixer_devinfo_t *));
204 void	aucc_encode __P((int, int, int, int, u_char *, u_short **));
205 int	aucc_set_params __P((void *, int, int,
206 	    struct audio_params *, struct audio_params *));
207 int	aucc_get_props __P((void *));
208 
209 
210 static void aucc_decode_slinear8_1ch __P((u_char **, u_char *, int));
211 static void aucc_decode_slinear8_2ch __P((u_char **, u_char *, int));
212 static void aucc_decode_slinear8_3ch __P((u_char **, u_char *, int));
213 static void aucc_decode_slinear8_4ch __P((u_char **, u_char *, int));
214 
215 static void aucc_decode_ulinear8_1ch __P((u_char **, u_char *, int));
216 static void aucc_decode_ulinear8_2ch __P((u_char **, u_char *, int));
217 static void aucc_decode_ulinear8_3ch __P((u_char **, u_char *, int));
218 static void aucc_decode_ulinear8_4ch __P((u_char **, u_char *, int));
219 
220 static void aucc_decode_ulaw_1ch __P((u_char **, u_char *, int));
221 static void aucc_decode_ulaw_2ch __P((u_char **, u_char *, int));
222 static void aucc_decode_ulaw_3ch __P((u_char **, u_char *, int));
223 static void aucc_decode_ulaw_4ch __P((u_char **, u_char *, int));
224 
225 static void aucc_decode_slinear16_1ch __P((u_char **, u_char *, int));
226 static void aucc_decode_slinear16_2ch __P((u_char **, u_char *, int));
227 static void aucc_decode_slinear16_3ch __P((u_char **, u_char *, int));
228 static void aucc_decode_slinear16_4ch __P((u_char **, u_char *, int));
229 
230 static void aucc_decode_slinear16sw_1ch __P((u_char **, u_char *, int));
231 static void aucc_decode_slinear16sw_2ch __P((u_char **, u_char *, int));
232 static void aucc_decode_slinear16sw_3ch __P((u_char **, u_char *, int));
233 static void aucc_decode_slinear16sw_4ch __P((u_char **, u_char *, int));
234 
235 
236 
237 struct audio_hw_if sa_hw_if = {
238 	aucc_open,
239 	aucc_close,
240 	NULL,
241 	aucc_query_encoding,
242 	aucc_set_params,
243 	aucc_round_blocksize,
244 	aucc_commit_settings,
245 	NULL,
246 	NULL,
247 	aucc_start_output,
248 	aucc_start_input,
249 	aucc_halt_output,
250 	aucc_halt_input,
251 	NULL,
252 	aucc_getdev,
253 	NULL,
254 	aucc_set_port,
255 	aucc_get_port,
256 	aucc_query_devinfo,
257 	NULL,
258 	NULL,
259 	NULL,
260 	NULL,
261 	aucc_get_props,
262 };
263 
264 /* autoconfig routines */
265 
266 int
267 auccmatch(pdp, cfp, aux)
268 	struct device *pdp;
269 	struct cfdata *cfp;
270 	void *aux;
271 {
272 	static int aucc_matched = 0;
273 
274 	if (!matchname((char *)aux, "aucc") ||
275 #ifdef DRACO
276 	    is_draco() ||
277 #endif
278 	    aucc_matched)
279 		return 0;
280 
281 	aucc_matched = 1;
282 	return 1;
283 }
284 
285 /*
286  * Audio chip found.
287  */
288 void
289 auccattach(parent, self, args)
290 	struct device *parent, *self;
291 	void *args;
292 {
293 	register struct aucc_softc *sc = (struct aucc_softc *)self;
294 	register int i;
295 
296 	printf("\n");
297 
298 	if((i=init_aucc(sc))) {
299 		printf("audio: no chipmem\n");
300 		return;
301 	}
302 
303 	audio_attach_mi(&sa_hw_if, sc, &sc->sc_dev);
304 }
305 
306 
307 static int
308 init_aucc(sc)
309 	struct aucc_softc *sc;
310 {
311 	register int i, err=0;
312 
313 	/* init values per channel */
314  	for (i=0;i<4;i++) {
315 		sc->sc_channel[i].nd_freq=8000;
316 		sc->sc_channel[i].nd_per=freqtoper(8000);
317 		sc->sc_channel[i].nd_busy=0;
318 		sc->sc_channel[i].nd_dma=alloc_chipmem(AUDIO_BUF_SIZE*2);
319 		if (sc->sc_channel[i].nd_dma==NULL)
320 			err=1;
321 	 	sc->sc_channel[i].nd_dmalength=0;
322 		sc->sc_channel[i].nd_volume=64;
323 		sc->sc_channel[i].nd_intr=NULL;
324 		sc->sc_channel[i].nd_intrdata=NULL;
325 		sc->sc_channel[i].nd_doublebuf=0;
326 		DPRINTF(("dma buffer for channel %d is %p\n", i,
327 		    sc->sc_channel[i].nd_dma));
328 	}
329 
330 	if (err) {
331 		for(i=0;i<4;i++)
332 			if (sc->sc_channel[i].nd_dma)
333 				free_chipmem(sc->sc_channel[i].nd_dma);
334 	}
335 
336 	sc->sc_channels=1;
337 	sc->sc_channelmask=0xf;
338 	sc->sc_precision=8;
339 	sc->sc_14bit = 0;
340 	sc->sc_encoding=AUDIO_ENCODING_ULAW;
341 	sc->sc_decodefunc = aucc_decode_ulaw_1ch;
342 
343 	/* clear interrupts and dma: */
344 	custom.intena = AUCC_ALLINTF;
345 	custom.dmacon = AUCC_ALLDMAF;
346 
347 	return err;
348 }
349 
350 int
351 aucc_open(addr, flags)
352 	void *addr;
353 	int flags;
354 {
355 	struct aucc_softc *sc = addr;
356 	int i;
357 
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=0x%p\n",sc));
371 
372 	return (0);
373 }
374 
375 void
376 aucc_close(addr)
377 	void *addr;
378 {
379 	register struct aucc_softc *sc = addr;
380 
381 	DPRINTF(("sa_close: sc=0x%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(addr, sr)
393 	void *addr;
394 	u_long sr;
395 {
396 	struct aucc_softc *sc=addr;
397 	u_long per;
398 	register int i;
399 
400 	per=freqtoper(sr);
401 	if (per>0xffff)
402 		return EINVAL;
403 	sr=pertofreq(per);
404 
405 	for (i=0;i<4;i++) {
406 		sc->sc_channel[i].nd_freq=sr;
407 		sc->sc_channel[i].nd_per=per;
408 	}
409 
410 	return(0);
411 }
412 
413 int
414 aucc_query_encoding(addr, fp)
415 	void *addr;
416 	struct audio_encoding *fp;
417 {
418 	switch (fp->index) {
419 		case 0:
420 			strcpy(fp->name, AudioEslinear);
421 			fp->encoding = AUDIO_ENCODING_SLINEAR;
422 			fp->precision = 8;
423 			fp->flags = 0;
424 			break;
425 		case 1:
426 			strcpy(fp->name, AudioEmulaw);
427 			fp->encoding = AUDIO_ENCODING_ULAW;
428 			fp->precision = 8;
429 			fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
430 			break;
431 
432 		case 2:
433 			strcpy(fp->name, AudioEulinear);
434 			fp->encoding = AUDIO_ENCODING_ULINEAR;
435 			fp->precision = 8;
436 			fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
437 			break;
438 
439 		case 3:
440 			strcpy(fp->name, AudioEslinear);
441 			fp->encoding = AUDIO_ENCODING_SLINEAR;
442 			fp->precision = 16;
443 			fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
444 			break;
445 
446 		case 4:
447 			strcpy(fp->name, AudioEslinear_be);
448 			fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
449 			fp->precision = 16;
450 			fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
451 			break;
452 
453 		case 5:
454 			strcpy(fp->name, AudioEslinear_le);
455 			fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
456 			fp->precision = 16;
457 			fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
458 			break;
459 
460 		default:
461 			return(EINVAL);
462 			/*NOTREACHED*/
463 	}
464 	return(0);
465 }
466 
467 int
468 aucc_set_params(addr, setmode, usemode, p, r)
469 	void *addr;
470 	int setmode, usemode;
471 	struct  audio_params *p, *r;
472 {
473 	struct aucc_softc *sc = addr;
474 
475 	/* if (setmode & AUMODE_RECORD)
476 		return 0 ENXIO*/;
477 
478 #ifdef AUCCDEBUG
479 	printf("aucc_set_params(setmode 0x%x, usemode 0x%x, "
480 		"enc %d, bits %d, chn %d, sr %ld)\n", setmode, usemode,
481 		p->encoding, p->precision, p->channels, p->sample_rate);
482 #endif
483 
484 	switch (p->precision) {
485 	case 8:
486 		switch (p->encoding) {
487 		case AUDIO_ENCODING_ULAW:
488 			switch (p->channels) {
489 			case 1:
490 				sc->sc_decodefunc = aucc_decode_ulaw_1ch;
491 				break;
492 			case 2:
493 				sc->sc_decodefunc = aucc_decode_ulaw_2ch;
494 				break;
495 			case 3:
496 				sc->sc_decodefunc = aucc_decode_ulaw_3ch;
497 				break;
498 			case 4:
499 				sc->sc_decodefunc = aucc_decode_ulaw_4ch;
500 				break;
501 			default:
502 				return EINVAL;
503 			}
504 			break;
505 
506 		case AUDIO_ENCODING_SLINEAR:
507 		case AUDIO_ENCODING_SLINEAR_BE:
508 		case AUDIO_ENCODING_SLINEAR_LE:
509 			switch (p->channels) {
510 			case 1:
511 				sc->sc_decodefunc = aucc_decode_slinear8_1ch;
512 				break;
513 			case 2:
514 				sc->sc_decodefunc = aucc_decode_slinear8_2ch;
515 				break;
516 			case 3:
517 				sc->sc_decodefunc = aucc_decode_slinear8_3ch;
518 				break;
519 			case 4:
520 				sc->sc_decodefunc = aucc_decode_slinear8_4ch;
521 				break;
522 			default:
523 				return EINVAL;
524 			}
525 			break;
526 
527 		case AUDIO_ENCODING_ULINEAR:
528 		case AUDIO_ENCODING_ULINEAR_BE:
529 		case AUDIO_ENCODING_ULINEAR_LE:
530 			switch (p->channels) {
531 			case 1:
532 				sc->sc_decodefunc = aucc_decode_ulinear8_1ch;
533 				break;
534 			case 2:
535 				sc->sc_decodefunc = aucc_decode_ulinear8_2ch;
536 				break;
537 			case 3:
538 				sc->sc_decodefunc = aucc_decode_ulinear8_3ch;
539 				break;
540 			case 4:
541 				sc->sc_decodefunc = aucc_decode_ulinear8_4ch;
542 				break;
543 			default:
544 				return EINVAL;
545 			}
546 			break;
547 
548 		default:
549 			return EINVAL;
550 		}
551 		break;
552 
553 	case 16:
554 		switch (p->encoding) {
555 #if BYTE_ORDER == BIG_ENDIAN
556 		case AUDIO_ENCODING_SLINEAR:
557 #endif
558 		case AUDIO_ENCODING_SLINEAR_BE:
559 			switch (p->channels) {
560 			case 1:
561 				sc->sc_decodefunc = aucc_decode_slinear16_1ch;
562 				break;
563 
564 			case 2:
565 				sc->sc_decodefunc = aucc_decode_slinear16_2ch;
566 				break;
567 			case 3:
568 				sc->sc_decodefunc = aucc_decode_slinear16_3ch;
569 				break;
570 			case 4:
571 				sc->sc_decodefunc = aucc_decode_slinear16_4ch;
572 				break;
573 			default:
574 				return EINVAL;
575 			}
576 			break;
577 
578 #if BYTE_ORDER == LITTLE_ENDIAN
579 		case AUDIO_ENCODING_SLINEAR:
580 #endif
581 		case AUDIO_ENCODING_SLINEAR_LE:
582 			switch (p->channels) {
583 			case 1:
584 				sc->sc_decodefunc = aucc_decode_slinear16sw_1ch;
585 				break;
586 			case 2:
587 				sc->sc_decodefunc = aucc_decode_slinear16sw_2ch;
588 				break;
589 			case 3:
590 				sc->sc_decodefunc = aucc_decode_slinear16sw_3ch;
591 				break;
592 			case 4:
593 				sc->sc_decodefunc = aucc_decode_slinear16sw_4ch;
594 				break;
595 			default:
596 				return EINVAL;
597 			}
598 			break;
599 
600 		default:
601 			return EINVAL;
602 		}
603 		break;
604 
605 	default:
606 		return EINVAL;
607 	}
608 
609 	sc->sc_encoding = p->encoding;
610 	sc->sc_precision = p->precision;
611 	sc->sc_14bit = ((p->precision == 16) && (p->channels <= 2));
612 	sc->sc_channels = sc->sc_14bit ? (p->channels * 2) : p->channels;
613 
614 	return aucc_set_out_sr(addr, p->sample_rate);
615 }
616 
617 int
618 aucc_round_blocksize(addr, blk)
619 	void *addr;
620 	int blk;
621 {
622 	/* round up to even size */
623 	return blk > AUDIO_BUF_SIZE ? AUDIO_BUF_SIZE : blk;
624 }
625 
626 int
627 aucc_commit_settings(addr)
628 	void *addr;
629 {
630 	register struct aucc_softc *sc = addr;
631 	register int i;
632 
633 	DPRINTF(("sa_commit.\n"));
634 
635 	for (i=0;i<4;i++) {
636 		custom.aud[i].vol=sc->sc_channel[i].nd_volume;
637 		custom.aud[i].per=sc->sc_channel[i].nd_per;
638 	}
639 
640 	DPRINTF(("commit done\n"));
641 
642 	return(0);
643 }
644 
645 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
646 static int masks2[4] = {1,2,4,8};
647 
648 int
649 aucc_start_output(addr, p, cc, intr, arg)
650 	void *addr;
651 	void *p;
652 	int cc;
653 	void (*intr) __P((void *));
654 	void *arg;
655 {
656 	struct aucc_softc *sc;
657 	int mask;
658 	int i, j, k, len;
659 	u_char *dmap[4];
660 
661 
662 	sc = addr;
663 	mask = sc->sc_channelmask;
664 
665 	dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
666 
667 	DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
668 
669 	if (sc->sc_channels > 1)
670 		mask &= masks[sc->sc_channels - 1];
671 		/* we use first sc_channels channels */
672 	if (mask == 0) /* active and used channels are disjoint */
673 		return EINVAL;
674 
675 	for (i=0;i<4;i++) {
676 		/* channels available ? */
677 		if ((masks2[i] & mask) && (sc->sc_channel[i].nd_busy))
678 			return EBUSY; /* channel is busy */
679 		if (channel[i].isaudio == -1)
680 			return EBUSY; /* system uses them */
681 	}
682 
683 	/* enable interrupt on 1st channel */
684 	for (i = j = 0; i < AUCC_MAXINT; i++) {
685 		if (masks2[i] & mask) {
686 			DPRINTF(("first channel is %d\n",i));
687 			j=i;
688 			sc->sc_channel[i].nd_intr=intr;
689 			sc->sc_channel[i].nd_intrdata=arg;
690 			break;
691 		}
692 	}
693 
694 	DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
695 		dmap[2], dmap[3], mask));
696 
697 	/* disable ints, dma for channels, until all parameters set */
698 	/* XXX dont disable DMA! custom.dmacon=mask;*/
699 	custom.intreq = mask << INTB_AUD0;
700 	custom.intena = mask << INTB_AUD0;
701 
702 	/* copy data to dma buffer */
703 
704 	if (sc->sc_channels == 1) {
705 		dmap[0] =
706 		dmap[1] =
707 		dmap[2] =
708 		dmap[3] = (u_char *)sc->sc_channel[j].nd_dma;
709 	}
710 	else {
711 		for (k=0; k<4; k++) {
712 			if (masks2[k+j] & mask)
713 				dmap[k] = (u_char *)sc->sc_channel[k+j].nd_dma;
714 		}
715 	}
716 
717 	sc->sc_channel[j].nd_doublebuf ^= 1;
718 	if (sc->sc_channel[j].nd_doublebuf) {
719 		dmap[0] += AUDIO_BUF_SIZE;
720 		dmap[1] += AUDIO_BUF_SIZE;
721 		dmap[2] += AUDIO_BUF_SIZE;
722 		dmap[3] += AUDIO_BUF_SIZE;
723 	}
724 
725 	/* compute output length in bytes per channel.
726 	 * divide by two only for 16bit->8bit conversion.
727 	 */
728 	len = cc / sc->sc_channels;
729 	if (!sc->sc_14bit && (sc->sc_precision == 16))
730 		len /= 2;
731 
732 	/* call audio decoding routine */
733 	sc->sc_decodefunc (dmap, (u_char *)p, len);
734 
735 	/* dma buffers: we use same buffer 4 all channels
736 	 * write dma location and length
737 	 */
738 	for (i = k = 0; i < 4; i++) {
739 		if (masks2[i] & mask) {
740 			DPRINTF(("turning channel %d on\n",i));
741 			/* sc->sc_channel[i].nd_busy=1; */
742 			channel[i].isaudio = 1;
743 			channel[i].play_count = 1;
744 			channel[i].handler = NULL;
745 			custom.aud[i].per = sc->sc_channel[i].nd_per;
746 			if (sc->sc_14bit && (i > 1))
747 				custom.aud[i].vol = 1;
748 			else
749 				custom.aud[i].vol = sc->sc_channel[i].nd_volume;
750 			custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
751 			custom.aud[i].len = len / 2;
752 			sc->sc_channel[i].nd_mask = mask;
753 			DPRINTF(("per is %d, vol is %d, len is %d\n",\
754 			    sc->sc_channel[i].nd_per,
755 			    sc->sc_channel[i].nd_volume, len));
756 		}
757 	}
758 
759 	channel[j].handler=aucc_inthdl;
760 
761 	/* enable ints */
762 	custom.intena = INTF_SETCLR | INTF_INTEN | (masks2[j] << INTB_AUD0);
763 
764 	DPRINTF(("enabled ints: 0x%x\n", (masks2[j] << INTB_AUD0)));
765 
766 	/* enable dma */
767 	custom.dmacon = DMAF_SETCLR | DMAF_MASTER | mask;
768 
769 	DPRINTF(("enabled dma, mask=0x%x\n",mask));
770 
771 	return(0);
772 }
773 
774 /* ARGSUSED */
775 int
776 aucc_start_input(addr, p, cc, intr, arg)
777 	void *addr;
778 	void *p;
779 	int cc;
780 	void (*intr) __P((void *));
781 	void *arg;
782 {
783 
784 	return ENXIO; /* no input */
785 }
786 
787 int
788 aucc_halt_output(addr)
789 	void *addr;
790 {
791 	register struct aucc_softc *sc = addr;
792 	register int i;
793 
794 	/* XXX only halt, if input is also halted ?? */
795 	/* stop dma, etc */
796 	custom.intena = AUCC_ALLINTF;
797 	custom.dmacon = AUCC_ALLDMAF;
798 	/* mark every busy unit idle */
799 	for (i=0;i<4;i++) {
800 		sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0;
801 		channel[i].isaudio=0;
802 		channel[i].play_count=0;
803 	}
804 
805 	return(0);
806 }
807 
808 int
809 aucc_halt_input(addr)
810 	void *addr;
811 {
812 	/* no input */
813 
814 	return ENXIO;
815 }
816 
817 int
818 aucc_getdev(addr, retp)
819         void *addr;
820         struct audio_device *retp;
821 {
822         *retp = aucc_device;
823         return 0;
824 }
825 
826 int
827 aucc_set_port(addr, cp)
828 	void *addr;
829 	mixer_ctrl_t *cp;
830 {
831 	register struct aucc_softc *sc = addr;
832 	register int i,j;
833 
834 	DPRINTF(("aucc_set_port: port=%d", cp->dev));
835 
836 	switch (cp->type) {
837 	case AUDIO_MIXER_SET:
838 		if (cp->dev!=AUCC_CHANNELS)
839 			return EINVAL;
840 		i=cp->un.mask;
841 		if ((i<1) || (i>15))
842 			return EINVAL;
843 
844 		sc->sc_channelmask=i;
845 		break;
846 
847 	case AUDIO_MIXER_VALUE:
848 		i=cp->un.value.num_channels;
849 		if ((i<1) || (i>4))
850 			return EINVAL;
851 
852 #ifdef __XXXwhatsthat
853 		if (cp->dev!=AUCC_VOLUME)
854 			return EINVAL;
855 #endif
856 
857 		/* set volume for channel 0..i-1 */
858 
859 		/* evil workaround for xanim bug, IMO */
860 		if ((sc->sc_channels == 1) && (i == 2)) {
861 			sc->sc_channel[0].nd_volume =
862 			    sc->sc_channel[3].nd_volume =
863 			    cp->un.value.level[0]>>2;
864 			sc->sc_channel[1].nd_volume =
865 			    sc->sc_channel[2].nd_volume =
866 			    cp->un.value.level[1]>>2;
867 		} else if (i>1) {
868 			for (j=0;j<i;j++)
869 	 			sc->sc_channel[j].nd_volume =
870 				    cp->un.value.level[j]>>2;
871 		} else if (sc->sc_channels > 1)
872 			for (j=0; j<sc->sc_channels; j++)
873 	 			sc->sc_channel[j].nd_volume =
874 				    cp->un.value.level[0]>>2;
875 		else
876 			for (j=0; j<4; j++)
877 	 			sc->sc_channel[j].nd_volume =
878 				    cp->un.value.level[0]>>2;
879 		break;
880 
881 	default:
882 		return EINVAL;
883 		break;
884 	}
885 	return 0;
886 }
887 
888 
889 int
890 aucc_get_port(addr, cp)
891 	void *addr;
892 	mixer_ctrl_t *cp;
893 {
894 	register struct aucc_softc *sc = addr;
895 	register int i,j;
896 
897 	DPRINTF(("aucc_get_port: port=%d", cp->dev));
898 
899 	switch (cp->type) {
900 	case AUDIO_MIXER_SET:
901 		if (cp->dev!=AUCC_CHANNELS)
902 			return EINVAL;
903 		cp->un.mask=sc->sc_channelmask;
904 		break;
905 
906 	case AUDIO_MIXER_VALUE:
907 		i = cp->un.value.num_channels;
908 		if ((i<1)||(i>4))
909 			return EINVAL;
910 
911 		for (j=0;j<i;j++)
912 			cp->un.value.level[j] =
913 			    (sc->sc_channel[j].nd_volume<<2) +
914 			    (sc->sc_channel[j].nd_volume>>4);
915 		break;
916 
917 	default:
918 		return EINVAL;
919 	}
920 	return 0;
921 }
922 
923 
924 int
925 aucc_get_props(addr)
926 	void *addr;
927 {
928 	return 0;
929 }
930 
931 int
932 aucc_query_devinfo(addr, dip)
933 	void *addr;
934 	register mixer_devinfo_t *dip;
935 {
936 	register int i;
937 
938 	switch(dip->index) {
939 	case AUCC_CHANNELS:
940 		dip->type = AUDIO_MIXER_SET;
941 		dip->mixer_class = AUCC_OUTPUT_CLASS;
942 		dip->prev = dip->next = AUDIO_MIXER_LAST;
943                 strcpy(dip->label.name, AudioNspeaker);
944 		for (i=0;i<16;i++) {
945 			sprintf(dip->un.s.member[i].label.name,
946 			    "channelmask%d", i);
947 			dip->un.s.member[i].mask = i;
948 		}
949 		dip->un.s.num_mem = 16;
950 		break;
951 
952 	case AUCC_VOLUME:
953 		dip->type = AUDIO_MIXER_VALUE;
954 		dip->mixer_class = AUCC_OUTPUT_CLASS;
955 		dip->prev = dip->next = AUDIO_MIXER_LAST;
956 		strcpy(dip->label.name, AudioNmaster);
957 		dip->un.v.num_channels = 4;
958 		strcpy(dip->un.v.units.name, AudioNvolume);
959 		break;
960 
961 	case AUCC_OUTPUT_CLASS:
962 		dip->type = AUDIO_MIXER_CLASS;
963 		dip->mixer_class = AUCC_OUTPUT_CLASS;
964 		dip->next = dip->prev = AUDIO_MIXER_LAST;
965 		strcpy(dip->label.name, AudioCoutputs);
966 		break;
967 
968 	default:
969 		return ENXIO;
970 	}
971 
972 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
973 
974 	return(0);
975 }
976 
977 
978 /* audio int handler */
979 void
980 aucc_inthdl(int ch)
981 {
982 	register int i;
983 	register int mask=aucc->sc_channel[ch].nd_mask;
984 
985 	/* for all channels in this maskgroup:
986 	   disable dma, int
987 	   mark idle */
988 	DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask));
989 
990 	custom.intreq=mask<<INTB_AUD0; /* clear request */
991 	/*
992 	 * XXX: maybe we can leave ints and/or DMA on,
993 	 * if another sample has to be played?
994 	 */
995 	custom.intena=mask<<INTB_AUD0;
996 	/*
997 	 * XXX custom.dmacon=mask; NO!!!
998 	 */
999 	for (i=0; i<4; i++) {
1000 		if (masks2[i]&&mask) {
1001 			DPRINTF(("marking channel %d idle\n",i));
1002 			aucc->sc_channel[i].nd_busy=0;
1003 			aucc->sc_channel[i].nd_mask=0;
1004 			channel[i].isaudio=channel[i].play_count=0;
1005 		}
1006 	}
1007 
1008 	/* call handler */
1009 	if (aucc->sc_channel[ch].nd_intr) {
1010 		DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
1011 		(*(aucc->sc_channel[ch].nd_intr))
1012 		    (aucc->sc_channel[ch].nd_intrdata);
1013 	}
1014 	else
1015 		DPRINTF(("zero int handler\n"));
1016 	DPRINTF(("ints done\n"));
1017 }
1018 
1019 
1020 
1021 
1022 /* transform frequency to period, adjust bounds */
1023 static u_int
1024 freqtoper(u_int freq) {
1025 	u_int per=eclockfreq*5/freq;
1026 
1027 	if (per<124)
1028 		per=124; /* must have at least 124 ticks between samples */
1029 
1030 	return per;
1031 }
1032 
1033 /* transform period to frequency */
1034 static u_int
1035 pertofreq(u_int per) {
1036 	u_int freq=eclockfreq*5/per;
1037 
1038 	return freq;
1039 }
1040 
1041 static void aucc_decode_slinear8_1ch (u_char **dmap, u_char *p, int i) {
1042 	memcpy (dmap[0], p, i);
1043 }
1044 
1045 static void aucc_decode_slinear8_2ch (u_char **dmap, u_char *p, int i) {
1046 	u_char *ch0 = dmap[0];
1047 	u_char *ch1 = dmap[1];
1048 
1049 	while (i--) {
1050 		*ch0++ = *p++;
1051 		*ch1++ = *p++;
1052 	}
1053 }
1054 
1055 static void aucc_decode_slinear8_3ch (u_char **dmap, u_char *p, int i) {
1056 	u_char *ch0 = dmap[0];
1057 	u_char *ch1 = dmap[1];
1058 	u_char *ch2 = dmap[2];
1059 
1060 	while (i--) {
1061 		*ch0++ = *p++;
1062 		*ch1++ = *p++;
1063 		*ch2++ = *p++;
1064 	}
1065 }
1066 
1067 static void aucc_decode_slinear8_4ch (u_char **dmap, u_char *p, int i) {
1068 	u_char *ch0 = dmap[0];
1069 	u_char *ch1 = dmap[1];
1070 	u_char *ch2 = dmap[2];
1071 	u_char *ch3 = dmap[3];
1072 
1073 	while (i--) {
1074 		*ch0++ = *p++;
1075 		*ch1++ = *p++;
1076 		*ch2++ = *p++;
1077 		*ch3++ = *p++;
1078 	}
1079 }
1080 
1081 static void
1082 aucc_decode_ulinear8_1ch (dmap, p, i)
1083 	u_char **dmap;
1084 	u_char *p;
1085 	int i;
1086 {
1087 	u_char *ch0 = dmap[0];
1088 
1089 	while (i--)
1090 		*ch0++ = *p++ - 128;
1091 }
1092 
1093 static void
1094 aucc_decode_ulinear8_2ch(dmap, p, i)
1095 	u_char **dmap;
1096 	u_char *p;
1097 	int i;
1098 {
1099 	u_char *ch0 = dmap[0];
1100 	u_char *ch1 = dmap[1];
1101 
1102 	while (i--) {
1103 		*ch0++ = *p++ - 128;
1104 		*ch1++ = *p++ - 128;
1105 	}
1106 }
1107 
1108 static void
1109 aucc_decode_ulinear8_3ch(dmap, p, i)
1110 	u_char **dmap;
1111 	u_char *p;
1112 	int i;
1113 {
1114 	u_char *ch0 = dmap[0];
1115 	u_char *ch1 = dmap[1];
1116 	u_char *ch2 = dmap[2];
1117 
1118 	while (i--) {
1119 		*ch0++ = *p++ - 128;
1120 		*ch1++ = *p++ - 128;
1121 		*ch2++ = *p++ - 128;
1122 	}
1123 }
1124 
1125 static void
1126 aucc_decode_ulinear8_4ch(dmap, p, i)
1127 	u_char **dmap;
1128 	u_char *p;
1129 	int i;
1130 {
1131 	u_char *ch0 = dmap[0];
1132 	u_char *ch1 = dmap[1];
1133 	u_char *ch2 = dmap[2];
1134 	u_char *ch3 = dmap[3];
1135 
1136 	while (i--) {
1137 		*ch0++ = *p++ - 128;
1138 		*ch1++ = *p++ - 128;
1139 		*ch2++ = *p++ - 128;
1140 		*ch3++ = *p++ - 128;
1141 	}
1142 }
1143 
1144 
1145 static void
1146 aucc_decode_ulaw_1ch (dmap, p, i)
1147 	u_char **dmap;
1148 	u_char *p;
1149 	int i;
1150 {
1151 	u_char *ch0 = dmap[0];
1152 
1153 	while (i--)
1154 		*ch0++ = ulaw_to_lin[*p++];
1155 }
1156 
1157 static void
1158 aucc_decode_ulaw_2ch(dmap, p, i)
1159 	u_char **dmap;
1160 	u_char *p;
1161 	int i;
1162 {
1163 	u_char *ch0 = dmap[0];
1164 	u_char *ch1 = dmap[1];
1165 
1166 	while (i--) {
1167 		*ch0++ = ulaw_to_lin[*p++];
1168 		*ch1++ = ulaw_to_lin[*p++];
1169 	}
1170 }
1171 
1172 static void
1173 aucc_decode_ulaw_3ch(dmap, p, i)
1174 	u_char **dmap;
1175 	u_char *p;
1176 	int i;
1177 {
1178 	u_char *ch0 = dmap[0];
1179 	u_char *ch1 = dmap[1];
1180 	u_char *ch2 = dmap[2];
1181 
1182 	while (i--) {
1183 		*ch0++ = ulaw_to_lin[*p++];
1184 		*ch1++ = ulaw_to_lin[*p++];
1185 		*ch2++ = ulaw_to_lin[*p++];
1186 	}
1187 }
1188 
1189 static void
1190 aucc_decode_ulaw_4ch(dmap, p, i)
1191 	u_char **dmap;
1192 	u_char *p;
1193 	int i;
1194 {
1195 	u_char *ch0 = dmap[0];
1196 	u_char *ch1 = dmap[1];
1197 	u_char *ch2 = dmap[2];
1198 	u_char *ch3 = dmap[3];
1199 
1200 	while (i--) {
1201 		*ch0++ = ulaw_to_lin[*p++];
1202 		*ch1++ = ulaw_to_lin[*p++];
1203 		*ch2++ = ulaw_to_lin[*p++];
1204 		*ch3++ = ulaw_to_lin[*p++];
1205 	}
1206 }
1207 
1208 
1209 /* 14bit output */
1210 static void
1211 aucc_decode_slinear16_1ch(dmap, p, i)
1212 	u_char **dmap;
1213 	u_char *p;
1214 	int i;
1215 {
1216 	u_char *ch0 = dmap[0];
1217 	u_char *ch3 = dmap[1]; /* XXX should be 3 */
1218 
1219 	while (i--) {
1220 		*ch0++ = *p++;
1221 		*ch3++ = *p++ >> 2;
1222 	}
1223 }
1224 
1225 /* 14bit stereo output */
1226 static void
1227 aucc_decode_slinear16_2ch(dmap, p, i)
1228 	u_char **dmap;
1229 	u_char *p;
1230 	int i;
1231 {
1232 	u_char *ch0 = dmap[0];
1233 	u_char *ch1 = dmap[1];
1234 	u_char *ch2 = dmap[2];
1235 	u_char *ch3 = dmap[3];
1236 
1237 	while (i--) {
1238 		*ch0++ = *p++;
1239 		*ch3++ = *p++ >> 2;
1240 		*ch1++ = *p++;
1241 		*ch2++ = *p++ >> 2;
1242 	}
1243 }
1244 
1245 static void
1246 aucc_decode_slinear16_3ch(dmap, p, i)
1247 	u_char **dmap;
1248 	u_char *p;
1249 	int i;
1250 {
1251 	u_char *ch0 = dmap[0];
1252 	u_char *ch1 = dmap[1];
1253 	u_char *ch2 = dmap[2];
1254 
1255 	while (i--) {
1256 		*ch0++ = *p++; p++;
1257 		*ch1++ = *p++; p++;
1258 		*ch2++ = *p++; p++;
1259 	}
1260 }
1261 
1262 static void
1263 aucc_decode_slinear16_4ch (dmap, p, i)
1264 	u_char **dmap;
1265 	u_char *p;
1266 	int i;
1267 {
1268 	u_char *ch0 = dmap[0];
1269 	u_char *ch1 = dmap[1];
1270 	u_char *ch2 = dmap[2];
1271 	u_char *ch3 = dmap[3];
1272 
1273 	while (i--) {
1274 		*ch0++ = *p++; p++;
1275 		*ch1++ = *p++; p++;
1276 		*ch2++ = *p++; p++;
1277 		*ch3++ = *p++; p++;
1278 	}
1279 }
1280 
1281 /* 14bit output, swap bytes */
1282 static void
1283 aucc_decode_slinear16sw_1ch(dmap, p, i)
1284 	u_char **dmap;
1285 	u_char *p;
1286 	int i;
1287 {
1288 	u_char *ch0 = dmap[0];
1289 	u_char *ch3 = dmap[3];
1290 
1291 	while (i--) {
1292 		*ch3++ = *p++ >> 2;
1293 		*ch0++ = *p++;
1294 	}
1295 }
1296 
1297 static void
1298 aucc_decode_slinear16sw_2ch(dmap, p, i)
1299 	u_char **dmap;
1300 	u_char *p;
1301 	int i;
1302 {
1303 	u_char *ch0 = dmap[0];
1304 	u_char *ch1 = dmap[1];
1305 	u_char *ch2 = dmap[2];
1306 	u_char *ch3 = dmap[3];
1307 
1308 	while (i--) {
1309 		*ch3++ = *p++ >> 2;
1310 		*ch0++ = *p++;
1311 		*ch2++ = *p++ >> 2;
1312 		*ch1++ = *p++;
1313 	}
1314 }
1315 
1316 static void
1317 aucc_decode_slinear16sw_3ch(dmap, p, i)
1318 	u_char **dmap;
1319 	u_char *p;
1320 	int i;
1321 {
1322 	u_char *ch0 = dmap[0];
1323 	u_char *ch1 = dmap[1];
1324 	u_char *ch2 = dmap[2];
1325 
1326 	while (i--) {
1327 		p++; *ch0++ = *p++;
1328 		p++; *ch1++ = *p++;
1329 		p++; *ch2++ = *p++;
1330 	}
1331 }
1332 
1333 static void
1334 aucc_decode_slinear16sw_4ch(dmap, p, i)
1335 	u_char **dmap;
1336 	u_char *p;
1337 	int i;
1338 {
1339 	u_char *ch0 = dmap[0];
1340 	u_char *ch1 = dmap[1];
1341 	u_char *ch2 = dmap[2];
1342 	u_char *ch3 = dmap[3];
1343 
1344 	while (i--) {
1345 		p++; *ch0++ = *p++;
1346 		p++; *ch1++ = *p++;
1347 		p++; *ch2++ = *p++;
1348 		p++; *ch3++ = *p++;
1349 	}
1350 }
1351 
1352 
1353 #endif /* NAUCC > 0 */
1354