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