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