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