1 /* $NetBSD: aucc.c,v 1.39 2005/12/11 12:16:28 christos Exp $ */
4 * Copyright (c) 1999 Bernardo Innocenti
7 * Copyright (c) 1997 Stephan Thesing
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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
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.
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.
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
49 * - 14bit output requires maximum volume
55 #include <sys/cdefs.h>
56 __KERNEL_RCSID(0, "$NetBSD: aucc.c,v 1.39 2005/12/11 12:16:28 christos Exp $");
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>
64 #include <machine/cpu.h>
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>
73 #include "opt_lev6_defer.h"
78 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2)
81 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3)
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)
87 /*extern printf(const char *,...);*/
89 #define DPRINTF(x) if (auccdebug) printf x
98 #define splaudio() spl4();
100 /* clock frequency.. */
101 extern int eclockfreq
;
105 extern struct audio_channel channel
[4];
112 struct device sc_dev
; /* base device */
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 */
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 */
127 /* interrupt interfaces */
128 void aucc_inthdl(int);
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
);
135 /* autoconfiguration driver */
136 void auccattach(struct device
*, struct device
*, void *);
137 int auccmatch(struct device
*, struct cfdata
*, void *);
139 CFATTACH_DECL(aucc
, sizeof(struct aucc_softc
),
140 auccmatch
, auccattach
, NULL
, NULL
);
142 struct audio_device aucc_device
= {
149 struct aucc_softc
*aucc
= NULL
;
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,
188 * Define our interface to the higher level audio driver.
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 *);
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);
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);
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);
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);
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);
237 const struct audio_hw_if sa_hw_if
= {
243 aucc_round_blocksize
,
244 aucc_commit_settings
,
267 /* autoconfig routines */
270 auccmatch(struct device
*pdp
, struct cfdata
*cfp
, void *aux
)
272 static int aucc_matched
= 0;
274 if (!matchname((char *)aux
, "aucc") ||
289 auccattach(struct device
*parent
, struct device
*self
, void *args
)
291 struct aucc_softc
*sc
;
294 sc
= (struct aucc_softc
*)self
;
297 if ((i
=init_aucc(sc
))) {
298 printf("audio: no chipmem\n");
302 audio_attach_mi(&sa_hw_if
, sc
, &sc
->sc_dev
);
307 init_aucc(struct aucc_softc
*sc
)
312 /* init values per channel */
313 for (i
= 0; i
< 4; i
++) {
314 sc
->sc_channel
[i
].nd_freq
= 8000;
315 sc
->sc_channel
[i
].nd_per
= freqtoper(8000);
316 sc
->sc_channel
[i
].nd_busy
= 0;
317 sc
->sc_channel
[i
].nd_dma
= alloc_chipmem(AUDIO_BUF_SIZE
*2);
318 if (sc
->sc_channel
[i
].nd_dma
== NULL
)
320 sc
->sc_channel
[i
].nd_dmalength
= 0;
321 sc
->sc_channel
[i
].nd_volume
= 64;
322 sc
->sc_channel
[i
].nd_intr
= NULL
;
323 sc
->sc_channel
[i
].nd_intrdata
= NULL
;
324 sc
->sc_channel
[i
].nd_doublebuf
= 0;
325 DPRINTF(("DMA buffer for channel %d is %p\n", i
,
326 sc
->sc_channel
[i
].nd_dma
));
330 for (i
= 0; i
< 4; i
++)
331 if (sc
->sc_channel
[i
].nd_dma
)
332 free_chipmem(sc
->sc_channel
[i
].nd_dma
);
336 sc
->sc_channelmask
= 0xf;
337 sc
->sc_precision
= 8;
339 sc
->sc_encoding
= AUDIO_ENCODING_ULAW
;
340 sc
->sc_decodefunc
= aucc_decode_mulaw_1ch
;
342 /* clear interrupts and DMA: */
343 custom
.intena
= AUCC_ALLINTF
;
344 custom
.dmacon
= AUCC_ALLDMAF
;
350 aucc_open(void *addr
, int flags
)
352 struct aucc_softc
*sc
;
356 DPRINTF(("sa_open: unit %p\n",sc
));
361 for (i
= 0; i
< AUCC_MAXINT
; i
++) {
362 sc
->sc_channel
[i
].nd_intr
= NULL
;
363 sc
->sc_channel
[i
].nd_intrdata
= NULL
;
366 sc
->sc_channelmask
= 0xf;
368 DPRINTF(("saopen: ok -> sc=%p\n",sc
));
374 aucc_close(void *addr
)
376 struct aucc_softc
*sc
;
379 DPRINTF(("sa_close: sc=%p\n", sc
));
381 * halt i/o, clear open flag, and done.
383 aucc_halt_output(sc
);
386 DPRINTF(("sa_close: closed.\n"));
390 aucc_set_out_sr(void *addr
, u_int sr
)
392 struct aucc_softc
*sc
;
402 for (i
= 0; i
< 4; i
++) {
403 sc
->sc_channel
[i
].nd_freq
= sr
;
404 sc
->sc_channel
[i
].nd_per
= per
;
411 aucc_query_encoding(void *addr
, struct audio_encoding
*fp
)
416 strcpy(fp
->name
, AudioEslinear
);
417 fp
->encoding
= AUDIO_ENCODING_SLINEAR
;
422 strcpy(fp
->name
, AudioEmulaw
);
423 fp
->encoding
= AUDIO_ENCODING_ULAW
;
425 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
429 strcpy(fp
->name
, AudioEulinear
);
430 fp
->encoding
= AUDIO_ENCODING_ULINEAR
;
432 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
436 strcpy(fp
->name
, AudioEslinear
);
437 fp
->encoding
= AUDIO_ENCODING_SLINEAR
;
439 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
443 strcpy(fp
->name
, AudioEslinear_be
);
444 fp
->encoding
= AUDIO_ENCODING_SLINEAR_BE
;
446 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
450 strcpy(fp
->name
, AudioEslinear_le
);
451 fp
->encoding
= AUDIO_ENCODING_SLINEAR_LE
;
453 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
464 aucc_set_params(void *addr
, int setmode
, int usemode
,
465 audio_params_t
*p
, audio_params_t
*r
,
466 stream_filter_list_t
*pfil
, stream_filter_list_t
*rfil
)
468 struct aucc_softc
*sc
;
471 /* if (setmode & AUMODE_RECORD)
475 printf("aucc_set_params(setmode 0x%x, usemode 0x%x, "
476 "enc %u, bits %u, chn %u, sr %u)\n", setmode
, usemode
,
477 p
->encoding
, p
->precision
, p
->channels
, p
->sample_rate
);
480 switch (p
->precision
) {
482 switch (p
->encoding
) {
483 case AUDIO_ENCODING_ULAW
:
484 switch (p
->channels
) {
486 sc
->sc_decodefunc
= aucc_decode_mulaw_1ch
;
489 sc
->sc_decodefunc
= aucc_decode_mulaw_2ch
;
492 sc
->sc_decodefunc
= aucc_decode_mulaw_3ch
;
495 sc
->sc_decodefunc
= aucc_decode_mulaw_4ch
;
502 case AUDIO_ENCODING_SLINEAR
:
503 case AUDIO_ENCODING_SLINEAR_BE
:
504 case AUDIO_ENCODING_SLINEAR_LE
:
505 switch (p
->channels
) {
507 sc
->sc_decodefunc
= aucc_decode_slinear8_1ch
;
510 sc
->sc_decodefunc
= aucc_decode_slinear8_2ch
;
513 sc
->sc_decodefunc
= aucc_decode_slinear8_3ch
;
516 sc
->sc_decodefunc
= aucc_decode_slinear8_4ch
;
523 case AUDIO_ENCODING_ULINEAR
:
524 case AUDIO_ENCODING_ULINEAR_BE
:
525 case AUDIO_ENCODING_ULINEAR_LE
:
526 switch (p
->channels
) {
528 sc
->sc_decodefunc
= aucc_decode_ulinear8_1ch
;
531 sc
->sc_decodefunc
= aucc_decode_ulinear8_2ch
;
534 sc
->sc_decodefunc
= aucc_decode_ulinear8_3ch
;
537 sc
->sc_decodefunc
= aucc_decode_ulinear8_4ch
;
550 switch (p
->encoding
) {
551 #if BYTE_ORDER == BIG_ENDIAN
552 case AUDIO_ENCODING_SLINEAR
:
554 case AUDIO_ENCODING_SLINEAR_BE
:
555 switch (p
->channels
) {
557 sc
->sc_decodefunc
= aucc_decode_slinear16_1ch
;
561 sc
->sc_decodefunc
= aucc_decode_slinear16_2ch
;
564 sc
->sc_decodefunc
= aucc_decode_slinear16_3ch
;
567 sc
->sc_decodefunc
= aucc_decode_slinear16_4ch
;
574 #if BYTE_ORDER == LITTLE_ENDIAN
575 case AUDIO_ENCODING_SLINEAR
:
577 case AUDIO_ENCODING_SLINEAR_LE
:
578 switch (p
->channels
) {
580 sc
->sc_decodefunc
= aucc_decode_slinear16sw_1ch
;
583 sc
->sc_decodefunc
= aucc_decode_slinear16sw_2ch
;
586 sc
->sc_decodefunc
= aucc_decode_slinear16sw_3ch
;
589 sc
->sc_decodefunc
= aucc_decode_slinear16sw_4ch
;
605 sc
->sc_encoding
= p
->encoding
;
606 sc
->sc_precision
= p
->precision
;
607 sc
->sc_14bit
= ((p
->precision
== 16) && (p
->channels
<= 2));
608 sc
->sc_channels
= sc
->sc_14bit
? (p
->channels
* 2) : p
->channels
;
610 return aucc_set_out_sr(addr
, p
->sample_rate
);
614 aucc_round_blocksize(void *addr
, int blk
,
615 int mode
, const audio_params_t
*param
)
618 /* round up to even size */
619 return blk
> AUDIO_BUF_SIZE
? AUDIO_BUF_SIZE
: blk
;
623 aucc_commit_settings(void *addr
)
625 struct aucc_softc
*sc
;
628 DPRINTF(("sa_commit.\n"));
631 for (i
= 0; i
< 4; i
++) {
632 custom
.aud
[i
].vol
= sc
->sc_channel
[i
].nd_volume
;
633 custom
.aud
[i
].per
= sc
->sc_channel
[i
].nd_per
;
636 DPRINTF(("commit done\n"));
641 static int masks
[4] = {1,3,7,15}; /* masks for n first channels */
642 static int masks2
[4] = {1,2,4,8};
645 aucc_start_output(void *addr
, void *p
, int cc
, void (*intr
)(void *), void *arg
)
647 struct aucc_softc
*sc
;
654 mask
= sc
->sc_channelmask
;
656 dmap
[0] = dmap
[1] = dmap
[2] = dmap
[3] = NULL
;
658 DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc
, intr
, arg
));
660 if (sc
->sc_channels
> 1)
661 mask
&= masks
[sc
->sc_channels
- 1];
662 /* we use first sc_channels channels */
663 if (mask
== 0) /* active and used channels are disjoint */
666 for (i
= 0; i
< 4; i
++) {
667 /* channels available ? */
668 if ((masks2
[i
] & mask
) && (sc
->sc_channel
[i
].nd_busy
))
669 return EBUSY
; /* channel is busy */
670 if (channel
[i
].isaudio
== -1)
671 return EBUSY
; /* system uses them */
674 /* enable interrupt on 1st channel */
675 for (i
= j
= 0; i
< AUCC_MAXINT
; i
++) {
676 if (masks2
[i
] & mask
) {
677 DPRINTF(("first channel is %d\n",i
));
679 sc
->sc_channel
[i
].nd_intr
= intr
;
680 sc
->sc_channel
[i
].nd_intrdata
= arg
;
685 DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap
[0], dmap
[1],
686 dmap
[2], dmap
[3], mask
));
688 /* disable ints, DMA for channels, until all parameters set */
689 /* XXX dont disable DMA! custom.dmacon=mask;*/
690 custom
.intreq
= mask
<< INTB_AUD0
;
691 custom
.intena
= mask
<< INTB_AUD0
;
693 /* copy data to DMA buffer */
695 if (sc
->sc_channels
== 1) {
699 dmap
[3] = (u_char
*)sc
->sc_channel
[j
].nd_dma
;
701 for (k
= 0; k
< 4; k
++) {
702 if (masks2
[k
+j
] & mask
)
703 dmap
[k
] = (u_char
*)sc
->sc_channel
[k
+j
].nd_dma
;
707 sc
->sc_channel
[j
].nd_doublebuf
^= 1;
708 if (sc
->sc_channel
[j
].nd_doublebuf
) {
709 dmap
[0] += AUDIO_BUF_SIZE
;
710 dmap
[1] += AUDIO_BUF_SIZE
;
711 dmap
[2] += AUDIO_BUF_SIZE
;
712 dmap
[3] += AUDIO_BUF_SIZE
;
716 * compute output length in bytes per channel.
717 * divide by two only for 16bit->8bit conversion.
719 len
= cc
/ sc
->sc_channels
;
720 if (!sc
->sc_14bit
&& (sc
->sc_precision
== 16))
723 /* call audio decoding routine */
724 sc
->sc_decodefunc (dmap
, (u_char
*)p
, len
);
726 /* DMA buffers: we use same buffer 4 all channels
727 * write DMA location and length
729 for (i
= k
= 0; i
< 4; i
++) {
730 if (masks2
[i
] & mask
) {
731 DPRINTF(("turning channel %d on\n",i
));
732 /* sc->sc_channel[i].nd_busy=1; */
733 channel
[i
].isaudio
= 1;
734 channel
[i
].play_count
= 1;
735 channel
[i
].handler
= NULL
;
736 custom
.aud
[i
].per
= sc
->sc_channel
[i
].nd_per
;
737 if (sc
->sc_14bit
&& (i
> 1))
738 custom
.aud
[i
].vol
= 1;
740 custom
.aud
[i
].vol
= sc
->sc_channel
[i
].nd_volume
;
741 custom
.aud
[i
].lc
= PREP_DMA_MEM(dmap
[k
++]);
742 custom
.aud
[i
].len
= len
/ 2;
743 sc
->sc_channel
[i
].nd_mask
= mask
;
744 DPRINTF(("per is %d, vol is %d, len is %d\n",\
745 sc
->sc_channel
[i
].nd_per
,
746 sc
->sc_channel
[i
].nd_volume
, len
));
750 channel
[j
].handler
= aucc_inthdl
;
753 custom
.intena
= INTF_SETCLR
| INTF_INTEN
| (masks2
[j
] << INTB_AUD0
);
755 DPRINTF(("enabled ints: 0x%x\n", (masks2
[j
] << INTB_AUD0
)));
758 custom
.dmacon
= DMAF_SETCLR
| DMAF_MASTER
| mask
;
760 DPRINTF(("enabled DMA, mask=0x%x\n",mask
));
767 aucc_start_input(void *addr
, void *p
, int cc
, void (*intr
)(void *), void *arg
)
770 return ENXIO
; /* no input */
774 aucc_halt_output(void *addr
)
776 struct aucc_softc
*sc
;
779 /* XXX only halt, if input is also halted ?? */
782 custom
.intena
= AUCC_ALLINTF
;
783 custom
.dmacon
= AUCC_ALLDMAF
;
784 /* mark every busy unit idle */
785 for (i
= 0; i
< 4; i
++) {
786 sc
->sc_channel
[i
].nd_busy
= sc
->sc_channel
[i
].nd_mask
= 0;
787 channel
[i
].isaudio
= 0;
788 channel
[i
].play_count
= 0;
795 aucc_halt_input(void *addr
)
803 aucc_getdev(void *addr
, struct audio_device
*retp
)
811 aucc_set_port(void *addr
, mixer_ctrl_t
*cp
)
813 struct aucc_softc
*sc
;
816 DPRINTF(("aucc_set_port: port=%d", cp
->dev
));
819 case AUDIO_MIXER_SET
:
820 if (cp
->dev
!= AUCC_CHANNELS
)
823 if ((i
< 1) || (i
> 15))
826 sc
->sc_channelmask
= i
;
829 case AUDIO_MIXER_VALUE
:
830 i
= cp
->un
.value
.num_channels
;
831 if ((i
< 1) || (i
> 4))
834 #ifdef __XXXwhatsthat
835 if (cp
->dev
!= AUCC_VOLUME
)
839 /* set volume for channel 0..i-1 */
841 /* evil workaround for xanim bug, IMO */
842 if ((sc
->sc_channels
== 1) && (i
== 2)) {
843 sc
->sc_channel
[0].nd_volume
=
844 sc
->sc_channel
[3].nd_volume
=
845 cp
->un
.value
.level
[0] >> 2;
846 sc
->sc_channel
[1].nd_volume
=
847 sc
->sc_channel
[2].nd_volume
=
848 cp
->un
.value
.level
[1] >> 2;
850 for (j
= 0; j
< i
; j
++)
851 sc
->sc_channel
[j
].nd_volume
=
852 cp
->un
.value
.level
[j
] >> 2;
853 } else if (sc
->sc_channels
> 1)
854 for (j
= 0; j
< sc
->sc_channels
; j
++)
855 sc
->sc_channel
[j
].nd_volume
=
856 cp
->un
.value
.level
[0] >> 2;
858 for (j
= 0; j
< 4; j
++)
859 sc
->sc_channel
[j
].nd_volume
=
860 cp
->un
.value
.level
[0] >> 2;
872 aucc_get_port(void *addr
, mixer_ctrl_t
*cp
)
874 struct aucc_softc
*sc
;
877 DPRINTF(("aucc_get_port: port=%d", cp
->dev
));
880 case AUDIO_MIXER_SET
:
881 if (cp
->dev
!= AUCC_CHANNELS
)
883 cp
->un
.mask
= sc
->sc_channelmask
;
886 case AUDIO_MIXER_VALUE
:
887 i
= cp
->un
.value
.num_channels
;
888 if ((i
< 1) || (i
> 4))
891 for (j
= 0; j
< i
; j
++)
892 cp
->un
.value
.level
[j
] =
893 (sc
->sc_channel
[j
].nd_volume
<< 2) +
894 (sc
->sc_channel
[j
].nd_volume
>> 4);
905 aucc_get_props(void *addr
)
911 aucc_query_devinfo(void *addr
, register mixer_devinfo_t
*dip
)
917 dip
->type
= AUDIO_MIXER_SET
;
918 dip
->mixer_class
= AUCC_OUTPUT_CLASS
;
919 dip
->prev
= dip
->next
= AUDIO_MIXER_LAST
;
920 strcpy(dip
->label
.name
, AudioNspeaker
);
921 for (i
= 0; i
< 16; i
++) {
922 sprintf(dip
->un
.s
.member
[i
].label
.name
,
924 dip
->un
.s
.member
[i
].mask
= i
;
926 dip
->un
.s
.num_mem
= 16;
930 dip
->type
= AUDIO_MIXER_VALUE
;
931 dip
->mixer_class
= AUCC_OUTPUT_CLASS
;
932 dip
->prev
= dip
->next
= AUDIO_MIXER_LAST
;
933 strcpy(dip
->label
.name
, AudioNmaster
);
934 dip
->un
.v
.num_channels
= 4;
935 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
938 case AUCC_OUTPUT_CLASS
:
939 dip
->type
= AUDIO_MIXER_CLASS
;
940 dip
->mixer_class
= AUCC_OUTPUT_CLASS
;
941 dip
->next
= dip
->prev
= AUDIO_MIXER_LAST
;
942 strcpy(dip
->label
.name
, AudioCoutputs
);
949 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip
->label
.name
));
954 /* audio int handler */
961 mask
= aucc
->sc_channel
[ch
].nd_mask
;
963 * for all channels in this maskgroup:
967 DPRINTF(("inthandler called, channel %d, mask 0x%x\n", ch
, mask
));
969 custom
.intreq
= mask
<< INTB_AUD0
; /* clear request */
971 * XXX: maybe we can leave ints and/or DMA on,
972 * if another sample has to be played?
974 custom
.intena
= mask
<< INTB_AUD0
;
976 * XXX custom.dmacon=mask; NO!!!
978 for (i
= 0; i
< 4; i
++) {
979 if (masks2
[i
] && mask
) {
980 DPRINTF(("marking channel %d idle\n",i
));
981 aucc
->sc_channel
[i
].nd_busy
= 0;
982 aucc
->sc_channel
[i
].nd_mask
= 0;
983 channel
[i
].isaudio
= channel
[i
].play_count
= 0;
988 if (aucc
->sc_channel
[ch
].nd_intr
) {
989 DPRINTF(("calling %p\n",aucc
->sc_channel
[ch
].nd_intr
));
990 (*(aucc
->sc_channel
[ch
].nd_intr
))
991 (aucc
->sc_channel
[ch
].nd_intrdata
);
993 DPRINTF(("zero int handler\n"));
994 DPRINTF(("ints done\n"));
997 /* transform frequency to period, adjust bounds */
999 freqtoper(u_int freq
)
1003 per
= eclockfreq
* 5 / freq
;
1005 per
= 124; /* must have at least 124 ticks between samples */
1010 /* transform period to frequency */
1012 pertofreq(u_int per
)
1015 return eclockfreq
* 5 / per
;
1019 aucc_decode_slinear8_1ch(u_char
**dmap
, u_char
*p
, int i
)
1021 memcpy(dmap
[0], p
, i
);
1025 aucc_decode_slinear8_2ch(u_char
**dmap
, u_char
*p
, int i
)
1039 aucc_decode_slinear8_3ch(u_char
**dmap
, u_char
*p
, int i
)
1056 aucc_decode_slinear8_4ch(u_char
**dmap
, u_char
*p
, int i
)
1076 aucc_decode_ulinear8_1ch(u_char
**dmap
, u_char
*p
, int i
)
1082 *ch0
++ = *p
++ - 128;
1086 aucc_decode_ulinear8_2ch(u_char
**dmap
, u_char
*p
, int i
)
1094 *ch0
++ = *p
++ - 128;
1095 *ch1
++ = *p
++ - 128;
1100 aucc_decode_ulinear8_3ch(u_char
**dmap
, u_char
*p
, int i
)
1110 *ch0
++ = *p
++ - 128;
1111 *ch1
++ = *p
++ - 128;
1112 *ch2
++ = *p
++ - 128;
1117 aucc_decode_ulinear8_4ch(u_char
**dmap
, u_char
*p
, int i
)
1129 *ch0
++ = *p
++ - 128;
1130 *ch1
++ = *p
++ - 128;
1131 *ch2
++ = *p
++ - 128;
1132 *ch3
++ = *p
++ - 128;
1138 aucc_decode_mulaw_1ch(u_char
**dmap
, u_char
*p
, int i
)
1144 *ch0
++ = mulaw_to_lin
[*p
++];
1148 aucc_decode_mulaw_2ch(u_char
**dmap
, u_char
*p
, int i
)
1156 *ch0
++ = mulaw_to_lin
[*p
++];
1157 *ch1
++ = mulaw_to_lin
[*p
++];
1162 aucc_decode_mulaw_3ch(u_char
**dmap
, u_char
*p
, int i
)
1172 *ch0
++ = mulaw_to_lin
[*p
++];
1173 *ch1
++ = mulaw_to_lin
[*p
++];
1174 *ch2
++ = mulaw_to_lin
[*p
++];
1179 aucc_decode_mulaw_4ch(u_char
**dmap
, u_char
*p
, int i
)
1191 *ch0
++ = mulaw_to_lin
[*p
++];
1192 *ch1
++ = mulaw_to_lin
[*p
++];
1193 *ch2
++ = mulaw_to_lin
[*p
++];
1194 *ch3
++ = mulaw_to_lin
[*p
++];
1201 aucc_decode_slinear16_1ch(u_char
**dmap
, u_char
*p
, int i
)
1207 ch3
= dmap
[1]; /* XXX should be 3 */
1214 /* 14bit stereo output */
1216 aucc_decode_slinear16_2ch(u_char
**dmap
, u_char
*p
, int i
)
1236 aucc_decode_slinear16_3ch(u_char
**dmap
, u_char
*p
, int i
)
1253 aucc_decode_slinear16_4ch(u_char
**dmap
, u_char
*p
, int i
)
1272 /* 14bit output, swap bytes */
1274 aucc_decode_slinear16sw_1ch(u_char
**dmap
, u_char
*p
, int i
)
1280 ch3
= dmap
[1]; /* XXX should be 3 */
1288 aucc_decode_slinear16sw_2ch(u_char
**dmap
, u_char
*p
, int i
)
1308 aucc_decode_slinear16sw_3ch(u_char
**dmap
, u_char
*p
, int i
)
1325 aucc_decode_slinear16sw_4ch(u_char
**dmap
, u_char
*p
, int i
)
1345 #endif /* NAUCC > 0 */