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