aucc.c revision 1.36 1 /* $NetBSD: aucc.c,v 1.36 2005/01/10 22:01:36 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.36 2005/01/10 22:01:36 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 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 int mode, const audio_params_t *param)
609 {
610 /* round up to even size */
611 return blk > AUDIO_BUF_SIZE ? AUDIO_BUF_SIZE : blk;
612 }
613
614 int
615 aucc_commit_settings(void *addr)
616 {
617 register struct aucc_softc *sc = addr;
618 register int i;
619
620 DPRINTF(("sa_commit.\n"));
621
622 for (i=0;i<4;i++) {
623 custom.aud[i].vol=sc->sc_channel[i].nd_volume;
624 custom.aud[i].per=sc->sc_channel[i].nd_per;
625 }
626
627 DPRINTF(("commit done\n"));
628
629 return(0);
630 }
631
632 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
633 static int masks2[4] = {1,2,4,8};
634
635 int
636 aucc_start_output(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
637 {
638 struct aucc_softc *sc;
639 int mask;
640 int i, j, k, len;
641 u_char *dmap[4];
642
643
644 sc = addr;
645 mask = sc->sc_channelmask;
646
647 dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
648
649 DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
650
651 if (sc->sc_channels > 1)
652 mask &= masks[sc->sc_channels - 1];
653 /* we use first sc_channels channels */
654 if (mask == 0) /* active and used channels are disjoint */
655 return EINVAL;
656
657 for (i=0;i<4;i++) {
658 /* channels available ? */
659 if ((masks2[i] & mask) && (sc->sc_channel[i].nd_busy))
660 return EBUSY; /* channel is busy */
661 if (channel[i].isaudio == -1)
662 return EBUSY; /* system uses them */
663 }
664
665 /* enable interrupt on 1st channel */
666 for (i = j = 0; i < AUCC_MAXINT; i++) {
667 if (masks2[i] & mask) {
668 DPRINTF(("first channel is %d\n",i));
669 j=i;
670 sc->sc_channel[i].nd_intr=intr;
671 sc->sc_channel[i].nd_intrdata=arg;
672 break;
673 }
674 }
675
676 DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
677 dmap[2], dmap[3], mask));
678
679 /* disable ints, DMA for channels, until all parameters set */
680 /* XXX dont disable DMA! custom.dmacon=mask;*/
681 custom.intreq = mask << INTB_AUD0;
682 custom.intena = mask << INTB_AUD0;
683
684 /* copy data to DMA buffer */
685
686 if (sc->sc_channels == 1) {
687 dmap[0] =
688 dmap[1] =
689 dmap[2] =
690 dmap[3] = (u_char *)sc->sc_channel[j].nd_dma;
691 }
692 else {
693 for (k=0; k<4; k++) {
694 if (masks2[k+j] & mask)
695 dmap[k] = (u_char *)sc->sc_channel[k+j].nd_dma;
696 }
697 }
698
699 sc->sc_channel[j].nd_doublebuf ^= 1;
700 if (sc->sc_channel[j].nd_doublebuf) {
701 dmap[0] += AUDIO_BUF_SIZE;
702 dmap[1] += AUDIO_BUF_SIZE;
703 dmap[2] += AUDIO_BUF_SIZE;
704 dmap[3] += AUDIO_BUF_SIZE;
705 }
706
707 /* compute output length in bytes per channel.
708 * divide by two only for 16bit->8bit conversion.
709 */
710 len = cc / sc->sc_channels;
711 if (!sc->sc_14bit && (sc->sc_precision == 16))
712 len /= 2;
713
714 /* call audio decoding routine */
715 sc->sc_decodefunc (dmap, (u_char *)p, len);
716
717 /* DMA buffers: we use same buffer 4 all channels
718 * write DMA location and length
719 */
720 for (i = k = 0; i < 4; i++) {
721 if (masks2[i] & mask) {
722 DPRINTF(("turning channel %d on\n",i));
723 /* sc->sc_channel[i].nd_busy=1; */
724 channel[i].isaudio = 1;
725 channel[i].play_count = 1;
726 channel[i].handler = NULL;
727 custom.aud[i].per = sc->sc_channel[i].nd_per;
728 if (sc->sc_14bit && (i > 1))
729 custom.aud[i].vol = 1;
730 else
731 custom.aud[i].vol = sc->sc_channel[i].nd_volume;
732 custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
733 custom.aud[i].len = len / 2;
734 sc->sc_channel[i].nd_mask = mask;
735 DPRINTF(("per is %d, vol is %d, len is %d\n",\
736 sc->sc_channel[i].nd_per,
737 sc->sc_channel[i].nd_volume, len));
738 }
739 }
740
741 channel[j].handler=aucc_inthdl;
742
743 /* enable ints */
744 custom.intena = INTF_SETCLR | INTF_INTEN | (masks2[j] << INTB_AUD0);
745
746 DPRINTF(("enabled ints: 0x%x\n", (masks2[j] << INTB_AUD0)));
747
748 /* enable DMA */
749 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | mask;
750
751 DPRINTF(("enabled DMA, mask=0x%x\n",mask));
752
753 return(0);
754 }
755
756 /* ARGSUSED */
757 int
758 aucc_start_input(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
759 {
760
761 return ENXIO; /* no input */
762 }
763
764 int
765 aucc_halt_output(void *addr)
766 {
767 register struct aucc_softc *sc = addr;
768 register int i;
769
770 /* XXX only halt, if input is also halted ?? */
771 /* stop DMA, etc */
772 custom.intena = AUCC_ALLINTF;
773 custom.dmacon = AUCC_ALLDMAF;
774 /* mark every busy unit idle */
775 for (i=0;i<4;i++) {
776 sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0;
777 channel[i].isaudio=0;
778 channel[i].play_count=0;
779 }
780
781 return(0);
782 }
783
784 int
785 aucc_halt_input(void *addr)
786 {
787 /* no input */
788
789 return ENXIO;
790 }
791
792 int
793 aucc_getdev(void *addr, struct audio_device *retp)
794 {
795 *retp = aucc_device;
796 return 0;
797 }
798
799 int
800 aucc_set_port(void *addr, mixer_ctrl_t *cp)
801 {
802 register struct aucc_softc *sc = addr;
803 register int i,j;
804
805 DPRINTF(("aucc_set_port: port=%d", cp->dev));
806
807 switch (cp->type) {
808 case AUDIO_MIXER_SET:
809 if (cp->dev!=AUCC_CHANNELS)
810 return EINVAL;
811 i=cp->un.mask;
812 if ((i<1) || (i>15))
813 return EINVAL;
814
815 sc->sc_channelmask=i;
816 break;
817
818 case AUDIO_MIXER_VALUE:
819 i=cp->un.value.num_channels;
820 if ((i<1) || (i>4))
821 return EINVAL;
822
823 #ifdef __XXXwhatsthat
824 if (cp->dev!=AUCC_VOLUME)
825 return EINVAL;
826 #endif
827
828 /* set volume for channel 0..i-1 */
829
830 /* evil workaround for xanim bug, IMO */
831 if ((sc->sc_channels == 1) && (i == 2)) {
832 sc->sc_channel[0].nd_volume =
833 sc->sc_channel[3].nd_volume =
834 cp->un.value.level[0]>>2;
835 sc->sc_channel[1].nd_volume =
836 sc->sc_channel[2].nd_volume =
837 cp->un.value.level[1]>>2;
838 } else if (i>1) {
839 for (j=0;j<i;j++)
840 sc->sc_channel[j].nd_volume =
841 cp->un.value.level[j]>>2;
842 } else if (sc->sc_channels > 1)
843 for (j=0; j<sc->sc_channels; j++)
844 sc->sc_channel[j].nd_volume =
845 cp->un.value.level[0]>>2;
846 else
847 for (j=0; j<4; j++)
848 sc->sc_channel[j].nd_volume =
849 cp->un.value.level[0]>>2;
850 break;
851
852 default:
853 return EINVAL;
854 break;
855 }
856 return 0;
857 }
858
859
860 int
861 aucc_get_port(void *addr, mixer_ctrl_t *cp)
862 {
863 register struct aucc_softc *sc = addr;
864 register int i,j;
865
866 DPRINTF(("aucc_get_port: port=%d", cp->dev));
867
868 switch (cp->type) {
869 case AUDIO_MIXER_SET:
870 if (cp->dev!=AUCC_CHANNELS)
871 return EINVAL;
872 cp->un.mask=sc->sc_channelmask;
873 break;
874
875 case AUDIO_MIXER_VALUE:
876 i = cp->un.value.num_channels;
877 if ((i<1)||(i>4))
878 return EINVAL;
879
880 for (j=0;j<i;j++)
881 cp->un.value.level[j] =
882 (sc->sc_channel[j].nd_volume<<2) +
883 (sc->sc_channel[j].nd_volume>>4);
884 break;
885
886 default:
887 return EINVAL;
888 }
889 return 0;
890 }
891
892
893 int
894 aucc_get_props(void *addr)
895 {
896 return 0;
897 }
898
899 int
900 aucc_query_devinfo(void *addr, register mixer_devinfo_t *dip)
901 {
902 register int i;
903
904 switch(dip->index) {
905 case AUCC_CHANNELS:
906 dip->type = AUDIO_MIXER_SET;
907 dip->mixer_class = AUCC_OUTPUT_CLASS;
908 dip->prev = dip->next = AUDIO_MIXER_LAST;
909 strcpy(dip->label.name, AudioNspeaker);
910 for (i=0;i<16;i++) {
911 sprintf(dip->un.s.member[i].label.name,
912 "channelmask%d", i);
913 dip->un.s.member[i].mask = i;
914 }
915 dip->un.s.num_mem = 16;
916 break;
917
918 case AUCC_VOLUME:
919 dip->type = AUDIO_MIXER_VALUE;
920 dip->mixer_class = AUCC_OUTPUT_CLASS;
921 dip->prev = dip->next = AUDIO_MIXER_LAST;
922 strcpy(dip->label.name, AudioNmaster);
923 dip->un.v.num_channels = 4;
924 strcpy(dip->un.v.units.name, AudioNvolume);
925 break;
926
927 case AUCC_OUTPUT_CLASS:
928 dip->type = AUDIO_MIXER_CLASS;
929 dip->mixer_class = AUCC_OUTPUT_CLASS;
930 dip->next = dip->prev = AUDIO_MIXER_LAST;
931 strcpy(dip->label.name, AudioCoutputs);
932 break;
933
934 default:
935 return ENXIO;
936 }
937
938 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
939
940 return(0);
941 }
942
943
944 /* audio int handler */
945 void
946 aucc_inthdl(int ch)
947 {
948 register int i;
949 register int mask=aucc->sc_channel[ch].nd_mask;
950
951 /* for all channels in this maskgroup:
952 disable DMA, int
953 mark idle */
954 DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask));
955
956 custom.intreq=mask<<INTB_AUD0; /* clear request */
957 /*
958 * XXX: maybe we can leave ints and/or DMA on,
959 * if another sample has to be played?
960 */
961 custom.intena=mask<<INTB_AUD0;
962 /*
963 * XXX custom.dmacon=mask; NO!!!
964 */
965 for (i=0; i<4; i++) {
966 if (masks2[i]&&mask) {
967 DPRINTF(("marking channel %d idle\n",i));
968 aucc->sc_channel[i].nd_busy=0;
969 aucc->sc_channel[i].nd_mask=0;
970 channel[i].isaudio=channel[i].play_count=0;
971 }
972 }
973
974 /* call handler */
975 if (aucc->sc_channel[ch].nd_intr) {
976 DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
977 (*(aucc->sc_channel[ch].nd_intr))
978 (aucc->sc_channel[ch].nd_intrdata);
979 }
980 else
981 DPRINTF(("zero int handler\n"));
982 DPRINTF(("ints done\n"));
983 }
984
985
986
987
988 /* transform frequency to period, adjust bounds */
989 static u_int
990 freqtoper(u_int freq)
991 {
992 u_int per=eclockfreq*5/freq;
993
994 if (per<124)
995 per=124; /* must have at least 124 ticks between samples */
996
997 return per;
998 }
999
1000 /* transform period to frequency */
1001 static u_int
1002 pertofreq(u_int per)
1003 {
1004 u_int freq=eclockfreq*5/per;
1005
1006 return freq;
1007 }
1008
1009 static void
1010 aucc_decode_slinear8_1ch(u_char **dmap, u_char *p, int i)
1011 {
1012 memcpy (dmap[0], p, i);
1013 }
1014
1015 static void
1016 aucc_decode_slinear8_2ch(u_char **dmap, u_char *p, int i)
1017 {
1018 u_char *ch0 = dmap[0];
1019 u_char *ch1 = dmap[1];
1020
1021 while (i--) {
1022 *ch0++ = *p++;
1023 *ch1++ = *p++;
1024 }
1025 }
1026
1027 static void
1028 aucc_decode_slinear8_3ch(u_char **dmap, u_char *p, int i)
1029 {
1030 u_char *ch0 = dmap[0];
1031 u_char *ch1 = dmap[1];
1032 u_char *ch2 = dmap[2];
1033
1034 while (i--) {
1035 *ch0++ = *p++;
1036 *ch1++ = *p++;
1037 *ch2++ = *p++;
1038 }
1039 }
1040
1041 static void
1042 aucc_decode_slinear8_4ch(u_char **dmap, u_char *p, int i)
1043 {
1044 u_char *ch0 = dmap[0];
1045 u_char *ch1 = dmap[1];
1046 u_char *ch2 = dmap[2];
1047 u_char *ch3 = dmap[3];
1048
1049 while (i--) {
1050 *ch0++ = *p++;
1051 *ch1++ = *p++;
1052 *ch2++ = *p++;
1053 *ch3++ = *p++;
1054 }
1055 }
1056
1057 static void
1058 aucc_decode_ulinear8_1ch(u_char **dmap, u_char *p, int i)
1059 {
1060 u_char *ch0 = dmap[0];
1061
1062 while (i--)
1063 *ch0++ = *p++ - 128;
1064 }
1065
1066 static void
1067 aucc_decode_ulinear8_2ch(u_char **dmap, u_char *p, int i)
1068 {
1069 u_char *ch0 = dmap[0];
1070 u_char *ch1 = dmap[1];
1071
1072 while (i--) {
1073 *ch0++ = *p++ - 128;
1074 *ch1++ = *p++ - 128;
1075 }
1076 }
1077
1078 static void
1079 aucc_decode_ulinear8_3ch(u_char **dmap, u_char *p, int i)
1080 {
1081 u_char *ch0 = dmap[0];
1082 u_char *ch1 = dmap[1];
1083 u_char *ch2 = dmap[2];
1084
1085 while (i--) {
1086 *ch0++ = *p++ - 128;
1087 *ch1++ = *p++ - 128;
1088 *ch2++ = *p++ - 128;
1089 }
1090 }
1091
1092 static void
1093 aucc_decode_ulinear8_4ch(u_char **dmap, u_char *p, int i)
1094 {
1095 u_char *ch0 = dmap[0];
1096 u_char *ch1 = dmap[1];
1097 u_char *ch2 = dmap[2];
1098 u_char *ch3 = dmap[3];
1099
1100 while (i--) {
1101 *ch0++ = *p++ - 128;
1102 *ch1++ = *p++ - 128;
1103 *ch2++ = *p++ - 128;
1104 *ch3++ = *p++ - 128;
1105 }
1106 }
1107
1108
1109 static void
1110 aucc_decode_mulaw_1ch(u_char **dmap, u_char *p, int i)
1111 {
1112 u_char *ch0 = dmap[0];
1113
1114 while (i--)
1115 *ch0++ = mulaw_to_lin[*p++];
1116 }
1117
1118 static void
1119 aucc_decode_mulaw_2ch(u_char **dmap, u_char *p, int i)
1120 {
1121 u_char *ch0 = dmap[0];
1122 u_char *ch1 = dmap[1];
1123
1124 while (i--) {
1125 *ch0++ = mulaw_to_lin[*p++];
1126 *ch1++ = mulaw_to_lin[*p++];
1127 }
1128 }
1129
1130 static void
1131 aucc_decode_mulaw_3ch(u_char **dmap, u_char *p, int i)
1132 {
1133 u_char *ch0 = dmap[0];
1134 u_char *ch1 = dmap[1];
1135 u_char *ch2 = dmap[2];
1136
1137 while (i--) {
1138 *ch0++ = mulaw_to_lin[*p++];
1139 *ch1++ = mulaw_to_lin[*p++];
1140 *ch2++ = mulaw_to_lin[*p++];
1141 }
1142 }
1143
1144 static void
1145 aucc_decode_mulaw_4ch(u_char **dmap, u_char *p, int i)
1146 {
1147 u_char *ch0 = dmap[0];
1148 u_char *ch1 = dmap[1];
1149 u_char *ch2 = dmap[2];
1150 u_char *ch3 = dmap[3];
1151
1152 while (i--) {
1153 *ch0++ = mulaw_to_lin[*p++];
1154 *ch1++ = mulaw_to_lin[*p++];
1155 *ch2++ = mulaw_to_lin[*p++];
1156 *ch3++ = mulaw_to_lin[*p++];
1157 }
1158 }
1159
1160
1161 /* 14bit output */
1162 static void
1163 aucc_decode_slinear16_1ch(u_char **dmap, u_char *p, int i)
1164 {
1165 u_char *ch0 = dmap[0];
1166 u_char *ch3 = dmap[1]; /* XXX should be 3 */
1167
1168 while (i--) {
1169 *ch0++ = *p++;
1170 *ch3++ = *p++ >> 2;
1171 }
1172 }
1173
1174 /* 14bit stereo output */
1175 static void
1176 aucc_decode_slinear16_2ch(u_char **dmap, u_char *p, int i)
1177 {
1178 u_char *ch0 = dmap[0];
1179 u_char *ch1 = dmap[1];
1180 u_char *ch2 = dmap[2];
1181 u_char *ch3 = dmap[3];
1182
1183 while (i--) {
1184 *ch0++ = *p++;
1185 *ch3++ = *p++ >> 2;
1186 *ch1++ = *p++;
1187 *ch2++ = *p++ >> 2;
1188 }
1189 }
1190
1191 static void
1192 aucc_decode_slinear16_3ch(u_char **dmap, u_char *p, int i)
1193 {
1194 u_char *ch0 = dmap[0];
1195 u_char *ch1 = dmap[1];
1196 u_char *ch2 = dmap[2];
1197
1198 while (i--) {
1199 *ch0++ = *p++; p++;
1200 *ch1++ = *p++; p++;
1201 *ch2++ = *p++; p++;
1202 }
1203 }
1204
1205 static void
1206 aucc_decode_slinear16_4ch(u_char **dmap, u_char *p, int i)
1207 {
1208 u_char *ch0 = dmap[0];
1209 u_char *ch1 = dmap[1];
1210 u_char *ch2 = dmap[2];
1211 u_char *ch3 = dmap[3];
1212
1213 while (i--) {
1214 *ch0++ = *p++; p++;
1215 *ch1++ = *p++; p++;
1216 *ch2++ = *p++; p++;
1217 *ch3++ = *p++; p++;
1218 }
1219 }
1220
1221 /* 14bit output, swap bytes */
1222 static void
1223 aucc_decode_slinear16sw_1ch(u_char **dmap, u_char *p, int i)
1224 {
1225 u_char *ch0 = dmap[0];
1226 u_char *ch3 = dmap[1]; /* XXX should be 3 */
1227
1228 while (i--) {
1229 *ch3++ = *p++ >> 2;
1230 *ch0++ = *p++;
1231 }
1232 }
1233
1234 static void
1235 aucc_decode_slinear16sw_2ch(u_char **dmap, u_char *p, 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 *ch3++ = *p++ >> 2;
1244 *ch0++ = *p++;
1245 *ch2++ = *p++ >> 2;
1246 *ch1++ = *p++;
1247 }
1248 }
1249
1250 static void
1251 aucc_decode_slinear16sw_3ch(u_char **dmap, u_char *p, int i)
1252 {
1253 u_char *ch0 = dmap[0];
1254 u_char *ch1 = dmap[1];
1255 u_char *ch2 = dmap[2];
1256
1257 while (i--) {
1258 p++; *ch0++ = *p++;
1259 p++; *ch1++ = *p++;
1260 p++; *ch2++ = *p++;
1261 }
1262 }
1263
1264 static void
1265 aucc_decode_slinear16sw_4ch(u_char **dmap, u_char *p, int i)
1266 {
1267 u_char *ch0 = dmap[0];
1268 u_char *ch1 = dmap[1];
1269 u_char *ch2 = dmap[2];
1270 u_char *ch3 = dmap[3];
1271
1272 while (i--) {
1273 p++; *ch0++ = *p++;
1274 p++; *ch1++ = *p++;
1275 p++; *ch2++ = *p++;
1276 p++; *ch3++ = *p++;
1277 }
1278 }
1279
1280
1281 #endif /* NAUCC > 0 */
1282