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