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