aucc.c revision 1.46 1 /* $NetBSD: aucc.c,v 1.46 2019/06/08 08:02:36 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 * - channel allocation is wrong for 14bit mono
39 * - perhaps use a calibration table for better 14bit output
40 * - set 31 kHz AGA video mode to allow 44.1 kHz even if grfcc is missing
41 * in the kernel
42 * - 14bit output requires maximum volume
43 */
44
45 #include "aucc.h"
46 #if NAUCC > 0
47
48 #include <sys/cdefs.h>
49 __KERNEL_RCSID(0, "$NetBSD: aucc.c,v 1.46 2019/06/08 08:02:36 isaki Exp $");
50
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/errno.h>
54 #include <sys/ioctl.h>
55 #include <sys/device.h>
56 #include <sys/proc.h>
57 #include <machine/cpu.h>
58
59 #include <sys/audioio.h>
60 #include <dev/audio/audio_if.h>
61 #include <dev/audio/audiovar.h> /* for AUDIO_MIN_FREQUENCY */
62
63 #include <amiga/amiga/cc.h>
64 #include <amiga/amiga/custom.h>
65 #include <amiga/amiga/device.h>
66 #include <amiga/dev/auccvar.h>
67
68 #include "opt_lev6_defer.h"
69
70
71 #ifdef LEV6_DEFER
72 #define AUCC_MAXINT 3
73 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2)
74 #else
75 #define AUCC_MAXINT 4
76 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3)
77 #endif
78 /* this unconditionally; we may use AUD3 as slave channel with LEV6_DEFER */
79 #define AUCC_ALLDMAF (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3)
80
81 #ifdef AUDIO_DEBUG
82 /*extern printf(const char *,...);*/
83 int auccdebug = 1;
84 #define DPRINTF(x) if (auccdebug) printf x
85 #else
86 #define DPRINTF(x)
87 #endif
88
89 /* clock frequency.. */
90 extern int eclockfreq;
91
92
93 /* hw audio ch */
94 extern struct audio_channel channel[4];
95
96
97 /*
98 * Software state.
99 */
100 struct aucc_softc {
101 aucc_data_t sc_channel[4]; /* per channel freq, ... */
102 u_int sc_encoding; /* encoding AUDIO_ENCODING_.*/
103 int sc_channels; /* # of channels used */
104 int sc_precision; /* 8 or 16 bits */
105 int sc_14bit; /* 14bit output enabled */
106
107 int sc_intrcnt; /* interrupt count */
108 int sc_channelmask; /* which channels are used ? */
109 void (*sc_decodefunc)(u_char **, u_char *, int);
110 /* pointer to format conversion routine */
111
112 kmutex_t sc_lock;
113 kmutex_t sc_intr_lock;
114 };
115
116 /* interrupt interfaces */
117 void aucc_inthdl(int);
118
119 /* forward declarations */
120 static int init_aucc(struct aucc_softc *);
121 static u_int freqtoper(u_int);
122 static u_int pertofreq(u_int);
123
124 /* autoconfiguration driver */
125 void auccattach(device_t, device_t, void *);
126 int auccmatch(device_t, cfdata_t, void *);
127
128 CFATTACH_DECL_NEW(aucc, sizeof(struct aucc_softc),
129 auccmatch, auccattach, NULL, NULL);
130
131 struct audio_device aucc_device = {
132 "Amiga-audio",
133 "2.0",
134 "aucc"
135 };
136
137
138 struct aucc_softc *aucc = NULL;
139
140
141 /*
142 * Define our interface to the higher level audio driver.
143 */
144 int aucc_open(void *, int);
145 void aucc_close(void *);
146 int aucc_set_out_sr(void *, u_int);
147 int aucc_query_format(void *, audio_format_query_t *);
148 int aucc_round_blocksize(void *, int, int, const audio_params_t *);
149 int aucc_commit_settings(void *);
150 int aucc_start_output(void *, void *, int, void (*)(void *), void *);
151 int aucc_start_input(void *, void *, int, void (*)(void *), void *);
152 int aucc_halt_output(void *);
153 int aucc_halt_input(void *);
154 int aucc_getdev(void *, struct audio_device *);
155 int aucc_set_port(void *, mixer_ctrl_t *);
156 int aucc_get_port(void *, mixer_ctrl_t *);
157 int aucc_query_devinfo(void *, mixer_devinfo_t *);
158 void aucc_encode(int, int, int, int, u_char *, u_short **);
159 int aucc_set_format(void *, int,
160 const audio_params_t *, const audio_params_t *,
161 audio_filter_reg_t *, audio_filter_reg_t *);
162 int aucc_get_props(void *);
163 void aucc_get_locks(void *, kmutex_t **, kmutex_t **);
164
165
166 static void aucc_decode_slinear16_1ch(u_char **, u_char *, int);
167 static void aucc_decode_slinear16_2ch(u_char **, u_char *, int);
168 static void aucc_decode_slinear16_3ch(u_char **, u_char *, int);
169 static void aucc_decode_slinear16_4ch(u_char **, u_char *, int);
170
171
172 const struct audio_hw_if sa_hw_if = {
173 .open = aucc_open,
174 .close = aucc_close,
175 .query_format = aucc_query_format,
176 .set_format = aucc_set_format,
177 .round_blocksize = aucc_round_blocksize,
178 .commit_settings = aucc_commit_settings,
179 .start_output = aucc_start_output,
180 .start_input = aucc_start_input,
181 .halt_output = aucc_halt_output,
182 .halt_input = aucc_halt_input,
183 .getdev = aucc_getdev,
184 .set_port = aucc_set_port,
185 .get_port = aucc_get_port,
186 .query_devinfo = aucc_query_devinfo,
187 .get_props = aucc_get_props,
188 .get_locks = aucc_get_locks,
189 };
190
191 /*
192 * XXX *1 How lower limit of frequency should be? same as audio(4)?
193 * XXX *2 Should avoid a magic number at the upper limit of frequency.
194 * XXX *3 In fact, there is a number in this range that have minimal errors.
195 * It would be better if there is a mechanism which such frequency
196 * is prioritized.
197 * XXX *4 3/4ch modes use 8bits, 1/2ch modes use 14bits,
198 * so I imagined that 1/2ch modes are better.
199 */
200 #define AUCC_FORMAT(prio, ch, chmask) \
201 { \
202 .mode = AUMODE_PLAY, \
203 .priority = (prio), \
204 .encoding = AUDIO_ENCODING_SLINEAR_BE, \
205 .validbits = 16, \
206 .precision = 16, \
207 .channels = (ch), \
208 .channel_mask = (chmask), \
209 .frequency_type = 0, \
210 .frequency = { AUDIO_MIN_FREQUENCY, 28867 }, \
211 }
212 static const struct audio_format aucc_formats[] = {
213 AUCC_FORMAT(1, 1, AUFMT_MONAURAL),
214 AUCC_FORMAT(1, 2, AUFMT_STEREO),
215 AUCC_FORMAT(0, 3, AUFMT_UNKNOWN_POSITION),
216 AUCC_FORMAT(0, 4, AUFMT_UNKNOWN_POSITION),
217 };
218 #define AUCC_NFORMATS __arraycount(aucc_formats)
219
220 /* autoconfig routines */
221
222 int
223 auccmatch(device_t parent, cfdata_t cf, void *aux)
224 {
225 static int aucc_matched = 0;
226
227 if (!matchname((char *)aux, "aucc") ||
228 #ifdef DRACO
229 is_draco() ||
230 #endif
231 aucc_matched)
232 return 0;
233
234 aucc_matched = 1;
235 return 1;
236 }
237
238 /*
239 * Audio chip found.
240 */
241 void
242 auccattach(device_t parent, device_t self, void *args)
243 {
244 struct aucc_softc *sc;
245 int i;
246
247 sc = device_private(self);
248 printf("\n");
249
250 if ((i=init_aucc(sc))) {
251 printf("audio: no chipmem\n");
252 return;
253 }
254
255 audio_attach_mi(&sa_hw_if, sc, self);
256 }
257
258
259 static int
260 init_aucc(struct aucc_softc *sc)
261 {
262 int i, err;
263
264 err = 0;
265 /* init values per channel */
266 for (i = 0; i < 4; i++) {
267 sc->sc_channel[i].nd_freq = 8000;
268 sc->sc_channel[i].nd_per = freqtoper(8000);
269 sc->sc_channel[i].nd_busy = 0;
270 sc->sc_channel[i].nd_dma = alloc_chipmem(AUDIO_BUF_SIZE*2);
271 if (sc->sc_channel[i].nd_dma == NULL)
272 err = 1;
273 sc->sc_channel[i].nd_dmalength = 0;
274 sc->sc_channel[i].nd_volume = 64;
275 sc->sc_channel[i].nd_intr = NULL;
276 sc->sc_channel[i].nd_intrdata = NULL;
277 sc->sc_channel[i].nd_doublebuf = 0;
278 DPRINTF(("DMA buffer for channel %d is %p\n", i,
279 sc->sc_channel[i].nd_dma));
280 }
281
282 if (err) {
283 for (i = 0; i < 4; i++)
284 if (sc->sc_channel[i].nd_dma)
285 free_chipmem(sc->sc_channel[i].nd_dma);
286 }
287
288 sc->sc_channels = 1;
289 sc->sc_channelmask = 0xf;
290 sc->sc_precision = 16;
291 sc->sc_14bit = 1;
292 sc->sc_encoding = AUDIO_ENCODING_SLINEAR_BE;
293 sc->sc_decodefunc = aucc_decode_slinear16_2ch;
294
295 /* clear interrupts and DMA: */
296 custom.intena = AUCC_ALLINTF;
297 custom.dmacon = AUCC_ALLDMAF;
298
299 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
300 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
301
302 return err;
303 }
304
305 int
306 aucc_open(void *addr, int flags)
307 {
308 struct aucc_softc *sc;
309 int i;
310
311 sc = addr;
312 DPRINTF(("sa_open: unit %p\n",sc));
313
314 for (i = 0; i < AUCC_MAXINT; i++) {
315 sc->sc_channel[i].nd_intr = NULL;
316 sc->sc_channel[i].nd_intrdata = NULL;
317 }
318 aucc = sc;
319 sc->sc_channelmask = 0xf;
320
321 DPRINTF(("saopen: ok -> sc=%p\n",sc));
322
323 return 0;
324 }
325
326 void
327 aucc_close(void *addr)
328 {
329
330 DPRINTF(("sa_close: closed.\n"));
331 }
332
333 int
334 aucc_set_out_sr(void *addr, u_int sr)
335 {
336 struct aucc_softc *sc;
337 u_long per;
338 int i;
339
340 sc = addr;
341 per = freqtoper(sr);
342 if (per > 0xffff)
343 return EINVAL;
344 sr = pertofreq(per);
345
346 for (i = 0; i < 4; i++) {
347 sc->sc_channel[i].nd_freq = sr;
348 sc->sc_channel[i].nd_per = per;
349 }
350
351 return 0;
352 }
353
354 int
355 aucc_query_format(void *addr, audio_format_query_t *afp)
356 {
357
358 return audio_query_format(aucc_formats, AUCC_NFORMATS, afp);
359 }
360
361 int
362 aucc_set_format(void *addr, int setmode,
363 const audio_params_t *p, const audio_params_t *r,
364 audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
365 {
366 struct aucc_softc *sc;
367
368 sc = addr;
369 KASSERT((setmode & AUMODE_RECORD) == 0);
370
371 #ifdef AUCCDEBUG
372 printf("%s(setmode 0x%x,"
373 "enc %u bits %u, chn %u, sr %u)\n", setmode,
374 p->encoding, p->precision, p->channels, p->sample_rate);
375 #endif
376
377 switch (p->channels) {
378 case 1:
379 sc->sc_decodefunc = aucc_decode_slinear16_1ch;
380 break;
381 case 2:
382 sc->sc_decodefunc = aucc_decode_slinear16_2ch;
383 break;
384 case 3:
385 sc->sc_decodefunc = aucc_decode_slinear16_3ch;
386 break;
387 case 4:
388 sc->sc_decodefunc = aucc_decode_slinear16_4ch;
389 break;
390 default:
391 return EINVAL;
392 }
393
394 sc->sc_encoding = p->encoding;
395 sc->sc_precision = p->precision;
396 sc->sc_14bit = ((p->precision == 16) && (p->channels <= 2));
397 sc->sc_channels = sc->sc_14bit ? (p->channels * 2) : p->channels;
398
399 return aucc_set_out_sr(addr, p->sample_rate);
400 }
401
402 int
403 aucc_round_blocksize(void *addr, int blk,
404 int mode, const audio_params_t *param)
405 {
406
407 /* round up to even size */
408 return blk > AUDIO_BUF_SIZE ? AUDIO_BUF_SIZE : blk;
409 }
410
411 int
412 aucc_commit_settings(void *addr)
413 {
414 struct aucc_softc *sc;
415 int i;
416
417 DPRINTF(("sa_commit.\n"));
418
419 sc = addr;
420 for (i = 0; i < 4; i++) {
421 custom.aud[i].vol = sc->sc_channel[i].nd_volume;
422 custom.aud[i].per = sc->sc_channel[i].nd_per;
423 }
424
425 DPRINTF(("commit done\n"));
426
427 return 0;
428 }
429
430 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
431 static int masks2[4] = {1,2,4,8};
432
433 int
434 aucc_start_output(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
435 {
436 struct aucc_softc *sc;
437 int mask;
438 int i, j, k, len;
439 u_char *dmap[4];
440
441
442 sc = addr;
443 mask = sc->sc_channelmask;
444
445 dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
446
447 DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
448
449 if (sc->sc_channels > 1)
450 mask &= masks[sc->sc_channels - 1];
451 /* we use first sc_channels channels */
452 if (mask == 0) /* active and used channels are disjoint */
453 return EINVAL;
454
455 for (i = 0; i < 4; i++) {
456 /* channels available ? */
457 if ((masks2[i] & mask) && (sc->sc_channel[i].nd_busy))
458 return EBUSY; /* channel is busy */
459 if (channel[i].isaudio == -1)
460 return EBUSY; /* system uses them */
461 }
462
463 /* enable interrupt on 1st channel */
464 for (i = j = 0; i < AUCC_MAXINT; i++) {
465 if (masks2[i] & mask) {
466 DPRINTF(("first channel is %d\n",i));
467 j = i;
468 sc->sc_channel[i].nd_intr = intr;
469 sc->sc_channel[i].nd_intrdata = arg;
470 break;
471 }
472 }
473
474 DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
475 dmap[2], dmap[3], mask));
476
477 /* disable ints, DMA for channels, until all parameters set */
478 /* XXX dont disable DMA! custom.dmacon=mask;*/
479 custom.intreq = mask << INTB_AUD0;
480 custom.intena = mask << INTB_AUD0;
481
482 /* copy data to DMA buffer */
483
484 if (sc->sc_channels == 1) {
485 dmap[0] =
486 dmap[1] =
487 dmap[2] =
488 dmap[3] = (u_char *)sc->sc_channel[j].nd_dma;
489 } else {
490 for (k = 0; k < 4; k++) {
491 if (masks2[k+j] & mask)
492 dmap[k] = (u_char *)sc->sc_channel[k+j].nd_dma;
493 }
494 }
495
496 sc->sc_channel[j].nd_doublebuf ^= 1;
497 if (sc->sc_channel[j].nd_doublebuf) {
498 dmap[0] += AUDIO_BUF_SIZE;
499 dmap[1] += AUDIO_BUF_SIZE;
500 dmap[2] += AUDIO_BUF_SIZE;
501 dmap[3] += AUDIO_BUF_SIZE;
502 }
503
504 /*
505 * compute output length in bytes per channel.
506 * divide by two only for 16bit->8bit conversion.
507 */
508 len = cc / sc->sc_channels;
509 if (!sc->sc_14bit && (sc->sc_precision == 16))
510 len /= 2;
511
512 /* call audio decoding routine */
513 sc->sc_decodefunc (dmap, (u_char *)p, len);
514
515 /* DMA buffers: we use same buffer 4 all channels
516 * write DMA location and length
517 */
518 for (i = k = 0; i < 4; i++) {
519 if (masks2[i] & mask) {
520 DPRINTF(("turning channel %d on\n",i));
521 /* sc->sc_channel[i].nd_busy=1; */
522 channel[i].isaudio = 1;
523 channel[i].play_count = 1;
524 channel[i].handler = NULL;
525 custom.aud[i].per = sc->sc_channel[i].nd_per;
526 if (sc->sc_14bit && (i > 1))
527 custom.aud[i].vol = 1;
528 else
529 custom.aud[i].vol = sc->sc_channel[i].nd_volume;
530 custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
531 custom.aud[i].len = len / 2;
532 sc->sc_channel[i].nd_mask = mask;
533 DPRINTF(("per is %d, vol is %d, len is %d\n",\
534 sc->sc_channel[i].nd_per,
535 sc->sc_channel[i].nd_volume, len));
536 }
537 }
538
539 channel[j].handler = aucc_inthdl;
540
541 /* enable ints */
542 custom.intena = INTF_SETCLR | INTF_INTEN | (masks2[j] << INTB_AUD0);
543
544 DPRINTF(("enabled ints: 0x%x\n", (masks2[j] << INTB_AUD0)));
545
546 /* enable DMA */
547 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | mask;
548
549 DPRINTF(("enabled DMA, mask=0x%x\n",mask));
550
551 return 0;
552 }
553
554 /* ARGSUSED */
555 int
556 aucc_start_input(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
557 {
558
559 return ENXIO; /* no input */
560 }
561
562 int
563 aucc_halt_output(void *addr)
564 {
565 struct aucc_softc *sc;
566 int i;
567
568 /* XXX only halt, if input is also halted ?? */
569 sc = addr;
570 /* stop DMA, etc */
571 custom.intena = AUCC_ALLINTF;
572 custom.dmacon = AUCC_ALLDMAF;
573 /* mark every busy unit idle */
574 for (i = 0; i < 4; i++) {
575 sc->sc_channel[i].nd_busy = sc->sc_channel[i].nd_mask = 0;
576 channel[i].isaudio = 0;
577 channel[i].play_count = 0;
578 }
579
580 return 0;
581 }
582
583 int
584 aucc_halt_input(void *addr)
585 {
586
587 /* no input */
588 return ENXIO;
589 }
590
591 int
592 aucc_getdev(void *addr, struct audio_device *retp)
593 {
594
595 *retp = aucc_device;
596 return 0;
597 }
598
599 int
600 aucc_set_port(void *addr, mixer_ctrl_t *cp)
601 {
602 struct aucc_softc *sc;
603 int i,j;
604
605 DPRINTF(("aucc_set_port: port=%d", cp->dev));
606 sc = addr;
607 switch (cp->type) {
608 case AUDIO_MIXER_SET:
609 if (cp->dev != AUCC_CHANNELS)
610 return EINVAL;
611 i = cp->un.mask;
612 if ((i < 1) || (i > 15))
613 return EINVAL;
614
615 sc->sc_channelmask = i;
616 break;
617
618 case AUDIO_MIXER_VALUE:
619 i = cp->un.value.num_channels;
620 if ((i < 1) || (i > 4))
621 return EINVAL;
622
623 #ifdef __XXXwhatsthat
624 if (cp->dev != AUCC_VOLUME)
625 return EINVAL;
626 #endif
627
628 /* set volume for channel 0..i-1 */
629
630 /* evil workaround for xanim bug, IMO */
631 if ((sc->sc_channels == 1) && (i == 2)) {
632 sc->sc_channel[0].nd_volume =
633 sc->sc_channel[3].nd_volume =
634 cp->un.value.level[0] >> 2;
635 sc->sc_channel[1].nd_volume =
636 sc->sc_channel[2].nd_volume =
637 cp->un.value.level[1] >> 2;
638 } else if (i > 1) {
639 for (j = 0; j < i; j++)
640 sc->sc_channel[j].nd_volume =
641 cp->un.value.level[j] >> 2;
642 } else if (sc->sc_channels > 1)
643 for (j = 0; j < sc->sc_channels; j++)
644 sc->sc_channel[j].nd_volume =
645 cp->un.value.level[0] >> 2;
646 else
647 for (j = 0; j < 4; j++)
648 sc->sc_channel[j].nd_volume =
649 cp->un.value.level[0] >> 2;
650 break;
651
652 default:
653 return EINVAL;
654 break;
655 }
656 return 0;
657 }
658
659
660 int
661 aucc_get_port(void *addr, mixer_ctrl_t *cp)
662 {
663 struct aucc_softc *sc;
664 int i,j;
665
666 DPRINTF(("aucc_get_port: port=%d", cp->dev));
667 sc = addr;
668 switch (cp->type) {
669 case AUDIO_MIXER_SET:
670 if (cp->dev != AUCC_CHANNELS)
671 return EINVAL;
672 cp->un.mask = sc->sc_channelmask;
673 break;
674
675 case AUDIO_MIXER_VALUE:
676 i = cp->un.value.num_channels;
677 if ((i < 1) || (i > 4))
678 return EINVAL;
679
680 for (j = 0; j < i; j++)
681 cp->un.value.level[j] =
682 (sc->sc_channel[j].nd_volume << 2) +
683 (sc->sc_channel[j].nd_volume >> 4);
684 break;
685
686 default:
687 return EINVAL;
688 }
689 return 0;
690 }
691
692
693 int
694 aucc_get_props(void *addr)
695 {
696
697 return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE;
698 }
699
700
701 void
702 aucc_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread)
703 {
704 struct aucc_softc *sc = opaque;
705
706 *intr = &sc->sc_intr_lock;
707 *thread = &sc->sc_lock;
708 }
709
710 int
711 aucc_query_devinfo(void *addr, register mixer_devinfo_t *dip)
712 {
713 int i;
714
715 switch(dip->index) {
716 case AUCC_CHANNELS:
717 dip->type = AUDIO_MIXER_SET;
718 dip->mixer_class = AUCC_OUTPUT_CLASS;
719 dip->prev = dip->next = AUDIO_MIXER_LAST;
720 #define setname(a) strlcpy(dip->label.name, (a), sizeof(dip->label.name))
721 setname(AudioNspeaker);
722 for (i = 0; i < 16; i++) {
723 snprintf(dip->un.s.member[i].label.name,
724 sizeof(dip->un.s.member[i].label.name),
725 "channelmask%d", i);
726 dip->un.s.member[i].mask = i;
727 }
728 dip->un.s.num_mem = 16;
729 break;
730
731 case AUCC_VOLUME:
732 dip->type = AUDIO_MIXER_VALUE;
733 dip->mixer_class = AUCC_OUTPUT_CLASS;
734 dip->prev = dip->next = AUDIO_MIXER_LAST;
735 setname(AudioNmaster);
736 dip->un.v.num_channels = 4;
737 strcpy(dip->un.v.units.name, AudioNvolume);
738 break;
739
740 case AUCC_OUTPUT_CLASS:
741 dip->type = AUDIO_MIXER_CLASS;
742 dip->mixer_class = AUCC_OUTPUT_CLASS;
743 dip->next = dip->prev = AUDIO_MIXER_LAST;
744 setname(AudioCoutputs);
745 break;
746
747 default:
748 return ENXIO;
749 }
750
751 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
752
753 return 0;
754 }
755
756 /* audio int handler */
757 void
758 aucc_inthdl(int ch)
759 {
760 int i;
761 int mask;
762
763 mutex_spin_enter(&aucc->sc_intr_lock);
764 mask = aucc->sc_channel[ch].nd_mask;
765 /*
766 * for all channels in this maskgroup:
767 * disable DMA, int
768 * mark idle
769 */
770 DPRINTF(("inthandler called, channel %d, mask 0x%x\n", ch, mask));
771
772 custom.intreq = mask << INTB_AUD0; /* clear request */
773 /*
774 * XXX: maybe we can leave ints and/or DMA on,
775 * if another sample has to be played?
776 */
777 custom.intena = mask << INTB_AUD0;
778 /*
779 * XXX custom.dmacon=mask; NO!!!
780 */
781 for (i = 0; i < 4; i++) {
782 if (masks2[i] && mask) {
783 DPRINTF(("marking channel %d idle\n",i));
784 aucc->sc_channel[i].nd_busy = 0;
785 aucc->sc_channel[i].nd_mask = 0;
786 channel[i].isaudio = channel[i].play_count = 0;
787 }
788 }
789
790 /* call handler */
791 if (aucc->sc_channel[ch].nd_intr) {
792 DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
793 (*(aucc->sc_channel[ch].nd_intr))
794 (aucc->sc_channel[ch].nd_intrdata);
795 } else
796 DPRINTF(("zero int handler\n"));
797 mutex_spin_exit(&aucc->sc_intr_lock);
798 DPRINTF(("ints done\n"));
799 }
800
801 /* transform frequency to period, adjust bounds */
802 static u_int
803 freqtoper(u_int freq)
804 {
805 u_int per;
806
807 per = eclockfreq * 5 / freq;
808 if (per < 124)
809 per = 124; /* must have at least 124 ticks between samples */
810
811 return per;
812 }
813
814 /* transform period to frequency */
815 static u_int
816 pertofreq(u_int per)
817 {
818
819 return eclockfreq * 5 / per;
820 }
821
822
823 /* 14bit output */
824 static void
825 aucc_decode_slinear16_1ch(u_char **dmap, u_char *p, int i)
826 {
827 u_char *ch0;
828 u_char *ch3;
829
830 ch0 = dmap[0];
831 ch3 = dmap[1]; /* XXX should be 3 */
832 while (i--) {
833 *ch0++ = *p++;
834 *ch3++ = *p++ >> 2;
835 }
836 }
837
838 /* 14bit stereo output */
839 static void
840 aucc_decode_slinear16_2ch(u_char **dmap, u_char *p, int i)
841 {
842 u_char *ch0;
843 u_char *ch1;
844 u_char *ch2;
845 u_char *ch3;
846
847 ch0 = dmap[0];
848 ch1 = dmap[1];
849 ch2 = dmap[2];
850 ch3 = dmap[3];
851 while (i--) {
852 *ch0++ = *p++;
853 *ch3++ = *p++ >> 2;
854 *ch1++ = *p++;
855 *ch2++ = *p++ >> 2;
856 }
857 }
858
859 static void
860 aucc_decode_slinear16_3ch(u_char **dmap, u_char *p, int i)
861 {
862 u_char *ch0;
863 u_char *ch1;
864 u_char *ch2;
865
866 ch0 = dmap[0];
867 ch1 = dmap[1];
868 ch2 = dmap[2];
869 while (i--) {
870 *ch0++ = *p++; p++;
871 *ch1++ = *p++; p++;
872 *ch2++ = *p++; p++;
873 }
874 }
875
876 static void
877 aucc_decode_slinear16_4ch(u_char **dmap, u_char *p, int i)
878 {
879 u_char *ch0;
880 u_char *ch1;
881 u_char *ch2;
882 u_char *ch3;
883
884 ch0 = dmap[0];
885 ch1 = dmap[1];
886 ch2 = dmap[2];
887 ch3 = dmap[3];
888 while (i--) {
889 *ch0++ = *p++; p++;
890 *ch1++ = *p++; p++;
891 *ch2++ = *p++; p++;
892 *ch3++ = *p++; p++;
893 }
894 }
895
896 #endif /* NAUCC > 0 */
897