aucc.c revision 1.20 1 /* $NetBSD: aucc.c,v 1.20 1997/10/19 07:41:33 augustss Exp $ */
2
3 /*
4 * Copyright (c) 1997 Stephan Thesing
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Stephan Thesing.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include "aucc.h"
34 #if NAUCC > 0
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/errno.h>
39 #include <sys/ioctl.h>
40 #include <sys/device.h>
41 #include <sys/proc.h>
42 #include <machine/cpu.h>
43
44 #include <sys/audioio.h>
45 #include <dev/audio_if.h>
46 #include <amiga/amiga/cc.h>
47 #include <amiga/amiga/custom.h>
48 #include <amiga/amiga/device.h>
49 #include <amiga/dev/auccvar.h>
50
51
52 #ifdef LEV6_DEFER
53 #define AUCC_MAXINT 3
54 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2)
55 #else
56 #define AUCC_MAXINT 4
57 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3)
58 #endif
59 /* this unconditionally; we may use AUD3 as slave channel with LEV6_DEFER */
60 #define AUCC_ALLDMAF (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3)
61
62 #ifdef AUDIO_DEBUG
63 /*extern printf __P((const char *,...));*/
64 int auccdebug = 1;
65 #define DPRINTF(x) if (auccdebug) printf x
66 #else
67 #define DPRINTF(x)
68 #endif
69
70 #ifdef splaudio
71 #undef splaudio
72 #endif
73
74 #define splaudio() spl4();
75
76 /* clock frequency.. */
77 extern int eclockfreq;
78
79
80 /* hw audio ch */
81 extern struct audio_channel channel[4];
82
83
84 /*
85 * Software state.
86 */
87 struct aucc_softc {
88 struct device sc_dev; /* base device */
89
90 int sc_open; /* single use device */
91 aucc_data_t sc_channel[4]; /* per channel freq, ... */
92 u_int sc_encoding; /* encoding AUDIO_ENCODING_.*/
93 int sc_channels; /* # of channels used */
94
95 int sc_intrcnt; /* interrupt count */
96 int sc_channelmask; /* which channels are used ? */
97 };
98
99 /* interrupt interfaces */
100 void aucc_inthdl __P((int));
101
102 /* forward declarations */
103 static int init_aucc __P((struct aucc_softc *));
104 static u_int freqtoper __P((u_int));
105 static u_int pertofreq __P((u_int));
106
107 /* autoconfiguration driver */
108 void auccattach __P((struct device *, struct device *, void *));
109 int auccmatch __P((struct device *, struct cfdata *, void *));
110
111 struct cfattach aucc_ca = {
112 sizeof(struct aucc_softc),
113 auccmatch,
114 auccattach
115 };
116
117 struct cfdriver aucc_cd = {
118 NULL, "aucc", DV_DULL, NULL, 0
119 };
120
121 struct audio_device aucc_device = {
122 "Amiga-audio",
123 "x",
124 "aucc"
125 };
126
127
128 struct aucc_softc *aucc=NULL;
129
130
131 unsigned char ulaw_to_lin[] = {
132 0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
133 0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
134 0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf,
135 0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf,
136 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
137 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
138 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4,
139 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8,
140 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
141 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
142 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd,
143 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe,
144 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
145 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
146 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
147 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
148 0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61,
149 0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, 0x45, 0x41,
150 0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30,
151 0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20,
152 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17,
153 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f,
154 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b,
155 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07,
156 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05,
157 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
158 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02,
159 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
160 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 };
165
166 /*
167 * Define our interface to the higher level audio driver.
168 */
169 int aucc_open __P((void *, int));
170 void aucc_close __P((void *));
171 int aucc_set_out_sr __P((void *, u_long));
172 int aucc_query_encoding __P((void *, struct audio_encoding *));
173 int aucc_round_blocksize __P((void *, int));
174 int aucc_commit_settings __P((void *));
175 int aucc_start_output __P((void *, void *, int, void (*)(void *),
176 void *));
177 int aucc_start_input __P((void *, void *, int, void (*)(void *),
178 void *));
179 int aucc_halt_output __P((void *));
180 int aucc_halt_input __P((void *));
181 int aucc_getdev __P((void *, struct audio_device *));
182 int aucc_set_port __P((void *, mixer_ctrl_t *));
183 int aucc_get_port __P((void *, mixer_ctrl_t *));
184 int aucc_query_devinfo __P((void *, mixer_devinfo_t *));
185 void aucc_encode __P((int, int, int, u_char *, u_short **));
186 int aucc_set_params __P((void *, int, int,
187 struct audio_params *, struct audio_params *));
188 int aucc_get_props __P((void *));
189
190 struct audio_hw_if sa_hw_if = {
191 aucc_open,
192 aucc_close,
193 NULL,
194 aucc_query_encoding,
195 aucc_set_params,
196 aucc_round_blocksize,
197 aucc_commit_settings,
198 NULL,
199 NULL,
200 aucc_start_output,
201 aucc_start_input,
202 aucc_halt_output,
203 aucc_halt_input,
204 NULL,
205 aucc_getdev,
206 NULL,
207 aucc_set_port,
208 aucc_get_port,
209 aucc_query_devinfo,
210 NULL,
211 NULL,
212 NULL,
213 NULL,
214 aucc_get_props,
215 };
216
217 /* autoconfig routines */
218
219 int
220 auccmatch(pdp, cfp, aux)
221 struct device *pdp;
222 struct cfdata *cfp;
223 void *aux;
224 {
225 if (matchname((char *)aux, "aucc") &&
226 #ifdef DRACO
227 !is_draco() &&
228 #endif
229 (cfp->cf_unit == 0))
230 return 1;
231
232 return 0;
233 }
234
235 /*
236 * Audio chip found.
237 */
238 void
239 auccattach(parent, self, args)
240 struct device *parent, *self;
241 void *args;
242 {
243 register struct aucc_softc *sc = (struct aucc_softc *)self;
244 register int i;
245
246 printf("\n");
247
248 if((i=init_aucc(sc))) {
249 printf("audio: no chipmem\n");
250 return;
251 }
252
253 audio_attach_mi(&sa_hw_if, 0, sc, &sc->sc_dev);
254 }
255
256
257 static int
258 init_aucc(sc)
259 struct aucc_softc *sc;
260 {
261 register int i, err=0;
262
263 /* init values per channel */
264 for (i=0;i<4;i++) {
265 sc->sc_channel[i].nd_freq=8000;
266 sc->sc_channel[i].nd_per=freqtoper(8000);
267 sc->sc_channel[i].nd_busy=0;
268 sc->sc_channel[i].nd_dma=alloc_chipmem(AUDIO_BUF_SIZE*2);
269 if (sc->sc_channel[i].nd_dma==NULL)
270 err=1;
271 sc->sc_channel[i].nd_dmalength=0;
272 sc->sc_channel[i].nd_volume=64;
273 sc->sc_channel[i].nd_intr=NULL;
274 sc->sc_channel[i].nd_intrdata=NULL;
275 sc->sc_channel[i].nd_doublebuf=0;
276 DPRINTF(("dma buffer for channel %d is %p\n", i,
277 sc->sc_channel[i].nd_dma));
278
279 }
280
281 if (err) {
282 for(i=0;i<4;i++)
283 if (sc->sc_channel[i].nd_dma)
284 free_chipmem(sc->sc_channel[i].nd_dma);
285 }
286
287 sc->sc_channels=1;
288 sc->sc_channelmask=0xf;
289
290 /* clear interrupts and dma: */
291 custom.intena = AUCC_ALLINTF;
292 custom.dmacon = AUCC_ALLDMAF;;
293
294 sc->sc_encoding=AUDIO_ENCODING_ULAW;
295
296 return err;
297
298 }
299
300 int
301 aucc_open(addr, flags)
302 void *addr;
303 int flags;
304 {
305 struct aucc_softc *sc = addr;
306 int i;
307
308 DPRINTF(("sa_open: unit %p\n",sc));
309
310 if (sc->sc_open)
311 return (EBUSY);
312 sc->sc_open = 1;
313 for (i=0;i<AUCC_MAXINT;i++) {
314 sc->sc_channel[i].nd_intr=NULL;
315 sc->sc_channel[i].nd_intrdata=NULL;
316 }
317 aucc=sc;
318 sc->sc_channelmask=0xf;
319
320 DPRINTF(("saopen: ok -> sc=0x%p\n",sc));
321
322 return (0);
323 }
324
325 void
326 aucc_close(addr)
327 void *addr;
328 {
329 register struct aucc_softc *sc = addr;
330
331 DPRINTF(("sa_close: sc=0x%p\n", sc));
332 /*
333 * halt i/o, clear open flag, and done.
334 */
335 aucc_halt_output(sc);
336 sc->sc_open = 0;
337
338 DPRINTF(("sa_close: closed.\n"));
339 }
340
341 int
342 aucc_set_out_sr(addr, sr)
343 void *addr;
344 u_long sr;
345 {
346 struct aucc_softc *sc=addr;
347 u_long per;
348 register int i;
349
350 per=freqtoper(sr);
351 if (per>0xffff)
352 return EINVAL;
353 sr=pertofreq(per);
354
355 for (i=0;i<4;i++) {
356 sc->sc_channel[i].nd_freq=sr;
357 sc->sc_channel[i].nd_per=per;
358 }
359
360 return(0);
361 }
362
363 int
364 aucc_query_encoding(addr, fp)
365 void *addr;
366 struct audio_encoding *fp;
367 {
368 switch (fp->index) {
369 case 0:
370 strcpy(fp->name, AudioEslinear);
371 fp->encoding = AUDIO_ENCODING_SLINEAR;
372 fp->precision = 8;
373 fp->flags = 0;
374 break;
375 case 1:
376 strcpy(fp->name, AudioEmulaw);
377 fp->encoding = AUDIO_ENCODING_ULAW;
378 fp->precision = 8;
379 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
380 break;
381
382 case 2:
383 strcpy(fp->name, AudioEulinear);
384 fp->encoding = AUDIO_ENCODING_ULINEAR;
385 fp->precision = 8;
386 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
387 break;
388
389 default:
390 return(EINVAL);
391 /*NOTREACHED*/
392 }
393 return(0);
394 }
395
396 int
397 aucc_set_params(addr, setmode, usemode, p, r)
398 void *addr;
399 int setmode, usemode;
400 struct audio_params *p, *r;
401 {
402 struct aucc_softc *sc = addr;
403
404 /* if (setmode & AUMODE_RECORD)
405 return 0 ENXIO*/;
406
407 #ifdef AUCCDEBUG
408 printf("aucc_set_params(setmode 0x%x, usemode 0x%x, enc %d, bits %d, chn %d, sr %ld)\n",
409 setmode, usemode, p->encoding, p->precision, p->channels, p->sample_rate);
410 #endif
411
412 switch (p->encoding) {
413 case AUDIO_ENCODING_ULAW:
414 case AUDIO_ENCODING_SLINEAR:
415 case AUDIO_ENCODING_SLINEAR_BE:
416 case AUDIO_ENCODING_SLINEAR_LE:
417 case AUDIO_ENCODING_ULINEAR_BE:
418 case AUDIO_ENCODING_ULINEAR_LE:
419 break;
420
421 default:
422 return EINVAL;
423 /* NOTREADCHED */
424 }
425
426 if (p->precision != 8)
427 return EINVAL;
428
429 if ((p->channels<1) || (p->channels>4))
430 return(EINVAL);
431
432 sc->sc_channels = p->channels;
433 sc->sc_encoding = p->encoding;
434
435 return aucc_set_out_sr(addr, p->sample_rate);
436 }
437
438 int
439 aucc_round_blocksize(addr, blk)
440 void *addr;
441 int blk;
442 {
443
444
445 return blk>AUDIO_BUF_SIZE?AUDIO_BUF_SIZE:blk; /* round up to even size */
446 }
447
448 int
449 aucc_commit_settings(addr)
450 void *addr;
451 {
452 register struct aucc_softc *sc = addr;
453 register int i;
454
455 DPRINTF(("sa_commit.\n"));
456
457 for (i=0;i<4;i++) {
458 custom.aud[i].vol=sc->sc_channel[i].nd_volume;
459 custom.aud[i].per=sc->sc_channel[i].nd_per;
460 }
461
462 DPRINTF(("commit done\n"));
463
464 return(0);
465 }
466
467 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
468 static int masks2[4] = {1,2,4,8};
469
470 int
471 aucc_start_output(addr, p, cc, intr, arg)
472 void *addr;
473 void *p;
474 int cc;
475 void (*intr) __P((void *));
476 void *arg;
477 {
478 struct aucc_softc *sc;
479 int mask;
480 int i,j,k;
481 u_short *dmap[4];
482 u_char *pp;
483
484
485 sc = addr;
486 mask = sc->sc_channelmask;
487
488 dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
489
490 DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
491
492 if (sc->sc_channels > 1)
493 mask &=masks[sc->sc_channels-1];
494 /* we use first sc_channels channels */
495 if (mask==0) /* active and used channels are disjoint */
496 return EINVAL;
497
498 for (i=0;i<4;i++) { /* channels available ? */
499 if ((masks2[i]&mask)&&(sc->sc_channel[i].nd_busy))
500 return EBUSY; /* channel is busy */
501 if (channel[i].isaudio==-1)
502 return EBUSY; /* system uses them */
503 }
504
505 /* enable interrupt on 1st channel */
506 for (i=j=0;i<AUCC_MAXINT;i++) {
507 if (masks2[i]&mask) {
508 DPRINTF(("first channel is %d\n",i));
509 j=i;
510 sc->sc_channel[i].nd_intr=intr;
511 sc->sc_channel[i].nd_intrdata=arg;
512 break;
513 }
514 }
515
516 DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
517 dmap[2], dmap[3], mask));
518
519 /* disable ints, dma for channels, until all parameters set */
520 /* XXX dont disable DMA! custom.dmacon=mask;*/
521 custom.intreq=mask<<INTB_AUD0;
522 custom.intena=mask<<INTB_AUD0;
523
524 /* copy data to dma buffer */
525
526
527 pp=(u_char *)p;
528
529 if (sc->sc_channels == 1) {
530 dmap[0] =
531 dmap[1] =
532 dmap[2] =
533 dmap[3] = sc->sc_channel[j].nd_dma;
534 } else {
535 for (k=0; k<4; k++) {
536 if (masks2[k+j]&mask)
537 dmap[k]=sc->sc_channel[k+j].nd_dma;
538 }
539 }
540
541 sc->sc_channel[j].nd_doublebuf ^= 1;
542 if (sc->sc_channel[j].nd_doublebuf) {
543 dmap[0] += AUDIO_BUF_SIZE/sizeof(u_short);
544 dmap[1] += AUDIO_BUF_SIZE/sizeof(u_short);
545 dmap[2] += AUDIO_BUF_SIZE/sizeof(u_short);
546 dmap[3] += AUDIO_BUF_SIZE/sizeof(u_short);
547 }
548
549 aucc_encode(sc->sc_encoding, sc->sc_channels, cc, pp, dmap);
550
551 /* dma buffers: we use same buffer 4 all channels */
552 /* write dma location and length */
553 for (i=k=0; i<4; i++) {
554 if (masks2[i] & mask) {
555 DPRINTF(("turning channel %d on\n",i));
556 /* sc->sc_channel[i].nd_busy=1;*/
557 channel[i].isaudio=1;
558 channel[i].play_count=1;
559 channel[i].handler=NULL;
560 custom.aud[i].per=sc->sc_channel[i].nd_per;
561 custom.aud[i].vol=sc->sc_channel[i].nd_volume;
562 custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
563 custom.aud[i].len=cc/(sc->sc_channels*2);
564 sc->sc_channel[i].nd_mask=mask;
565 DPRINTF(("per is %d, vol is %d, len is %d\n",\
566 sc->sc_channel[i].nd_per,
567 sc->sc_channel[i].nd_volume, cc>>1));
568
569 }
570 }
571
572 channel[j].handler=aucc_inthdl;
573
574 /* enable ints */
575 custom.intena=INTF_SETCLR|INTF_INTEN| (masks2[j]<<INTB_AUD0);
576
577 DPRINTF(("enabled ints: 0x%x\n",(masks2[j]<<INTB_AUD0)));
578
579 /* enable dma */
580 custom.dmacon=DMAF_SETCLR|DMAF_MASTER|mask;
581
582 DPRINTF(("enabled dma, mask=0x%x\n",mask));
583
584 return(0);
585 }
586
587 /* ARGSUSED */
588 int
589 aucc_start_input(addr, p, cc, intr, arg)
590 void *addr;
591 void *p;
592 int cc;
593 void (*intr) __P((void *));
594 void *arg;
595 {
596
597 return ENXIO; /* no input */
598 }
599
600 int
601 aucc_halt_output(addr)
602 void *addr;
603 {
604 register struct aucc_softc *sc = addr;
605 register int i;
606
607 /* XXX only halt, if input is also halted ?? */
608 /* stop dma, etc */
609 custom.intena = AUCC_ALLINTF;
610 custom.dmacon = AUCC_ALLDMAF;
611 /* mark every busy unit idle */
612 for (i=0;i<4;i++) {
613 sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0;
614 channel[i].isaudio=0;
615 channel[i].play_count=0;
616 }
617
618 return(0);
619 }
620
621 int
622 aucc_halt_input(addr)
623 void *addr;
624 {
625 /* no input */
626
627 return ENXIO;
628 }
629
630 int
631 aucc_getdev(addr, retp)
632 void *addr;
633 struct audio_device *retp;
634 {
635 *retp = aucc_device;
636 return 0;
637 }
638
639 int
640 aucc_set_port(addr, cp)
641 void *addr;
642 mixer_ctrl_t *cp;
643 {
644 register struct aucc_softc *sc = addr;
645 register int i,j;
646
647 DPRINTF(("aucc_set_port: port=%d", cp->dev));
648
649 switch (cp->type) {
650 case AUDIO_MIXER_SET:
651 if (cp->dev!=AUCC_CHANNELS)
652 return EINVAL;
653 i=cp->un.mask;
654 if ((i<1)||(i>15))
655 return EINVAL;
656 sc->sc_channelmask=i;
657 break;
658
659 case AUDIO_MIXER_VALUE:
660 i=cp->un.value.num_channels;
661 if ((i<1)||(i>4))
662 return EINVAL;
663
664 #ifdef __XXXwhatsthat
665 if (cp->dev!=AUCC_VOLUME)
666 return EINVAL;
667 #endif
668
669 /* set volume for channel 0..i-1 */
670 if (i>1)
671 for (j=0;j<i;j++)
672 sc->sc_channel[j].nd_volume =
673 cp->un.value.level[j]>>2;
674 else if (sc->sc_channels > 1)
675 for (j=0; j<sc->sc_channels; j++)
676 sc->sc_channel[j].nd_volume =
677 cp->un.value.level[0]>>2;
678 else
679 for (j=0; j<4; j++)
680 sc->sc_channel[j].nd_volume =
681 cp->un.value.level[0]>>2;
682 break;
683
684 default:
685 return EINVAL;
686 break;
687 }
688 return 0;
689 }
690
691
692 int
693 aucc_get_port(addr, cp)
694 void *addr;
695 mixer_ctrl_t *cp;
696 {
697 register struct aucc_softc *sc = addr;
698 register int i,j;
699
700 DPRINTF(("aucc_get_port: port=%d", cp->dev));
701
702 switch (cp->type) {
703 case AUDIO_MIXER_SET:
704 if (cp->dev!=AUCC_CHANNELS)
705 return EINVAL;
706 cp->un.mask=sc->sc_channelmask;
707 break;
708
709 case AUDIO_MIXER_VALUE:
710 i = cp->un.value.num_channels;
711 if ((i<1)||(i>4))
712 return EINVAL;
713
714 for (j=0;j<i;j++)
715 cp->un.value.level[j] =
716 (sc->sc_channel[j].nd_volume<<2) +
717 (sc->sc_channel[j].nd_volume>>4);
718 break;
719
720 default:
721 return EINVAL;
722 }
723 return 0;
724 }
725
726
727 int
728 aucc_get_props(addr)
729 void *addr;
730 {
731 return 0;
732 }
733
734 int
735 aucc_query_devinfo(addr, dip)
736 void *addr;
737 register mixer_devinfo_t *dip;
738 {
739 register int i;
740
741 switch(dip->index) {
742 case AUCC_CHANNELS:
743 dip->type = AUDIO_MIXER_SET;
744 dip->mixer_class = AUCC_OUTPUT_CLASS;
745 dip->prev = dip->next = AUDIO_MIXER_LAST;
746 strcpy(dip->label.name, AudioNspeaker);
747 for (i=0;i<16;i++) {
748 sprintf(dip->un.s.member[i].label.name,
749 "channelmask%d", i);
750 dip->un.s.member[i].mask = i;
751 }
752 dip->un.s.num_mem = 16;
753 break;
754
755 case AUCC_VOLUME:
756 dip->type = AUDIO_MIXER_VALUE;
757 dip->mixer_class = AUCC_OUTPUT_CLASS;
758 dip->prev = dip->next = AUDIO_MIXER_LAST;
759 strcpy(dip->label.name, AudioNmaster);
760 dip->un.v.num_channels = 4;
761 strcpy(dip->un.v.units.name, AudioNvolume);
762 break;
763
764 case AUCC_OUTPUT_CLASS:
765 dip->type = AUDIO_MIXER_CLASS;
766 dip->mixer_class = AUCC_OUTPUT_CLASS;
767 dip->next = dip->prev = AUDIO_MIXER_LAST;
768 strcpy(dip->label.name, AudioCoutputs);
769 break;
770
771 default:
772 return ENXIO;
773 }
774
775 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
776
777 return(0);
778 }
779
780
781 /* audio int handler */
782 void
783 aucc_inthdl(int ch)
784 {
785 register int i;
786 register int mask=aucc->sc_channel[ch].nd_mask;
787
788 /* for all channels in this maskgroup:
789 disable dma, int
790 mark idle */
791 DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask));
792
793 custom.intreq=mask<<INTB_AUD0; /* clear request */
794 /* XXX: maybe we can leave ints and/or DMA on, if another sample has to be played?*/
795 custom.intena=mask<<INTB_AUD0;
796 /*
797 * XXX custom.dmacon=mask; NO!!!
798 */
799 for (i=0;i<4;i++) {
800 if (masks2[i]&&mask) {
801 DPRINTF(("marking channel %d idle\n",i));
802 aucc->sc_channel[i].nd_busy=0;
803 aucc->sc_channel[i].nd_mask=0;
804 channel[i].isaudio=channel[i].play_count=0;
805 }
806 }
807
808 /* call handler */
809 if (aucc->sc_channel[ch].nd_intr) {
810 DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
811 (*(aucc->sc_channel[ch].nd_intr))(aucc->sc_channel[ch].nd_intrdata);
812 }
813 else DPRINTF(("zero int handler\n"));
814 DPRINTF(("ints done\n"));
815 }
816
817
818
819
820 /* transform frequency to period, adjust bounds */
821 static u_int
822 freqtoper(u_int freq)
823 {
824 u_int per=eclockfreq*5/freq;
825
826 if (per<124)
827 per=124; /* must have at least 124 ticks between samples */
828
829 return per;
830 }
831
832 /* transform period to frequency */
833 static u_int
834 pertofreq(u_int per)
835 {
836 u_int freq=eclockfreq*5/per;
837
838
839 return freq;
840 }
841
842
843
844 void
845 aucc_encode(enc, channels, i, p, dmap)
846 int enc, channels, i;
847 u_char *p;
848 u_short **dmap;
849 {
850 char *q, *r, *s, *t;
851 int off;
852 u_char *tab;
853
854 #ifdef AUCCDEBUG
855 static int debctl = 6;
856 #endif
857
858 off = 0;
859 tab = NULL;
860
861 #ifdef AUCCDEBUG
862 if (--debctl >= 0)
863 printf("Enc: enc %d, chan %d, dmap %p %p %p %p\n",
864 enc, channels, dmap[0], dmap[1], dmap[2], dmap[3]);
865 #endif
866
867 switch (enc) {
868 case AUDIO_ENCODING_ULAW:
869 tab=ulaw_to_lin;
870 break;
871 case AUDIO_ENCODING_ULINEAR_BE:
872 case AUDIO_ENCODING_ULINEAR_LE:
873 off=-128;
874 break;
875 case AUDIO_ENCODING_SLINEAR_BE:
876 case AUDIO_ENCODING_SLINEAR_LE:
877 break;
878 default:
879 return;
880 }
881
882 q = (char *)dmap[0];
883 r = (char *)dmap[1];
884 s = (char *)dmap[2];
885 t = (char *)dmap[3];
886
887 if (tab)
888 while (i) {
889 switch (channels) {
890 case 4: *t++ = tab[*p++];
891 case 3: *s++ = tab[*p++];
892 case 2: *r++ = tab[*p++];
893 case 1: *q++ = tab[*p++];
894 }
895 i -= channels;
896 }
897 else
898 while (i) {
899 switch (channels) {
900 case 4: *t++ = *p++ + off;
901 case 3: *s++ = *p++ + off;
902 case 2: *r++ = *p++ + off;
903 case 1: *q++ = *p++ + off;
904 }
905 i -= channels;
906 }
907
908 }
909
910 #endif /* NAUCC > 0 */
911