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