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