aucc.c revision 1.48 1 1.48 isaki /* $NetBSD: aucc.c,v 1.48 2020/02/29 06:03:55 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.48 isaki __KERNEL_RCSID(0, "$NetBSD: aucc.c,v 1.48 2020/02/29 06:03:55 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.48 isaki if (blk > AUDIO_BUF_SIZE)
408 1.48 isaki blk = AUDIO_BUF_SIZE;
409 1.48 isaki
410 1.48 isaki blk = rounddown(blk, param->channels * param->precision / NBBY);
411 1.48 isaki return blk;
412 1.1 is }
413 1.1 is
414 1.1 is int
415 1.29 aymeric aucc_commit_settings(void *addr)
416 1.1 is {
417 1.37 kent struct aucc_softc *sc;
418 1.37 kent int i;
419 1.1 is
420 1.1 is DPRINTF(("sa_commit.\n"));
421 1.1 is
422 1.37 kent sc = addr;
423 1.37 kent for (i = 0; i < 4; i++) {
424 1.37 kent custom.aud[i].vol = sc->sc_channel[i].nd_volume;
425 1.37 kent custom.aud[i].per = sc->sc_channel[i].nd_per;
426 1.1 is }
427 1.1 is
428 1.1 is DPRINTF(("commit done\n"));
429 1.1 is
430 1.37 kent return 0;
431 1.1 is }
432 1.1 is
433 1.1 is static int masks[4] = {1,3,7,15}; /* masks for n first channels */
434 1.1 is static int masks2[4] = {1,2,4,8};
435 1.1 is
436 1.1 is int
437 1.29 aymeric aucc_start_output(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
438 1.1 is {
439 1.8 is struct aucc_softc *sc;
440 1.8 is int mask;
441 1.24 is int i, j, k, len;
442 1.24 is u_char *dmap[4];
443 1.8 is
444 1.1 is
445 1.8 is sc = addr;
446 1.8 is mask = sc->sc_channelmask;
447 1.1 is
448 1.8 is dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
449 1.1 is
450 1.1 is DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
451 1.1 is
452 1.10 is if (sc->sc_channels > 1)
453 1.24 is mask &= masks[sc->sc_channels - 1];
454 1.10 is /* we use first sc_channels channels */
455 1.24 is if (mask == 0) /* active and used channels are disjoint */
456 1.1 is return EINVAL;
457 1.1 is
458 1.37 kent for (i = 0; i < 4; i++) {
459 1.24 is /* channels available ? */
460 1.24 is if ((masks2[i] & mask) && (sc->sc_channel[i].nd_busy))
461 1.1 is return EBUSY; /* channel is busy */
462 1.24 is if (channel[i].isaudio == -1)
463 1.1 is return EBUSY; /* system uses them */
464 1.1 is }
465 1.1 is
466 1.1 is /* enable interrupt on 1st channel */
467 1.24 is for (i = j = 0; i < AUCC_MAXINT; i++) {
468 1.24 is if (masks2[i] & mask) {
469 1.1 is DPRINTF(("first channel is %d\n",i));
470 1.37 kent j = i;
471 1.37 kent sc->sc_channel[i].nd_intr = intr;
472 1.37 kent sc->sc_channel[i].nd_intrdata = arg;
473 1.1 is break;
474 1.1 is }
475 1.1 is }
476 1.1 is
477 1.8 is DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
478 1.37 kent dmap[2], dmap[3], mask));
479 1.8 is
480 1.34 wiz /* disable ints, DMA for channels, until all parameters set */
481 1.8 is /* XXX dont disable DMA! custom.dmacon=mask;*/
482 1.24 is custom.intreq = mask << INTB_AUD0;
483 1.24 is custom.intena = mask << INTB_AUD0;
484 1.1 is
485 1.34 wiz /* copy data to DMA buffer */
486 1.29 aymeric
487 1.8 is if (sc->sc_channels == 1) {
488 1.8 is dmap[0] =
489 1.8 is dmap[1] =
490 1.8 is dmap[2] =
491 1.24 is dmap[3] = (u_char *)sc->sc_channel[j].nd_dma;
492 1.37 kent } else {
493 1.37 kent for (k = 0; k < 4; k++) {
494 1.24 is if (masks2[k+j] & mask)
495 1.24 is dmap[k] = (u_char *)sc->sc_channel[k+j].nd_dma;
496 1.8 is }
497 1.8 is }
498 1.8 is
499 1.8 is sc->sc_channel[j].nd_doublebuf ^= 1;
500 1.8 is if (sc->sc_channel[j].nd_doublebuf) {
501 1.24 is dmap[0] += AUDIO_BUF_SIZE;
502 1.24 is dmap[1] += AUDIO_BUF_SIZE;
503 1.24 is dmap[2] += AUDIO_BUF_SIZE;
504 1.24 is dmap[3] += AUDIO_BUF_SIZE;
505 1.8 is }
506 1.1 is
507 1.37 kent /*
508 1.37 kent * compute output length in bytes per channel.
509 1.24 is * divide by two only for 16bit->8bit conversion.
510 1.24 is */
511 1.24 is len = cc / sc->sc_channels;
512 1.24 is if (!sc->sc_14bit && (sc->sc_precision == 16))
513 1.24 is len /= 2;
514 1.24 is
515 1.24 is /* call audio decoding routine */
516 1.24 is sc->sc_decodefunc (dmap, (u_char *)p, len);
517 1.1 is
518 1.34 wiz /* DMA buffers: we use same buffer 4 all channels
519 1.34 wiz * write DMA location and length
520 1.24 is */
521 1.24 is for (i = k = 0; i < 4; i++) {
522 1.8 is if (masks2[i] & mask) {
523 1.1 is DPRINTF(("turning channel %d on\n",i));
524 1.24 is /* sc->sc_channel[i].nd_busy=1; */
525 1.24 is channel[i].isaudio = 1;
526 1.24 is channel[i].play_count = 1;
527 1.24 is channel[i].handler = NULL;
528 1.24 is custom.aud[i].per = sc->sc_channel[i].nd_per;
529 1.24 is if (sc->sc_14bit && (i > 1))
530 1.24 is custom.aud[i].vol = 1;
531 1.24 is else
532 1.24 is custom.aud[i].vol = sc->sc_channel[i].nd_volume;
533 1.8 is custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
534 1.24 is custom.aud[i].len = len / 2;
535 1.24 is sc->sc_channel[i].nd_mask = mask;
536 1.1 is DPRINTF(("per is %d, vol is %d, len is %d\n",\
537 1.8 is sc->sc_channel[i].nd_per,
538 1.24 is sc->sc_channel[i].nd_volume, len));
539 1.1 is }
540 1.1 is }
541 1.1 is
542 1.37 kent channel[j].handler = aucc_inthdl;
543 1.1 is
544 1.1 is /* enable ints */
545 1.24 is custom.intena = INTF_SETCLR | INTF_INTEN | (masks2[j] << INTB_AUD0);
546 1.1 is
547 1.24 is DPRINTF(("enabled ints: 0x%x\n", (masks2[j] << INTB_AUD0)));
548 1.1 is
549 1.34 wiz /* enable DMA */
550 1.24 is custom.dmacon = DMAF_SETCLR | DMAF_MASTER | mask;
551 1.1 is
552 1.34 wiz DPRINTF(("enabled DMA, mask=0x%x\n",mask));
553 1.1 is
554 1.37 kent return 0;
555 1.1 is }
556 1.1 is
557 1.1 is /* ARGSUSED */
558 1.1 is int
559 1.29 aymeric aucc_start_input(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
560 1.1 is {
561 1.1 is
562 1.1 is return ENXIO; /* no input */
563 1.1 is }
564 1.1 is
565 1.1 is int
566 1.29 aymeric aucc_halt_output(void *addr)
567 1.1 is {
568 1.37 kent struct aucc_softc *sc;
569 1.37 kent int i;
570 1.1 is
571 1.1 is /* XXX only halt, if input is also halted ?? */
572 1.37 kent sc = addr;
573 1.34 wiz /* stop DMA, etc */
574 1.7 is custom.intena = AUCC_ALLINTF;
575 1.7 is custom.dmacon = AUCC_ALLDMAF;
576 1.1 is /* mark every busy unit idle */
577 1.37 kent for (i = 0; i < 4; i++) {
578 1.37 kent sc->sc_channel[i].nd_busy = sc->sc_channel[i].nd_mask = 0;
579 1.37 kent channel[i].isaudio = 0;
580 1.37 kent channel[i].play_count = 0;
581 1.1 is }
582 1.1 is
583 1.37 kent return 0;
584 1.1 is }
585 1.1 is
586 1.1 is int
587 1.29 aymeric aucc_halt_input(void *addr)
588 1.1 is {
589 1.37 kent
590 1.1 is /* no input */
591 1.1 is return ENXIO;
592 1.1 is }
593 1.1 is
594 1.1 is int
595 1.29 aymeric aucc_getdev(void *addr, struct audio_device *retp)
596 1.1 is {
597 1.37 kent
598 1.37 kent *retp = aucc_device;
599 1.37 kent return 0;
600 1.1 is }
601 1.1 is
602 1.1 is int
603 1.29 aymeric aucc_set_port(void *addr, mixer_ctrl_t *cp)
604 1.1 is {
605 1.37 kent struct aucc_softc *sc;
606 1.37 kent int i,j;
607 1.1 is
608 1.1 is DPRINTF(("aucc_set_port: port=%d", cp->dev));
609 1.37 kent sc = addr;
610 1.1 is switch (cp->type) {
611 1.1 is case AUDIO_MIXER_SET:
612 1.37 kent if (cp->dev != AUCC_CHANNELS)
613 1.1 is return EINVAL;
614 1.37 kent i = cp->un.mask;
615 1.37 kent if ((i < 1) || (i > 15))
616 1.1 is return EINVAL;
617 1.24 is
618 1.37 kent sc->sc_channelmask = i;
619 1.1 is break;
620 1.1 is
621 1.1 is case AUDIO_MIXER_VALUE:
622 1.37 kent i = cp->un.value.num_channels;
623 1.37 kent if ((i < 1) || (i > 4))
624 1.1 is return EINVAL;
625 1.1 is
626 1.10 is #ifdef __XXXwhatsthat
627 1.37 kent if (cp->dev != AUCC_VOLUME)
628 1.1 is return EINVAL;
629 1.10 is #endif
630 1.1 is
631 1.1 is /* set volume for channel 0..i-1 */
632 1.21 is
633 1.21 is /* evil workaround for xanim bug, IMO */
634 1.21 is if ((sc->sc_channels == 1) && (i == 2)) {
635 1.29 aymeric sc->sc_channel[0].nd_volume =
636 1.29 aymeric sc->sc_channel[3].nd_volume =
637 1.37 kent cp->un.value.level[0] >> 2;
638 1.29 aymeric sc->sc_channel[1].nd_volume =
639 1.29 aymeric sc->sc_channel[2].nd_volume =
640 1.37 kent cp->un.value.level[1] >> 2;
641 1.37 kent } else if (i > 1) {
642 1.37 kent for (j = 0; j < i; j++)
643 1.37 kent sc->sc_channel[j].nd_volume =
644 1.37 kent cp->un.value.level[j] >> 2;
645 1.21 is } else if (sc->sc_channels > 1)
646 1.37 kent for (j = 0; j < sc->sc_channels; j++)
647 1.37 kent sc->sc_channel[j].nd_volume =
648 1.37 kent cp->un.value.level[0] >> 2;
649 1.10 is else
650 1.37 kent for (j = 0; j < 4; j++)
651 1.37 kent sc->sc_channel[j].nd_volume =
652 1.37 kent cp->un.value.level[0] >> 2;
653 1.10 is break;
654 1.1 is
655 1.1 is default:
656 1.1 is return EINVAL;
657 1.1 is break;
658 1.1 is }
659 1.1 is return 0;
660 1.1 is }
661 1.1 is
662 1.1 is
663 1.1 is int
664 1.29 aymeric aucc_get_port(void *addr, mixer_ctrl_t *cp)
665 1.1 is {
666 1.37 kent struct aucc_softc *sc;
667 1.37 kent int i,j;
668 1.1 is
669 1.1 is DPRINTF(("aucc_get_port: port=%d", cp->dev));
670 1.37 kent sc = addr;
671 1.1 is switch (cp->type) {
672 1.1 is case AUDIO_MIXER_SET:
673 1.37 kent if (cp->dev != AUCC_CHANNELS)
674 1.1 is return EINVAL;
675 1.37 kent cp->un.mask = sc->sc_channelmask;
676 1.1 is break;
677 1.1 is
678 1.1 is case AUDIO_MIXER_VALUE:
679 1.1 is i = cp->un.value.num_channels;
680 1.37 kent if ((i < 1) || (i > 4))
681 1.1 is return EINVAL;
682 1.1 is
683 1.37 kent for (j = 0; j < i; j++)
684 1.10 is cp->un.value.level[j] =
685 1.37 kent (sc->sc_channel[j].nd_volume << 2) +
686 1.37 kent (sc->sc_channel[j].nd_volume >> 4);
687 1.1 is break;
688 1.1 is
689 1.1 is default:
690 1.1 is return EINVAL;
691 1.1 is }
692 1.1 is return 0;
693 1.1 is }
694 1.1 is
695 1.16 augustss
696 1.16 augustss int
697 1.29 aymeric aucc_get_props(void *addr)
698 1.16 augustss {
699 1.46 isaki
700 1.47 rin return AUDIO_PROP_PLAYBACK;
701 1.16 augustss }
702 1.1 is
703 1.41 jmcneill
704 1.41 jmcneill void
705 1.41 jmcneill aucc_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread)
706 1.41 jmcneill {
707 1.41 jmcneill struct aucc_softc *sc = opaque;
708 1.41 jmcneill
709 1.41 jmcneill *intr = &sc->sc_intr_lock;
710 1.41 jmcneill *thread = &sc->sc_lock;
711 1.41 jmcneill }
712 1.41 jmcneill
713 1.1 is int
714 1.29 aymeric aucc_query_devinfo(void *addr, register mixer_devinfo_t *dip)
715 1.1 is {
716 1.37 kent int i;
717 1.1 is
718 1.1 is switch(dip->index) {
719 1.1 is case AUCC_CHANNELS:
720 1.1 is dip->type = AUDIO_MIXER_SET;
721 1.1 is dip->mixer_class = AUCC_OUTPUT_CLASS;
722 1.1 is dip->prev = dip->next = AUDIO_MIXER_LAST;
723 1.43 christos #define setname(a) strlcpy(dip->label.name, (a), sizeof(dip->label.name))
724 1.43 christos setname(AudioNspeaker);
725 1.37 kent for (i = 0; i < 16; i++) {
726 1.43 christos snprintf(dip->un.s.member[i].label.name,
727 1.43 christos sizeof(dip->un.s.member[i].label.name),
728 1.1 is "channelmask%d", i);
729 1.1 is dip->un.s.member[i].mask = i;
730 1.1 is }
731 1.1 is dip->un.s.num_mem = 16;
732 1.1 is break;
733 1.1 is
734 1.1 is case AUCC_VOLUME:
735 1.1 is dip->type = AUDIO_MIXER_VALUE;
736 1.1 is dip->mixer_class = AUCC_OUTPUT_CLASS;
737 1.1 is dip->prev = dip->next = AUDIO_MIXER_LAST;
738 1.43 christos setname(AudioNmaster);
739 1.1 is dip->un.v.num_channels = 4;
740 1.1 is strcpy(dip->un.v.units.name, AudioNvolume);
741 1.1 is break;
742 1.1 is
743 1.1 is case AUCC_OUTPUT_CLASS:
744 1.1 is dip->type = AUDIO_MIXER_CLASS;
745 1.1 is dip->mixer_class = AUCC_OUTPUT_CLASS;
746 1.1 is dip->next = dip->prev = AUDIO_MIXER_LAST;
747 1.43 christos setname(AudioCoutputs);
748 1.1 is break;
749 1.20 augustss
750 1.1 is default:
751 1.1 is return ENXIO;
752 1.1 is }
753 1.1 is
754 1.1 is DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
755 1.1 is
756 1.37 kent return 0;
757 1.1 is }
758 1.1 is
759 1.1 is /* audio int handler */
760 1.1 is void
761 1.1 is aucc_inthdl(int ch)
762 1.1 is {
763 1.37 kent int i;
764 1.37 kent int mask;
765 1.1 is
766 1.41 jmcneill mutex_spin_enter(&aucc->sc_intr_lock);
767 1.37 kent mask = aucc->sc_channel[ch].nd_mask;
768 1.37 kent /*
769 1.37 kent * for all channels in this maskgroup:
770 1.37 kent * disable DMA, int
771 1.37 kent * mark idle
772 1.37 kent */
773 1.37 kent DPRINTF(("inthandler called, channel %d, mask 0x%x\n", ch, mask));
774 1.1 is
775 1.37 kent custom.intreq = mask << INTB_AUD0; /* clear request */
776 1.24 is /*
777 1.24 is * XXX: maybe we can leave ints and/or DMA on,
778 1.24 is * if another sample has to be played?
779 1.24 is */
780 1.37 kent custom.intena = mask << INTB_AUD0;
781 1.1 is /*
782 1.29 aymeric * XXX custom.dmacon=mask; NO!!!
783 1.29 aymeric */
784 1.37 kent for (i = 0; i < 4; i++) {
785 1.37 kent if (masks2[i] && mask) {
786 1.1 is DPRINTF(("marking channel %d idle\n",i));
787 1.37 kent aucc->sc_channel[i].nd_busy = 0;
788 1.37 kent aucc->sc_channel[i].nd_mask = 0;
789 1.37 kent channel[i].isaudio = channel[i].play_count = 0;
790 1.1 is }
791 1.1 is }
792 1.1 is
793 1.1 is /* call handler */
794 1.1 is if (aucc->sc_channel[ch].nd_intr) {
795 1.1 is DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
796 1.24 is (*(aucc->sc_channel[ch].nd_intr))
797 1.24 is (aucc->sc_channel[ch].nd_intrdata);
798 1.37 kent } else
799 1.24 is DPRINTF(("zero int handler\n"));
800 1.41 jmcneill mutex_spin_exit(&aucc->sc_intr_lock);
801 1.1 is DPRINTF(("ints done\n"));
802 1.1 is }
803 1.1 is
804 1.1 is /* transform frequency to period, adjust bounds */
805 1.1 is static u_int
806 1.29 aymeric freqtoper(u_int freq)
807 1.29 aymeric {
808 1.37 kent u_int per;
809 1.29 aymeric
810 1.37 kent per = eclockfreq * 5 / freq;
811 1.37 kent if (per < 124)
812 1.37 kent per = 124; /* must have at least 124 ticks between samples */
813 1.1 is
814 1.1 is return per;
815 1.1 is }
816 1.1 is
817 1.1 is /* transform period to frequency */
818 1.1 is static u_int
819 1.29 aymeric pertofreq(u_int per)
820 1.29 aymeric {
821 1.24 is
822 1.37 kent return eclockfreq * 5 / per;
823 1.24 is }
824 1.24 is
825 1.1 is
826 1.24 is /* 14bit output */
827 1.24 is static void
828 1.29 aymeric aucc_decode_slinear16_1ch(u_char **dmap, u_char *p, int i)
829 1.24 is {
830 1.37 kent u_char *ch0;
831 1.37 kent u_char *ch3;
832 1.24 is
833 1.37 kent ch0 = dmap[0];
834 1.37 kent ch3 = dmap[1]; /* XXX should be 3 */
835 1.24 is while (i--) {
836 1.24 is *ch0++ = *p++;
837 1.24 is *ch3++ = *p++ >> 2;
838 1.24 is }
839 1.24 is }
840 1.1 is
841 1.24 is /* 14bit stereo output */
842 1.24 is static void
843 1.29 aymeric aucc_decode_slinear16_2ch(u_char **dmap, u_char *p, int i)
844 1.24 is {
845 1.37 kent u_char *ch0;
846 1.37 kent u_char *ch1;
847 1.37 kent u_char *ch2;
848 1.37 kent u_char *ch3;
849 1.37 kent
850 1.37 kent ch0 = dmap[0];
851 1.37 kent ch1 = dmap[1];
852 1.37 kent ch2 = dmap[2];
853 1.37 kent ch3 = dmap[3];
854 1.24 is while (i--) {
855 1.24 is *ch0++ = *p++;
856 1.24 is *ch3++ = *p++ >> 2;
857 1.24 is *ch1++ = *p++;
858 1.24 is *ch2++ = *p++ >> 2;
859 1.24 is }
860 1.24 is }
861 1.24 is
862 1.24 is static void
863 1.29 aymeric aucc_decode_slinear16_3ch(u_char **dmap, u_char *p, int i)
864 1.24 is {
865 1.37 kent u_char *ch0;
866 1.37 kent u_char *ch1;
867 1.37 kent u_char *ch2;
868 1.37 kent
869 1.37 kent ch0 = dmap[0];
870 1.37 kent ch1 = dmap[1];
871 1.37 kent ch2 = dmap[2];
872 1.24 is while (i--) {
873 1.24 is *ch0++ = *p++; p++;
874 1.24 is *ch1++ = *p++; p++;
875 1.24 is *ch2++ = *p++; p++;
876 1.24 is }
877 1.24 is }
878 1.24 is
879 1.24 is static void
880 1.29 aymeric aucc_decode_slinear16_4ch(u_char **dmap, u_char *p, int i)
881 1.1 is {
882 1.37 kent u_char *ch0;
883 1.37 kent u_char *ch1;
884 1.37 kent u_char *ch2;
885 1.37 kent u_char *ch3;
886 1.37 kent
887 1.37 kent ch0 = dmap[0];
888 1.37 kent ch1 = dmap[1];
889 1.37 kent ch2 = dmap[2];
890 1.37 kent ch3 = dmap[3];
891 1.24 is while (i--) {
892 1.24 is *ch0++ = *p++; p++;
893 1.24 is *ch1++ = *p++; p++;
894 1.24 is *ch2++ = *p++; p++;
895 1.24 is *ch3++ = *p++; p++;
896 1.24 is }
897 1.24 is }
898 1.8 is
899 1.1 is #endif /* NAUCC > 0 */
900