aucc.c revision 1.8 1 /* $NetBSD: aucc.c,v 1.8 1997/07/04 21:00:15 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 printf("aucc_set_params(mode %x, enc %d, bits %d, chn %d, sr %ld)\n",
427 mode, p->encoding, p->precision, p->channels, p->sample_rate);
428
429 switch (p->encoding) {
430 case AUDIO_ENCODING_ULAW:
431 case AUDIO_ENCODING_LINEAR:
432 case AUDIO_ENCODING_LINEAR_BE:
433 case AUDIO_ENCODING_LINEAR_LE:
434 case AUDIO_ENCODING_ULINEAR_BE:
435 case AUDIO_ENCODING_ULINEAR_LE:
436 break;
437
438 default:
439 return EINVAL;
440 /* NOTREADCHED */
441 }
442
443 if (p->precision != 8)
444 return EINVAL;
445
446 if ((p->channels<1) || (p->channels>4))
447 return(EINVAL);
448
449 sc->sc_channels = p->channels;
450 sc->sc_encoding = p->encoding;
451
452 q->encoding = p->encoding;
453 q->precision = p->precision;
454 q->channels = p->channels;
455 q->sample_rate = p->sample_rate;
456
457 return aucc_set_out_sr(addr, p->sample_rate);
458 }
459
460 int
461 aucc_get_encoding(addr)
462 void *addr;
463 {
464 return ((struct aucc_softc *)addr)->sc_encoding;
465 }
466
467 int
468 aucc_get_precision(addr)
469 void *addr;
470 {
471 return(8);
472 }
473
474 int
475 aucc_get_channels(addr)
476 void *addr;
477 {
478 return ((struct aucc_softc *)addr)->sc_channels;
479 }
480
481 int
482 aucc_round_blocksize(addr, blk)
483 void *addr;
484 int blk;
485 {
486
487
488 return blk>AUDIO_BUF_SIZE?AUDIO_BUF_SIZE:blk; /* round up to even size */
489 }
490
491 int
492 aucc_set_out_port(addr, port) /* can set channels */
493 void *addr;
494 int port;
495 {
496 register struct aucc_softc *sc = addr;
497
498 /* port is mask for channels 0..3 */
499 if ((port<0)||(port>15))
500 return EINVAL;
501
502 sc->sc_channelmask=port;
503
504 return(0);
505 }
506
507 int
508 aucc_get_out_port(addr)
509 void *addr;
510 {
511 register struct aucc_softc *sc = addr;
512
513 return sc->sc_channelmask;
514 }
515
516 int
517 aucc_set_in_port(addr, port)
518 void *addr;
519 int port;
520 {
521 return(EINVAL); /* no input possible */
522
523 }
524
525 int
526 aucc_get_in_port(addr)
527 void *addr;
528 {
529 return(0);
530 }
531
532 int
533 aucc_commit_settings(addr)
534 void *addr;
535 {
536 register struct aucc_softc *sc = addr;
537 register int i;
538
539 DPRINTF(("sa_commit.\n"));
540
541 for (i=0;i<4;i++) {
542 custom.aud[i].vol=sc->sc_channel[i].nd_volume;
543 custom.aud[i].per=sc->sc_channel[i].nd_per;
544 }
545
546 DPRINTF(("commit done\n"));
547
548 return(0);
549 }
550
551 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
552 static int masks2[4] = {1,2,4,8};
553
554 int
555 aucc_start_output(addr, p, cc, intr, arg)
556 void *addr;
557 void *p;
558 int cc;
559 void (*intr) __P((void *));
560 void *arg;
561 {
562 struct aucc_softc *sc;
563 int mask;
564 int i,j,k;
565 u_short *dmap[4];
566 u_char *pp;
567
568
569 sc = addr;
570 mask = sc->sc_channelmask;
571
572 dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
573
574 DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
575
576 mask &=masks[sc->sc_channels-1]; /* we use first sc_channels channels */
577 if (mask==0) /* active and used channels are disjoint */
578 return EINVAL;
579
580 for (i=0;i<4;i++) { /* channels available ? */
581 if ((masks2[i]&mask)&&(sc->sc_channel[i].nd_busy))
582 return EBUSY; /* channel is busy */
583 if (channel[i].isaudio==-1)
584 return EBUSY; /* system uses them */
585 }
586
587 /* enable interrupt on 1st channel */
588 for (i=j=0;i<AUCC_MAXINT;i++) {
589 if (masks2[i]&mask) {
590 DPRINTF(("first channel is %d\n",i));
591 j=i;
592 sc->sc_channel[i].nd_intr=intr;
593 sc->sc_channel[i].nd_intrdata=arg;
594 break;
595 }
596 }
597
598 DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
599 dmap[2], dmap[3], mask));
600
601 /* disable ints, dma for channels, until all parameters set */
602 /* XXX dont disable DMA! custom.dmacon=mask;*/
603 custom.intreq=mask<<INTB_AUD0;
604 custom.intena=mask<<INTB_AUD0;
605
606 /* copy data to dma buffer */
607
608
609 pp=(u_char *)p;
610
611 if (sc->sc_channels == 1) {
612 dmap[0] =
613 dmap[1] =
614 dmap[2] =
615 dmap[3] = sc->sc_channel[j].nd_dma;
616 } else {
617 for (k=0; k<4; k++) {
618 if (masks2[k+j]&mask)
619 dmap[k]=sc->sc_channel[k+j].nd_dma;
620 }
621 }
622
623 sc->sc_channel[j].nd_doublebuf ^= 1;
624 if (sc->sc_channel[j].nd_doublebuf) {
625 dmap[0] += AUDIO_BUF_SIZE/sizeof(u_short);
626 dmap[1] += AUDIO_BUF_SIZE/sizeof(u_short);
627 dmap[2] += AUDIO_BUF_SIZE/sizeof(u_short);
628 dmap[3] += AUDIO_BUF_SIZE/sizeof(u_short);
629 }
630
631 aucc_encode(sc->sc_encoding, sc->sc_channels, cc, pp, dmap);
632
633 /* dma buffers: we use same buffer 4 all channels */
634 /* write dma location and length */
635 for (i=k=0; i<4; i++) {
636 if (masks2[i] & mask) {
637 DPRINTF(("turning channel %d on\n",i));
638 /* sc->sc_channel[i].nd_busy=1;*/
639 channel[i].isaudio=1;
640 channel[i].play_count=1;
641 channel[i].handler=NULL;
642 custom.aud[i].per=sc->sc_channel[i].nd_per;
643 custom.aud[i].vol=sc->sc_channel[i].nd_volume;
644 custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
645 custom.aud[i].len=cc>>1;
646 sc->sc_channel[i].nd_mask=mask;
647 DPRINTF(("per is %d, vol is %d, len is %d\n",\
648 sc->sc_channel[i].nd_per,
649 sc->sc_channel[i].nd_volume, cc>>1));
650
651 }
652 }
653
654 channel[j].handler=aucc_inthdl;
655
656 /* enable ints */
657 custom.intena=INTF_SETCLR|INTF_INTEN| (masks2[j]<<INTB_AUD0);
658
659 DPRINTF(("enabled ints: 0x%x\n",(masks2[j]<<INTB_AUD0)));
660
661 /* enable dma */
662 custom.dmacon=DMAF_SETCLR|DMAF_MASTER|mask;
663
664 DPRINTF(("enabled dma, mask=0x%x\n",mask));
665
666 return(0);
667 }
668
669 /* ARGSUSED */
670 int
671 aucc_start_input(addr, p, cc, intr, arg)
672 void *addr;
673 void *p;
674 int cc;
675 void (*intr) __P((void *));
676 void *arg;
677 {
678
679 return ENXIO; /* no input */
680 }
681
682 int
683 aucc_halt_output(addr)
684 void *addr;
685 {
686 register struct aucc_softc *sc = addr;
687 register int i;
688
689 /* XXX only halt, if input is also halted ?? */
690 /* stop dma, etc */
691 custom.intena = AUCC_ALLINTF;
692 custom.dmacon = AUCC_ALLDMAF;
693 /* mark every busy unit idle */
694 for (i=0;i<4;i++) {
695 sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0;
696 channel[i].isaudio=0;
697 channel[i].play_count=0;
698 }
699
700 return(0);
701 }
702
703 int
704 aucc_halt_input(addr)
705 void *addr;
706 {
707 /* no input */
708
709 return ENXIO;
710 }
711
712 int
713 aucc_cont_output(addr)
714 void *addr;
715 {
716 DPRINTF(("aucc_cont_output: never called, what should it do?!\n"));
717 /* reenable DMA XXX */
718 return ENXIO;
719 }
720
721 int
722 aucc_cont_input(addr)
723 void *addr;
724 {
725 DPRINTF(("aucc_cont_input: never called, what should it do?!\n"));
726 return(0);
727 }
728
729 int
730 aucc_getdev(addr, retp)
731 void *addr;
732 struct audio_device *retp;
733 {
734 *retp = aucc_device;
735 return 0;
736 }
737
738 int
739 aucc_setfd(addr, flag)
740 void *addr;
741 int flag;
742 {
743 return flag?EINVAL:0; /* Always half-duplex */
744 }
745
746 int
747 aucc_set_port(addr, cp)
748 void *addr;
749 mixer_ctrl_t *cp;
750 {
751 register struct aucc_softc *sc = addr;
752 register int i,j;
753
754 DPRINTF(("aucc_set_port: port=%d", cp->dev));
755
756 switch (cp->type) {
757 case AUDIO_MIXER_SET:
758 if (cp->dev!=AUCC_CHANNELS)
759 return EINVAL;
760 i=cp->un.mask;
761 if ((i<1)||(i>15))
762 return EINVAL;
763 sc->sc_channelmask=i;
764 break;
765
766 case AUDIO_MIXER_VALUE:
767 i=cp->un.value.num_channels;
768 if ((i<1)||(i>4))
769 return EINVAL;
770
771 if (cp->dev!=AUCC_VOLUME)
772 return EINVAL;
773
774 /* set volume for channel 0..i-1 */
775 for (j=0;j<i;j++)
776 sc->sc_channel[j].nd_volume=cp->un.value.level[j]>>2;
777 break;
778
779 default:
780 return EINVAL;
781 break;
782 }
783 return 0;
784 }
785
786
787 int
788 aucc_get_port(addr, cp)
789 void *addr;
790 mixer_ctrl_t *cp;
791 {
792 register struct aucc_softc *sc = addr;
793 register int i,j;
794
795 DPRINTF(("aucc_get_port: port=%d", cp->dev));
796
797 switch (cp->type) {
798 case AUDIO_MIXER_SET:
799 if (cp->dev!=AUCC_CHANNELS)
800 return EINVAL;
801 cp->un.mask=sc->sc_channelmask;
802 break;
803
804 case AUDIO_MIXER_VALUE:
805 i = cp->un.value.num_channels;
806 if ((i<1)||(i>4))
807 return EINVAL;
808
809 for (j=0;j<i;j++)
810 cp->un.value.level[j]=sc->sc_channel[j].nd_volume<<2;
811 break;
812
813 default:
814 return EINVAL;
815 }
816 return 0;
817 }
818
819
820 int
821 aucc_query_devinfo(addr, dip)
822 void *addr;
823 register mixer_devinfo_t *dip;
824 {
825 register int i;
826
827 switch(dip->index) {
828 case AUCC_CHANNELS:
829 dip->type = AUDIO_MIXER_SET;
830 dip->mixer_class = AUCC_OUTPUT_CLASS;
831 dip->prev = dip->next = AUDIO_MIXER_LAST;
832 strcpy(dip->label.name, AudioNspeaker);
833 for (i=0;i<16;i++) {
834 sprintf(dip->un.s.member[i].label.name,
835 "channelmask%d", i);
836 dip->un.s.member[i].mask = i;
837 }
838 dip->un.s.num_mem = 16;
839 break;
840
841 case AUCC_VOLUME:
842 dip->type = AUDIO_MIXER_VALUE;
843 dip->mixer_class = AUCC_OUTPUT_CLASS;
844 dip->prev = dip->next = AUDIO_MIXER_LAST;
845 strcpy(dip->label.name, AudioNspeaker);
846 dip->un.v.num_channels = 4;
847 strcpy(dip->un.v.units.name, AudioNvolume);
848 break;
849
850 case AUCC_OUTPUT_CLASS:
851 dip->type = AUDIO_MIXER_CLASS;
852 dip->mixer_class = AUCC_OUTPUT_CLASS;
853 dip->next = dip->prev = AUDIO_MIXER_LAST;
854 strcpy(dip->label.name, AudioCOutputs);
855 break;
856 default:
857 return ENXIO;
858 /*NOTREACHED*/
859 }
860
861 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
862
863 return(0);
864 }
865
866
867 /* audio int handler */
868 void
869 aucc_inthdl(int ch)
870 {
871 register int i;
872 register int mask=aucc->sc_channel[ch].nd_mask;
873
874 /* for all channels in this maskgroup:
875 disable dma, int
876 mark idle */
877 DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask));
878
879 custom.intreq=mask<<INTB_AUD0; /* clear request */
880 /* XXX: maybe we can leave ints and/or DMA on, if another sample has to be played?*/
881 custom.intena=mask<<INTB_AUD0;
882 /*
883 * XXX custom.dmacon=mask; NO!!!
884 */
885 for (i=0;i<4;i++) {
886 if (masks2[i]&&mask) {
887 DPRINTF(("marking channel %d idle\n",i));
888 aucc->sc_channel[i].nd_busy=0;
889 aucc->sc_channel[i].nd_mask=0;
890 channel[i].isaudio=channel[i].play_count=0;
891 }
892 }
893
894 /* call handler */
895 if (aucc->sc_channel[ch].nd_intr) {
896 DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
897 (*(aucc->sc_channel[ch].nd_intr))(aucc->sc_channel[ch].nd_intrdata);
898 }
899 else DPRINTF(("zero int handler\n"));
900 DPRINTF(("ints done\n"));
901 }
902
903
904
905
906 /* transform frequency to period, adjust bounds */
907 static u_int
908 freqtoper(u_int freq)
909 {
910 u_int per=eclockfreq*5/freq;
911
912 if (per<124)
913 per=124; /* must have at least 124 ticks between samples */
914
915 return per;
916 }
917
918 /* transform period to frequency */
919 static u_int
920 pertofreq(u_int per)
921 {
922 u_int freq=eclockfreq*5/per;
923
924
925 return freq;
926 }
927
928
929
930 void
931 aucc_encode(enc, channels, i, p, dmap)
932 int enc, channels, i;
933 u_char *p;
934 u_short **dmap;
935 {
936 char *q, *r, *s, *t;
937 int off;
938 u_char *tab;
939
940 static int debctl = 6;
941
942 off = 0;
943 tab = NULL;
944
945 if (--debctl >= 0)
946 printf("Enc: enc %d, chan %d, dmap %p %p %p %p\n",
947 enc, channels, dmap[0], dmap[1], dmap[2], dmap[3]);
948
949 switch (enc) {
950 case AUDIO_ENCODING_ULAW:
951 tab=ulaw_to_lin;
952 break;
953 case AUDIO_ENCODING_ULINEAR:
954 case AUDIO_ENCODING_ULINEAR_BE:
955 case AUDIO_ENCODING_ULINEAR_LE:
956 off=-128;
957 break;
958 case AUDIO_ENCODING_LINEAR:
959 case AUDIO_ENCODING_LINEAR_BE:
960 case AUDIO_ENCODING_LINEAR_LE:
961 break;
962 default:
963 return;
964 }
965
966 q = (char *)dmap[0];
967 r = (char *)dmap[1];
968 s = (char *)dmap[2];
969 t = (char *)dmap[3];
970
971 if (tab)
972 while (i--) {
973 switch (channels) {
974 case 4: *t++ = tab[*p++];
975 case 3: *s++ = tab[*p++];
976 case 2: *r++ = tab[*p++];
977 case 1: *q++ = tab[*p++];
978 }
979 }
980 else
981 while (i--) {
982 switch (channels) {
983 case 4: *t++ = *p++ + off;
984 case 3: *s++ = *p++ + off;
985 case 2: *r++ = *p++ + off;
986 case 1: *q++ = *p++ + off;
987 }
988 }
989
990 }
991
992 #endif /* NAUCC > 0 */
993