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