aucc.c revision 1.9 1 /* $NetBSD: aucc.c,v 1.9 1997/07/09 22:37:08 is 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_LINEAR;
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_LINEAR:
434 case AUDIO_ENCODING_LINEAR_BE:
435 case AUDIO_ENCODING_LINEAR_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 mask &=masks[sc->sc_channels-1]; /* we use first sc_channels channels */
579 if (mask==0) /* active and used channels are disjoint */
580 return EINVAL;
581
582 for (i=0;i<4;i++) { /* channels available ? */
583 if ((masks2[i]&mask)&&(sc->sc_channel[i].nd_busy))
584 return EBUSY; /* channel is busy */
585 if (channel[i].isaudio==-1)
586 return EBUSY; /* system uses them */
587 }
588
589 /* enable interrupt on 1st channel */
590 for (i=j=0;i<AUCC_MAXINT;i++) {
591 if (masks2[i]&mask) {
592 DPRINTF(("first channel is %d\n",i));
593 j=i;
594 sc->sc_channel[i].nd_intr=intr;
595 sc->sc_channel[i].nd_intrdata=arg;
596 break;
597 }
598 }
599
600 DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
601 dmap[2], dmap[3], mask));
602
603 /* disable ints, dma for channels, until all parameters set */
604 /* XXX dont disable DMA! custom.dmacon=mask;*/
605 custom.intreq=mask<<INTB_AUD0;
606 custom.intena=mask<<INTB_AUD0;
607
608 /* copy data to dma buffer */
609
610
611 pp=(u_char *)p;
612
613 if (sc->sc_channels == 1) {
614 dmap[0] =
615 dmap[1] =
616 dmap[2] =
617 dmap[3] = sc->sc_channel[j].nd_dma;
618 } else {
619 for (k=0; k<4; k++) {
620 if (masks2[k+j]&mask)
621 dmap[k]=sc->sc_channel[k+j].nd_dma;
622 }
623 }
624
625 sc->sc_channel[j].nd_doublebuf ^= 1;
626 if (sc->sc_channel[j].nd_doublebuf) {
627 dmap[0] += AUDIO_BUF_SIZE/sizeof(u_short);
628 dmap[1] += AUDIO_BUF_SIZE/sizeof(u_short);
629 dmap[2] += AUDIO_BUF_SIZE/sizeof(u_short);
630 dmap[3] += AUDIO_BUF_SIZE/sizeof(u_short);
631 }
632
633 aucc_encode(sc->sc_encoding, sc->sc_channels, cc, pp, dmap);
634
635 /* dma buffers: we use same buffer 4 all channels */
636 /* write dma location and length */
637 for (i=k=0; i<4; i++) {
638 if (masks2[i] & mask) {
639 DPRINTF(("turning channel %d on\n",i));
640 /* sc->sc_channel[i].nd_busy=1;*/
641 channel[i].isaudio=1;
642 channel[i].play_count=1;
643 channel[i].handler=NULL;
644 custom.aud[i].per=sc->sc_channel[i].nd_per;
645 custom.aud[i].vol=sc->sc_channel[i].nd_volume;
646 custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
647 custom.aud[i].len=cc/(sc->sc_channels*2);
648 sc->sc_channel[i].nd_mask=mask;
649 DPRINTF(("per is %d, vol is %d, len is %d\n",\
650 sc->sc_channel[i].nd_per,
651 sc->sc_channel[i].nd_volume, cc>>1));
652
653 }
654 }
655
656 channel[j].handler=aucc_inthdl;
657
658 /* enable ints */
659 custom.intena=INTF_SETCLR|INTF_INTEN| (masks2[j]<<INTB_AUD0);
660
661 DPRINTF(("enabled ints: 0x%x\n",(masks2[j]<<INTB_AUD0)));
662
663 /* enable dma */
664 custom.dmacon=DMAF_SETCLR|DMAF_MASTER|mask;
665
666 DPRINTF(("enabled dma, mask=0x%x\n",mask));
667
668 return(0);
669 }
670
671 /* ARGSUSED */
672 int
673 aucc_start_input(addr, p, cc, intr, arg)
674 void *addr;
675 void *p;
676 int cc;
677 void (*intr) __P((void *));
678 void *arg;
679 {
680
681 return ENXIO; /* no input */
682 }
683
684 int
685 aucc_halt_output(addr)
686 void *addr;
687 {
688 register struct aucc_softc *sc = addr;
689 register int i;
690
691 /* XXX only halt, if input is also halted ?? */
692 /* stop dma, etc */
693 custom.intena = AUCC_ALLINTF;
694 custom.dmacon = AUCC_ALLDMAF;
695 /* mark every busy unit idle */
696 for (i=0;i<4;i++) {
697 sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0;
698 channel[i].isaudio=0;
699 channel[i].play_count=0;
700 }
701
702 return(0);
703 }
704
705 int
706 aucc_halt_input(addr)
707 void *addr;
708 {
709 /* no input */
710
711 return ENXIO;
712 }
713
714 int
715 aucc_cont_output(addr)
716 void *addr;
717 {
718 DPRINTF(("aucc_cont_output: never called, what should it do?!\n"));
719 /* reenable DMA XXX */
720 return ENXIO;
721 }
722
723 int
724 aucc_cont_input(addr)
725 void *addr;
726 {
727 DPRINTF(("aucc_cont_input: never called, what should it do?!\n"));
728 return(0);
729 }
730
731 int
732 aucc_getdev(addr, retp)
733 void *addr;
734 struct audio_device *retp;
735 {
736 *retp = aucc_device;
737 return 0;
738 }
739
740 int
741 aucc_setfd(addr, flag)
742 void *addr;
743 int flag;
744 {
745 return flag?EINVAL:0; /* Always half-duplex */
746 }
747
748 int
749 aucc_set_port(addr, cp)
750 void *addr;
751 mixer_ctrl_t *cp;
752 {
753 register struct aucc_softc *sc = addr;
754 register int i,j;
755
756 DPRINTF(("aucc_set_port: port=%d", cp->dev));
757
758 switch (cp->type) {
759 case AUDIO_MIXER_SET:
760 if (cp->dev!=AUCC_CHANNELS)
761 return EINVAL;
762 i=cp->un.mask;
763 if ((i<1)||(i>15))
764 return EINVAL;
765 sc->sc_channelmask=i;
766 break;
767
768 case AUDIO_MIXER_VALUE:
769 i=cp->un.value.num_channels;
770 if ((i<1)||(i>4))
771 return EINVAL;
772
773 if (cp->dev!=AUCC_VOLUME)
774 return EINVAL;
775
776 /* set volume for channel 0..i-1 */
777 for (j=0;j<i;j++)
778 sc->sc_channel[j].nd_volume=cp->un.value.level[j]>>2;
779 break;
780
781 default:
782 return EINVAL;
783 break;
784 }
785 return 0;
786 }
787
788
789 int
790 aucc_get_port(addr, cp)
791 void *addr;
792 mixer_ctrl_t *cp;
793 {
794 register struct aucc_softc *sc = addr;
795 register int i,j;
796
797 DPRINTF(("aucc_get_port: port=%d", cp->dev));
798
799 switch (cp->type) {
800 case AUDIO_MIXER_SET:
801 if (cp->dev!=AUCC_CHANNELS)
802 return EINVAL;
803 cp->un.mask=sc->sc_channelmask;
804 break;
805
806 case AUDIO_MIXER_VALUE:
807 i = cp->un.value.num_channels;
808 if ((i<1)||(i>4))
809 return EINVAL;
810
811 for (j=0;j<i;j++)
812 cp->un.value.level[j]=sc->sc_channel[j].nd_volume<<2;
813 break;
814
815 default:
816 return EINVAL;
817 }
818 return 0;
819 }
820
821
822 int
823 aucc_query_devinfo(addr, dip)
824 void *addr;
825 register mixer_devinfo_t *dip;
826 {
827 register int i;
828
829 switch(dip->index) {
830 case AUCC_CHANNELS:
831 dip->type = AUDIO_MIXER_SET;
832 dip->mixer_class = AUCC_OUTPUT_CLASS;
833 dip->prev = dip->next = AUDIO_MIXER_LAST;
834 strcpy(dip->label.name, AudioNspeaker);
835 for (i=0;i<16;i++) {
836 sprintf(dip->un.s.member[i].label.name,
837 "channelmask%d", i);
838 dip->un.s.member[i].mask = i;
839 }
840 dip->un.s.num_mem = 16;
841 break;
842
843 case AUCC_VOLUME:
844 dip->type = AUDIO_MIXER_VALUE;
845 dip->mixer_class = AUCC_OUTPUT_CLASS;
846 dip->prev = dip->next = AUDIO_MIXER_LAST;
847 strcpy(dip->label.name, AudioNspeaker);
848 dip->un.v.num_channels = 4;
849 strcpy(dip->un.v.units.name, AudioNvolume);
850 break;
851
852 case AUCC_OUTPUT_CLASS:
853 dip->type = AUDIO_MIXER_CLASS;
854 dip->mixer_class = AUCC_OUTPUT_CLASS;
855 dip->next = dip->prev = AUDIO_MIXER_LAST;
856 strcpy(dip->label.name, AudioCOutputs);
857 break;
858 default:
859 return ENXIO;
860 /*NOTREACHED*/
861 }
862
863 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
864
865 return(0);
866 }
867
868
869 /* audio int handler */
870 void
871 aucc_inthdl(int ch)
872 {
873 register int i;
874 register int mask=aucc->sc_channel[ch].nd_mask;
875
876 /* for all channels in this maskgroup:
877 disable dma, int
878 mark idle */
879 DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask));
880
881 custom.intreq=mask<<INTB_AUD0; /* clear request */
882 /* XXX: maybe we can leave ints and/or DMA on, if another sample has to be played?*/
883 custom.intena=mask<<INTB_AUD0;
884 /*
885 * XXX custom.dmacon=mask; NO!!!
886 */
887 for (i=0;i<4;i++) {
888 if (masks2[i]&&mask) {
889 DPRINTF(("marking channel %d idle\n",i));
890 aucc->sc_channel[i].nd_busy=0;
891 aucc->sc_channel[i].nd_mask=0;
892 channel[i].isaudio=channel[i].play_count=0;
893 }
894 }
895
896 /* call handler */
897 if (aucc->sc_channel[ch].nd_intr) {
898 DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
899 (*(aucc->sc_channel[ch].nd_intr))(aucc->sc_channel[ch].nd_intrdata);
900 }
901 else DPRINTF(("zero int handler\n"));
902 DPRINTF(("ints done\n"));
903 }
904
905
906
907
908 /* transform frequency to period, adjust bounds */
909 static u_int
910 freqtoper(u_int freq)
911 {
912 u_int per=eclockfreq*5/freq;
913
914 if (per<124)
915 per=124; /* must have at least 124 ticks between samples */
916
917 return per;
918 }
919
920 /* transform period to frequency */
921 static u_int
922 pertofreq(u_int per)
923 {
924 u_int freq=eclockfreq*5/per;
925
926
927 return freq;
928 }
929
930
931
932 void
933 aucc_encode(enc, channels, i, p, dmap)
934 int enc, channels, i;
935 u_char *p;
936 u_short **dmap;
937 {
938 char *q, *r, *s, *t;
939 int off;
940 u_char *tab;
941
942 #ifdef AUCCDEBUG
943 static int debctl = 6;
944 #endif
945
946 off = 0;
947 tab = NULL;
948
949 #ifdef AUCCDEBUG
950 if (--debctl >= 0)
951 printf("Enc: enc %d, chan %d, dmap %p %p %p %p\n",
952 enc, channels, dmap[0], dmap[1], dmap[2], dmap[3]);
953 #endif
954
955 switch (enc) {
956 case AUDIO_ENCODING_ULAW:
957 tab=ulaw_to_lin;
958 break;
959 case AUDIO_ENCODING_ULINEAR:
960 case AUDIO_ENCODING_ULINEAR_BE:
961 case AUDIO_ENCODING_ULINEAR_LE:
962 off=-128;
963 break;
964 case AUDIO_ENCODING_LINEAR:
965 case AUDIO_ENCODING_LINEAR_BE:
966 case AUDIO_ENCODING_LINEAR_LE:
967 break;
968 default:
969 return;
970 }
971
972 q = (char *)dmap[0];
973 r = (char *)dmap[1];
974 s = (char *)dmap[2];
975 t = (char *)dmap[3];
976
977 if (tab)
978 while (i) {
979 switch (channels) {
980 case 4: *t++ = tab[*p++];
981 case 3: *s++ = tab[*p++];
982 case 2: *r++ = tab[*p++];
983 case 1: *q++ = tab[*p++];
984 }
985 i -= channels;
986 }
987 else
988 while (i) {
989 switch (channels) {
990 case 4: *t++ = *p++ + off;
991 case 3: *s++ = *p++ + off;
992 case 2: *r++ = *p++ + off;
993 case 1: *q++ = *p++ + off;
994 }
995 i -= channels;
996 }
997
998 }
999
1000 #endif /* NAUCC > 0 */
1001