aucc.c revision 1.14 1 /* $NetBSD: aucc.c,v 1.14 1997/07/28 10:04:35 augustss Exp $ */
2 #undef AUDIO_DEBUG
3 /*
4 * Copyright (c) 1997 Stephan Thesing
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Stephan Thesing.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include "aucc.h"
34 #if NAUCC > 0
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/errno.h>
39 #include <sys/ioctl.h>
40 #include <sys/device.h>
41 #include <sys/proc.h>
42 #include <machine/cpu.h>
43
44 #include <sys/audioio.h>
45 #include <dev/audio_if.h>
46 #include <amiga/amiga/cc.h>
47 #include <amiga/amiga/custom.h>
48 #include <amiga/amiga/device.h>
49 #include <amiga/dev/auccvar.h>
50
51
52 #ifdef LEV6_DEFER
53 #define AUCC_MAXINT 3
54 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2)
55 #else
56 #define AUCC_MAXINT 4
57 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3)
58 #endif
59 /* this unconditionally; we may use AUD3 as slave channel with LEV6_DEFER */
60 #define AUCC_ALLDMAF (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3)
61
62 #ifdef AUDIO_DEBUG
63 /*extern printf __P((const char *,...));*/
64 int auccdebug = 1;
65 #define DPRINTF(x) if (auccdebug) printf x
66 #else
67 #define DPRINTF(x)
68 #endif
69
70 #ifdef splaudio
71 #undef splaudio
72 #endif
73
74 #define splaudio() spl4();
75
76 /* clock frequency.. */
77 extern int eclockfreq;
78
79
80 /* hw audio ch */
81 extern struct audio_channel channel[4];
82
83
84 /*
85 * Software state.
86 */
87 struct aucc_softc {
88 struct device sc_dev; /* base device */
89
90 int sc_open; /* single use device */
91 aucc_data_t sc_channel[4]; /* per channel freq, ... */
92 u_int sc_encoding; /* encoding AUDIO_ENCODING_.*/
93 int sc_channels; /* # of channels used */
94
95 int sc_intrcnt; /* interrupt count */
96 int sc_channelmask; /* which channels are used ? */
97 };
98
99 /* interrupt interfaces */
100 void aucc_inthdl __P((int));
101
102 /* forward declarations */
103 static int init_aucc __P((struct aucc_softc *));
104 static u_int freqtoper __P((u_int));
105 static u_int pertofreq __P((u_int));
106
107 /* autoconfiguration driver */
108 void auccattach __P((struct device *, struct device *, void *));
109 int auccmatch __P((struct device *, struct cfdata *, void *));
110
111 struct cfattach aucc_ca = {
112 sizeof(struct aucc_softc),
113 auccmatch,
114 auccattach
115 };
116
117 struct cfdriver aucc_cd = {
118 NULL, "aucc", DV_DULL, NULL, 0
119 };
120
121 struct audio_device aucc_device = {
122 "Amiga-audio",
123 "x",
124 "aucc"
125 };
126
127
128 struct aucc_softc *aucc=NULL;
129
130
131 unsigned char ulaw_to_lin[] = {
132 0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
133 0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
134 0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf,
135 0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf,
136 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
137 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
138 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4,
139 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8,
140 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
141 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
142 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd,
143 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe,
144 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
145 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
146 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
147 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
148 0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61,
149 0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, 0x45, 0x41,
150 0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30,
151 0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20,
152 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17,
153 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f,
154 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b,
155 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07,
156 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05,
157 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
158 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02,
159 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
160 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 };
165
166 /*
167 * Define our interface to the higher level audio driver.
168 */
169 int aucc_open __P((dev_t, int));
170 void aucc_close __P((void *));
171 int aucc_set_out_sr __P((void *, u_long));
172 int aucc_query_encoding __P((void *, struct audio_encoding *));
173 int aucc_round_blocksize __P((void *, int));
174 int aucc_set_out_port __P((void *, int));
175 int aucc_get_out_port __P((void *));
176 int aucc_set_in_port __P((void *, int));
177 int aucc_get_in_port __P((void *));
178 int aucc_commit_settings __P((void *));
179 int aucc_start_output __P((void *, void *, int, void (*)(void *),
180 void *));
181 int aucc_start_input __P((void *, void *, int, void (*)(void *),
182 void *));
183 int aucc_halt_output __P((void *));
184 int aucc_halt_input __P((void *));
185 int aucc_cont_output __P((void *));
186 int aucc_cont_input __P((void *));
187 int aucc_getdev __P((void *, struct audio_device *));
188 int aucc_set_port __P((void *, mixer_ctrl_t *));
189 int aucc_get_port __P((void *, mixer_ctrl_t *));
190 int aucc_query_devinfo __P((void *, mixer_devinfo_t *));
191 void aucc_encode __P((int, int, int, u_char *, u_short **));
192 int aucc_set_params __P((void *, int, struct audio_params *,
193 struct audio_params *));
194
195 struct audio_hw_if sa_hw_if = {
196 aucc_open,
197 aucc_close,
198 NULL,
199 aucc_query_encoding,
200 aucc_set_params,
201 aucc_round_blocksize,
202 aucc_set_out_port,
203 aucc_get_out_port,
204 aucc_set_in_port,
205 aucc_get_in_port,
206 aucc_commit_settings,
207 NULL,
208 NULL,
209 aucc_start_output,
210 aucc_start_input,
211 aucc_halt_output,
212 aucc_halt_input,
213 aucc_cont_output,
214 aucc_cont_input,
215 NULL,
216 aucc_getdev,
217 NULL,
218 aucc_set_port,
219 aucc_get_port,
220 aucc_query_devinfo,
221 NULL,
222 NULL,
223 NULL,
224 0,
225 0
226 };
227
228 /* autoconfig routines */
229
230 int
231 auccmatch(pdp, cfp, aux)
232 struct device *pdp;
233 struct cfdata *cfp;
234 void *aux;
235 {
236 if (matchname((char *)aux, "aucc") &&
237 #ifdef DRACO
238 !is_draco() &&
239 #endif
240 (cfp->cf_unit == 0))
241 return 1;
242
243 return 0;
244 }
245
246 /*
247 * Audio chip found.
248 */
249 void
250 auccattach(parent, self, args)
251 struct device *parent, *self;
252 void *args;
253 {
254 register struct aucc_softc *sc = (struct aucc_softc *)self;
255 register int i;
256
257 printf("\n");
258
259 if((i=init_aucc(sc))) {
260 printf("audio: no chipmem\n");
261 return;
262 }
263
264 if (audio_hardware_attach(&sa_hw_if, sc) != 0)
265 printf("audio: could not attach to audio pseudo-device driver\n");
266 /* XXX: no way to return error, if init fails */
267 }
268
269
270 static int
271 init_aucc(sc)
272 struct aucc_softc *sc;
273 {
274 register int i, err=0;
275
276 /* init values per channel */
277 for (i=0;i<4;i++) {
278 sc->sc_channel[i].nd_freq=8000;
279 sc->sc_channel[i].nd_per=freqtoper(8000);
280 sc->sc_channel[i].nd_busy=0;
281 sc->sc_channel[i].nd_dma=alloc_chipmem(AUDIO_BUF_SIZE*2);
282 if (sc->sc_channel[i].nd_dma==NULL)
283 err=1;
284 sc->sc_channel[i].nd_dmalength=0;
285 sc->sc_channel[i].nd_volume=64;
286 sc->sc_channel[i].nd_intr=NULL;
287 sc->sc_channel[i].nd_intrdata=NULL;
288 sc->sc_channel[i].nd_doublebuf=0;
289 DPRINTF(("dma buffer for channel %d is %p\n", i,
290 sc->sc_channel[i].nd_dma));
291
292 }
293
294 if (err) {
295 for(i=0;i<4;i++)
296 if (sc->sc_channel[i].nd_dma)
297 free_chipmem(sc->sc_channel[i].nd_dma);
298 }
299
300 sc->sc_channels=1;
301 sc->sc_channelmask=0xf;
302
303 /* clear interrupts and dma: */
304 custom.intena = AUCC_ALLINTF;
305 custom.dmacon = AUCC_ALLDMAF;;
306
307 sc->sc_encoding=AUDIO_ENCODING_ULAW;
308
309 return err;
310
311 }
312
313 int
314 aucc_open(dev, flags)
315 dev_t dev;
316 int flags;
317 {
318 register struct aucc_softc *sc;
319 int unit = AUDIOUNIT(dev);
320 register int i;
321
322 DPRINTF(("sa_open: unit %d\n",unit));
323
324 if (unit >= aucc_cd.cd_ndevs)
325 return (ENODEV);
326 if ((sc = aucc_cd.cd_devs[unit]) == NULL)
327 return (ENXIO);
328 if (sc->sc_open)
329 return (EBUSY);
330 sc->sc_open = 1;
331 for (i=0;i<AUCC_MAXINT;i++) {
332 sc->sc_channel[i].nd_intr=NULL;
333 sc->sc_channel[i].nd_intrdata=NULL;
334 }
335 aucc=sc;
336 sc->sc_channelmask=0xf;
337
338 DPRINTF(("saopen: ok -> sc=0x%p\n",sc));
339
340 return (0);
341 }
342
343 void
344 aucc_close(addr)
345 void *addr;
346 {
347 register struct aucc_softc *sc = addr;
348
349 DPRINTF(("sa_close: sc=0x%p\n", sc));
350 /*
351 * halt i/o, clear open flag, and done.
352 */
353 aucc_halt_output(sc);
354 sc->sc_open = 0;
355
356 DPRINTF(("sa_close: closed.\n"));
357 }
358
359 int
360 aucc_set_out_sr(addr, sr)
361 void *addr;
362 u_long sr;
363 {
364 struct aucc_softc *sc=addr;
365 u_long per;
366 register int i;
367
368 per=freqtoper(sr);
369 if (per>0xffff)
370 return EINVAL;
371 sr=pertofreq(per);
372
373 for (i=0;i<4;i++) {
374 sc->sc_channel[i].nd_freq=sr;
375 sc->sc_channel[i].nd_per=per;
376 }
377
378 return(0);
379 }
380
381 int
382 aucc_query_encoding(addr, fp)
383 void *addr;
384 struct audio_encoding *fp;
385 {
386 switch (fp->index) {
387 case 0:
388 strcpy(fp->name, AudioElinear);
389 fp->encoding = AUDIO_ENCODING_SLINEAR;
390 fp->precision = 8;
391 fp->flags = 0;
392 break;
393 case 1:
394 strcpy(fp->name, AudioEmulaw);
395 fp->encoding = AUDIO_ENCODING_ULAW;
396 fp->precision = 8;
397 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
398 break;
399
400 case 2:
401 strcpy(fp->name, AudioEulinear);
402 fp->encoding = AUDIO_ENCODING_ULINEAR;
403 fp->precision = 8;
404 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
405 break;
406
407 default:
408 return(EINVAL);
409 /*NOTREACHED*/
410 }
411 return(0);
412 }
413
414 int
415 aucc_set_params(addr, mode, p, q)
416 void *addr;
417 int mode;
418 struct audio_params *p, *q;
419 {
420 struct aucc_softc *sc;
421
422 sc = addr;
423
424 /* if (mode == AUMODE_RECORD)
425 return 0 ENXIO*/;
426
427 #ifdef AUCCDEBUG
428 printf("aucc_set_params(mode %x, enc %d, bits %d, chn %d, sr %ld)\n",
429 mode, p->encoding, p->precision, p->channels, p->sample_rate);
430 #endif
431
432 switch (p->encoding) {
433 case AUDIO_ENCODING_ULAW:
434 case AUDIO_ENCODING_SLINEAR:
435 case AUDIO_ENCODING_SLINEAR_BE:
436 case AUDIO_ENCODING_SLINEAR_LE:
437 case AUDIO_ENCODING_ULINEAR_BE:
438 case AUDIO_ENCODING_ULINEAR_LE:
439 break;
440
441 default:
442 return EINVAL;
443 /* NOTREADCHED */
444 }
445
446 if (p->precision != 8)
447 return EINVAL;
448
449 if ((p->channels<1) || (p->channels>4))
450 return(EINVAL);
451
452 sc->sc_channels = p->channels;
453 sc->sc_encoding = p->encoding;
454
455 q->encoding = p->encoding;
456 q->precision = p->precision;
457 q->channels = p->channels;
458 q->sample_rate = p->sample_rate;
459
460 return aucc_set_out_sr(addr, p->sample_rate);
461 }
462
463 int
464 aucc_round_blocksize(addr, blk)
465 void *addr;
466 int blk;
467 {
468
469
470 return blk>AUDIO_BUF_SIZE?AUDIO_BUF_SIZE:blk; /* round up to even size */
471 }
472
473 int
474 aucc_set_out_port(addr, port) /* can set channels */
475 void *addr;
476 int port;
477 {
478 register struct aucc_softc *sc = addr;
479
480 /* port is mask for channels 0..3 */
481 if ((port<0)||(port>15))
482 return EINVAL;
483
484 sc->sc_channelmask=port;
485
486 return(0);
487 }
488
489 int
490 aucc_get_out_port(addr)
491 void *addr;
492 {
493 register struct aucc_softc *sc = addr;
494
495 return sc->sc_channelmask;
496 }
497
498 int
499 aucc_set_in_port(addr, port)
500 void *addr;
501 int port;
502 {
503 return(EINVAL); /* no input possible */
504
505 }
506
507 int
508 aucc_get_in_port(addr)
509 void *addr;
510 {
511 return(0);
512 }
513
514 int
515 aucc_commit_settings(addr)
516 void *addr;
517 {
518 register struct aucc_softc *sc = addr;
519 register int i;
520
521 DPRINTF(("sa_commit.\n"));
522
523 for (i=0;i<4;i++) {
524 custom.aud[i].vol=sc->sc_channel[i].nd_volume;
525 custom.aud[i].per=sc->sc_channel[i].nd_per;
526 }
527
528 DPRINTF(("commit done\n"));
529
530 return(0);
531 }
532
533 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
534 static int masks2[4] = {1,2,4,8};
535
536 int
537 aucc_start_output(addr, p, cc, intr, arg)
538 void *addr;
539 void *p;
540 int cc;
541 void (*intr) __P((void *));
542 void *arg;
543 {
544 struct aucc_softc *sc;
545 int mask;
546 int i,j,k;
547 u_short *dmap[4];
548 u_char *pp;
549
550
551 sc = addr;
552 mask = sc->sc_channelmask;
553
554 dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
555
556 DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
557
558 if (sc->sc_channels > 1)
559 mask &=masks[sc->sc_channels-1];
560 /* we use first sc_channels channels */
561 if (mask==0) /* active and used channels are disjoint */
562 return EINVAL;
563
564 for (i=0;i<4;i++) { /* channels available ? */
565 if ((masks2[i]&mask)&&(sc->sc_channel[i].nd_busy))
566 return EBUSY; /* channel is busy */
567 if (channel[i].isaudio==-1)
568 return EBUSY; /* system uses them */
569 }
570
571 /* enable interrupt on 1st channel */
572 for (i=j=0;i<AUCC_MAXINT;i++) {
573 if (masks2[i]&mask) {
574 DPRINTF(("first channel is %d\n",i));
575 j=i;
576 sc->sc_channel[i].nd_intr=intr;
577 sc->sc_channel[i].nd_intrdata=arg;
578 break;
579 }
580 }
581
582 DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
583 dmap[2], dmap[3], mask));
584
585 /* disable ints, dma for channels, until all parameters set */
586 /* XXX dont disable DMA! custom.dmacon=mask;*/
587 custom.intreq=mask<<INTB_AUD0;
588 custom.intena=mask<<INTB_AUD0;
589
590 /* copy data to dma buffer */
591
592
593 pp=(u_char *)p;
594
595 if (sc->sc_channels == 1) {
596 dmap[0] =
597 dmap[1] =
598 dmap[2] =
599 dmap[3] = sc->sc_channel[j].nd_dma;
600 } else {
601 for (k=0; k<4; k++) {
602 if (masks2[k+j]&mask)
603 dmap[k]=sc->sc_channel[k+j].nd_dma;
604 }
605 }
606
607 sc->sc_channel[j].nd_doublebuf ^= 1;
608 if (sc->sc_channel[j].nd_doublebuf) {
609 dmap[0] += AUDIO_BUF_SIZE/sizeof(u_short);
610 dmap[1] += AUDIO_BUF_SIZE/sizeof(u_short);
611 dmap[2] += AUDIO_BUF_SIZE/sizeof(u_short);
612 dmap[3] += AUDIO_BUF_SIZE/sizeof(u_short);
613 }
614
615 aucc_encode(sc->sc_encoding, sc->sc_channels, cc, pp, dmap);
616
617 /* dma buffers: we use same buffer 4 all channels */
618 /* write dma location and length */
619 for (i=k=0; i<4; i++) {
620 if (masks2[i] & mask) {
621 DPRINTF(("turning channel %d on\n",i));
622 /* sc->sc_channel[i].nd_busy=1;*/
623 channel[i].isaudio=1;
624 channel[i].play_count=1;
625 channel[i].handler=NULL;
626 custom.aud[i].per=sc->sc_channel[i].nd_per;
627 custom.aud[i].vol=sc->sc_channel[i].nd_volume;
628 custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
629 custom.aud[i].len=cc/(sc->sc_channels*2);
630 sc->sc_channel[i].nd_mask=mask;
631 DPRINTF(("per is %d, vol is %d, len is %d\n",\
632 sc->sc_channel[i].nd_per,
633 sc->sc_channel[i].nd_volume, cc>>1));
634
635 }
636 }
637
638 channel[j].handler=aucc_inthdl;
639
640 /* enable ints */
641 custom.intena=INTF_SETCLR|INTF_INTEN| (masks2[j]<<INTB_AUD0);
642
643 DPRINTF(("enabled ints: 0x%x\n",(masks2[j]<<INTB_AUD0)));
644
645 /* enable dma */
646 custom.dmacon=DMAF_SETCLR|DMAF_MASTER|mask;
647
648 DPRINTF(("enabled dma, mask=0x%x\n",mask));
649
650 return(0);
651 }
652
653 /* ARGSUSED */
654 int
655 aucc_start_input(addr, p, cc, intr, arg)
656 void *addr;
657 void *p;
658 int cc;
659 void (*intr) __P((void *));
660 void *arg;
661 {
662
663 return ENXIO; /* no input */
664 }
665
666 int
667 aucc_halt_output(addr)
668 void *addr;
669 {
670 register struct aucc_softc *sc = addr;
671 register int i;
672
673 /* XXX only halt, if input is also halted ?? */
674 /* stop dma, etc */
675 custom.intena = AUCC_ALLINTF;
676 custom.dmacon = AUCC_ALLDMAF;
677 /* mark every busy unit idle */
678 for (i=0;i<4;i++) {
679 sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0;
680 channel[i].isaudio=0;
681 channel[i].play_count=0;
682 }
683
684 return(0);
685 }
686
687 int
688 aucc_halt_input(addr)
689 void *addr;
690 {
691 /* no input */
692
693 return ENXIO;
694 }
695
696 int
697 aucc_cont_output(addr)
698 void *addr;
699 {
700 DPRINTF(("aucc_cont_output: never called, what should it do?!\n"));
701 /* reenable DMA XXX */
702 return ENXIO;
703 }
704
705 int
706 aucc_cont_input(addr)
707 void *addr;
708 {
709 DPRINTF(("aucc_cont_input: never called, what should it do?!\n"));
710 return(0);
711 }
712
713 int
714 aucc_getdev(addr, retp)
715 void *addr;
716 struct audio_device *retp;
717 {
718 *retp = aucc_device;
719 return 0;
720 }
721
722 int
723 aucc_set_port(addr, cp)
724 void *addr;
725 mixer_ctrl_t *cp;
726 {
727 register struct aucc_softc *sc = addr;
728 register int i,j;
729
730 DPRINTF(("aucc_set_port: port=%d", cp->dev));
731
732 switch (cp->type) {
733 case AUDIO_MIXER_SET:
734 if (cp->dev!=AUCC_CHANNELS)
735 return EINVAL;
736 i=cp->un.mask;
737 if ((i<1)||(i>15))
738 return EINVAL;
739 sc->sc_channelmask=i;
740 break;
741
742 case AUDIO_MIXER_VALUE:
743 i=cp->un.value.num_channels;
744 if ((i<1)||(i>4))
745 return EINVAL;
746
747 #ifdef __XXXwhatsthat
748 if (cp->dev!=AUCC_VOLUME)
749 return EINVAL;
750 #endif
751
752 /* set volume for channel 0..i-1 */
753 if (i>1)
754 for (j=0;j<i;j++)
755 sc->sc_channel[j].nd_volume =
756 cp->un.value.level[j]>>2;
757 else if (sc->sc_channels > 1)
758 for (j=0; j<sc->sc_channels; j++)
759 sc->sc_channel[j].nd_volume =
760 cp->un.value.level[0]>>2;
761 else
762 for (j=0; j<4; j++)
763 sc->sc_channel[j].nd_volume =
764 cp->un.value.level[0]>>2;
765 break;
766
767 default:
768 return EINVAL;
769 break;
770 }
771 return 0;
772 }
773
774
775 int
776 aucc_get_port(addr, cp)
777 void *addr;
778 mixer_ctrl_t *cp;
779 {
780 register struct aucc_softc *sc = addr;
781 register int i,j;
782
783 DPRINTF(("aucc_get_port: port=%d", cp->dev));
784
785 switch (cp->type) {
786 case AUDIO_MIXER_SET:
787 if (cp->dev!=AUCC_CHANNELS)
788 return EINVAL;
789 cp->un.mask=sc->sc_channelmask;
790 break;
791
792 case AUDIO_MIXER_VALUE:
793 i = cp->un.value.num_channels;
794 if ((i<1)||(i>4))
795 return EINVAL;
796
797 for (j=0;j<i;j++)
798 cp->un.value.level[j] =
799 (sc->sc_channel[j].nd_volume<<2) +
800 (sc->sc_channel[j].nd_volume>>4);
801 break;
802
803 default:
804 return EINVAL;
805 }
806 return 0;
807 }
808
809
810 int
811 aucc_query_devinfo(addr, dip)
812 void *addr;
813 register mixer_devinfo_t *dip;
814 {
815 register int i;
816
817 switch(dip->index) {
818 case AUCC_CHANNELS:
819 dip->type = AUDIO_MIXER_SET;
820 dip->mixer_class = AUCC_OUTPUT_CLASS;
821 dip->prev = dip->next = AUDIO_MIXER_LAST;
822 strcpy(dip->label.name, AudioNspeaker);
823 for (i=0;i<16;i++) {
824 sprintf(dip->un.s.member[i].label.name,
825 "channelmask%d", i);
826 dip->un.s.member[i].mask = i;
827 }
828 dip->un.s.num_mem = 16;
829 break;
830
831 case AUCC_VOLUME:
832 dip->type = AUDIO_MIXER_VALUE;
833 dip->mixer_class = AUCC_OUTPUT_CLASS;
834 dip->prev = dip->next = AUDIO_MIXER_LAST;
835 strcpy(dip->label.name, AudioNspeaker);
836 dip->un.v.num_channels = 4;
837 strcpy(dip->un.v.units.name, AudioNvolume);
838 break;
839
840 case AUCC_OUTPUT_CLASS:
841 dip->type = AUDIO_MIXER_CLASS;
842 dip->mixer_class = AUCC_OUTPUT_CLASS;
843 dip->next = dip->prev = AUDIO_MIXER_LAST;
844 strcpy(dip->label.name, AudioCOutputs);
845 break;
846 default:
847 return ENXIO;
848 /*NOTREACHED*/
849 }
850
851 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
852
853 return(0);
854 }
855
856
857 /* audio int handler */
858 void
859 aucc_inthdl(int ch)
860 {
861 register int i;
862 register int mask=aucc->sc_channel[ch].nd_mask;
863
864 /* for all channels in this maskgroup:
865 disable dma, int
866 mark idle */
867 DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask));
868
869 custom.intreq=mask<<INTB_AUD0; /* clear request */
870 /* XXX: maybe we can leave ints and/or DMA on, if another sample has to be played?*/
871 custom.intena=mask<<INTB_AUD0;
872 /*
873 * XXX custom.dmacon=mask; NO!!!
874 */
875 for (i=0;i<4;i++) {
876 if (masks2[i]&&mask) {
877 DPRINTF(("marking channel %d idle\n",i));
878 aucc->sc_channel[i].nd_busy=0;
879 aucc->sc_channel[i].nd_mask=0;
880 channel[i].isaudio=channel[i].play_count=0;
881 }
882 }
883
884 /* call handler */
885 if (aucc->sc_channel[ch].nd_intr) {
886 DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
887 (*(aucc->sc_channel[ch].nd_intr))(aucc->sc_channel[ch].nd_intrdata);
888 }
889 else DPRINTF(("zero int handler\n"));
890 DPRINTF(("ints done\n"));
891 }
892
893
894
895
896 /* transform frequency to period, adjust bounds */
897 static u_int
898 freqtoper(u_int freq)
899 {
900 u_int per=eclockfreq*5/freq;
901
902 if (per<124)
903 per=124; /* must have at least 124 ticks between samples */
904
905 return per;
906 }
907
908 /* transform period to frequency */
909 static u_int
910 pertofreq(u_int per)
911 {
912 u_int freq=eclockfreq*5/per;
913
914
915 return freq;
916 }
917
918
919
920 void
921 aucc_encode(enc, channels, i, p, dmap)
922 int enc, channels, i;
923 u_char *p;
924 u_short **dmap;
925 {
926 char *q, *r, *s, *t;
927 int off;
928 u_char *tab;
929
930 #ifdef AUCCDEBUG
931 static int debctl = 6;
932 #endif
933
934 off = 0;
935 tab = NULL;
936
937 #ifdef AUCCDEBUG
938 if (--debctl >= 0)
939 printf("Enc: enc %d, chan %d, dmap %p %p %p %p\n",
940 enc, channels, dmap[0], dmap[1], dmap[2], dmap[3]);
941 #endif
942
943 switch (enc) {
944 case AUDIO_ENCODING_ULAW:
945 tab=ulaw_to_lin;
946 break;
947 case AUDIO_ENCODING_ULINEAR_BE:
948 case AUDIO_ENCODING_ULINEAR_LE:
949 off=-128;
950 break;
951 case AUDIO_ENCODING_SLINEAR_BE:
952 case AUDIO_ENCODING_SLINEAR_LE:
953 break;
954 default:
955 return;
956 }
957
958 q = (char *)dmap[0];
959 r = (char *)dmap[1];
960 s = (char *)dmap[2];
961 t = (char *)dmap[3];
962
963 if (tab)
964 while (i) {
965 switch (channels) {
966 case 4: *t++ = tab[*p++];
967 case 3: *s++ = tab[*p++];
968 case 2: *r++ = tab[*p++];
969 case 1: *q++ = tab[*p++];
970 }
971 i -= channels;
972 }
973 else
974 while (i) {
975 switch (channels) {
976 case 4: *t++ = *p++ + off;
977 case 3: *s++ = *p++ + off;
978 case 2: *r++ = *p++ + off;
979 case 1: *q++ = *p++ + off;
980 }
981 i -= channels;
982 }
983
984 }
985
986 #endif /* NAUCC > 0 */
987