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