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