xref: /netbsd-src/sys/arch/amiga/dev/aucc.c (revision bada23909e740596d0a3785a73bd3583a9807fb8)
1 /*	$NetBSD: aucc.c,v 1.24 1999/03/04 20:45:01 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 
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 	if (matchname((char *)aux, "aucc") &&
273 #ifdef DRACO
274 	    !is_draco() &&
275 #endif
276 	    (cfp->cf_unit == 0))
277 		return 1;
278 
279 	return 0;
280 }
281 
282 /*
283  * Audio chip found.
284  */
285 void
286 auccattach(parent, self, args)
287 	struct device *parent, *self;
288 	void *args;
289 {
290 	register struct aucc_softc *sc = (struct aucc_softc *)self;
291 	register int i;
292 
293 	printf("\n");
294 
295 	if((i=init_aucc(sc))) {
296 		printf("audio: no chipmem\n");
297 		return;
298 	}
299 
300 	audio_attach_mi(&sa_hw_if, sc, &sc->sc_dev);
301 }
302 
303 
304 static int
305 init_aucc(sc)
306 	struct aucc_softc *sc;
307 {
308 	register int i, err=0;
309 
310 	/* init values per channel */
311  	for (i=0;i<4;i++) {
312 		sc->sc_channel[i].nd_freq=8000;
313 		sc->sc_channel[i].nd_per=freqtoper(8000);
314 		sc->sc_channel[i].nd_busy=0;
315 		sc->sc_channel[i].nd_dma=alloc_chipmem(AUDIO_BUF_SIZE*2);
316 		if (sc->sc_channel[i].nd_dma==NULL)
317 			err=1;
318 	 	sc->sc_channel[i].nd_dmalength=0;
319 		sc->sc_channel[i].nd_volume=64;
320 		sc->sc_channel[i].nd_intr=NULL;
321 		sc->sc_channel[i].nd_intrdata=NULL;
322 		sc->sc_channel[i].nd_doublebuf=0;
323 		DPRINTF(("dma buffer for channel %d is %p\n", i,
324 		    sc->sc_channel[i].nd_dma));
325 	}
326 
327 	if (err) {
328 		for(i=0;i<4;i++)
329 			if (sc->sc_channel[i].nd_dma)
330 				free_chipmem(sc->sc_channel[i].nd_dma);
331 	}
332 
333 	sc->sc_channels=1;
334 	sc->sc_channelmask=0xf;
335 	sc->sc_precision=8;
336 	sc->sc_14bit = 0;
337 	sc->sc_encoding=AUDIO_ENCODING_ULAW;
338 	sc->sc_decodefunc = aucc_decode_ulaw_1ch;
339 
340 	/* clear interrupts and dma: */
341 	custom.intena = AUCC_ALLINTF;
342 	custom.dmacon = AUCC_ALLDMAF;
343 
344 	return err;
345 }
346 
347 int
348 aucc_open(addr, flags)
349 	void *addr;
350 	int flags;
351 {
352 	struct aucc_softc *sc = addr;
353 	int i;
354 
355 	DPRINTF(("sa_open: unit %p\n",sc));
356 
357 	if (sc->sc_open)
358 		return (EBUSY);
359 	sc->sc_open = 1;
360 	for (i=0;i<AUCC_MAXINT;i++) {
361 		sc->sc_channel[i].nd_intr=NULL;
362 		sc->sc_channel[i].nd_intrdata=NULL;
363 	}
364 	aucc=sc;
365 	sc->sc_channelmask=0xf;
366 
367 	DPRINTF(("saopen: ok -> sc=0x%p\n",sc));
368 
369 	return (0);
370 }
371 
372 void
373 aucc_close(addr)
374 	void *addr;
375 {
376 	register struct aucc_softc *sc = addr;
377 
378 	DPRINTF(("sa_close: sc=0x%p\n", sc));
379 	/*
380 	 * halt i/o, clear open flag, and done.
381 	 */
382 	aucc_halt_output(sc);
383 	sc->sc_open = 0;
384 
385 	DPRINTF(("sa_close: closed.\n"));
386 }
387 
388 int
389 aucc_set_out_sr(addr, sr)
390 	void *addr;
391 	u_long sr;
392 {
393 	struct aucc_softc *sc=addr;
394 	u_long per;
395 	register int i;
396 
397 	per=freqtoper(sr);
398 	if (per>0xffff)
399 		return EINVAL;
400 	sr=pertofreq(per);
401 
402 	for (i=0;i<4;i++) {
403 		sc->sc_channel[i].nd_freq=sr;
404 		sc->sc_channel[i].nd_per=per;
405 	}
406 
407 	return(0);
408 }
409 
410 int
411 aucc_query_encoding(addr, fp)
412 	void *addr;
413 	struct audio_encoding *fp;
414 {
415 	switch (fp->index) {
416 		case 0:
417 			strcpy(fp->name, AudioEslinear);
418 			fp->encoding = AUDIO_ENCODING_SLINEAR;
419 			fp->precision = 8;
420 			fp->flags = 0;
421 			break;
422 		case 1:
423 			strcpy(fp->name, AudioEmulaw);
424 			fp->encoding = AUDIO_ENCODING_ULAW;
425 			fp->precision = 8;
426 			fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
427 			break;
428 
429 		case 2:
430 			strcpy(fp->name, AudioEulinear);
431 			fp->encoding = AUDIO_ENCODING_ULINEAR;
432 			fp->precision = 8;
433 			fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
434 			break;
435 
436 		case 3:
437 			strcpy(fp->name, AudioEslinear);
438 			fp->encoding = AUDIO_ENCODING_SLINEAR;
439 			fp->precision = 16;
440 			fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
441 			break;
442 
443 		case 4:
444 			strcpy(fp->name, AudioEslinear_be);
445 			fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
446 			fp->precision = 16;
447 			fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
448 			break;
449 
450 		case 5:
451 			strcpy(fp->name, AudioEslinear_le);
452 			fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
453 			fp->precision = 16;
454 			fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
455 			break;
456 
457 		default:
458 			return(EINVAL);
459 			/*NOTREACHED*/
460 	}
461 	return(0);
462 }
463 
464 int
465 aucc_set_params(addr, setmode, usemode, p, r)
466 	void *addr;
467 	int setmode, usemode;
468 	struct  audio_params *p, *r;
469 {
470 	struct aucc_softc *sc = addr;
471 
472 	/* if (setmode & AUMODE_RECORD)
473 		return 0 ENXIO*/;
474 
475 #ifdef AUCCDEBUG
476 	printf("aucc_set_params(setmode 0x%x, usemode 0x%x, "
477 		"enc %d, bits %d, chn %d, sr %ld)\n", setmode, usemode,
478 		p->encoding, p->precision, p->channels, p->sample_rate);
479 #endif
480 
481 	switch (p->precision) {
482 	case 8:
483 		switch (p->encoding) {
484 		case AUDIO_ENCODING_ULAW:
485 			switch (p->channels) {
486 			case 1:
487 				sc->sc_decodefunc = aucc_decode_ulaw_1ch;
488 				break;
489 			case 2:
490 				sc->sc_decodefunc = aucc_decode_ulaw_2ch;
491 				break;
492 			case 3:
493 				sc->sc_decodefunc = aucc_decode_ulaw_3ch;
494 				break;
495 			case 4:
496 				sc->sc_decodefunc = aucc_decode_ulaw_4ch;
497 				break;
498 			default:
499 				return EINVAL;
500 			}
501 			break;
502 
503 		case AUDIO_ENCODING_SLINEAR:
504 		case AUDIO_ENCODING_SLINEAR_BE:
505 		case AUDIO_ENCODING_SLINEAR_LE:
506 			switch (p->channels) {
507 			case 1:
508 				sc->sc_decodefunc = aucc_decode_slinear8_1ch;
509 				break;
510 			case 2:
511 				sc->sc_decodefunc = aucc_decode_slinear8_2ch;
512 				break;
513 			case 3:
514 				sc->sc_decodefunc = aucc_decode_slinear8_3ch;
515 				break;
516 			case 4:
517 				sc->sc_decodefunc = aucc_decode_slinear8_4ch;
518 				break;
519 			default:
520 				return EINVAL;
521 			}
522 			break;
523 
524 		case AUDIO_ENCODING_ULINEAR:
525 		case AUDIO_ENCODING_ULINEAR_BE:
526 		case AUDIO_ENCODING_ULINEAR_LE:
527 			switch (p->channels) {
528 			case 1:
529 				sc->sc_decodefunc = aucc_decode_ulinear8_1ch;
530 				break;
531 			case 2:
532 				sc->sc_decodefunc = aucc_decode_ulinear8_2ch;
533 				break;
534 			case 3:
535 				sc->sc_decodefunc = aucc_decode_ulinear8_3ch;
536 				break;
537 			case 4:
538 				sc->sc_decodefunc = aucc_decode_ulinear8_4ch;
539 				break;
540 			default:
541 				return EINVAL;
542 			}
543 			break;
544 
545 		default:
546 			return EINVAL;
547 		}
548 		break;
549 
550 	case 16:
551 		switch (p->encoding) {
552 #if BYTE_ORDER == BIG_ENDIAN
553 		case AUDIO_ENCODING_SLINEAR:
554 #endif
555 		case AUDIO_ENCODING_SLINEAR_BE:
556 			switch (p->channels) {
557 			case 1:
558 				sc->sc_decodefunc = aucc_decode_slinear16_1ch;
559 				break;
560 
561 			case 2:
562 				sc->sc_decodefunc = aucc_decode_slinear16_2ch;
563 				break;
564 			case 3:
565 				sc->sc_decodefunc = aucc_decode_slinear16_3ch;
566 				break;
567 			case 4:
568 				sc->sc_decodefunc = aucc_decode_slinear16_4ch;
569 				break;
570 			default:
571 				return EINVAL;
572 			}
573 			break;
574 
575 #if BYTE_ORDER == LITTLE_ENDIAN
576 		case AUDIO_ENCODING_SLINEAR:
577 #endif
578 		case AUDIO_ENCODING_SLINEAR_LE:
579 			switch (p->channels) {
580 			case 1:
581 				sc->sc_decodefunc = aucc_decode_slinear16sw_1ch;
582 				break;
583 			case 2:
584 				sc->sc_decodefunc = aucc_decode_slinear16sw_2ch;
585 				break;
586 			case 3:
587 				sc->sc_decodefunc = aucc_decode_slinear16sw_3ch;
588 				break;
589 			case 4:
590 				sc->sc_decodefunc = aucc_decode_slinear16sw_4ch;
591 				break;
592 			default:
593 				return EINVAL;
594 			}
595 			break;
596 
597 		default:
598 			return EINVAL;
599 		}
600 		break;
601 
602 	default:
603 		return EINVAL;
604 	}
605 
606 	sc->sc_encoding = p->encoding;
607 	sc->sc_precision = p->precision;
608 	sc->sc_14bit = ((p->precision == 16) && (p->channels <= 2));
609 	sc->sc_channels = sc->sc_14bit ? (p->channels * 2) : p->channels;
610 
611 	return aucc_set_out_sr(addr, p->sample_rate);
612 }
613 
614 int
615 aucc_round_blocksize(addr, blk)
616 	void *addr;
617 	int blk;
618 {
619 	/* round up to even size */
620 	return blk > AUDIO_BUF_SIZE ? AUDIO_BUF_SIZE : blk;
621 }
622 
623 int
624 aucc_commit_settings(addr)
625 	void *addr;
626 {
627 	register struct aucc_softc *sc = addr;
628 	register int i;
629 
630 	DPRINTF(("sa_commit.\n"));
631 
632 	for (i=0;i<4;i++) {
633 		custom.aud[i].vol=sc->sc_channel[i].nd_volume;
634 		custom.aud[i].per=sc->sc_channel[i].nd_per;
635 	}
636 
637 	DPRINTF(("commit done\n"));
638 
639 	return(0);
640 }
641 
642 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
643 static int masks2[4] = {1,2,4,8};
644 
645 int
646 aucc_start_output(addr, p, cc, intr, arg)
647 	void *addr;
648 	void *p;
649 	int cc;
650 	void (*intr) __P((void *));
651 	void *arg;
652 {
653 	struct aucc_softc *sc;
654 	int mask;
655 	int i, j, k, len;
656 	u_char *dmap[4];
657 
658 
659 	sc = addr;
660 	mask = sc->sc_channelmask;
661 
662 	dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
663 
664 	DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
665 
666 	if (sc->sc_channels > 1)
667 		mask &= masks[sc->sc_channels - 1];
668 		/* we use first sc_channels channels */
669 	if (mask == 0) /* active and used channels are disjoint */
670 		return EINVAL;
671 
672 	for (i=0;i<4;i++) {
673 		/* channels available ? */
674 		if ((masks2[i] & mask) && (sc->sc_channel[i].nd_busy))
675 			return EBUSY; /* channel is busy */
676 		if (channel[i].isaudio == -1)
677 			return EBUSY; /* system uses them */
678 	}
679 
680 	/* enable interrupt on 1st channel */
681 	for (i = j = 0; i < AUCC_MAXINT; i++) {
682 		if (masks2[i] & mask) {
683 			DPRINTF(("first channel is %d\n",i));
684 			j=i;
685 			sc->sc_channel[i].nd_intr=intr;
686 			sc->sc_channel[i].nd_intrdata=arg;
687 			break;
688 		}
689 	}
690 
691 	DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
692 		dmap[2], dmap[3], mask));
693 
694 	/* disable ints, dma for channels, until all parameters set */
695 	/* XXX dont disable DMA! custom.dmacon=mask;*/
696 	custom.intreq = mask << INTB_AUD0;
697 	custom.intena = mask << INTB_AUD0;
698 
699 	/* copy data to dma buffer */
700 
701 	if (sc->sc_channels == 1) {
702 		dmap[0] =
703 		dmap[1] =
704 		dmap[2] =
705 		dmap[3] = (u_char *)sc->sc_channel[j].nd_dma;
706 	}
707 	else {
708 		for (k=0; k<4; k++) {
709 			if (masks2[k+j] & mask)
710 				dmap[k] = (u_char *)sc->sc_channel[k+j].nd_dma;
711 		}
712 	}
713 
714 	sc->sc_channel[j].nd_doublebuf ^= 1;
715 	if (sc->sc_channel[j].nd_doublebuf) {
716 		dmap[0] += AUDIO_BUF_SIZE;
717 		dmap[1] += AUDIO_BUF_SIZE;
718 		dmap[2] += AUDIO_BUF_SIZE;
719 		dmap[3] += AUDIO_BUF_SIZE;
720 	}
721 
722 	/* compute output length in bytes per channel.
723 	 * divide by two only for 16bit->8bit conversion.
724 	 */
725 	len = cc / sc->sc_channels;
726 	if (!sc->sc_14bit && (sc->sc_precision == 16))
727 		len /= 2;
728 
729 	/* call audio decoding routine */
730 	sc->sc_decodefunc (dmap, (u_char *)p, len);
731 
732 	/* dma buffers: we use same buffer 4 all channels
733 	 * write dma location and length
734 	 */
735 	for (i = k = 0; i < 4; i++) {
736 		if (masks2[i] & mask) {
737 			DPRINTF(("turning channel %d on\n",i));
738 			/* sc->sc_channel[i].nd_busy=1; */
739 			channel[i].isaudio = 1;
740 			channel[i].play_count = 1;
741 			channel[i].handler = NULL;
742 			custom.aud[i].per = sc->sc_channel[i].nd_per;
743 			if (sc->sc_14bit && (i > 1))
744 				custom.aud[i].vol = 1;
745 			else
746 				custom.aud[i].vol = sc->sc_channel[i].nd_volume;
747 			custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
748 			custom.aud[i].len = len / 2;
749 			sc->sc_channel[i].nd_mask = mask;
750 			DPRINTF(("per is %d, vol is %d, len is %d\n",\
751 			    sc->sc_channel[i].nd_per,
752 			    sc->sc_channel[i].nd_volume, len));
753 		}
754 	}
755 
756 	channel[j].handler=aucc_inthdl;
757 
758 	/* enable ints */
759 	custom.intena = INTF_SETCLR | INTF_INTEN | (masks2[j] << INTB_AUD0);
760 
761 	DPRINTF(("enabled ints: 0x%x\n", (masks2[j] << INTB_AUD0)));
762 
763 	/* enable dma */
764 	custom.dmacon = DMAF_SETCLR | DMAF_MASTER | mask;
765 
766 	DPRINTF(("enabled dma, mask=0x%x\n",mask));
767 
768 	return(0);
769 }
770 
771 /* ARGSUSED */
772 int
773 aucc_start_input(addr, p, cc, intr, arg)
774 	void *addr;
775 	void *p;
776 	int cc;
777 	void (*intr) __P((void *));
778 	void *arg;
779 {
780 
781 	return ENXIO; /* no input */
782 }
783 
784 int
785 aucc_halt_output(addr)
786 	void *addr;
787 {
788 	register struct aucc_softc *sc = addr;
789 	register int i;
790 
791 	/* XXX only halt, if input is also halted ?? */
792 	/* stop dma, etc */
793 	custom.intena = AUCC_ALLINTF;
794 	custom.dmacon = AUCC_ALLDMAF;
795 	/* mark every busy unit idle */
796 	for (i=0;i<4;i++) {
797 		sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0;
798 		channel[i].isaudio=0;
799 		channel[i].play_count=0;
800 	}
801 
802 	return(0);
803 }
804 
805 int
806 aucc_halt_input(addr)
807 	void *addr;
808 {
809 	/* no input */
810 
811 	return ENXIO;
812 }
813 
814 int
815 aucc_getdev(addr, retp)
816         void *addr;
817         struct audio_device *retp;
818 {
819         *retp = aucc_device;
820         return 0;
821 }
822 
823 int
824 aucc_set_port(addr, cp)
825 	void *addr;
826 	mixer_ctrl_t *cp;
827 {
828 	register struct aucc_softc *sc = addr;
829 	register int i,j;
830 
831 	DPRINTF(("aucc_set_port: port=%d", cp->dev));
832 
833 	switch (cp->type) {
834 	case AUDIO_MIXER_SET:
835 		if (cp->dev!=AUCC_CHANNELS)
836 			return EINVAL;
837 		i=cp->un.mask;
838 		if ((i<1) || (i>15))
839 			return EINVAL;
840 
841 		sc->sc_channelmask=i;
842 		break;
843 
844 	case AUDIO_MIXER_VALUE:
845 		i=cp->un.value.num_channels;
846 		if ((i<1) || (i>4))
847 			return EINVAL;
848 
849 #ifdef __XXXwhatsthat
850 		if (cp->dev!=AUCC_VOLUME)
851 			return EINVAL;
852 #endif
853 
854 		/* set volume for channel 0..i-1 */
855 
856 		/* evil workaround for xanim bug, IMO */
857 		if ((sc->sc_channels == 1) && (i == 2)) {
858 			sc->sc_channel[0].nd_volume =
859 			    sc->sc_channel[3].nd_volume =
860 			    cp->un.value.level[0]>>2;
861 			sc->sc_channel[1].nd_volume =
862 			    sc->sc_channel[2].nd_volume =
863 			    cp->un.value.level[1]>>2;
864 		} else if (i>1) {
865 			for (j=0;j<i;j++)
866 	 			sc->sc_channel[j].nd_volume =
867 				    cp->un.value.level[j]>>2;
868 		} else if (sc->sc_channels > 1)
869 			for (j=0; j<sc->sc_channels; j++)
870 	 			sc->sc_channel[j].nd_volume =
871 				    cp->un.value.level[0]>>2;
872 		else
873 			for (j=0; j<4; j++)
874 	 			sc->sc_channel[j].nd_volume =
875 				    cp->un.value.level[0]>>2;
876 		break;
877 
878 	default:
879 		return EINVAL;
880 		break;
881 	}
882 	return 0;
883 }
884 
885 
886 int
887 aucc_get_port(addr, cp)
888 	void *addr;
889 	mixer_ctrl_t *cp;
890 {
891 	register struct aucc_softc *sc = addr;
892 	register int i,j;
893 
894 	DPRINTF(("aucc_get_port: port=%d", cp->dev));
895 
896 	switch (cp->type) {
897 	case AUDIO_MIXER_SET:
898 		if (cp->dev!=AUCC_CHANNELS)
899 			return EINVAL;
900 		cp->un.mask=sc->sc_channelmask;
901 		break;
902 
903 	case AUDIO_MIXER_VALUE:
904 		i = cp->un.value.num_channels;
905 		if ((i<1)||(i>4))
906 			return EINVAL;
907 
908 		for (j=0;j<i;j++)
909 			cp->un.value.level[j] =
910 			    (sc->sc_channel[j].nd_volume<<2) +
911 			    (sc->sc_channel[j].nd_volume>>4);
912 		break;
913 
914 	default:
915 		return EINVAL;
916 	}
917 	return 0;
918 }
919 
920 
921 int
922 aucc_get_props(addr)
923 	void *addr;
924 {
925 	return 0;
926 }
927 
928 int
929 aucc_query_devinfo(addr, dip)
930 	void *addr;
931 	register mixer_devinfo_t *dip;
932 {
933 	register int i;
934 
935 	switch(dip->index) {
936 	case AUCC_CHANNELS:
937 		dip->type = AUDIO_MIXER_SET;
938 		dip->mixer_class = AUCC_OUTPUT_CLASS;
939 		dip->prev = dip->next = AUDIO_MIXER_LAST;
940                 strcpy(dip->label.name, AudioNspeaker);
941 		for (i=0;i<16;i++) {
942 			sprintf(dip->un.s.member[i].label.name,
943 			    "channelmask%d", i);
944 			dip->un.s.member[i].mask = i;
945 		}
946 		dip->un.s.num_mem = 16;
947 		break;
948 
949 	case AUCC_VOLUME:
950 		dip->type = AUDIO_MIXER_VALUE;
951 		dip->mixer_class = AUCC_OUTPUT_CLASS;
952 		dip->prev = dip->next = AUDIO_MIXER_LAST;
953 		strcpy(dip->label.name, AudioNmaster);
954 		dip->un.v.num_channels = 4;
955 		strcpy(dip->un.v.units.name, AudioNvolume);
956 		break;
957 
958 	case AUCC_OUTPUT_CLASS:
959 		dip->type = AUDIO_MIXER_CLASS;
960 		dip->mixer_class = AUCC_OUTPUT_CLASS;
961 		dip->next = dip->prev = AUDIO_MIXER_LAST;
962 		strcpy(dip->label.name, AudioCoutputs);
963 		break;
964 
965 	default:
966 		return ENXIO;
967 	}
968 
969 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
970 
971 	return(0);
972 }
973 
974 
975 /* audio int handler */
976 void
977 aucc_inthdl(int ch)
978 {
979 	register int i;
980 	register int mask=aucc->sc_channel[ch].nd_mask;
981 
982 	/* for all channels in this maskgroup:
983 	   disable dma, int
984 	   mark idle */
985 	DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask));
986 
987 	custom.intreq=mask<<INTB_AUD0; /* clear request */
988 	/*
989 	 * XXX: maybe we can leave ints and/or DMA on,
990 	 * if another sample has to be played?
991 	 */
992 	custom.intena=mask<<INTB_AUD0;
993 	/*
994 	 * XXX custom.dmacon=mask; NO!!!
995 	 */
996 	for (i=0; i<4; i++) {
997 		if (masks2[i]&&mask) {
998 			DPRINTF(("marking channel %d idle\n",i));
999 			aucc->sc_channel[i].nd_busy=0;
1000 			aucc->sc_channel[i].nd_mask=0;
1001 			channel[i].isaudio=channel[i].play_count=0;
1002 		}
1003 	}
1004 
1005 	/* call handler */
1006 	if (aucc->sc_channel[ch].nd_intr) {
1007 		DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
1008 		(*(aucc->sc_channel[ch].nd_intr))
1009 		    (aucc->sc_channel[ch].nd_intrdata);
1010 	}
1011 	else
1012 		DPRINTF(("zero int handler\n"));
1013 	DPRINTF(("ints done\n"));
1014 }
1015 
1016 
1017 
1018 
1019 /* transform frequency to period, adjust bounds */
1020 static u_int
1021 freqtoper(u_int freq) {
1022 	u_int per=eclockfreq*5/freq;
1023 
1024 	if (per<124)
1025 		per=124; /* must have at least 124 ticks between samples */
1026 
1027 	return per;
1028 }
1029 
1030 /* transform period to frequency */
1031 static u_int
1032 pertofreq(u_int per) {
1033 	u_int freq=eclockfreq*5/per;
1034 
1035 	return freq;
1036 }
1037 
1038 static void aucc_decode_slinear8_1ch (u_char **dmap, u_char *p, int i) {
1039 	memcpy (dmap[0], p, i);
1040 }
1041 
1042 static void aucc_decode_slinear8_2ch (u_char **dmap, u_char *p, int i) {
1043 	u_char *ch0 = dmap[0];
1044 	u_char *ch1 = dmap[1];
1045 
1046 	while (i--) {
1047 		*ch0++ = *p++;
1048 		*ch1++ = *p++;
1049 	}
1050 }
1051 
1052 static void aucc_decode_slinear8_3ch (u_char **dmap, u_char *p, int i) {
1053 	u_char *ch0 = dmap[0];
1054 	u_char *ch1 = dmap[1];
1055 	u_char *ch2 = dmap[2];
1056 
1057 	while (i--) {
1058 		*ch0++ = *p++;
1059 		*ch1++ = *p++;
1060 		*ch2++ = *p++;
1061 	}
1062 }
1063 
1064 static void aucc_decode_slinear8_4ch (u_char **dmap, u_char *p, int i) {
1065 	u_char *ch0 = dmap[0];
1066 	u_char *ch1 = dmap[1];
1067 	u_char *ch2 = dmap[2];
1068 	u_char *ch3 = dmap[3];
1069 
1070 	while (i--) {
1071 		*ch0++ = *p++;
1072 		*ch1++ = *p++;
1073 		*ch2++ = *p++;
1074 		*ch3++ = *p++;
1075 	}
1076 }
1077 
1078 static void
1079 aucc_decode_ulinear8_1ch (dmap, p, i)
1080 	u_char **dmap;
1081 	u_char *p;
1082 	int i;
1083 {
1084 	u_char *ch0 = dmap[0];
1085 
1086 	while (i--)
1087 		*ch0++ = *p++ - 128;
1088 }
1089 
1090 static void
1091 aucc_decode_ulinear8_2ch(dmap, p, i)
1092 	u_char **dmap;
1093 	u_char *p;
1094 	int i;
1095 {
1096 	u_char *ch0 = dmap[0];
1097 	u_char *ch1 = dmap[1];
1098 
1099 	while (i--) {
1100 		*ch0++ = *p++ - 128;
1101 		*ch1++ = *p++ - 128;
1102 	}
1103 }
1104 
1105 static void
1106 aucc_decode_ulinear8_3ch(dmap, p, i)
1107 	u_char **dmap;
1108 	u_char *p;
1109 	int i;
1110 {
1111 	u_char *ch0 = dmap[0];
1112 	u_char *ch1 = dmap[1];
1113 	u_char *ch2 = dmap[2];
1114 
1115 	while (i--) {
1116 		*ch0++ = *p++ - 128;
1117 		*ch1++ = *p++ - 128;
1118 		*ch2++ = *p++ - 128;
1119 	}
1120 }
1121 
1122 static void
1123 aucc_decode_ulinear8_4ch(dmap, p, i)
1124 	u_char **dmap;
1125 	u_char *p;
1126 	int i;
1127 {
1128 	u_char *ch0 = dmap[0];
1129 	u_char *ch1 = dmap[1];
1130 	u_char *ch2 = dmap[2];
1131 	u_char *ch3 = dmap[3];
1132 
1133 	while (i--) {
1134 		*ch0++ = *p++ - 128;
1135 		*ch1++ = *p++ - 128;
1136 		*ch2++ = *p++ - 128;
1137 		*ch3++ = *p++ - 128;
1138 	}
1139 }
1140 
1141 
1142 static void
1143 aucc_decode_ulaw_1ch (dmap, p, i)
1144 	u_char **dmap;
1145 	u_char *p;
1146 	int i;
1147 {
1148 	u_char *ch0 = dmap[0];
1149 
1150 	while (i--)
1151 		*ch0++ = ulaw_to_lin[*p++];
1152 }
1153 
1154 static void
1155 aucc_decode_ulaw_2ch(dmap, p, i)
1156 	u_char **dmap;
1157 	u_char *p;
1158 	int i;
1159 {
1160 	u_char *ch0 = dmap[0];
1161 	u_char *ch1 = dmap[1];
1162 
1163 	while (i--) {
1164 		*ch0++ = ulaw_to_lin[*p++];
1165 		*ch1++ = ulaw_to_lin[*p++];
1166 	}
1167 }
1168 
1169 static void
1170 aucc_decode_ulaw_3ch(dmap, p, i)
1171 	u_char **dmap;
1172 	u_char *p;
1173 	int i;
1174 {
1175 	u_char *ch0 = dmap[0];
1176 	u_char *ch1 = dmap[1];
1177 	u_char *ch2 = dmap[2];
1178 
1179 	while (i--) {
1180 		*ch0++ = ulaw_to_lin[*p++];
1181 		*ch1++ = ulaw_to_lin[*p++];
1182 		*ch2++ = ulaw_to_lin[*p++];
1183 	}
1184 }
1185 
1186 static void
1187 aucc_decode_ulaw_4ch(dmap, p, i)
1188 	u_char **dmap;
1189 	u_char *p;
1190 	int i;
1191 {
1192 	u_char *ch0 = dmap[0];
1193 	u_char *ch1 = dmap[1];
1194 	u_char *ch2 = dmap[2];
1195 	u_char *ch3 = dmap[3];
1196 
1197 	while (i--) {
1198 		*ch0++ = ulaw_to_lin[*p++];
1199 		*ch1++ = ulaw_to_lin[*p++];
1200 		*ch2++ = ulaw_to_lin[*p++];
1201 		*ch3++ = ulaw_to_lin[*p++];
1202 	}
1203 }
1204 
1205 
1206 /* 14bit output */
1207 static void
1208 aucc_decode_slinear16_1ch(dmap, p, i)
1209 	u_char **dmap;
1210 	u_char *p;
1211 	int i;
1212 {
1213 	u_char *ch0 = dmap[0];
1214 	u_char *ch3 = dmap[1]; /* XXX should be 3 */
1215 
1216 	while (i--) {
1217 		*ch0++ = *p++;
1218 		*ch3++ = *p++ >> 2;
1219 	}
1220 }
1221 
1222 /* 14bit stereo output */
1223 static void
1224 aucc_decode_slinear16_2ch(dmap, p, i)
1225 	u_char **dmap;
1226 	u_char *p;
1227 	int i;
1228 {
1229 	u_char *ch0 = dmap[0];
1230 	u_char *ch1 = dmap[1];
1231 	u_char *ch2 = dmap[2];
1232 	u_char *ch3 = dmap[3];
1233 
1234 	while (i--) {
1235 		*ch0++ = *p++;
1236 		*ch3++ = *p++ >> 2;
1237 		*ch1++ = *p++;
1238 		*ch2++ = *p++ >> 2;
1239 	}
1240 }
1241 
1242 static void
1243 aucc_decode_slinear16_3ch(dmap, p, i)
1244 	u_char **dmap;
1245 	u_char *p;
1246 	int i;
1247 {
1248 	u_char *ch0 = dmap[0];
1249 	u_char *ch1 = dmap[1];
1250 	u_char *ch2 = dmap[2];
1251 
1252 	while (i--) {
1253 		*ch0++ = *p++; p++;
1254 		*ch1++ = *p++; p++;
1255 		*ch2++ = *p++; p++;
1256 	}
1257 }
1258 
1259 static void
1260 aucc_decode_slinear16_4ch (dmap, p, i)
1261 	u_char **dmap;
1262 	u_char *p;
1263 	int i;
1264 {
1265 	u_char *ch0 = dmap[0];
1266 	u_char *ch1 = dmap[1];
1267 	u_char *ch2 = dmap[2];
1268 	u_char *ch3 = dmap[3];
1269 
1270 	while (i--) {
1271 		*ch0++ = *p++; p++;
1272 		*ch1++ = *p++; p++;
1273 		*ch2++ = *p++; p++;
1274 		*ch3++ = *p++; p++;
1275 	}
1276 }
1277 
1278 /* 14bit output, swap bytes */
1279 static void
1280 aucc_decode_slinear16sw_1ch(dmap, p, i)
1281 	u_char **dmap;
1282 	u_char *p;
1283 	int i;
1284 {
1285 	u_char *ch0 = dmap[0];
1286 	u_char *ch3 = dmap[3];
1287 
1288 	while (i--) {
1289 		*ch3++ = *p++ >> 2;
1290 		*ch0++ = *p++;
1291 	}
1292 }
1293 
1294 static void
1295 aucc_decode_slinear16sw_2ch(dmap, p, i)
1296 	u_char **dmap;
1297 	u_char *p;
1298 	int i;
1299 {
1300 	u_char *ch0 = dmap[0];
1301 	u_char *ch1 = dmap[1];
1302 	u_char *ch2 = dmap[2];
1303 	u_char *ch3 = dmap[3];
1304 
1305 	while (i--) {
1306 		*ch3++ = *p++ >> 2;
1307 		*ch0++ = *p++;
1308 		*ch2++ = *p++ >> 2;
1309 		*ch1++ = *p++;
1310 	}
1311 }
1312 
1313 static void
1314 aucc_decode_slinear16sw_3ch(dmap, p, i)
1315 	u_char **dmap;
1316 	u_char *p;
1317 	int i;
1318 {
1319 	u_char *ch0 = dmap[0];
1320 	u_char *ch1 = dmap[1];
1321 	u_char *ch2 = dmap[2];
1322 
1323 	while (i--) {
1324 		p++; *ch0++ = *p++;
1325 		p++; *ch1++ = *p++;
1326 		p++; *ch2++ = *p++;
1327 	}
1328 }
1329 
1330 static void
1331 aucc_decode_slinear16sw_4ch(dmap, p, i)
1332 	u_char **dmap;
1333 	u_char *p;
1334 	int i;
1335 {
1336 	u_char *ch0 = dmap[0];
1337 	u_char *ch1 = dmap[1];
1338 	u_char *ch2 = dmap[2];
1339 	u_char *ch3 = dmap[3];
1340 
1341 	while (i--) {
1342 		p++; *ch0++ = *p++;
1343 		p++; *ch1++ = *p++;
1344 		p++; *ch2++ = *p++;
1345 		p++; *ch3++ = *p++;
1346 	}
1347 }
1348 
1349 
1350 #endif /* NAUCC > 0 */
1351