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