aucc.c revision 1.16 1 /* $NetBSD: aucc.c,v 1.16 1997/07/31 22:33:08 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((void *, 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 int aucc_get_props __P((void *));
195
196 struct audio_hw_if sa_hw_if = {
197 aucc_open,
198 aucc_close,
199 NULL,
200 aucc_query_encoding,
201 aucc_set_params,
202 aucc_round_blocksize,
203 aucc_set_out_port,
204 aucc_get_out_port,
205 aucc_set_in_port,
206 aucc_get_in_port,
207 aucc_commit_settings,
208 NULL,
209 NULL,
210 aucc_start_output,
211 aucc_start_input,
212 aucc_halt_output,
213 aucc_halt_input,
214 aucc_cont_output,
215 aucc_cont_input,
216 NULL,
217 aucc_getdev,
218 NULL,
219 aucc_set_port,
220 aucc_get_port,
221 aucc_query_devinfo,
222 NULL,
223 NULL,
224 NULL,
225 NULL,
226 aucc_get_props,
227 };
228
229 /* autoconfig routines */
230
231 int
232 auccmatch(pdp, cfp, aux)
233 struct device *pdp;
234 struct cfdata *cfp;
235 void *aux;
236 {
237 if (matchname((char *)aux, "aucc") &&
238 #ifdef DRACO
239 !is_draco() &&
240 #endif
241 (cfp->cf_unit == 0))
242 return 1;
243
244 return 0;
245 }
246
247 /*
248 * Audio chip found.
249 */
250 void
251 auccattach(parent, self, args)
252 struct device *parent, *self;
253 void *args;
254 {
255 register struct aucc_softc *sc = (struct aucc_softc *)self;
256 register int i;
257
258 printf("\n");
259
260 if((i=init_aucc(sc))) {
261 printf("audio: no chipmem\n");
262 return;
263 }
264
265 if (audio_hardware_attach(&sa_hw_if, sc, &sc->sc_dev) != 0)
266 printf("audio: could not attach to audio pseudo-device driver\n");
267 /* XXX: no way to return error, if init fails */
268 }
269
270
271 static int
272 init_aucc(sc)
273 struct aucc_softc *sc;
274 {
275 register int i, err=0;
276
277 /* init values per channel */
278 for (i=0;i<4;i++) {
279 sc->sc_channel[i].nd_freq=8000;
280 sc->sc_channel[i].nd_per=freqtoper(8000);
281 sc->sc_channel[i].nd_busy=0;
282 sc->sc_channel[i].nd_dma=alloc_chipmem(AUDIO_BUF_SIZE*2);
283 if (sc->sc_channel[i].nd_dma==NULL)
284 err=1;
285 sc->sc_channel[i].nd_dmalength=0;
286 sc->sc_channel[i].nd_volume=64;
287 sc->sc_channel[i].nd_intr=NULL;
288 sc->sc_channel[i].nd_intrdata=NULL;
289 sc->sc_channel[i].nd_doublebuf=0;
290 DPRINTF(("dma buffer for channel %d is %p\n", i,
291 sc->sc_channel[i].nd_dma));
292
293 }
294
295 if (err) {
296 for(i=0;i<4;i++)
297 if (sc->sc_channel[i].nd_dma)
298 free_chipmem(sc->sc_channel[i].nd_dma);
299 }
300
301 sc->sc_channels=1;
302 sc->sc_channelmask=0xf;
303
304 /* clear interrupts and dma: */
305 custom.intena = AUCC_ALLINTF;
306 custom.dmacon = AUCC_ALLDMAF;;
307
308 sc->sc_encoding=AUDIO_ENCODING_ULAW;
309
310 return err;
311
312 }
313
314 int
315 aucc_open(addr, flags)
316 void *addr;
317 int flags;
318 {
319 struct aucc_softc *sc = addr;
320 int i;
321
322 DPRINTF(("sa_open: unit %p\n",sc));
323
324 if (sc->sc_open)
325 return (EBUSY);
326 sc->sc_open = 1;
327 for (i=0;i<AUCC_MAXINT;i++) {
328 sc->sc_channel[i].nd_intr=NULL;
329 sc->sc_channel[i].nd_intrdata=NULL;
330 }
331 aucc=sc;
332 sc->sc_channelmask=0xf;
333
334 DPRINTF(("saopen: ok -> sc=0x%p\n",sc));
335
336 return (0);
337 }
338
339 void
340 aucc_close(addr)
341 void *addr;
342 {
343 register struct aucc_softc *sc = addr;
344
345 DPRINTF(("sa_close: sc=0x%p\n", sc));
346 /*
347 * halt i/o, clear open flag, and done.
348 */
349 aucc_halt_output(sc);
350 sc->sc_open = 0;
351
352 DPRINTF(("sa_close: closed.\n"));
353 }
354
355 int
356 aucc_set_out_sr(addr, sr)
357 void *addr;
358 u_long sr;
359 {
360 struct aucc_softc *sc=addr;
361 u_long per;
362 register int i;
363
364 per=freqtoper(sr);
365 if (per>0xffff)
366 return EINVAL;
367 sr=pertofreq(per);
368
369 for (i=0;i<4;i++) {
370 sc->sc_channel[i].nd_freq=sr;
371 sc->sc_channel[i].nd_per=per;
372 }
373
374 return(0);
375 }
376
377 int
378 aucc_query_encoding(addr, fp)
379 void *addr;
380 struct audio_encoding *fp;
381 {
382 switch (fp->index) {
383 case 0:
384 strcpy(fp->name, AudioElinear);
385 fp->encoding = AUDIO_ENCODING_SLINEAR;
386 fp->precision = 8;
387 fp->flags = 0;
388 break;
389 case 1:
390 strcpy(fp->name, AudioEmulaw);
391 fp->encoding = AUDIO_ENCODING_ULAW;
392 fp->precision = 8;
393 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
394 break;
395
396 case 2:
397 strcpy(fp->name, AudioEulinear);
398 fp->encoding = AUDIO_ENCODING_ULINEAR;
399 fp->precision = 8;
400 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
401 break;
402
403 default:
404 return(EINVAL);
405 /*NOTREACHED*/
406 }
407 return(0);
408 }
409
410 int
411 aucc_set_params(addr, mode, p, q)
412 void *addr;
413 int mode;
414 struct audio_params *p, *q;
415 {
416 struct aucc_softc *sc;
417
418 sc = addr;
419
420 /* if (mode == AUMODE_RECORD)
421 return 0 ENXIO*/;
422
423 #ifdef AUCCDEBUG
424 printf("aucc_set_params(mode %x, enc %d, bits %d, chn %d, sr %ld)\n",
425 mode, p->encoding, p->precision, p->channels, p->sample_rate);
426 #endif
427
428 switch (p->encoding) {
429 case AUDIO_ENCODING_ULAW:
430 case AUDIO_ENCODING_SLINEAR:
431 case AUDIO_ENCODING_SLINEAR_BE:
432 case AUDIO_ENCODING_SLINEAR_LE:
433 case AUDIO_ENCODING_ULINEAR_BE:
434 case AUDIO_ENCODING_ULINEAR_LE:
435 break;
436
437 default:
438 return EINVAL;
439 /* NOTREADCHED */
440 }
441
442 if (p->precision != 8)
443 return EINVAL;
444
445 if ((p->channels<1) || (p->channels>4))
446 return(EINVAL);
447
448 sc->sc_channels = p->channels;
449 sc->sc_encoding = p->encoding;
450
451 q->encoding = p->encoding;
452 q->precision = p->precision;
453 q->channels = p->channels;
454 q->sample_rate = p->sample_rate;
455
456 return aucc_set_out_sr(addr, p->sample_rate);
457 }
458
459 int
460 aucc_round_blocksize(addr, blk)
461 void *addr;
462 int blk;
463 {
464
465
466 return blk>AUDIO_BUF_SIZE?AUDIO_BUF_SIZE:blk; /* round up to even size */
467 }
468
469 int
470 aucc_set_out_port(addr, port) /* can set channels */
471 void *addr;
472 int port;
473 {
474 register struct aucc_softc *sc = addr;
475
476 /* port is mask for channels 0..3 */
477 if ((port<0)||(port>15))
478 return EINVAL;
479
480 sc->sc_channelmask=port;
481
482 return(0);
483 }
484
485 int
486 aucc_get_out_port(addr)
487 void *addr;
488 {
489 register struct aucc_softc *sc = addr;
490
491 return sc->sc_channelmask;
492 }
493
494 int
495 aucc_set_in_port(addr, port)
496 void *addr;
497 int port;
498 {
499 return(EINVAL); /* no input possible */
500
501 }
502
503 int
504 aucc_get_in_port(addr)
505 void *addr;
506 {
507 return(0);
508 }
509
510 int
511 aucc_commit_settings(addr)
512 void *addr;
513 {
514 register struct aucc_softc *sc = addr;
515 register int i;
516
517 DPRINTF(("sa_commit.\n"));
518
519 for (i=0;i<4;i++) {
520 custom.aud[i].vol=sc->sc_channel[i].nd_volume;
521 custom.aud[i].per=sc->sc_channel[i].nd_per;
522 }
523
524 DPRINTF(("commit done\n"));
525
526 return(0);
527 }
528
529 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
530 static int masks2[4] = {1,2,4,8};
531
532 int
533 aucc_start_output(addr, p, cc, intr, arg)
534 void *addr;
535 void *p;
536 int cc;
537 void (*intr) __P((void *));
538 void *arg;
539 {
540 struct aucc_softc *sc;
541 int mask;
542 int i,j,k;
543 u_short *dmap[4];
544 u_char *pp;
545
546
547 sc = addr;
548 mask = sc->sc_channelmask;
549
550 dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
551
552 DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
553
554 if (sc->sc_channels > 1)
555 mask &=masks[sc->sc_channels-1];
556 /* we use first sc_channels channels */
557 if (mask==0) /* active and used channels are disjoint */
558 return EINVAL;
559
560 for (i=0;i<4;i++) { /* channels available ? */
561 if ((masks2[i]&mask)&&(sc->sc_channel[i].nd_busy))
562 return EBUSY; /* channel is busy */
563 if (channel[i].isaudio==-1)
564 return EBUSY; /* system uses them */
565 }
566
567 /* enable interrupt on 1st channel */
568 for (i=j=0;i<AUCC_MAXINT;i++) {
569 if (masks2[i]&mask) {
570 DPRINTF(("first channel is %d\n",i));
571 j=i;
572 sc->sc_channel[i].nd_intr=intr;
573 sc->sc_channel[i].nd_intrdata=arg;
574 break;
575 }
576 }
577
578 DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
579 dmap[2], dmap[3], mask));
580
581 /* disable ints, dma for channels, until all parameters set */
582 /* XXX dont disable DMA! custom.dmacon=mask;*/
583 custom.intreq=mask<<INTB_AUD0;
584 custom.intena=mask<<INTB_AUD0;
585
586 /* copy data to dma buffer */
587
588
589 pp=(u_char *)p;
590
591 if (sc->sc_channels == 1) {
592 dmap[0] =
593 dmap[1] =
594 dmap[2] =
595 dmap[3] = sc->sc_channel[j].nd_dma;
596 } else {
597 for (k=0; k<4; k++) {
598 if (masks2[k+j]&mask)
599 dmap[k]=sc->sc_channel[k+j].nd_dma;
600 }
601 }
602
603 sc->sc_channel[j].nd_doublebuf ^= 1;
604 if (sc->sc_channel[j].nd_doublebuf) {
605 dmap[0] += AUDIO_BUF_SIZE/sizeof(u_short);
606 dmap[1] += AUDIO_BUF_SIZE/sizeof(u_short);
607 dmap[2] += AUDIO_BUF_SIZE/sizeof(u_short);
608 dmap[3] += AUDIO_BUF_SIZE/sizeof(u_short);
609 }
610
611 aucc_encode(sc->sc_encoding, sc->sc_channels, cc, pp, dmap);
612
613 /* dma buffers: we use same buffer 4 all channels */
614 /* write dma location and length */
615 for (i=k=0; i<4; i++) {
616 if (masks2[i] & mask) {
617 DPRINTF(("turning channel %d on\n",i));
618 /* sc->sc_channel[i].nd_busy=1;*/
619 channel[i].isaudio=1;
620 channel[i].play_count=1;
621 channel[i].handler=NULL;
622 custom.aud[i].per=sc->sc_channel[i].nd_per;
623 custom.aud[i].vol=sc->sc_channel[i].nd_volume;
624 custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
625 custom.aud[i].len=cc/(sc->sc_channels*2);
626 sc->sc_channel[i].nd_mask=mask;
627 DPRINTF(("per is %d, vol is %d, len is %d\n",\
628 sc->sc_channel[i].nd_per,
629 sc->sc_channel[i].nd_volume, cc>>1));
630
631 }
632 }
633
634 channel[j].handler=aucc_inthdl;
635
636 /* enable ints */
637 custom.intena=INTF_SETCLR|INTF_INTEN| (masks2[j]<<INTB_AUD0);
638
639 DPRINTF(("enabled ints: 0x%x\n",(masks2[j]<<INTB_AUD0)));
640
641 /* enable dma */
642 custom.dmacon=DMAF_SETCLR|DMAF_MASTER|mask;
643
644 DPRINTF(("enabled dma, mask=0x%x\n",mask));
645
646 return(0);
647 }
648
649 /* ARGSUSED */
650 int
651 aucc_start_input(addr, p, cc, intr, arg)
652 void *addr;
653 void *p;
654 int cc;
655 void (*intr) __P((void *));
656 void *arg;
657 {
658
659 return ENXIO; /* no input */
660 }
661
662 int
663 aucc_halt_output(addr)
664 void *addr;
665 {
666 register struct aucc_softc *sc = addr;
667 register int i;
668
669 /* XXX only halt, if input is also halted ?? */
670 /* stop dma, etc */
671 custom.intena = AUCC_ALLINTF;
672 custom.dmacon = AUCC_ALLDMAF;
673 /* mark every busy unit idle */
674 for (i=0;i<4;i++) {
675 sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0;
676 channel[i].isaudio=0;
677 channel[i].play_count=0;
678 }
679
680 return(0);
681 }
682
683 int
684 aucc_halt_input(addr)
685 void *addr;
686 {
687 /* no input */
688
689 return ENXIO;
690 }
691
692 int
693 aucc_cont_output(addr)
694 void *addr;
695 {
696 DPRINTF(("aucc_cont_output: never called, what should it do?!\n"));
697 /* reenable DMA XXX */
698 return ENXIO;
699 }
700
701 int
702 aucc_cont_input(addr)
703 void *addr;
704 {
705 DPRINTF(("aucc_cont_input: never called, what should it do?!\n"));
706 return(0);
707 }
708
709 int
710 aucc_getdev(addr, retp)
711 void *addr;
712 struct audio_device *retp;
713 {
714 *retp = aucc_device;
715 return 0;
716 }
717
718 int
719 aucc_set_port(addr, cp)
720 void *addr;
721 mixer_ctrl_t *cp;
722 {
723 register struct aucc_softc *sc = addr;
724 register int i,j;
725
726 DPRINTF(("aucc_set_port: port=%d", cp->dev));
727
728 switch (cp->type) {
729 case AUDIO_MIXER_SET:
730 if (cp->dev!=AUCC_CHANNELS)
731 return EINVAL;
732 i=cp->un.mask;
733 if ((i<1)||(i>15))
734 return EINVAL;
735 sc->sc_channelmask=i;
736 break;
737
738 case AUDIO_MIXER_VALUE:
739 i=cp->un.value.num_channels;
740 if ((i<1)||(i>4))
741 return EINVAL;
742
743 #ifdef __XXXwhatsthat
744 if (cp->dev!=AUCC_VOLUME)
745 return EINVAL;
746 #endif
747
748 /* set volume for channel 0..i-1 */
749 if (i>1)
750 for (j=0;j<i;j++)
751 sc->sc_channel[j].nd_volume =
752 cp->un.value.level[j]>>2;
753 else if (sc->sc_channels > 1)
754 for (j=0; j<sc->sc_channels; j++)
755 sc->sc_channel[j].nd_volume =
756 cp->un.value.level[0]>>2;
757 else
758 for (j=0; j<4; j++)
759 sc->sc_channel[j].nd_volume =
760 cp->un.value.level[0]>>2;
761 break;
762
763 default:
764 return EINVAL;
765 break;
766 }
767 return 0;
768 }
769
770
771 int
772 aucc_get_port(addr, cp)
773 void *addr;
774 mixer_ctrl_t *cp;
775 {
776 register struct aucc_softc *sc = addr;
777 register int i,j;
778
779 DPRINTF(("aucc_get_port: port=%d", cp->dev));
780
781 switch (cp->type) {
782 case AUDIO_MIXER_SET:
783 if (cp->dev!=AUCC_CHANNELS)
784 return EINVAL;
785 cp->un.mask=sc->sc_channelmask;
786 break;
787
788 case AUDIO_MIXER_VALUE:
789 i = cp->un.value.num_channels;
790 if ((i<1)||(i>4))
791 return EINVAL;
792
793 for (j=0;j<i;j++)
794 cp->un.value.level[j] =
795 (sc->sc_channel[j].nd_volume<<2) +
796 (sc->sc_channel[j].nd_volume>>4);
797 break;
798
799 default:
800 return EINVAL;
801 }
802 return 0;
803 }
804
805
806 int
807 aucc_get_props(addr)
808 void *addr;
809 {
810 return 0;
811 }
812
813 int
814 aucc_query_devinfo(addr, dip)
815 void *addr;
816 register mixer_devinfo_t *dip;
817 {
818 register int i;
819
820 switch(dip->index) {
821 case AUCC_CHANNELS:
822 dip->type = AUDIO_MIXER_SET;
823 dip->mixer_class = AUCC_OUTPUT_CLASS;
824 dip->prev = dip->next = AUDIO_MIXER_LAST;
825 strcpy(dip->label.name, AudioNspeaker);
826 for (i=0;i<16;i++) {
827 sprintf(dip->un.s.member[i].label.name,
828 "channelmask%d", i);
829 dip->un.s.member[i].mask = i;
830 }
831 dip->un.s.num_mem = 16;
832 break;
833
834 case AUCC_VOLUME:
835 dip->type = AUDIO_MIXER_VALUE;
836 dip->mixer_class = AUCC_OUTPUT_CLASS;
837 dip->prev = dip->next = AUDIO_MIXER_LAST;
838 strcpy(dip->label.name, AudioNspeaker);
839 dip->un.v.num_channels = 4;
840 strcpy(dip->un.v.units.name, AudioNvolume);
841 break;
842
843 case AUCC_OUTPUT_CLASS:
844 dip->type = AUDIO_MIXER_CLASS;
845 dip->mixer_class = AUCC_OUTPUT_CLASS;
846 dip->next = dip->prev = AUDIO_MIXER_LAST;
847 strcpy(dip->label.name, AudioCOutputs);
848 break;
849 default:
850 return ENXIO;
851 /*NOTREACHED*/
852 }
853
854 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
855
856 return(0);
857 }
858
859
860 /* audio int handler */
861 void
862 aucc_inthdl(int ch)
863 {
864 register int i;
865 register int mask=aucc->sc_channel[ch].nd_mask;
866
867 /* for all channels in this maskgroup:
868 disable dma, int
869 mark idle */
870 DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask));
871
872 custom.intreq=mask<<INTB_AUD0; /* clear request */
873 /* XXX: maybe we can leave ints and/or DMA on, if another sample has to be played?*/
874 custom.intena=mask<<INTB_AUD0;
875 /*
876 * XXX custom.dmacon=mask; NO!!!
877 */
878 for (i=0;i<4;i++) {
879 if (masks2[i]&&mask) {
880 DPRINTF(("marking channel %d idle\n",i));
881 aucc->sc_channel[i].nd_busy=0;
882 aucc->sc_channel[i].nd_mask=0;
883 channel[i].isaudio=channel[i].play_count=0;
884 }
885 }
886
887 /* call handler */
888 if (aucc->sc_channel[ch].nd_intr) {
889 DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
890 (*(aucc->sc_channel[ch].nd_intr))(aucc->sc_channel[ch].nd_intrdata);
891 }
892 else DPRINTF(("zero int handler\n"));
893 DPRINTF(("ints done\n"));
894 }
895
896
897
898
899 /* transform frequency to period, adjust bounds */
900 static u_int
901 freqtoper(u_int freq)
902 {
903 u_int per=eclockfreq*5/freq;
904
905 if (per<124)
906 per=124; /* must have at least 124 ticks between samples */
907
908 return per;
909 }
910
911 /* transform period to frequency */
912 static u_int
913 pertofreq(u_int per)
914 {
915 u_int freq=eclockfreq*5/per;
916
917
918 return freq;
919 }
920
921
922
923 void
924 aucc_encode(enc, channels, i, p, dmap)
925 int enc, channels, i;
926 u_char *p;
927 u_short **dmap;
928 {
929 char *q, *r, *s, *t;
930 int off;
931 u_char *tab;
932
933 #ifdef AUCCDEBUG
934 static int debctl = 6;
935 #endif
936
937 off = 0;
938 tab = NULL;
939
940 #ifdef AUCCDEBUG
941 if (--debctl >= 0)
942 printf("Enc: enc %d, chan %d, dmap %p %p %p %p\n",
943 enc, channels, dmap[0], dmap[1], dmap[2], dmap[3]);
944 #endif
945
946 switch (enc) {
947 case AUDIO_ENCODING_ULAW:
948 tab=ulaw_to_lin;
949 break;
950 case AUDIO_ENCODING_ULINEAR_BE:
951 case AUDIO_ENCODING_ULINEAR_LE:
952 off=-128;
953 break;
954 case AUDIO_ENCODING_SLINEAR_BE:
955 case AUDIO_ENCODING_SLINEAR_LE:
956 break;
957 default:
958 return;
959 }
960
961 q = (char *)dmap[0];
962 r = (char *)dmap[1];
963 s = (char *)dmap[2];
964 t = (char *)dmap[3];
965
966 if (tab)
967 while (i) {
968 switch (channels) {
969 case 4: *t++ = tab[*p++];
970 case 3: *s++ = tab[*p++];
971 case 2: *r++ = tab[*p++];
972 case 1: *q++ = tab[*p++];
973 }
974 i -= channels;
975 }
976 else
977 while (i) {
978 switch (channels) {
979 case 4: *t++ = *p++ + off;
980 case 3: *s++ = *p++ + off;
981 case 2: *r++ = *p++ + off;
982 case 1: *q++ = *p++ + off;
983 }
984 i -= channels;
985 }
986
987 }
988
989 #endif /* NAUCC > 0 */
990