1 /*	$OpenBSD: aria.c,v 1.10 2004/01/09 21:32:23 brad Exp $ */
2 
3 /*
4  * Copyright (c) 1995, 1996 Roland C. Dowdeswell.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by Roland C. Dowdeswell.
17  * 4. The name of the authors may not be used to endorse or promote products
18  *      derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * TODO:
34  *  o   Test the driver on cards other than a single
35  *      Prometheus Aria 16.
36  *  o   Look into where aria_prometheus_kludge() belongs.
37  *  o   Add some dma code.  It accomplishes its goal by
38  *      direct IO at the moment.
39  *  o   Look into return values on aria_set_sr(), if there is
40  *      no matching rate.  (I think that this behaves in the
41  *      same way as sbdsp.c)
42  *  o   Different programs should be able to open the device
43  *      with O_RDONLY and O_WRONLY at the same time.  But I
44  *      do not see support for this in /sys/dev/audio.c, so
45  *	I cannot effectively code it.
46  *  o   Separate the debugging code, with a #define.
47  *      Write more into aria_printsc().
48  *  o   Rework the mixer interface.
49  *       o   Deal with the lvls better.  We need to do better mapping
50  *           between logarithmic scales and the one byte that
51  *           we are passed.
52  *       o   Deal better with cards that have no mixer.
53  *
54  * roland@imrryr.org
55  * update from http://www.imrryr.org/NetBSD/hacks/aria/
56  */
57 
58 #include "aria.h"
59 #if NARIA > 0
60 
61 #include <sys/param.h>
62 #include <sys/systm.h>
63 #include <sys/errno.h>
64 #include <sys/ioctl.h>
65 #include <sys/syslog.h>
66 #include <sys/device.h>
67 #include <sys/proc.h>
68 #include <sys/buf.h>
69 
70 #include <machine/cpu.h>
71 #include <machine/pio.h>
72 
73 #include <sys/audioio.h>
74 #include <dev/audio_if.h>
75 
76 #include <dev/mulaw.h>
77 #include <dev/isa/isavar.h>
78 #include <dev/isa/isadmavar.h>
79 #include <i386/isa/icu.h>
80 
81 #include <dev/isa/ariareg.h>
82 
83 #define FREAD 1
84 #define FWRITE 2
85 
86 #ifdef AUDIO_DEBUG
87 extern void Dprintf(const char *, ...);
88 #define DPRINTF(x)	if (ariadebug) Dprintf x
89 int	ariadebug = 0;
90 #else
91 #define DPRINTF(x)
92 #endif
93 
94 struct aria_mixdev_info {
95 	u_char	num_channels;
96 	u_char	level[2];
97 	u_char	mute;
98 };
99 
100 struct aria_mixmaster {
101 	u_char num_channels;
102 	u_char level[2];
103 	u_char treble[2];
104 	u_char bass[2];
105 };
106 
107 struct aria_softc {
108 	struct	device sc_dev;		/* base device */
109 	struct	isadev sc_id;		/* ISA device */
110 	void	*sc_ih;			/* interrupt vectoring */
111 
112 	u_short	sc_iobase;		/* I/O port base address */
113 	u_short sc_irq;			/* interrupt */
114 	u_short sc_drq;			/* dma chan */
115 
116 	u_short	sc_open;		/* reference count of open calls */
117 	u_short sc_play;		/* non-paused play chans 2**chan */
118 	u_short sc_record;		/* non-paused record chans 2**chan */
119 	u_short sc_change;		/* to keep track of changes of a type */
120 	u_short gain[2];		/* left/right gain (play) */
121 	u_int	spkr_state;		/* non-null is on */
122 
123 	u_long	sc_rate;		/* Sample rate for input and output */
124 	u_int	sc_encoding;		/* audio encoding -- ulaw/linear */
125 	int	sc_chans;		/* # of channels */
126 	int	sc_precision;		/* # bits per sample */
127 
128 	u_long	sc_interrupts;		/* number of interrupts taken */
129 	void	(*sc_rintr)(void *);	/* record transfer completion intr handler */
130 	void	(*sc_pintr)(void *);	/* play transfer completion intr handler */
131 	void	*sc_rarg;		/* arg for sc_rintr() */
132 	void	*sc_parg;		/* arg for sc_pintr() */
133 
134 	int	sc_blocksize;		/* literal dio block size */
135 	void	*sc_rdiobuffer;		/* record: where the next samples should be */
136 	void	*sc_pdiobuffer;		/* play:   where the next samples are */
137 
138 	u_short sc_hardware;		/* bit field of hardware present */
139 #define ARIA_TELEPHONE	0x0001		/* has telephone input */
140 #define ARIA_MIXER	0x0002		/* has SC18075 digital mixer */
141 #define ARIA_MODEL	0x0004		/* is SC18025 (=0) or SC18026 (=1) */
142 
143 	struct aria_mixdev_info aria_mix[6];
144 	struct aria_mixmaster ariamix_master;
145 	u_char	aria_mix_source;
146 };
147 
148 struct {
149 	int sendcmd;
150 	int wmidi;
151 } ariaerr;
152 
153 
154 
155 int	ariaprobe();
156 void	ariaattach(struct device *, struct device *, void *);
157 void	ariaclose(void *);
158 int	ariaopen(dev_t, int);
159 int	aria_getdev(void *, struct audio_device *);
160 
161 void	aria_do_kludge(u_short, u_short, u_short, u_short, u_short);
162 void	aria_prometheus_kludge(struct isa_attach_args *);
163 
164 int	aria_set_sr(void *, u_long);
165 u_long	aria_get_sr(void *);
166 int	aria_query_encoding(void *, struct audio_encoding *);
167 int	aria_set_format(void *, u_int, u_int);
168 int	aria_get_encoding(void *);
169 int	aria_get_precision(void *);
170 int	aria_set_channels(void *, int);
171 int	aria_get_channels(void *);
172 int	aria_round_blocksize(void *, int);
173 int	aria_set_out_port(void *, int);
174 int	aria_get_out_port(void *);
175 int	aria_set_in_port(void *, int);
176 int	aria_get_in_port(void *);
177 int	aria_speaker_ctl(void *, int);
178 int	aria_commit_settings(void *);
179 
180 int	aria_start_output(void *, void *, int, void (*)(), void *);
181 int	aria_start_input(void *, void *, int, void (*)(), void *);
182 
183 int	aria_halt_input(void *);
184 int	aria_halt_output(void *);
185 int	aria_cont(void *);
186 
187 int	aria_sendcmd(u_short, u_short, int, int, int);
188 
189 u_short	aria_getdspmem(u_short, u_short);
190 u_short	aria_putdspmem(u_short, u_short, u_short);
191 
192 int	aria_intr(void *);
193 short	ariaversion(struct aria_softc *);
194 
195 int	aria_setfd(void *, int);
196 
197 void	aria_mix_write(struct aria_softc *, int, int);
198 int	aria_mix_read(struct aria_softc *, int);
199 
200 int	aria_mixer_set_port(void *, mixer_ctrl_t *);
201 int	aria_mixer_get_port(void *, mixer_ctrl_t *);
202 int	aria_mixer_query_devinfo(void *, mixer_devinfo_t *);
203 
204 /*
205  * Mixer defines...
206  */
207 
208 struct cfattach aria_ca = {
209 	sizeof(struct aria_softc), ariaprobe, ariaattach
210 };
211 
212 struct cfdriver aria_cd = {
213 	NULL, "aria", DV_DULL
214 };
215 
216 struct audio_device aria_device = {
217 	"Aria 16(se)",
218 	"x",
219 	"aria"
220 };
221 
222 /*
223  * Define our interface to the higher level audio driver.
224  */
225 
226 struct audio_hw_if aria_hw_if = {
227 	ariaopen,
228 	ariaclose,
229 	NULL,
230 	aria_set_sr,
231 	aria_get_sr,
232 	aria_set_sr,
233 	aria_get_sr,
234 	aria_query_encoding,
235 	aria_set_format,
236 	aria_get_encoding,
237 	aria_get_precision,
238 	aria_set_channels,
239 	aria_get_channels,
240 	aria_round_blocksize,
241 	aria_set_out_port,
242 	aria_get_out_port,
243 	aria_set_in_port,
244 	aria_get_in_port,
245 	aria_commit_settings,
246 	mulaw_expand,
247 	mulaw_compress,
248 	aria_start_output,
249 	aria_start_input,
250 	aria_halt_input,
251 	aria_halt_output,
252 	aria_cont,
253 	aria_cont,
254 	aria_speaker_ctl,
255 	aria_getdev,
256 	aria_setfd,
257 	aria_mixer_set_port,
258 	aria_mixer_get_port,
259 	aria_mixer_query_devinfo,
260 	1,	/* full-duplex */
261 	0,
262 	NULL,
263 	NULL
264 };
265 
266 /*
267  * Probe / attach routines.
268  */
269 
270 /*
271  * Probe for the aria hardware.
272  */
273 int
ariaprobe(parent,self,aux)274 ariaprobe(parent, self, aux)
275 	struct device *parent, *self;
276 	void *aux;
277 {
278 	register struct aria_softc *sc = (void *)self;
279 	register struct isa_attach_args *ia = aux;
280         struct cfdata *cf = sc->sc_dev.dv_cfdata;
281 	register u_short iobase = ia->ia_iobase;
282 	static u_char irq_conf[11] = {
283 	    -1, -1, 0x01, -1, -1, 0x02, -1, 0x04, -1, 0x01, 0x08
284 	};
285 	int i,j;
286 	int flags = cf->cf_flags;
287 
288 	if (!ARIA_BASE_VALID(ia->ia_iobase)) {
289 		printf("aria: configured iobase %d invalid\n", ia->ia_iobase);
290 		return 0;
291 	}
292 	sc->sc_iobase = iobase;
293 
294 	if (!ARIA_IRQ_VALID(ia->ia_irq)) {
295 		printf("aria: configured irq %d invalid\n", ia->ia_irq);
296 		return 0;
297 	}
298 
299 	sc->sc_irq = ia->ia_irq;
300 
301 	if (flags & ARIAR_PROMETHEUS_KLUDGE)
302 		aria_prometheus_kludge(ia);
303 
304 	if (aria_reset(sc) != 0) {
305 		DPRINTF(("aria: aria probe failed\n"));
306 		return 0;
307 	}
308 
309 	ia->ia_iosize = ARIADSP_NPORT;
310 	return 1;
311 }
312 
313 
314 
315 /*
316  * I didn't call this a kludge for
317  * nothing.  This is cribbed from
318  * ariainit, the author of that
319  * disassembled some code to discover
320  * how to set up the initial values of
321  * the card.  Without this, the card
322  * is dead. (It will not respond to _any_
323  * input at all.)
324  *
325  * ariainit can be found (ftp) at:
326  * ftp://ftp.wi.leidenuniv.nl/pub/audio/aria/programming/contrib/ariainit.zip
327  * currently.
328  */
329 
330 void
aria_prometheus_kludge(ia)331 aria_prometheus_kludge(ia)
332 	register struct isa_attach_args *ia;
333 {
334 	int	i, j;
335 	u_short	end;
336 	u_short rba = ia->ia_iobase;
337 
338 	DPRINTF(("aria_prometheus_kludge\n"));
339 
340 /* Begin Config Sequence */
341 
342         outb(0x204, 0x4c);
343         outb(0x205, 0x42);
344         outb(0x206, 0x00);
345         outw(0x200, 0x0f);
346         outb(0x201, 0x00);
347         outw(0x200, 0x02);
348         outb(0x201, rba>>2);
349 
350 /* These next three lines set up the iobase, and the irq; and disable the drq.  */
351 
352 	aria_do_kludge(0x111, ((ia->ia_iobase-0x280)>>2)+0xA0, 0xbf, 0xa0, rba);
353 	aria_do_kludge(0x011, ia->ia_irq-6, 0xf8, 0x00, rba);
354 	aria_do_kludge(0x011, 0x00, 0xef, 0x00, rba);
355 
356 /* The rest of these lines just disable everything else */
357 
358 	aria_do_kludge(0x113, 0x00, 0x88, 0x00, rba);
359 	aria_do_kludge(0x013, 0x00, 0xf8, 0x00, rba);
360 	aria_do_kludge(0x013, 0x00, 0xef, 0x00, rba);
361 	aria_do_kludge(0x117, 0x00, 0x88, 0x00, rba);
362 	aria_do_kludge(0x017, 0x00, 0xff, 0x00, rba);
363 
364 /* End Sequence */
365 
366 	outb(0x200, 0x0f);
367 	end = inb(rba);
368 	outw(0x200, 0x0f);
369 	outb(0x201, end|0x80);
370 	inb(0x200);
371 /*
372  * This delay is necessary for some reason,
373  * at least it would crash, and sometimes not
374  * probe properly if it did not exist.
375  */
376 	delay(1000000);
377 }
378 
379 void
aria_do_kludge(func,bits,and,or,rba)380 aria_do_kludge(func, bits, and, or, rba)
381 	u_short func;
382 	u_short bits;
383 	u_short and;
384 	u_short or;
385 	u_short rba;
386 {
387 	u_int i;
388 	if (func & 0x100) {
389 		func &= ~0x100;
390 		if (bits) {
391 			outw(0x200, func-1);
392 			outb(0x201, bits);
393 		}
394 	} else
395 		or |= bits;
396 
397 	outb(0x200, func);
398 	i = inb(rba);
399 	outw(0x200, func);
400 	outb(0x201, (i&and) | or);
401 }
402 
403 /*
404  * Attach hardware to driver, attach hardware driver to audio
405  * pseudo-device driver.
406  */
407 void
ariaattach(parent,self,aux)408 ariaattach(parent, self, aux)
409 	struct device *parent, *self;
410 	void *aux;
411 {
412 	register struct aria_softc *sc = (struct aria_softc *)self;
413 	struct isa_attach_args *ia = (struct isa_attach_args *)aux;
414 	register u_short iobase = ia->ia_iobase;
415 	register u_short i;
416 	int err;
417 
418 	sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
419 	    IPL_AUDIO, aria_intr, sc, sc->sc_dev.dv_xname);
420 
421 	i = aria_getdspmem(iobase, ARIAA_HARDWARE_A);
422 
423 	sc->sc_hardware  = 0;
424 	sc->sc_hardware |= ((i>>13)&0x01==1)?ARIA_TELEPHONE:0;
425 	sc->sc_hardware |= (((i>>5)&0x07)==0x04)?ARIA_MIXER:0;
426 	sc->sc_hardware |= (aria_getdspmem(iobase, ARIAA_MODEL_A)==1)?ARIA_MODEL:0;
427 
428 	sc->sc_open       = 0;
429 	sc->sc_play       = 0;
430 	sc->sc_record     = 0;
431 	sc->sc_rate       = 7875;
432 	sc->sc_chans      = 1;
433 	sc->sc_change     = 1;
434 	sc->sc_blocksize  = 1024;
435 	sc->sc_precision  = 8;
436         sc->sc_rintr      = 0;
437         sc->sc_rarg       = 0;
438         sc->sc_pintr      = 0;
439         sc->sc_parg       = 0;
440 	sc->gain[0]       = 127;
441 	sc->gain[1]       = 127;
442 
443 	for (i=0; i<6; i++) {
444 		if (i == ARIAMIX_TEL_LVL)
445 			sc->aria_mix[i].num_channels = 1;
446 		else
447 			sc->aria_mix[i].num_channels = 2;
448 		sc->aria_mix[i].level[0] = 127;
449 		sc->aria_mix[i].level[1] = 127;
450 	}
451 
452 	sc->ariamix_master.num_channels = 2;
453 	sc->ariamix_master.level[0] = 222;
454 	sc->ariamix_master.level[1] = 222;
455 	sc->ariamix_master.bass[0] = 127;
456 	sc->ariamix_master.bass[1] = 127;
457 	sc->ariamix_master.treble[0] = 127;
458 	sc->ariamix_master.treble[1] = 127;
459 	sc->aria_mix_source = 0;
460 
461 	sc->sc_change = 1;
462 	aria_commit_settings(sc); /* so that my cdplayer is at the 'right' vol */
463 
464 	printf(": dsp %s", (ARIA_MODEL&sc->sc_hardware)?"SC18026":"SC18025");
465 	if (ARIA_TELEPHONE&sc->sc_hardware)
466 		printf(", tel");
467 	if (ARIA_MIXER&sc->sc_hardware)
468 		printf(", SC18075 mixer");
469 	printf("\n");
470 
471 	snprintf(aria_device.version, sizeof aria_device.version, "%s",
472 	    (ARIA_MODEL&sc->sc_hardware?"SC18026":"SC18025"));
473 
474 	if ((err = audio_hardware_attach(&aria_hw_if, sc)) != 0)
475 		printf("aria: could not attach to audio pseudo-device driver (%d)\n", err);
476 }
477 
478 /*
479  * Various routines to interface to higher level audio driver
480  */
481 
482 int
ariaopen(dev,flags)483 ariaopen(dev, flags)
484 	dev_t dev;
485 	int flags;
486 {
487 	struct aria_softc *sc;
488 	register u_short iobase = sc->sc_iobase;
489 	int unit = AUDIOUNIT(dev);
490 	short err;
491 
492 	DPRINTF(("ariaopen() called\n"));
493 
494 	if (unit >= aria_cd.cd_ndevs)
495 		return ENODEV;
496 
497 	sc = aria_cd.cd_devs[unit];
498 
499 	if (!sc || sc->sc_open != 0)
500 		return ENXIO;
501 
502 	sc->sc_open  = 0;
503 	if (flags&FREAD)
504 		sc->sc_open |= ARIAR_OPEN_RECORD;
505 	if (flags&FWRITE)
506 		sc->sc_open |= ARIAR_OPEN_PLAY;
507 	sc->sc_play  = 0;
508 	sc->sc_record= 0;
509 	sc->sc_rintr = 0;
510 	sc->sc_rarg  = 0;
511 	sc->sc_pintr = 0;
512 	sc->sc_parg  = 0;
513 	sc->sc_change= 1;
514 
515 	return 0;
516 }
517 
518 int
aria_getdev(addr,retp)519 aria_getdev(addr, retp)
520 	void *addr;
521 	struct audio_device *retp;
522 {
523 	*retp = aria_device;
524 	return 0;
525 }
526 
527 #ifdef AUDIO_DEBUG
528 void
aria_printsc(struct aria_softc * sc)529 aria_printsc(struct aria_softc *sc)
530 {
531 	printf("open %x dmachan %d irq %d iobase %x nintr %d\n", sc->sc_open, sc->sc_drq,
532 		sc->sc_irq, sc->sc_iobase, sc->sc_interrupts);
533 	printf("irate %d encoding %x chans %d\n", sc->sc_rate, sc->encoding,
534 		sc->sc_chans);
535 	printf("\n");
536 }
537 #endif
538 
539 
540 /*
541  * Various routines to interface to higher level audio driver
542  */
543 
544 int
aria_set_sr(addr,sr)545 aria_set_sr(addr, sr)
546 	void *addr;
547 	u_long sr;
548 {
549         struct aria_softc *sc = addr;
550 
551 	if (sr<=9000)
552 		sr = 7875;
553 	else if (sr<=15000)
554 		sr = 11025;
555 	else if (sr<=20000)
556 		sr = 15750;
557 	else if (sr<=25000)
558 		sr = 22050;
559 	else if (sr<=40000)
560 		sr = 31500;
561 	else
562 		sr = 44100;
563 
564 	sc->sc_rate = sr;
565 	return 0;
566 }
567 
568 u_long
aria_get_sr(addr)569 aria_get_sr(addr)
570 	void *addr;
571 {
572         struct aria_softc *sc = addr;
573 	return sc->sc_rate;
574 }
575 
576 int
aria_query_encoding(addr,fp)577 aria_query_encoding(addr, fp)
578     void *addr;
579     struct audio_encoding *fp;
580 {
581 	register struct aria_softc *sc = addr;
582 
583 	switch (fp->index) {
584 		case 0:
585 			strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
586 			fp->format_id = AUDIO_ENCODING_ULAW;
587 			break;
588 		case 1:
589 			strlcpy(fp->name, AudioEpcm16, sizeof fp->name);
590 			fp->format_id = AUDIO_ENCODING_PCM16;
591 			break;
592 		default:
593 			return(EINVAL);
594 		/*NOTREACHED*/
595 	}
596 
597 	return (0);
598 }
599 
600 int
aria_set_format(addr,enc,precision)601 aria_set_format(addr, enc, precision)
602 	void *addr;
603 	u_int enc, prec;
604 {
605         register struct aria_softc *sc = addr;
606 
607 	DPRINTF(("aria_set_format\n"));
608 
609         switch(enc){
610         case AUDIO_ENCODING_ULAW:
611         case AUDIO_ENCODING_PCM16:
612 	case AUDIO_ENCODING_PCM8:
613 		break;
614         default:
615                 return (EINVAL);
616         }
617 
618 	if (prec!=8 && prec!=16)
619 		return (EINVAL);
620 
621 	if (sc->encoding!=AUDIO_ENCODING_PCM16 && prec==16)
622 		return (EINVAL);
623 
624 	sc->sc_encoding = enc;
625 	sc->sc_precision = prec;
626         return (0);
627 }
628 
629 int
aria_get_encoding(addr)630 aria_get_encoding(addr)
631 	void *addr;
632 {
633         register struct aria_softc *sc = addr;
634 
635 	DPRINTF(("aria_get_encoding\n"));
636 
637         return(sc->encoding);
638 }
639 
640 int
aria_get_precision(addr)641 aria_get_precision(addr)
642 	void *addr;
643 {
644         struct aria_softc *sc = addr;
645 
646 	DPRINTF(("aria_get_precision\n"));
647 
648 	return sc->sc_precision;
649 }
650 
651 int
aria_set_channels(addr,chans)652 aria_set_channels(addr, chans)
653 	void *addr;
654 	int chans;
655 {
656         struct aria_softc *sc = addr;
657 
658 	DPRINTF(("aria_set_channels\n"));
659 
660 	if (chans != 1 && chans != 2)
661 		return EINVAL;
662 
663 	sc->sc_chans = chans;
664 
665 	return(0);
666 }
667 
668 int
aria_get_channels(addr)669 aria_get_channels(addr)
670 	void *addr;
671 {
672         struct aria_softc *sc = addr;
673 
674 	DPRINTF(("aria_get_channels\n"));
675 
676 	return sc->sc_chans;
677 }
678 
679 /*
680  * There is only one way to output on
681  * this card.
682  */
683 int
aria_set_out_port(addr,port)684 aria_set_out_port(addr, port)
685 	void *addr;
686 	int port;
687 {
688 	DPRINTF(("aria_set_out_port\n"));
689 	return(0);
690 }
691 
692 int
aria_get_out_port(addr)693 aria_get_out_port(addr)
694 	void *addr;
695 {
696 	DPRINTF(("aria_get_out_port\n"));
697 	return(ARIAMIX_OUT_LVL);
698 }
699 
700 
701 int
aria_set_in_port(addr,port)702 aria_set_in_port(addr, port)
703 	void *addr;
704 	int port;
705 {
706 	register struct aria_softc *sc = addr;
707 
708 	DPRINTF(("aria_set_in_port\n"));
709 
710 	if (port<0 || port>6)
711 		return ENXIO;
712 
713 	sc->aria_mix_source = port;
714 	return(0);
715 }
716 
717 int
aria_get_in_port(addr)718 aria_get_in_port(addr)
719 	void *addr;
720 {
721 	register struct aria_softc *sc = addr;
722 
723 	DPRINTF(("aria_get_in_port\n"));
724 
725 	return(sc->aria_mix_source);
726 }
727 
728 /*
729  * XXX -- to be done
730  *  I should probably just add a mixer thing, and
731  *  access it through here.
732  */
733 int
aria_speaker_ctl(addr,newstate)734 aria_speaker_ctl(addr, newstate)
735 	void *addr;
736 	int newstate;
737 {
738 	return(0);
739 }
740 
741 /*
742  * Store blocksize in words (what the chipset
743  * understands), but report and take values
744  * in bytes.
745  */
746 
747 int
aria_round_blocksize(addr,blk)748 aria_round_blocksize(addr, blk)
749 	void *addr;
750 	int blk;
751 {
752 	int i;
753         struct aria_softc *sc = addr;
754 	for (i=64; i<1024; i*=2)
755 		if (blk <= i)
756 			break;
757 	sc->sc_blocksize = i;
758 	sc->sc_change = 1;
759 	return(i);
760 }
761 
762 /*
763  * This is where all of the twiddling goes on.
764  */
765 
766 int
aria_commit_settings(addr)767 aria_commit_settings(addr)
768 	void *addr;
769 {
770         struct aria_softc *sc = addr;
771 	register u_short iobase = sc->sc_iobase;
772 	u_char tones[16] = { 7, 6, 5, 4, 3, 2, 1, 0, 8, 9, 10, 11, 12, 13, 14, 15 };
773 	u_short format;
774 	u_short left, right;
775 	u_short samp;
776 	u_char i;
777 
778 	DPRINTF(("aria_commit_settings\n"));
779 
780 	switch (sc->sc_rate) {
781 		case  7875: format = 0x00; samp = 0x60; break;
782 		case 11025: format = 0x00; samp = 0x40; break;
783 		case 15750: format = 0x10; samp = 0x60; break;
784 		case 22050: format = 0x10; samp = 0x40; break;
785 		case 31500: format = 0x10; samp = 0x20; break;
786 		case 44100: format = 0x20; samp = 0x00; break;
787 		default:    format = 0x00; samp = 0x40; break;
788 	}
789 
790 	format |= (sc->sc_chans==2)?1:0;
791 	format |= (sc->sc_precision==16)?2:0;
792 
793 	aria_sendcmd(iobase, ARIADSPC_FORMAT, format, -1, -1);
794 	outw(iobase+ARIADSP_CONTROL, (inw(iobase+ARIADSP_STATUS)&~0x60)|samp); /* Addition parm for sample rate */
795 
796 	if (sc->sc_hardware&ARIA_MIXER) {
797 		for (i=0; i<6; i++) {
798 			u_char source;
799 			switch(i) {
800 			case ARIAMIX_MIC_LVL:     source = 0x0001; break;
801 			case ARIAMIX_CD_LVL:      source = 0x0002; break;
802 			case ARIAMIX_LINE_IN_LVL: source = 0x0008; break;
803 			case ARIAMIX_TEL_LVL:     source = 0x0020; break;
804 			case ARIAMIX_AUX_LVL:     source = 0x0010; break;
805 			case ARIAMIX_DAC_LVL:     source = 0x0004; break;
806 			default:               source = 0x0000; break;
807 			}
808 
809 			if (source != 0x0000 && source != 0x0004) {
810 				if (sc->aria_mix[i].mute == 1)
811 					aria_sendcmd(iobase, ARIADSPC_INPMONMODE, source, 3, -1);
812 				else
813 					aria_sendcmd(iobase, ARIADSPC_INPMONMODE, source, (sc->aria_mix[i].num_channels==2)?0:1, -1);
814 
815 				aria_sendcmd(iobase, ARIADSPC_INPMONMODE, 0x8000|source, (sc->aria_mix[i].num_channels==2)?0:1, -1);
816 				aria_sendcmd(iobase, ARIADSPC_MIXERVOL, source, sc->aria_mix[i].level[0] << 7, sc->aria_mix[i].level[1] << 7);
817 			}
818 
819 			if (sc->aria_mix_source == i) {
820 				aria_sendcmd(iobase, ARIADSPC_ADCSOURCE, source, -1, -1);
821 
822 				if (sc->sc_open & ARIAR_OPEN_RECORD)
823 					aria_sendcmd(iobase, ARIADSPC_ADCCONTROL, 1, -1, -1);
824 				else
825 					aria_sendcmd(iobase, ARIADSPC_ADCCONTROL, 0, -1, -1);
826 			}
827 		}
828 
829 		if (sc->sc_chans==2) {
830 			aria_sendcmd(iobase, ARIADSPC_CHAN_VOL, (sc->gain[0]+sc->gain[1])/2, -1, -1);
831 			aria_sendcmd(iobase, ARIADSPC_CHAN_PAN, (sc->gain[0]-sc->gain[1])/4+0x40, -1, -1);
832 		} else {
833 			aria_sendcmd(iobase, ARIADSPC_CHAN_VOL, sc->gain[0], -1, -1);
834 			aria_sendcmd(iobase, ARIADSPC_CHAN_PAN, 0x40, -1, -1);
835 		}
836 
837 		/* aria_sendcmd(iobase, ARIADSPC_MASMONMODE, (sc->ariamix_master.num_channels==2)?0:1 | (1<<8), -1, -1); */
838 		aria_sendcmd(iobase, ARIADSPC_MASMONMODE, (sc->ariamix_master.num_channels==2)?0:1, -1, -1);
839 
840 		aria_sendcmd(iobase, ARIADSPC_MIXERVOL, 0x0004, sc->ariamix_master.level[0] << 7, sc->ariamix_master.level[1] << 7);
841 
842 		/* Convert treb/bass from byte to soundcard style */
843 
844 		left  = tones[(sc->ariamix_master.bass[0]>>4)&0x0f]<<8 | tones[(sc->ariamix_master.treble[0]>>4)&0x0f];
845 		right = tones[(sc->ariamix_master.bass[1]>>4)&0x0f]<<8 | tones[(sc->ariamix_master.treble[1]>>4)&0x0f];
846 
847 		aria_sendcmd(iobase, ARIADSPC_TONE, left, right, -1);
848 	}
849 
850 	if (sc->sc_change != 0)
851 		aria_sendcmd(iobase, ARIADSPC_BLOCKSIZE, sc->sc_blocksize/2, -1, -1);
852 
853 /*
854  * If we think that the card is recording or playing, start it up again here.
855  * Some of the previous commands turn the channels off.
856  */
857 
858 	if (sc->sc_record&(1<<ARIAR_RECORD_CHAN)) {
859 		aria_sendcmd(iobase, ARIADSPC_START_REC, ARIAR_PLAY_CHAN, -1, -1);
860 		sc->sc_play |= (1<<ARIAR_RECORD_CHAN);
861 	}
862 
863 	if (sc->sc_play&(1<<ARIAR_PLAY_CHAN)) {
864 		aria_sendcmd(iobase, ARIADSPC_START_PLAY, ARIAR_PLAY_CHAN, -1, -1);
865 		sc->sc_play |= (1<<ARIAR_PLAY_CHAN);
866 	}
867 
868 	sc->sc_change = 0;
869 
870 	return(0);
871 }
872 
873 void
ariaclose(addr)874 ariaclose(addr)
875 	void *addr;
876 {
877         struct aria_softc *sc = addr;
878 	register u_int iobase = sc->sc_iobase;
879 
880 	DPRINTF(("aria_close sc=0x%x\n", sc));
881 
882         sc->spkr_state = SPKR_OFF;
883         sc->sc_rintr = 0;
884         sc->sc_pintr = 0;
885 	sc->sc_rdiobuffer = 0;
886 	sc->sc_pdiobuffer = 0;
887 
888 	if (sc->sc_play&(1<<ARIAR_PLAY_CHAN) && sc->sc_open & ARIAR_OPEN_PLAY) {
889 		aria_sendcmd(iobase, ARIADSPC_STOP_PLAY, ARIAR_PLAY_CHAN, -1, -1);
890 		sc->sc_play &= ~(1<<ARIAR_PLAY_CHAN);
891 	}
892 
893 	if (sc->sc_record&(1<<ARIAR_RECORD_CHAN) && sc->sc_open & ARIAR_OPEN_RECORD) {
894 		aria_sendcmd(iobase, ARIADSPC_STOP_REC, ARIAR_RECORD_CHAN, -1, -1);
895 		sc->sc_record &= ~(1<<ARIAR_RECORD_CHAN);
896 	}
897 
898 	sc->sc_open = 0;
899 
900 	if (aria_reset(sc) != 0) {
901 		delay(500);
902 		aria_reset(sc);
903 	}
904 }
905 
906 /*
907  * Reset the hardware.
908  */
909 
910 int
aria_reset(sc)911 aria_reset(sc)
912 	register struct aria_softc *sc;
913 {
914 	register u_short iobase = sc->sc_iobase;
915 	int fail=0;
916 
917 	outw(iobase + ARIADSP_CONTROL, ARIAR_ARIA_SYNTH|ARIAR_SR22K|ARIAR_DSPINTWR);
918 	aria_putdspmem(iobase, 0x6102, 0);
919 
920 	fail |= aria_sendcmd(iobase, ARIADSPC_SYSINIT, 0x0000, 0x0000, 0x0000);
921 
922 	while (aria_getdspmem(iobase, ARIAA_TASK_A) != 1)
923 		;
924 
925 	outw(iobase+ARIADSP_CONTROL, ARIAR_ARIA_SYNTH|ARIAR_SR22K|ARIAR_DSPINTWR|ARIAR_PCINTWR);
926 	fail |= aria_sendcmd(iobase, ARIADSPC_MODE, ARIAV_MODE_NO_SYNTH,-1,-1);
927 
928 	return (fail);
929 }
930 
931 /*
932  * Lower-level routines
933  */
934 
935 u_short
aria_putdspmem(iobase,loc,val)936 aria_putdspmem(iobase, loc, val)
937 	register u_short iobase;
938 	register u_short loc;
939 	register u_short val;
940 {
941 	outw(iobase + ARIADSP_DMAADDRESS, loc);
942 	outw(iobase + ARIADSP_DMADATA, val);
943 }
944 
945 u_short
aria_getdspmem(iobase,loc)946 aria_getdspmem(iobase, loc)
947 	register u_short iobase;
948 	register u_short loc;
949 {
950 	outw(iobase+ARIADSP_DMAADDRESS, loc);
951 	return inw(iobase+ARIADSP_DMADATA);
952 }
953 
954 /*
955  * aria_sendcmd()
956  *  each full DSP command is unified into this
957  *  function.
958  */
959 
960 int
aria_sendcmd(iobase,command,arg1,arg2,arg3)961 aria_sendcmd(iobase, command, arg1, arg2, arg3)
962 	u_short iobase;
963 	u_short command;
964 	int arg1;
965 	int arg2;
966 	int arg3;
967 {
968 	int i, fail = 0;
969 
970 	for (i = ARIAR_NPOLL; (inw(iobase + ARIADSP_STATUS) & ARIAR_BUSY) != 0 && i>0; i-- )
971 		;
972 
973 	fail |= (inw(iobase + ARIADSP_STATUS) & ARIAR_BUSY)==0?0:1;
974 	outw(iobase + ARIADSP_WRITE, (u_short) command);
975 
976 	if (arg1 != -1) {
977 		for (i = ARIAR_NPOLL; (inw(iobase + ARIADSP_STATUS) & ARIAR_BUSY) != 0 && i>0; i-- )
978 			;
979 
980 		fail |= (inw(iobase + ARIADSP_STATUS) & ARIAR_BUSY)==0?0:2;
981 		outw(iobase + ARIADSP_WRITE, (u_short) arg1);
982 	}
983 
984 	if (arg2 != -1) {
985 		for (i = ARIAR_NPOLL; (inw(iobase + ARIADSP_STATUS) & ARIAR_BUSY) != 0 && i>0; i-- )
986 			;
987 
988 		fail |= (inw(iobase + ARIADSP_STATUS) & ARIAR_BUSY)==0?0:4;
989 		outw(iobase + ARIADSP_WRITE, (u_short) arg2);
990 	}
991 
992 	if (arg3 != -1) {
993 		for (i = ARIAR_NPOLL; (inw(iobase + ARIADSP_STATUS) & ARIAR_BUSY) != 0 && i>0; i-- )
994 			;
995 
996 		fail |= (inw(iobase + ARIADSP_STATUS) & ARIAR_BUSY)==0?0:8;
997 		outw(iobase + ARIADSP_WRITE, (u_short) arg3);
998 	}
999 
1000 	for (i = ARIAR_NPOLL; (inw(iobase + ARIADSP_STATUS) & ARIAR_BUSY) != 0 && i>0; i-- )
1001 		;
1002 
1003         fail |= (inw(iobase + ARIADSP_STATUS) & ARIAR_BUSY)==0?0:16;
1004 	outw(iobase + ARIADSP_WRITE, (u_short) ARIADSPC_TERM);
1005 
1006 #ifdef AUDIO_DEBUG
1007 	if (fail) {
1008 		++ariaerr.sendcmd;
1009 		DPRINTF(("aria_sendcmd: failure=(%d) cmd=(0x%x) fail=(0x%x)\n", ariaerr.sendcmd, command, fail));
1010 		return -1;
1011 	}
1012 #else
1013 	if (fail != 0) {
1014 		++ariaerr.sendcmd;
1015 		return -1;
1016 	}
1017 #endif
1018 
1019 	return 0;
1020 }
1021 
1022 int
aria_halt_input(addr)1023 aria_halt_input(addr)
1024 	void *addr;
1025 {
1026 	register struct aria_softc *sc = addr;
1027 
1028 	DPRINTF(("aria_halt_input\n"));
1029 
1030 	if (sc->sc_record&(1<<0)) {
1031 		aria_sendcmd(sc->sc_iobase, ARIADSPC_STOP_REC, 0, -1, -1);
1032 		sc->sc_record &= ~(1<<0);
1033 	}
1034 
1035 	return(0);
1036 }
1037 
1038 int
aria_halt_output(addr)1039 aria_halt_output(addr)
1040 	void *addr;
1041 {
1042 	register struct aria_softc *sc = addr;
1043 
1044 	DPRINTF(("aria_halt_output\n"));
1045 
1046 	if (sc->sc_play & (1<<1)) {
1047 		aria_sendcmd(sc->sc_iobase, ARIADSPC_STOP_PLAY, 1, -1, -1);
1048 		sc->sc_play &= ~(1<<1);
1049 	}
1050 
1051 	return(0);
1052 }
1053 
1054 /*
1055  * This is not called in dev/audio.c?
1056  */
1057 int
aria_cont(addr)1058 aria_cont(addr)
1059 	void *addr;
1060 {
1061 	register struct aria_softc *sc = addr;
1062 
1063 	DPRINTF(("aria_cont\n"));
1064 
1065 	if (!sc->sc_record&(1<<0) && (sc->sc_open&ARIAR_OPEN_RECORD)) {
1066 		aria_sendcmd(sc->sc_iobase, ARIADSPC_START_REC,  ARIAR_RECORD_CHAN, -1, -1);
1067 		sc->sc_record |= ~(1<<ARIAR_RECORD_CHAN);
1068 	}
1069 
1070 	if (!sc->sc_play&(1<<ARIAR_PLAY_CHAN) && (sc->sc_open&ARIAR_OPEN_PLAY)) {
1071 		aria_sendcmd(sc->sc_iobase, ARIADSPC_START_PLAY, 1, -1, -1);
1072 		sc->sc_play |= ~(1<<ARIAR_PLAY_CHAN);
1073 	}
1074 
1075 	return(0);
1076 }
1077 
1078 /*
1079  * Here we just set up the buffers.  If we receive
1080  * an interrupt without these set, it is ignored.
1081  */
1082 
1083 int
aria_start_input(addr,p,cc,intr,arg)1084 aria_start_input(addr, p, cc, intr, arg)
1085 	void *addr;
1086 	void *p;
1087 	int cc;
1088 	void (*intr)();
1089 	void *arg;
1090 {
1091 	register struct aria_softc *sc = addr;
1092 	register int i;
1093 
1094 	DPRINTF(("aria_start_input %d @ %x\n", cc, p));
1095 
1096 	if (cc != sc->sc_blocksize) {
1097 		DPRINTF(("aria_start_input reqsize %d not sc_blocksize %d\n",
1098 			cc, sc->sc_blocksize));
1099 		return EINVAL;
1100 	}
1101 
1102 	sc->sc_rarg = arg;
1103 	sc->sc_rintr = intr;
1104 	sc->sc_rdiobuffer = p;
1105 
1106 	if (!(sc->sc_record&(1<<0))) {
1107 		aria_sendcmd(sc->sc_iobase, ARIADSPC_START_REC,  0, -1, -1);
1108 		sc->sc_record |= (1<<0);
1109 	}
1110 
1111 	return 0;
1112 }
1113 
1114 int
aria_start_output(addr,p,cc,intr,arg)1115 aria_start_output(addr, p, cc, intr, arg)
1116 	void *addr;
1117 	void *p;
1118 	int cc;
1119 	void (*intr)();
1120 	void *arg;
1121 {
1122 	register struct aria_softc *sc = addr;
1123 	register int i;
1124 
1125 	DPRINTF(("aria_start_output %d @ %x\n", cc, p));
1126 
1127 	if (cc != sc->sc_blocksize) {
1128 		DPRINTF(("aria_start_output reqsize %d not sc_blocksize %d\n",
1129 			cc, sc->sc_blocksize));
1130 		return EINVAL;
1131 	}
1132 
1133 	sc->sc_parg = arg;
1134 	sc->sc_pintr = intr;
1135 	sc->sc_pdiobuffer = p;
1136 
1137 	if (!(sc->sc_play&(1<<1))) {
1138 		aria_sendcmd(sc->sc_iobase, ARIADSPC_START_PLAY,  1, -1, -1);
1139 		sc->sc_play |= (1<<1);
1140 	}
1141 
1142 	return 0;
1143 }
1144 
1145 /*
1146  * Process an interrupt.  This should be a
1147  * request (from the card) to write or read
1148  * samples.
1149  */
1150 int
aria_intr(arg)1151 aria_intr(arg)
1152 	void *arg;
1153 {
1154 	register struct  aria_softc *sc = arg;
1155 	register u_short iobase = sc->sc_iobase;
1156 	register u_short *pdata = sc->sc_pdiobuffer;
1157 	register u_short *rdata = sc->sc_rdiobuffer;
1158 	u_short address;
1159 	int i;
1160 
1161 	if (inw(iobase) & 1 != 0x1)
1162 		return 0;  /* not for us */
1163 
1164 	sc->sc_interrupts++;
1165 
1166 	DPRINTF(("aria_intr\n"));
1167 
1168 	if ((sc->sc_open & ARIAR_OPEN_PLAY) && (pdata!=NULL)) {
1169 		DPRINTF(("aria_intr play=(%x)\n", pdata));
1170 		address = 0x8000 - 2*(sc->sc_blocksize);
1171 		address+= aria_getdspmem(iobase, ARIAA_PLAY_FIFO_A);
1172 		outw(iobase+ARIADSP_DMAADDRESS, address);
1173 		outsw(iobase + ARIADSP_DMADATA, pdata, sc->sc_blocksize/2);
1174 		if (sc->sc_pintr != NULL)
1175 			(*sc->sc_pintr)(sc->sc_parg);
1176 	}
1177 
1178 	if ((sc->sc_open & ARIAR_OPEN_RECORD) && (rdata!=NULL)) {
1179 		DPRINTF(("aria_intr record=(%x)\n", rdata));
1180 		address = 0x8000 - (sc->sc_blocksize);
1181 		address+= aria_getdspmem(iobase, ARIAA_REC_FIFO_A);
1182 		outw(iobase+ARIADSP_DMAADDRESS, address);
1183 		insw(iobase + ARIADSP_DMADATA, rdata, sc->sc_blocksize/2);
1184 		if (sc->sc_rintr != NULL)
1185 			(*sc->sc_rintr)(sc->sc_rarg);
1186 	}
1187 
1188 	aria_sendcmd(iobase, ARIADSPC_TRANSCOMPLETE, -1, -1, -1);
1189 
1190 	return 1;
1191 }
1192 
1193 int
aria_setfd(addr,flag)1194 aria_setfd(addr, flag)
1195 	void *addr;
1196 	int flag;
1197 {
1198 /*
1199  * okay return yes.  I'll assume that it will only
1200  * ask when the file open read/write...  Or before...
1201  */
1202 	return(0);
1203 }
1204 
1205 int
aria_mixer_set_port(addr,cp)1206 aria_mixer_set_port(addr, cp)
1207     void *addr;
1208     mixer_ctrl_t *cp;
1209 {
1210 	register struct aria_softc *sc = addr;
1211 	int error = EINVAL;
1212 
1213 	DPRINTF(("aria_mixer_set_port\n"));
1214 
1215 	if (!(ARIA_MIXER&sc->sc_hardware))  /* This could be done better, no mixer still has some controls. */
1216 		return ENXIO;
1217 
1218 	if (cp->type == AUDIO_MIXER_VALUE) {
1219 		register mixer_level_t *mv = &cp->un.value;
1220 		switch (cp->dev) {
1221 		case ARIAMIX_MIC_LVL:
1222 			if (mv->num_channels == 1 || mv->num_channels == 2) {
1223 				sc->aria_mix[ARIAMIX_MIC_LVL].num_channels = mv->num_channels;
1224 				sc->aria_mix[ARIAMIX_MIC_LVL].level[0] = mv->level[0];
1225 				sc->aria_mix[ARIAMIX_MIC_LVL].level[1] = mv->level[1];
1226 				error = 0;
1227 			}
1228 			break;
1229 
1230 		case ARIAMIX_LINE_IN_LVL:
1231 			if (mv->num_channels == 1 || mv->num_channels == 2) {
1232 				sc->aria_mix[ARIAMIX_LINE_IN_LVL].num_channels = mv->num_channels;
1233 				sc->aria_mix[ARIAMIX_LINE_IN_LVL].level[0] = mv->level[0];
1234 				sc->aria_mix[ARIAMIX_LINE_IN_LVL].level[1] = mv->level[1];
1235 				error = 0;
1236 			}
1237 			break;
1238 
1239 		case ARIAMIX_CD_LVL:
1240 			if (mv->num_channels == 1 || mv->num_channels == 2) {
1241 				sc->aria_mix[ARIAMIX_CD_LVL].num_channels = mv->num_channels;
1242 				sc->aria_mix[ARIAMIX_CD_LVL].level[0] = mv->level[0];
1243 				sc->aria_mix[ARIAMIX_CD_LVL].level[1] = mv->level[1];
1244 				error = 0;
1245 			}
1246 			break;
1247 
1248 		case ARIAMIX_TEL_LVL:
1249 			if (mv->num_channels == 1) {
1250 				sc->aria_mix[ARIAMIX_TEL_LVL].num_channels = mv->num_channels;
1251 				sc->aria_mix[ARIAMIX_TEL_LVL].level[0] = mv->level[0];
1252 				error = 0;
1253 			}
1254 			break;
1255 
1256 		case ARIAMIX_DAC_LVL:
1257 			if (mv->num_channels == 1 || mv->num_channels == 2) {
1258 				sc->aria_mix[ARIAMIX_DAC_LVL].num_channels = mv->num_channels;
1259 				sc->aria_mix[ARIAMIX_DAC_LVL].level[0] = mv->level[0];
1260 				sc->aria_mix[ARIAMIX_DAC_LVL].level[1] = mv->level[1];
1261 				error = 0;
1262 			}
1263 			break;
1264 
1265 		case ARIAMIX_AUX_LVL:
1266 			if (mv->num_channels == 1 || mv->num_channels == 2) {
1267 				sc->aria_mix[ARIAMIX_AUX_LVL].num_channels = mv->num_channels;
1268 				sc->aria_mix[ARIAMIX_AUX_LVL].level[0] = mv->level[0];
1269 				sc->aria_mix[ARIAMIX_AUX_LVL].level[1] = mv->level[1];
1270 				error = 0;
1271 			}
1272 			break;
1273 
1274 		case ARIAMIX_MASTER_LVL:
1275 			if (mv->num_channels == 1 || mv->num_channels == 2) {
1276 				sc->ariamix_master.num_channels = mv->num_channels;
1277 				sc->ariamix_master.level[0] = mv->level[0];
1278 				sc->ariamix_master.level[1] = mv->level[1];
1279 				error = 0;
1280 			}
1281 			break;
1282 
1283 		case ARIAMIX_MASTER_TREBLE:
1284 			if (mv->num_channels == 2) {
1285 				sc->ariamix_master.treble[0] = (mv->level[0]==0)?1:mv->level[0];
1286 				sc->ariamix_master.treble[1] = (mv->level[1]==0)?1:mv->level[1];
1287 				error = 0;
1288 			}
1289 			break;
1290 		case ARIAMIX_MASTER_BASS:
1291 			if (mv->num_channels == 2) {
1292 				sc->ariamix_master.bass[0] = (mv->level[0]==0)?1:mv->level[0];
1293 				sc->ariamix_master.bass[1] = (mv->level[1]==0)?1:mv->level[1];
1294 				error = 0;
1295 			}
1296 			break;
1297 		case ARIAMIX_OUT_LVL:
1298 			if (mv->num_channels == 1 || mv->num_channels == 2) {
1299 				sc->gain[0] = mv->level[0];
1300 				sc->gain[1] = mv->level[1];
1301 				error = 0;
1302 			}
1303 			break;
1304 		default:
1305 		}
1306 	}
1307 
1308 	if (cp->type == AUDIO_MIXER_ENUM)
1309 		switch(cp->dev) {
1310 		case ARIAMIX_RECORD_SOURCE:
1311 			if (cp->un.ord>=0 && cp->un.ord<=6) {
1312 				sc->aria_mix_source = cp->un.ord;
1313 				error = 0;
1314 			}
1315 			break;
1316 
1317 		case ARIAMIX_MIC_MUTE:
1318 			if (cp->un.ord == 0 || cp->un.ord == 1) {
1319 				sc->aria_mix[ARIAMIX_MIC_LVL].mute = cp->un.ord;
1320 				error = 0;
1321 			}
1322 			break;
1323 
1324 		case ARIAMIX_LINE_IN_MUTE:
1325 			if (cp->un.ord == 0 || cp->un.ord == 1) {
1326 				sc->aria_mix[ARIAMIX_LINE_IN_LVL].mute = cp->un.ord;
1327 				error = 0;
1328 			}
1329 			break;
1330 
1331 		case ARIAMIX_CD_MUTE:
1332 			if (cp->un.ord == 0 || cp->un.ord == 1) {
1333 				sc->aria_mix[ARIAMIX_CD_LVL].mute = cp->un.ord;
1334 				error = 0;
1335 			}
1336 			break;
1337 
1338 		case ARIAMIX_DAC_MUTE:
1339 			if (cp->un.ord == 0 || cp->un.ord == 1) {
1340 				sc->aria_mix[ARIAMIX_DAC_LVL].mute = cp->un.ord;
1341 				error = 0;
1342 			}
1343 			break;
1344 
1345 		case ARIAMIX_AUX_MUTE:
1346 			if (cp->un.ord == 0 || cp->un.ord == 1) {
1347 				sc->aria_mix[ARIAMIX_AUX_LVL].mute = cp->un.ord;
1348 				error = 0;
1349 			}
1350 			break;
1351 
1352 		case ARIAMIX_TEL_MUTE:
1353 			if (cp->un.ord == 0 || cp->un.ord == 1) {
1354 				sc->aria_mix[ARIAMIX_TEL_LVL].mute = cp->un.ord;
1355 				error = 0;
1356 			}
1357 			break;
1358 
1359 		default:
1360 			return ENXIO;
1361 			/* NOTREACHED */
1362 		}
1363 
1364 	return(error);
1365 }
1366 
1367 int
aria_mixer_get_port(addr,cp)1368 aria_mixer_get_port(addr, cp)
1369     void *addr;
1370     mixer_ctrl_t *cp;
1371 {
1372 	register struct aria_softc *sc = addr;
1373 	int error = EINVAL;
1374 
1375 	DPRINTF(("aria_mixer_get_port\n"));
1376 
1377 	if (!(ARIA_MIXER&sc->sc_hardware))  /* This could be done better, no mixer still has some controls. */
1378 		return ENXIO;
1379 
1380 	switch (cp->dev) {
1381 	case ARIAMIX_MIC_LVL:
1382 		if (cp->type == AUDIO_MIXER_VALUE) {
1383 			cp->un.value.num_channels = sc->aria_mix[ARIAMIX_MIC_LVL].num_channels;
1384 			cp->un.value.level[0] = sc->aria_mix[ARIAMIX_MIC_LVL].level[0];
1385 			cp->un.value.level[1] = sc->aria_mix[ARIAMIX_MIC_LVL].level[1];
1386 			error = 0;
1387 		}
1388 		break;
1389 
1390 	case ARIAMIX_LINE_IN_LVL:
1391 		if (cp->type == AUDIO_MIXER_VALUE) {
1392 			cp->un.value.num_channels = sc->aria_mix[ARIAMIX_LINE_IN_LVL].num_channels;
1393 			cp->un.value.level[0] = sc->aria_mix[ARIAMIX_LINE_IN_LVL].level[0];
1394 			cp->un.value.level[1] = sc->aria_mix[ARIAMIX_LINE_IN_LVL].level[1];
1395 			error = 0;
1396 		}
1397 		break;
1398 
1399 	case ARIAMIX_CD_LVL:
1400 		if (cp->type == AUDIO_MIXER_VALUE) {
1401 			cp->un.value.num_channels = sc->aria_mix[ARIAMIX_CD_LVL].num_channels;
1402 			cp->un.value.level[0] = sc->aria_mix[ARIAMIX_CD_LVL].level[0];
1403 			cp->un.value.level[1] = sc->aria_mix[ARIAMIX_CD_LVL].level[1];
1404 			error = 0;
1405 		}
1406 		break;
1407 
1408 	case ARIAMIX_TEL_LVL:
1409 		if (cp->type == AUDIO_MIXER_VALUE) {
1410 			cp->un.value.num_channels = sc->aria_mix[ARIAMIX_TEL_LVL].num_channels;
1411 			cp->un.value.level[0] = sc->aria_mix[ARIAMIX_TEL_LVL].level[0];
1412 			error = 0;
1413 		}
1414 		break;
1415 	case ARIAMIX_DAC_LVL:
1416 		if (cp->type == AUDIO_MIXER_VALUE) {
1417 			cp->un.value.num_channels = sc->aria_mix[ARIAMIX_DAC_LVL].num_channels;
1418 			cp->un.value.level[0] = sc->aria_mix[ARIAMIX_DAC_LVL].level[0];
1419 			cp->un.value.level[1] = sc->aria_mix[ARIAMIX_DAC_LVL].level[1];
1420 			error = 0;
1421 		}
1422 		break;
1423 
1424 	case ARIAMIX_AUX_LVL:
1425 		if (cp->type == AUDIO_MIXER_VALUE) {
1426 			cp->un.value.num_channels = sc->aria_mix[ARIAMIX_AUX_LVL].num_channels;
1427 			cp->un.value.level[0] = sc->aria_mix[ARIAMIX_AUX_LVL].level[0];
1428 			cp->un.value.level[1] = sc->aria_mix[ARIAMIX_AUX_LVL].level[1];
1429 			error = 0;
1430 		}
1431 		break;
1432 
1433 	case ARIAMIX_MIC_MUTE:
1434 		if (cp->type == AUDIO_MIXER_ENUM) {
1435 			cp->un.ord = sc->aria_mix[ARIAMIX_MIC_LVL].mute;
1436 			error = 0;
1437 		}
1438 		break;
1439 
1440 	case ARIAMIX_LINE_IN_MUTE:
1441 		if (cp->type == AUDIO_MIXER_ENUM) {
1442 			cp->un.ord = sc->aria_mix[ARIAMIX_LINE_IN_LVL].mute;
1443 			error = 0;
1444 		}
1445 		break;
1446 
1447 	case ARIAMIX_CD_MUTE:
1448 		if (cp->type == AUDIO_MIXER_ENUM) {
1449 			cp->un.ord = sc->aria_mix[ARIAMIX_CD_LVL].mute;
1450 			error = 0;
1451 		}
1452 		break;
1453 
1454 	case ARIAMIX_DAC_MUTE:
1455 		if (cp->type == AUDIO_MIXER_ENUM) {
1456 			cp->un.ord = sc->aria_mix[ARIAMIX_DAC_LVL].mute;
1457 			error = 0;
1458 		}
1459 		break;
1460 
1461 	case ARIAMIX_AUX_MUTE:
1462 		if (cp->type == AUDIO_MIXER_ENUM) {
1463 			cp->un.ord = sc->aria_mix[ARIAMIX_AUX_LVL].mute;
1464 			error = 0;
1465 		}
1466 		break;
1467 
1468 	case ARIAMIX_TEL_MUTE:
1469 		if (cp->type == AUDIO_MIXER_ENUM) {
1470 			cp->un.ord = sc->aria_mix[ARIAMIX_TEL_LVL].mute;
1471 			error = 0;
1472 		}
1473 		break;
1474 
1475 	case ARIAMIX_MASTER_LVL:
1476 		if (cp->type == AUDIO_MIXER_VALUE) {
1477 			cp->un.value.num_channels = sc->ariamix_master.num_channels;
1478 			cp->un.value.level[0] = sc->ariamix_master.level[0];
1479 			cp->un.value.level[1] = sc->ariamix_master.level[1];
1480 			error = 0;
1481 		}
1482 		break;
1483 
1484 	case ARIAMIX_MASTER_TREBLE:
1485 		if (cp->type == AUDIO_MIXER_VALUE) {
1486 			cp->un.value.num_channels = 2;
1487 			cp->un.value.level[0] = sc->ariamix_master.treble[0];
1488 			cp->un.value.level[1] = sc->ariamix_master.treble[1];
1489 			error = 0;
1490 		}
1491 		break;
1492 
1493 	case ARIAMIX_MASTER_BASS:
1494 		if (cp->type == AUDIO_MIXER_VALUE) {
1495 			cp->un.value.num_channels = 2;
1496 			cp->un.value.level[0] = sc->ariamix_master.bass[0];
1497 			cp->un.value.level[1] = sc->ariamix_master.bass[1];
1498 			error = 0;
1499 		}
1500 		break;
1501 
1502 	case ARIAMIX_OUT_LVL:
1503 		if (cp->type == AUDIO_MIXER_VALUE) {
1504 			cp->un.value.num_channels = sc->sc_chans;
1505 			cp->un.value.level[0] = sc->gain[0];
1506 			cp->un.value.level[1] = sc->gain[1];
1507 			error = 0;
1508 		}
1509 		break;
1510 	case ARIAMIX_RECORD_SOURCE:
1511 		if (cp->type == AUDIO_MIXER_ENUM) {
1512 			cp->un.ord = sc->aria_mix_source;
1513 			error = 0;
1514 		}
1515 		break;
1516 
1517 	default:
1518 		return ENXIO;
1519 		/* NOT REACHED */
1520 	}
1521 
1522 	return(error);
1523 }
1524 
1525 int
aria_mixer_query_devinfo(addr,dip)1526 aria_mixer_query_devinfo(addr, dip)
1527 	   void *addr;
1528 	   register mixer_devinfo_t *dip;
1529 {
1530 
1531 	register struct aria_softc *sc = addr;
1532 
1533 	DPRINTF(("aria_mixer_query_devinfo\n"));
1534 
1535 	if (!(ARIA_MIXER&sc->sc_hardware))  /* This could be done better, no mixer still has some controls. */
1536 		return ENXIO;
1537 
1538 	dip->prev = dip->next = AUDIO_MIXER_LAST;
1539 
1540 	switch(dip->index) {
1541 	case ARIAMIX_MIC_LVL:
1542 		dip->type = AUDIO_MIXER_VALUE;
1543 		dip->mixer_class = ARIAMIX_INPUT_CLASS;
1544 		dip->next = ARIAMIX_MIC_MUTE;
1545 		strlcpy(dip->label.name, AudioNmicrophone,
1546 		    sizeof dip->label.name);
1547 		dip->un.v.num_channels = 2;
1548 		strlcpy(dip->un.v.units.name, AudioNvolume,
1549 		    sizeof dip->un.v.units.name);
1550 		break;
1551 
1552 	case ARIAMIX_LINE_IN_LVL:
1553 		dip->type = AUDIO_MIXER_VALUE;
1554 		dip->mixer_class = ARIAMIX_INPUT_CLASS;
1555 		dip->next = ARIAMIX_LINE_IN_MUTE;
1556 		strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
1557 		dip->un.v.num_channels = 2;
1558 		strlcpy(dip->un.v.units.name, AudioNvolume,
1559 		    sizeof dip->un.v.units.name);
1560 		break;
1561 
1562 	case ARIAMIX_CD_LVL:
1563 		dip->type = AUDIO_MIXER_VALUE;
1564 		dip->mixer_class = ARIAMIX_INPUT_CLASS;
1565 		dip->next = ARIAMIX_CD_MUTE;
1566 		strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
1567 		dip->un.v.num_channels = 2;
1568 		strlcpy(dip->un.v.units.name, AudioNvolume,
1569 		    sizeof dip->un.v.units.name);
1570 		break;
1571 
1572 	case ARIAMIX_TEL_LVL:
1573 		dip->type = AUDIO_MIXER_VALUE;
1574 		dip->mixer_class = ARIAMIX_INPUT_CLASS;
1575 		dip->next = ARIAMIX_TEL_MUTE;
1576 		strlcpy(dip->label.name, "telephone", sizeof dip->label.name);
1577 		dip->un.v.num_channels = 1;
1578 		strlcpy(dip->un.v.units.name, AudioNvolume,
1579 		    sizeof dip->un.v.units.name);
1580 		break;
1581 
1582 	case ARIAMIX_DAC_LVL:
1583 		dip->type = AUDIO_MIXER_VALUE;
1584 		dip->mixer_class = ARIAMIX_INPUT_CLASS;
1585 		dip->next = ARIAMIX_DAC_MUTE;
1586 		strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
1587 		dip->un.v.num_channels = 1;
1588 		strlcpy(dip->un.v.units.name, AudioNvolume,
1589 		    sizeof dip->un.v.units.name);
1590 		break;
1591 
1592 	case ARIAMIX_AUX_LVL:
1593 		dip->type = AUDIO_MIXER_VALUE;
1594 		dip->mixer_class = ARIAMIX_INPUT_CLASS;
1595 		dip->next = ARIAMIX_AUX_MUTE;
1596 		strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
1597 		dip->un.v.num_channels = 1;
1598 		strlcpy(dip->un.v.units.name, AudioNvolume,
1599 		    sizeof dip->un.v.units.name);
1600 		break;
1601 
1602 	case ARIAMIX_MIC_MUTE:
1603 		dip->prev = ARIAMIX_MIC_LVL;
1604 		goto mode;
1605 
1606 	case ARIAMIX_LINE_IN_MUTE:
1607 		dip->prev = ARIAMIX_LINE_IN_LVL;
1608 		goto mode;
1609 
1610 	case ARIAMIX_CD_MUTE:
1611 		dip->prev = ARIAMIX_CD_LVL;
1612 		goto mode;
1613 
1614 	case ARIAMIX_DAC_MUTE:
1615 		dip->prev = ARIAMIX_DAC_LVL;
1616 		goto mode;
1617 
1618 	case ARIAMIX_AUX_MUTE:
1619 		dip->prev = ARIAMIX_AUX_LVL;
1620 		goto mode;
1621 
1622 	case ARIAMIX_TEL_MUTE:
1623 		dip->prev = ARIAMIX_TEL_LVL;
1624 		goto mode;
1625 
1626 mode:
1627 		dip->mixer_class = ARIAMIX_INPUT_CLASS;
1628 		dip->type = AUDIO_MIXER_ENUM;
1629 		strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
1630 		dip->un.e.num_mem = 2;
1631 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
1632 		    sizeof dip->un.e.member[0].label.name);
1633 		dip->un.e.member[0].ord = 0;
1634 		strlcpy(dip->un.e.member[1].label.name, AudioNon,
1635 		    sizeof dip->un.e.member[0].label.name);
1636 		dip->un.e.member[1].ord = 1;
1637 		break;
1638 
1639 	case ARIAMIX_MASTER_LVL:
1640 		dip->type = AUDIO_MIXER_VALUE;
1641 		dip->mixer_class = ARIAMIX_OUTPUT_CLASS;
1642 		dip->next = ARIAMIX_MASTER_TREBLE;
1643 		strlcpy(dip->label.name, AudioNvolume, sizeof dip->label.name);
1644 		dip->un.v.num_channels = 2;
1645 		strlcpy(dip->un.v.units.name, AudioNvolume,
1646 		    sizeof dip->un.v.units.name);
1647 		break;
1648 
1649 	case ARIAMIX_MASTER_TREBLE:
1650 		dip->type = AUDIO_MIXER_VALUE;
1651 		dip->mixer_class = ARIAMIX_OUTPUT_CLASS;
1652 		dip->prev = ARIAMIX_MASTER_LVL;
1653 		dip->next = ARIAMIX_MASTER_BASS;
1654 		strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
1655 		dip->un.v.num_channels = 2;
1656 		strlcpy(dip->un.v.units.name, AudioNtreble,
1657 		    sizeof dip->un.v.units.name);
1658 		break;
1659 
1660 	case ARIAMIX_MASTER_BASS:
1661 		dip->type = AUDIO_MIXER_VALUE;
1662 		dip->mixer_class = ARIAMIX_OUTPUT_CLASS;
1663 		dip->prev = ARIAMIX_MASTER_TREBLE;
1664 		strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
1665 		dip->un.v.num_channels = 2;
1666 		strlcpy(dip->un.v.units.name, AudioNbass,
1667 		    sizeof dip->un.v.units.name);
1668 		break;
1669 
1670 	case ARIAMIX_OUT_LVL:
1671 		dip->type = AUDIO_MIXER_VALUE;
1672 		dip->mixer_class = ARIAMIX_OUTPUT_CLASS;
1673 		strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
1674 		dip->un.v.num_channels = 2;
1675 		strlcpy(dip->un.v.units.name, AudioNvolume,
1676 		    sizeof dip->un.v.units.name);
1677 		break;
1678 
1679 	case ARIAMIX_RECORD_SOURCE:
1680 		dip->mixer_class = ARIAMIX_RECORD_CLASS;
1681 		dip->type = AUDIO_MIXER_ENUM;
1682 		strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
1683 		dip->un.e.num_mem = 6;
1684 		strlcpy(dip->un.e.member[0].label.name, AudioNoutput,
1685 		    sizeof dip->un.e.member[0].label.name);
1686 		dip->un.e.member[0].ord = ARIAMIX_AUX_LVL;
1687 		strlcpy(dip->un.e.member[1].label.name, AudioNmicrophone,
1688 		    sizeof dip->un.e.member[0].label.name);
1689 		dip->un.e.member[1].ord = ARIAMIX_MIC_LVL;
1690 		strlcpy(dip->un.e.member[2].label.name, AudioNdac,
1691 		    sizeof dip->un.e.member[0].label.name);
1692 		dip->un.e.member[2].ord = ARIAMIX_DAC_LVL;
1693 		strlcpy(dip->un.e.member[3].label.name, AudioNline,
1694 		    sizeof dip->un.e.member[0].label.name);
1695 		dip->un.e.member[3].ord = ARIAMIX_LINE_IN_LVL;
1696 		strlcpy(dip->un.e.member[3].label.name, AudioNcd,
1697 		    sizeof dip->un.e.member[0].label.name);
1698 		dip->un.e.member[4].ord = ARIAMIX_CD_LVL;
1699 		strlcpy(dip->un.e.member[3].label.name, "telephone",
1700 		    sizeof dip->un.e.member[0].label.name);
1701 		dip->un.e.member[5].ord = ARIAMIX_TEL_LVL;
1702 		break;
1703 
1704 	case ARIAMIX_INPUT_CLASS:
1705 		dip->type = AUDIO_MIXER_CLASS;
1706 		dip->mixer_class = ARIAMIX_INPUT_CLASS;
1707 		strlcpy(dip->label.name, AudioCInputs, sizeof dip->label.name);
1708 		break;
1709 
1710 	case ARIAMIX_OUTPUT_CLASS:
1711 		dip->type = AUDIO_MIXER_CLASS;
1712 		dip->mixer_class = ARIAMIX_OUTPUT_CLASS;
1713 		strlcpy(dip->label.name, AudioCOutputs,
1714 		    sizeof dip->label.name);
1715 		break;
1716 
1717 	case ARIAMIX_RECORD_CLASS:
1718 		dip->type = AUDIO_MIXER_CLASS;
1719 		dip->mixer_class = ARIAMIX_RECORD_CLASS;
1720 		strlcpy(dip->label.name, AudioCRecord, sizeof dip->label.name);
1721 		break;
1722 
1723 	case ARIAMIX_EQ_CLASS:
1724 		dip->type = AUDIO_MIXER_CLASS;
1725 		dip->mixer_class = ARIAMIX_EQ_CLASS;
1726 		strlcpy(dip->label.name, AudioCEqualization,
1727 		    sizeof dip->label.name);
1728 		break;
1729 
1730 	default:
1731 		return ENXIO;
1732 		/*NOTREACHED*/
1733 	}
1734 	return 0;
1735 }
1736 
1737 #endif /* NARIA */
1738