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