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