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