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