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