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