Annotation of sys/dev/isa/pss.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: pss.c,v 1.22 2003/04/27 11:22:53 ho Exp $ */
2: /* $NetBSD: pss.c,v 1.38 1998/01/12 09:43:44 thorpej Exp $ */
3:
4: /*
5: * Copyright (c) 1994 John Brezak
6: * Copyright (c) 1991-1993 Regents of the University of California.
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by the Computer Systems
20: * Engineering Group at Lawrence Berkeley Laboratory.
21: * 4. Neither the name of the University nor of the Laboratory may be used
22: * to endorse or promote products derived from this software without
23: * specific prior written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35: * SUCH DAMAGE.
36: *
37: */
38:
39: /*
40: * Copyright (c) 1993 Analog Devices Inc. All rights reserved
41: *
42: * Portions provided by Marc.Hoffman@analog.com and
43: * Greg.Yukna@analog.com .
44: *
45: */
46:
47: /*
48: * Todo:
49: * - Provide PSS driver to access DSP
50: * - Provide MIDI driver to access MPU
51: * - Finish support for CD drive (Sony and SCSI)
52: */
53:
54: #include <sys/param.h>
55: #include <sys/systm.h>
56: #include <sys/errno.h>
57: #include <sys/ioctl.h>
58: #include <sys/syslog.h>
59: #include <sys/device.h>
60: #include <sys/proc.h>
61: #include <sys/buf.h>
62:
63: #include <machine/cpu.h>
64: #include <machine/intr.h>
65: #include <machine/bus.h>
66:
67: #include <sys/audioio.h>
68: #include <dev/audio_if.h>
69:
70: #include <dev/isa/isavar.h>
71: #include <dev/isa/isadmavar.h>
72:
73: #include <dev/isa/ad1848var.h>
74: #include <dev/isa/wssreg.h>
75: #include <dev/isa/pssreg.h>
76:
77: /* XXX Default WSS base */
78: #define WSS_BASE_ADDRESS 0x0530
79:
80: /*
81: * Mixer devices
82: */
83: #define PSS_MIC_IN_LVL 0
84: #define PSS_LINE_IN_LVL 1
85: #define PSS_DAC_LVL 2
86: #define PSS_REC_LVL 3
87: #define PSS_MON_LVL 4
88: #define PSS_MASTER_VOL 5
89: #define PSS_MASTER_TREBLE 6
90: #define PSS_MASTER_BASS 7
91: #define PSS_MIC_IN_MUTE 8
92: #define PSS_LINE_IN_MUTE 9
93: #define PSS_DAC_MUTE 10
94:
95: #define PSS_OUTPUT_MODE 11
96: #define PSS_SPKR_MONO 0
97: #define PSS_SPKR_STEREO 1
98: #define PSS_SPKR_PSEUDO 2
99: #define PSS_SPKR_SPATIAL 3
100:
101: #define PSS_RECORD_SOURCE 12
102:
103: /* Classes */
104: #define PSS_INPUT_CLASS 13
105: #define PSS_RECORD_CLASS 14
106: #define PSS_MONITOR_CLASS 15
107: #define PSS_OUTPUT_CLASS 16
108:
109:
110: struct pss_softc {
111: struct device sc_dev; /* base device */
112: void *sc_ih; /* interrupt vectoring */
113:
114: int sc_iobase; /* I/O port base address */
115: int sc_drq; /* dma channel */
116:
117: struct ad1848_softc *ad1848_sc;
118:
119: int out_port;
120:
121: struct ad1848_volume master_volume;
122: int master_mode;
123:
124: int monitor_treble;
125: int monitor_bass;
126:
127: int mic_mute, cd_mute, dac_mute;
128: };
129:
130: #ifdef notyet
131: struct mpu_softc {
132: struct device sc_dev; /* base device */
133: void *sc_ih; /* interrupt vectoring */
134:
135: int sc_iobase; /* MIDI I/O port base address */
136: int sc_irq; /* MIDI interrupt */
137: };
138:
139: struct pcd_softc {
140: struct device sc_dev; /* base device */
141: void *sc_ih; /* interrupt vectoring */
142:
143: int sc_iobase; /* CD I/O port base address */
144: int sc_irq; /* CD interrupt */
145: };
146: #endif
147:
148: #ifdef AUDIO_DEBUG
149: #define DPRINTF(x) if (pssdebug) printf x
150: int pssdebug = 0;
151: #else
152: #define DPRINTF(x)
153: #endif
154:
155: int pssprobe(struct device *, void *, void *);
156: void pssattach(struct device *, struct device *, void *);
157:
158: int spprobe(struct device *, void *, void *);
159: void spattach(struct device *, struct device *, void *);
160:
161: #ifdef notyet
162: int mpuprobe(struct device *, void *, void *);
163: void mpuattach(struct device *, struct device *, void *);
164:
165: int pcdprobe(struct device *, void *, void *);
166: void pcdattach(struct device *, struct device *, void *);
167: #endif
168:
169: int pssintr(void *);
170: #ifdef notyet
171: int mpuintr(void *);
172: #endif
173:
174: int pss_speaker_ctl(void *, int);
175:
176: int pss_getdev(void *, struct audio_device *);
177:
178: int pss_mixer_set_port(void *, mixer_ctrl_t *);
179: int pss_mixer_get_port(void *, mixer_ctrl_t *);
180: int pss_query_devinfo(void *, mixer_devinfo_t *);
181:
182: #ifdef PSS_DSP
183: void pss_dspwrite(struct pss_softc *, int);
184: #endif
185: void pss_setaddr(int, int);
186: int pss_setint(int, int);
187: int pss_setdma(int, int);
188: int pss_testirq(struct pss_softc *, int);
189: int pss_testdma(struct pss_softc *, int);
190: #ifdef notyet
191: int pss_reset_dsp(struct pss_softc *);
192: int pss_download_dsp(struct pss_softc *, u_char *, int);
193: #endif
194: #ifdef AUDIO_DEBUG
195: void pss_dump_regs(struct pss_softc *);
196: #endif
197: int pss_set_master_gain(struct pss_softc *, struct ad1848_volume *);
198: int pss_set_master_mode(struct pss_softc *, int);
199: int pss_set_treble(struct pss_softc *, u_int);
200: int pss_set_bass(struct pss_softc *, u_int);
201: int pss_get_master_gain(struct pss_softc *, struct ad1848_volume *);
202: int pss_get_master_mode(struct pss_softc *, u_int *);
203: int pss_get_treble(struct pss_softc *, u_char *);
204: int pss_get_bass(struct pss_softc *, u_char *);
205:
206: #ifdef AUDIO_DEBUG
207: void wss_dump_regs(struct ad1848_softc *);
208: #endif
209:
210: /*
211: * Define our interface to the higher level audio driver.
212: */
213:
214: struct audio_hw_if pss_audio_if = {
215: ad1848_open,
216: ad1848_close,
217: NULL,
218: ad1848_query_encoding,
219: ad1848_set_params,
220: ad1848_round_blocksize,
221: ad1848_commit_settings,
222: ad1848_dma_init_output,
223: ad1848_dma_init_input,
224: ad1848_dma_output,
225: ad1848_dma_input,
226: ad1848_halt_out_dma,
227: ad1848_halt_in_dma,
228: pss_speaker_ctl,
229: pss_getdev,
230: NULL,
231: pss_mixer_set_port,
232: pss_mixer_get_port,
233: pss_query_devinfo,
234: ad1848_malloc,
235: ad1848_free,
236: ad1848_round,
237: ad1848_mappage,
238: ad1848_get_props,
239: NULL,
240: NULL
241: };
242:
243:
244: /* Interrupt translation for WSS config */
245: static u_char wss_interrupt_bits[16] = {
246: 0xff, 0xff, 0xff, 0xff,
247: 0xff, 0xff, 0xff, 0x08,
248: 0xff, 0x10, 0x18, 0x20,
249: 0xff, 0xff, 0xff, 0xff
250: };
251: /* ditto for WSS DMA channel */
252: static u_char wss_dma_bits[4] = {1, 2, 0, 3};
253:
254: struct cfattach pss_ca = {
255: sizeof(struct pss_softc), pssprobe, pssattach
256: };
257:
258: struct cfdriver pss_cd = {
259: NULL, "pss", DV_DULL, 1
260: };
261:
262: struct cfattach sp_ca = {
263: sizeof(struct ad1848_softc), spprobe, spattach
264: };
265:
266: struct cfdriver sp_cd = {
267: NULL, "sp", DV_DULL
268: };
269:
270: #ifdef notyet
271: struct cfattach mpu_ca = {
272: sizeof(struct mpu_softc), mpuprobe, mpuattach
273: };
274:
275: struct cfdriver mpu_cd = {
276: NULL, "mpu", DV_DULL
277: };
278:
279: struct cfattach pcd_ca = {
280: sizeof(struct pcd_softc), pcdprobe, pcdattach
281: };
282:
283: struct cfdriver pcd_cd = {
284: NULL, "pcd", DV_DULL
285: };
286: #endif
287:
288: struct audio_device pss_device = {
289: "pss,ad1848",
290: "",
291: "PSS"
292: };
293:
294: #ifdef PSS_DSP
295: void
296: pss_dspwrite(sc, data)
297: struct pss_softc *sc;
298: int data;
299: {
300: int i;
301: int pss_base = sc->sc_iobase;
302:
303: /*
304: * Note! the i<5000000 is an emergency exit. The dsp_command() is sometimes
305: * called while interrupts are disabled. This means that the timer is
306: * disabled also. However the timeout situation is a abnormal condition.
307: * Normally the DSP should be ready to accept commands after just couple of
308: * loops.
309: */
310: for (i = 0; i < 5000000; i++) {
311: if (inw(pss_base+PSS_STATUS) & PSS_WRITE_EMPTY) {
312: outw(pss_base+PSS_DATA, data);
313: return;
314: }
315: }
316: printf ("pss: DSP Command (%04x) Timeout.\n", data);
317: }
318: #endif /* PSS_DSP */
319:
320: void
321: pss_setaddr(addr, configAddr)
322: int addr;
323: int configAddr;
324: {
325: int val;
326:
327: val = inw(configAddr);
328: val &= ADDR_MASK;
329: val |= (addr << 4);
330: outw(configAddr,val);
331: }
332:
333: /* pss_setint
334: * This function sets the correct bits in the
335: * configuration register to
336: * enable the chosen interrupt.
337: */
338: int
339: pss_setint(intNum, configAddress)
340: int intNum;
341: int configAddress;
342: {
343: int val;
344:
345: switch(intNum) {
346: case 3:
347: val = inw(configAddress);
348: val &= INT_MASK;
349: val |= INT_3_BITS;
350: break;
351: case 5:
352: val = inw(configAddress);
353: val &= INT_MASK;
354: val |= INT_5_BITS;
355: break;
356: case 7:
357: val = inw(configAddress);
358: val &= INT_MASK;
359: val |= INT_7_BITS;
360: break;
361: case 9:
362: val = inw(configAddress);
363: val &= INT_MASK;
364: val |= INT_9_BITS;
365: break;
366: case 10:
367: val = inw(configAddress);
368: val &= INT_MASK;
369: val |= INT_10_BITS;
370: break;
371: case 11:
372: val = inw(configAddress);
373: val &= INT_MASK;
374: val |= INT_11_BITS;
375: break;
376: case 12:
377: val = inw(configAddress);
378: val &= INT_MASK;
379: val |= INT_12_BITS;
380: break;
381: default:
382: DPRINTF(("pss_setint: invalid irq (%d)\n", intNum));
383: return 1;
384: }
385: outw(configAddress,val);
386: return 0;
387: }
388:
389: int
390: pss_setdma(dmaNum, configAddress)
391: int dmaNum;
392: int configAddress;
393: {
394: int val;
395:
396: switch(dmaNum) {
397: case 0:
398: val = inw(configAddress);
399: val &= DMA_MASK;
400: val |= DMA_0_BITS;
401: break;
402: case 1:
403: val = inw(configAddress);
404: val &= DMA_MASK;
405: val |= DMA_1_BITS;
406: break;
407: case 3:
408: val = inw(configAddress);
409: val &= DMA_MASK;
410: val |= DMA_3_BITS;
411: break;
412: case 5:
413: val = inw(configAddress);
414: val &= DMA_MASK;
415: val |= DMA_5_BITS;
416: break;
417: case 6:
418: val = inw(configAddress);
419: val &= DMA_MASK;
420: val |= DMA_6_BITS;
421: break;
422: case 7:
423: val = inw(configAddress);
424: val &= DMA_MASK;
425: val |= DMA_7_BITS;
426: break;
427: default:
428: DPRINTF(("pss_setdma: invalid drq (%d)\n", dmaNum));
429: return 1;
430: }
431: outw(configAddress, val);
432: return 0;
433: }
434:
435: /*
436: * This function tests an interrupt number to see if
437: * it is available. It takes the interrupt button
438: * as its argument and returns TRUE if the interrupt
439: * is ok.
440: */
441: int
442: pss_testirq(struct pss_softc *sc, int intNum)
443: {
444: int config = sc->sc_iobase + PSS_CONFIG;
445: int val;
446: int ret;
447: int i;
448:
449: /* Set the interrupt bits */
450: switch(intNum) {
451: case 3:
452: val = inw(config);
453: val &= INT_MASK; /* Special: 0 */
454: break;
455: case 5:
456: val = inw(config);
457: val &= INT_MASK;
458: val |= INT_TEST_BIT | INT_5_BITS;
459: break;
460: case 7:
461: val = inw(config);
462: val &= INT_MASK;
463: val |= INT_TEST_BIT | INT_7_BITS;
464: break;
465: case 9:
466: val = inw(config);
467: val &= INT_MASK;
468: val |= INT_TEST_BIT | INT_9_BITS;
469: break;
470: case 10:
471: val = inw(config);
472: val &= INT_MASK;
473: val |= INT_TEST_BIT | INT_10_BITS;
474: break;
475: case 11:
476: val = inw(config);
477: val &= INT_MASK;
478: val |= INT_TEST_BIT | INT_11_BITS;
479: break;
480: case 12:
481: val = inw(config);
482: val &= INT_MASK;
483: val |= INT_TEST_BIT | INT_12_BITS;
484: break;
485: default:
486: DPRINTF(("pss_testirq: invalid irq (%d)\n", intNum));
487: return 0;
488: }
489: outw(config, val);
490:
491: /* Check if the interrupt is in use */
492: /* Do it a few times in case there is a delay */
493: ret = 0;
494: for (i = 0; i < 5; i++) {
495: val = inw(config);
496: if (val & INT_TEST_PASS) {
497: ret = 1;
498: break;
499: }
500: }
501:
502: /* Clear the Test bit and the interrupt bits */
503: val = inw(config);
504: val &= INT_TEST_BIT_MASK & INT_MASK;
505: outw(config, val);
506: return(ret);
507: }
508:
509: /*
510: * This function tests a dma channel to see if
511: * it is available. It takes the DMA channel button
512: * as its argument and returns TRUE if the channel
513: * is ok.
514: */
515: int
516: pss_testdma(sc, dmaNum)
517: struct pss_softc *sc;
518: int dmaNum;
519: {
520: int config = sc->sc_iobase + PSS_CONFIG;
521: int val;
522: int i, ret;
523:
524: switch (dmaNum) {
525: case 0:
526: val = inw(config);
527: val &= DMA_MASK;
528: val |= DMA_TEST_BIT | DMA_0_BITS;
529: break;
530: case 1:
531: val = inw(config);
532: val &= DMA_MASK;
533: val |= DMA_TEST_BIT | DMA_1_BITS;
534: break;
535: case 3:
536: val = inw(config);
537: val &= DMA_MASK;
538: val |= DMA_TEST_BIT | DMA_3_BITS;
539: break;
540: case 5:
541: val = inw(config);
542: val &= DMA_MASK;
543: val |= DMA_TEST_BIT | DMA_5_BITS;
544: break;
545: case 6:
546: val = inw(config);
547: val &= DMA_MASK;
548: val |= DMA_TEST_BIT | DMA_6_BITS;
549: break;
550: case 7:
551: val = inw(config);
552: val &= DMA_MASK;
553: val |= DMA_TEST_BIT | DMA_7_BITS;
554: break;
555: default:
556: DPRINTF(("pss_testdma: invalid drq (%d)\n", dmaNum));
557: return 0;
558: }
559: outw(config, val);
560:
561: /* Check if the DMA channel is in use */
562: /* Do it a few times in case there is a delay */
563: ret = 0;
564: for (i = 0; i < 3; i++) {
565: val = inw(config);
566: if (val & DMA_TEST_PASS) {
567: ret = 1;
568: break;
569: }
570: }
571:
572: /* Clear the Test bit and the DMA bits */
573: val = inw(config);
574: val &= DMA_TEST_BIT_MASK & DMA_MASK;
575: outw(config, val);
576: return(ret);
577: }
578:
579: #ifdef notyet
580: int
581: pss_reset_dsp(sc)
582: struct pss_softc *sc;
583: {
584: u_long i;
585: int pss_base = sc->sc_iobase;
586:
587: outw(pss_base+PSS_CONTROL, PSS_RESET);
588:
589: for (i = 0; i < 32768; i++)
590: inw(pss_base+PSS_CONTROL);
591:
592: outw(pss_base+PSS_CONTROL, 0);
593:
594: return 1;
595: }
596:
597: /*
598: * This function loads an image into the PSS
599: * card. The function loads the file by
600: * resetting the dsp and feeding it the boot bytes.
601: * First you feed the ASIC the first byte of
602: * the boot sequence. The ASIC waits until it
603: * detects a BMS and RD and asserts BR
604: * and outputs the byte. The host must poll for
605: * the BG signal. It then feeds the ASIC another
606: * byte which removes BR.
607: */
608: int
609: pss_download_dsp(sc, block, size)
610: struct pss_softc *sc;
611: u_char *block;
612: int size;
613: {
614: int i, val, count;
615: int pss_base = sc->sc_iobase;
616:
617: DPRINTF(("pss: downloading boot code..."));
618:
619: /* Warn DSP software that a boot is coming */
620: outw(pss_base+PSS_DATA, 0x00fe);
621:
622: for (i = 0; i < 32768; i++)
623: if (inw(pss_base+PSS_DATA) == 0x5500)
624: break;
625: outw(pss_base+PSS_DATA, *block++);
626:
627: pss_reset_dsp(sc);
628:
629: DPRINTF(("start "));
630:
631: count = 1;
632: while(1) {
633: int j;
634: for (j=0; j<327670; j++) {
635: /* Wait for BG to appear */
636: if (inw(pss_base+PSS_STATUS) & PSS_FLAG3)
637: break;
638: }
639:
640: if (j==327670) {
641: /* It's ok we timed out when the file was empty */
642: if (count >= size)
643: break;
644: else {
645: printf("\npss: DownLoad timeout problems, byte %d=%d\n",
646: count, size);
647: return 0;
648: }
649: }
650: /* Send the next byte */
651: outw(pss_base+PSS_DATA, *block++);
652: count++;
653: }
654:
655: outw(pss_base+PSS_DATA, 0);
656: for (i = 0; i < 32768; i++)
657: (void) inw(pss_base+PSS_STATUS);
658:
659: DPRINTF(("downloaded\n"));
660:
661: for (i = 0; i < 32768; i++) {
662: val = inw(pss_base+PSS_STATUS);
663: if (val & PSS_READ_FULL)
664: break;
665: }
666:
667: /* now read the version */
668: for (i = 0; i < 32000; i++) {
669: val = inw(pss_base+PSS_STATUS);
670: if (val & PSS_READ_FULL)
671: break;
672: }
673: if (i == 32000)
674: return 0;
675:
676: (void) inw(pss_base+PSS_DATA);
677:
678: return 1;
679: }
680: #endif /* notyet */
681:
682: #ifdef AUDIO_DEBUG
683: void
684: wss_dump_regs(sc)
685: struct ad1848_softc *sc;
686: {
687:
688: printf("WSS reg: status=%02x\n",
689: (u_char)inb(sc->sc_iobase-WSS_CODEC+WSS_STATUS));
690: }
691:
692: void
693: pss_dump_regs(sc)
694: struct pss_softc *sc;
695: {
696:
697: printf("PSS regs: status=%04x vers=%04x ",
698: (u_short)inw(sc->sc_iobase+PSS_STATUS),
699: (u_short)inw(sc->sc_iobase+PSS_ID_VERS));
700:
701: printf("config=%04x wss_config=%04x\n",
702: (u_short)inw(sc->sc_iobase+PSS_CONFIG),
703: (u_short)inw(sc->sc_iobase+PSS_WSS_CONFIG));
704: }
705: #endif
706:
707: /*
708: * Probe for the PSS hardware.
709: */
710: int
711: pssprobe(parent, self, aux)
712: struct device *parent;
713: void *self;
714: void *aux;
715: {
716: struct pss_softc *sc = self;
717: struct isa_attach_args *ia = aux;
718: int iobase = ia->ia_iobase;
719:
720: if (!PSS_BASE_VALID(iobase)) {
721: DPRINTF(("pss: configured iobase %x invalid\n", iobase));
722: return 0;
723: }
724:
725: /* Need to probe for iobase when IOBASEUNK {0x220 0x240} */
726: if (iobase == IOBASEUNK) {
727:
728: iobase = 0x220;
729: if ((inw(iobase+PSS_ID_VERS) & 0xff00) == 0x4500)
730: goto pss_found;
731:
732: iobase = 0x240;
733: if ((inw(iobase+PSS_ID_VERS) & 0xff00) == 0x4500)
734: goto pss_found;
735:
736: DPRINTF(("pss: no PSS found (at 0x220 or 0x240)\n"));
737: return 0;
738: }
739: else if ((inw(iobase+PSS_ID_VERS) & 0xff00) != 0x4500) {
740: DPRINTF(("pss: not a PSS - %x\n", inw(iobase+PSS_ID_VERS)));
741: return 0;
742: }
743:
744: pss_found:
745: sc->sc_iobase = iobase;
746:
747: /* Clear WSS config */
748: pss_setaddr(WSS_BASE_ADDRESS, sc->sc_iobase+PSS_WSS_CONFIG); /* XXX! */
749: outb(WSS_BASE_ADDRESS+WSS_CONFIG, 0);
750:
751: /* Clear config registers (POR reset state) */
752: outw(sc->sc_iobase+PSS_CONFIG, 0);
753: outw(sc->sc_iobase+PSS_WSS_CONFIG, 0);
754: outw(sc->sc_iobase+SB_CONFIG, 0);
755: outw(sc->sc_iobase+MIDI_CONFIG, 0);
756: outw(sc->sc_iobase+CD_CONFIG, 0);
757:
758: if (ia->ia_irq == IRQUNK) {
759: int i;
760: for (i = 0; i < 16; i++) {
761: if (pss_testirq(sc, i) != 0)
762: break;
763: }
764: if (i == 16) {
765: DPRINTF(("pss: unable to locate free IRQ channel\n"));
766: return 0;
767: }
768: else {
769: ia->ia_irq = i;
770: DPRINTF(("pss: found IRQ %d free\n", i));
771: }
772: }
773: else {
774: if (pss_testirq(sc, ia->ia_irq) == 0) {
775: DPRINTF(("pss: configured IRQ unavailable (%d)\n", ia->ia_irq));
776: return 0;
777: }
778: }
779:
780: /* XXX Need to deal with DRQUNK */
781: if (pss_testdma(sc, ia->ia_drq) == 0) {
782: DPRINTF(("pss: configured DMA channel unavailable (%d)\n", ia->ia_drq));
783: return 0;
784: }
785:
786: ia->ia_iosize = PSS_NPORT;
787:
788: /* Initialize PSS irq and dma */
789: pss_setint(ia->ia_irq, sc->sc_iobase+PSS_CONFIG);
790: pss_setdma(sc->sc_drq, sc->sc_iobase+PSS_CONFIG);
791:
792: #ifdef notyet
793: /* Setup the Game port */
794: #ifdef PSS_GAMEPORT
795: DPRINTF(("Turning Game Port On.\n"));
796: outw(sc->sc_iobase+PSS_STATUS, inw(sc->sc_iobase+PSS_STATUS) | GAME_BIT);
797: #else
798: outw(sc->sc_iobase+PSS_STATUS, inw(sc->sc_iobase+PSS_STATUS) & GAME_BIT_MASK);
799: #endif
800:
801: /* Reset DSP */
802: pss_reset_dsp(sc);
803: #endif /* notyet */
804:
805: return 1;
806: }
807:
808: /*
809: * Probe for the Soundport (ad1848)
810: */
811: int
812: spprobe(parent, match, aux)
813: struct device *parent;
814: void *match, *aux;
815: {
816: struct ad1848_softc *sc = match;
817: struct pss_softc *pc = (void *) parent;
818: struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
819: struct isa_attach_args *ia = aux;
820: u_char bits;
821: int i;
822:
823: sc->sc_iot = ia->ia_iot;
824: sc->sc_iobase = cf->cf_iobase + WSS_CODEC;
825:
826: /* Set WSS io address */
827: pss_setaddr(cf->cf_iobase, pc->sc_iobase+PSS_WSS_CONFIG);
828:
829: /* Is there an ad1848 chip at the WSS iobase ? */
830: if (ad1848_probe(sc) == 0) {
831: DPRINTF(("sp: no ad1848 ? iobase=%x\n", sc->sc_iobase));
832: return 0;
833: }
834:
835: /* Setup WSS interrupt and DMA if auto */
836: if (cf->cf_irq == IRQUNK) {
837:
838: /* Find unused IRQ for WSS */
839: for (i = 0; i < 12; i++) {
840: if (wss_interrupt_bits[i] != 0xff) {
841: if (pss_testirq(pc, i))
842: break;
843: }
844: }
845: if (i == 12) {
846: DPRINTF(("sp: unable to locate free IRQ for WSS\n"));
847: return 0;
848: }
849: else {
850: cf->cf_irq = i;
851: sc->sc_irq = i;
852: DPRINTF(("sp: found IRQ %d free\n", i));
853: }
854: }
855: else {
856: sc->sc_irq = cf->cf_irq;
857: if (pss_testirq(pc, sc->sc_irq) == 0) {
858: DPRINTF(("sp: configured IRQ unavailable (%d)\n", sc->sc_irq));
859: return 0;
860: }
861: }
862:
863: if (cf->cf_drq == DRQUNK) {
864: /* Find unused DMA channel for WSS */
865: for (i = 0; i < 4; i++) {
866: if (wss_dma_bits[i]) {
867: if (pss_testdma(pc, i))
868: break;
869: }
870: }
871: if (i == 4) {
872: DPRINTF(("sp: unable to locate free DMA channel for WSS\n"));
873: return 0;
874: }
875: else {
876: sc->sc_drq = cf->cf_drq = i;
877: DPRINTF(("sp: found DMA %d free\n", i));
878: }
879: }
880: else {
881: if (pss_testdma(pc, sc->sc_drq) == 0) {
882: DPRINTF(("sp: configured DMA channel unavailable (%d)\n", sc->sc_drq));
883: return 0;
884: }
885: sc->sc_drq = cf->cf_drq;
886: }
887: sc->sc_recdrq = sc->sc_drq;
888:
889: /* Set WSS config registers */
890: if ((bits = wss_interrupt_bits[sc->sc_irq]) == 0xff) {
891: DPRINTF(("sp: invalid interrupt configuration (irq=%d)\n", sc->sc_irq));
892: return 0;
893: }
894:
895: outb(sc->sc_iobase+WSS_CONFIG, (bits | 0x40));
896: if ((inb(sc->sc_iobase+WSS_STATUS) & 0x40) == 0) /* XXX What do these bits mean ? */
897: DPRINTF(("sp: IRQ %x\n", inb(sc->sc_iobase+WSS_STATUS)));
898:
899: outb(sc->sc_iobase+WSS_CONFIG, (bits | wss_dma_bits[sc->sc_drq]));
900:
901: pc->ad1848_sc = sc;
902: sc->parent = pc;
903:
904: return 1;
905: }
906:
907: #ifdef notyet
908: int
909: mpuprobe(parent, match, aux)
910: struct device *parent;
911: void *match, *aux;
912: {
913: struct mpu_softc *sc = match;
914: struct pss_softc *pc = (void *) parent;
915: struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
916:
917: /* Check if midi is enabled; if it is check the interrupt */
918: sc->sc_iobase = cf->cf_iobase;
919:
920: if (cf->cf_irq == IRQUNK) {
921: int i;
922: for (i = 0; i < 16; i++) {
923: if (pss_testirq(pc, i) != 0)
924: break;
925: }
926: if (i == 16) {
927: printf("mpu: unable to locate free IRQ channel for MIDI\n");
928: return 0;
929: }
930: else {
931: cf->cf_irq = i;
932: sc->sc_irq = i;
933: DPRINTF(("mpu: found IRQ %d free\n", i));
934: }
935: }
936: else {
937: sc->sc_irq = cf->cf_irq;
938:
939: if (pss_testirq(pc, sc->sc_irq) == 0) {
940: printf("pss: configured MIDI IRQ unavailable (%d)\n", sc->sc_irq);
941: return 0;
942: }
943: }
944:
945: outw(pc->sc_iobase+MIDI_CONFIG,0);
946: DPRINTF(("pss: mpu port 0x%x irq %d\n", sc->sc_iobase, sc->sc_irq));
947: pss_setaddr(sc->sc_iobase, pc->sc_iobase+MIDI_CONFIG);
948: pss_setint(sc->sc_irq, pc->sc_iobase+MIDI_CONFIG);
949:
950: return 1;
951: }
952:
953: int
954: pcdprobe(parent, match, aux)
955: struct device *parent;
956: void *match, *aux;
957: {
958: struct pcd_softc *sc = match;
959: struct pss_softc *pc = (void *) parent;
960: struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
961: u_short val;
962:
963: sc->sc_iobase = cf->cf_iobase;
964:
965: pss_setaddr(sc->sc_iobase, pc->sc_iobase+CD_CONFIG);
966:
967: /* Set the correct irq polarity. */
968: val = inw(pc->sc_iobase+CD_CONFIG);
969: outw(pc->sc_iobase+CD_CONFIG, 0);
970: val &= CD_POL_MASK;
971: val |= CD_POL_BIT; /* XXX if (pol) */
972: outw(pc->sc_iobase+CD_CONFIG, val);
973:
974: if (cf->cf_irq == IRQUNK) {
975: int i;
976: for (i = 0; i < 16; i++) {
977: if (pss_testirq(pc, i) != 0)
978: break;
979: }
980: if (i == 16) {
981: printf("pcd: unable to locate free IRQ channel for CD\n");
982: return 0;
983: }
984: else {
985: cf->cf_irq = i;
986: sc->sc_irq = i;
987: DPRINTF(("pcd: found IRQ %d free\n", i));
988: }
989: }
990: else {
991: sc->sc_irq = cf->cf_irq;
992:
993: if (pss_testirq(pc, sc->sc_irq) == 0) {
994: printf("pcd: configured CD IRQ unavailable (%d)\n", sc->sc_irq);
995: return 0;
996: }
997: return 1;
998: }
999: pss_setint(sc->sc_irq, pc->sc_iobase+CD_CONFIG);
1000:
1001: return 1;
1002: }
1003: #endif /* notyet */
1004:
1005: /*
1006: * Attach hardware to driver, attach hardware driver to audio
1007: * pseudo-device driver .
1008: */
1009: void
1010: pssattach(parent, self, aux)
1011: struct device *parent, *self;
1012: void *aux;
1013: {
1014: struct pss_softc *sc = (struct pss_softc *)self;
1015: struct isa_attach_args *ia = (struct isa_attach_args *)aux;
1016: int iobase = ia->ia_iobase;
1017: u_char vers;
1018: struct ad1848_volume vol = {150, 150};
1019:
1020: sc->sc_iobase = iobase;
1021: sc->sc_drq = ia->ia_drq;
1022:
1023: /* Setup interrupt handler for PSS */
1024: sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, IPL_AUDIO,
1025: pssintr, sc, sc->sc_dev.dv_xname);
1026:
1027: vers = (inw(sc->sc_iobase+PSS_ID_VERS)&0xff) - 1;
1028: printf(": ESC614%c\n", (vers > 0)?'A'+vers:' ');
1029:
1030: (void)config_found(self, ia->ia_ic, NULL); /* XXX */
1031:
1032: sc->out_port = PSS_MASTER_VOL;
1033:
1034: (void)pss_set_master_mode(sc, PSS_SPKR_STEREO);
1035: (void)pss_set_master_gain(sc, &vol);
1036: (void)pss_set_treble(sc, AUDIO_MAX_GAIN/2);
1037: (void)pss_set_bass(sc, AUDIO_MAX_GAIN/2);
1038:
1039: audio_attach_mi(&pss_audio_if, sc->ad1848_sc, &sc->ad1848_sc->sc_dev);
1040: }
1041:
1042: void
1043: spattach(parent, self, aux)
1044: struct device *parent, *self;
1045: void *aux;
1046: {
1047: struct ad1848_softc *sc = (struct ad1848_softc *)self;
1048: struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
1049: isa_chipset_tag_t ic = aux; /* XXX */
1050: int iobase = cf->cf_iobase;
1051:
1052: sc->sc_iobase = iobase;
1053: sc->sc_drq = cf->cf_drq;
1054:
1055: sc->sc_ih = isa_intr_establish(ic, cf->cf_irq, IST_EDGE, IPL_AUDIO,
1056: ad1848_intr, sc, sc->sc_dev.dv_xname);
1057:
1058: sc->sc_isa = parent->dv_parent;
1059:
1060: ad1848_attach(sc);
1061:
1062: printf("\n");
1063: }
1064:
1065: #ifdef notyet
1066: void
1067: mpuattach(parent, self, aux)
1068: struct device *parent, *self;
1069: void *aux;
1070: {
1071: struct mpu_softc *sc = (struct mpu_softc *)self;
1072: struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
1073: isa_chipset_tag_t ic = aux; /* XXX */
1074: int iobase = cf->cf_iobase;
1075:
1076: sc->sc_iobase = iobase;
1077:
1078: sc->sc_ih = isa_intr_establish(ic, cf->cf_irq, IST_EDGE, IPL_AUDIO,
1079: mpuintr, sc, sc->sc_dev.dv_xname);
1080:
1081: /* XXX might use pssprint func ?? */
1082: printf(" port 0x%x/%d irq %d\n",
1083: sc->sc_iobase, MIDI_NPORT, cf->cf_irq);
1084: }
1085:
1086: void
1087: pcdattach(parent, self, aux)
1088: struct device *parent, *self;
1089: void *aux;
1090: {
1091: struct pcd_softc *sc = (struct pcd_softc *)self;
1092: struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
1093: int iobase = cf->cf_iobase;
1094:
1095: /*
1096: * The pss driver simply enables the cd interface. The CD
1097: * appropriate driver - scsi (aic6360) or Sony needs to be
1098: * used after this to handle the device.
1099: */
1100: sc->sc_iobase = iobase;
1101:
1102: /* XXX might use pssprint func ?? */
1103: printf(" port 0x%x/%d irq %d\n",
1104: sc->sc_iobase, 2, cf->cf_irq);
1105: }
1106: #endif /* notyet */
1107:
1108:
1109: int
1110: pss_set_master_gain(sc, gp)
1111: struct pss_softc *sc;
1112: struct ad1848_volume *gp;
1113: {
1114: DPRINTF(("pss_set_master_gain: %d:%d\n", gp->left, gp->right));
1115:
1116: #ifdef PSS_DSP
1117: if (gp->left > PHILLIPS_VOL_MAX)
1118: gp->left = PHILLIPS_VOL_MAX;
1119: if (gp->left < PHILLIPS_VOL_MIN)
1120: gp->left = PHILLIPS_VOL_MIN;
1121: if (gp->right > PHILLIPS_VOL_MAX)
1122: gp->right = PHILLIPS_VOL_MAX;
1123: if (gp->right < PHILLIPS_VOL_MIN)
1124: gp->right = PHILLIPS_VOL_MIN;
1125:
1126: pss_dspwrite(sc, SET_MASTER_COMMAND);
1127: pss_dspwrite(sc, MASTER_VOLUME_LEFT|(PHILLIPS_VOL_CONSTANT + gp->left / PHILLIPS_VOL_STEP));
1128: pss_dspwrite(sc, SET_MASTER_COMMAND);
1129: pss_dspwrite(sc, MASTER_VOLUME_RIGHT|(PHILLIPS_VOL_CONSTANT + gp->right / PHILLIPS_VOL_STEP));
1130: #endif
1131:
1132: sc->master_volume = *gp;
1133: return(0);
1134: }
1135:
1136: int
1137: pss_set_master_mode(sc, mode)
1138: struct pss_softc *sc;
1139: int mode;
1140: {
1141: short phillips_mode;
1142:
1143: DPRINTF(("pss_set_master_mode: %d\n", mode));
1144:
1145: if (mode == PSS_SPKR_STEREO)
1146: phillips_mode = PSS_STEREO;
1147: else if (mode == PSS_SPKR_PSEUDO)
1148: phillips_mode = PSS_PSEUDO;
1149: else if (mode == PSS_SPKR_SPATIAL)
1150: phillips_mode = PSS_SPATIAL;
1151: else if (mode == PSS_SPKR_MONO)
1152: phillips_mode = PSS_MONO;
1153: else
1154: return (EINVAL);
1155:
1156: #ifdef PSS_DSP
1157: pss_dspwrite(sc, SET_MASTER_COMMAND);
1158: pss_dspwrite(sc, MASTER_SWITCH | mode);
1159: #endif
1160:
1161: sc->master_mode = mode;
1162:
1163: return(0);
1164: }
1165:
1166: int
1167: pss_set_treble(sc, treb)
1168: struct pss_softc *sc;
1169: u_int treb;
1170: {
1171: DPRINTF(("pss_set_treble: %d\n", treb));
1172:
1173: #ifdef PSS_DSP
1174: if (treb > PHILLIPS_TREBLE_MAX)
1175: treb = PHILLIPS_TREBLE_MAX;
1176: if (treb < PHILLIPS_TREBLE_MIN)
1177: treb = PHILLIPS_TREBLE_MIN;
1178: pss_dspwrite(sc, SET_MASTER_COMMAND);
1179: pss_dspwrite(sc, MASTER_TREBLE|(PHILLIPS_TREBLE_CONSTANT + treb / PHILLIPS_TREBLE_STEP));
1180: #endif
1181:
1182: sc->monitor_treble = treb;
1183:
1184: return(0);
1185: }
1186:
1187: int
1188: pss_set_bass(sc, bass)
1189: struct pss_softc *sc;
1190: u_int bass;
1191: {
1192: DPRINTF(("pss_set_bass: %d\n", bass));
1193:
1194: #ifdef PSS_DSP
1195: if (bass > PHILLIPS_BASS_MAX)
1196: bass = PHILLIPS_BASS_MAX;
1197: if (bass < PHILLIPS_BASS_MIN)
1198: bass = PHILLIPS_BASS_MIN;
1199: pss_dspwrite(sc, SET_MASTER_COMMAND);
1200: pss_dspwrite(sc, MASTER_BASS|(PHILLIPS_BASS_CONSTANT + bass / PHILLIPS_BASS_STEP));
1201: #endif
1202:
1203: sc->monitor_bass = bass;
1204:
1205: return(0);
1206: }
1207:
1208: int
1209: pss_get_master_gain(sc, gp)
1210: struct pss_softc *sc;
1211: struct ad1848_volume *gp;
1212: {
1213: *gp = sc->master_volume;
1214: return(0);
1215: }
1216:
1217: int
1218: pss_get_master_mode(sc, mode)
1219: struct pss_softc *sc;
1220: u_int *mode;
1221: {
1222: *mode = sc->master_mode;
1223: return(0);
1224: }
1225:
1226: int
1227: pss_get_treble(sc, tp)
1228: struct pss_softc *sc;
1229: u_char *tp;
1230: {
1231: *tp = sc->monitor_treble;
1232: return(0);
1233: }
1234:
1235: int
1236: pss_get_bass(sc, bp)
1237: struct pss_softc *sc;
1238: u_char *bp;
1239: {
1240: *bp = sc->monitor_bass;
1241: return(0);
1242: }
1243:
1244: int
1245: pss_speaker_ctl(addr, newstate)
1246: void *addr;
1247: int newstate;
1248: {
1249: return(0);
1250: }
1251:
1252: int
1253: pssintr(arg)
1254: void *arg;
1255: {
1256: struct pss_softc *sc = arg;
1257: u_short sr;
1258:
1259: sr = inw(sc->sc_iobase+PSS_STATUS);
1260:
1261: DPRINTF(("pssintr: sc=%p st=%x\n", sc, sr));
1262:
1263: /* Acknowledge intr */
1264: outw(sc->sc_iobase+PSS_IRQ_ACK, 0);
1265:
1266: /* Is it one of ours ? */
1267: if (sr & (PSS_WRITE_EMPTY|PSS_READ_FULL|PSS_IRQ|PSS_DMQ_TC)) {
1268: /* XXX do something */
1269: return 1;
1270: }
1271:
1272: return 0;
1273: }
1274:
1275: #ifdef notyet
1276: int
1277: mpuintr(arg)
1278: void *arg;
1279: {
1280: struct mpu_softc *sc = arg;
1281: u_char sr;
1282:
1283: sr = inb(sc->sc_iobase+MIDI_STATUS_REG);
1284:
1285: printf("mpuintr: sc=%p sr=%x\n", sc, sr);
1286:
1287: /* XXX Need to clear intr */
1288: return 1;
1289: }
1290: #endif
1291:
1292: int
1293: pss_getdev(addr, retp)
1294: void *addr;
1295: struct audio_device *retp;
1296: {
1297: DPRINTF(("pss_getdev: retp=%p\n", retp));
1298:
1299: *retp = pss_device;
1300: return 0;
1301: }
1302:
1303: static ad1848_devmap_t mappings[] = {
1304: { PSS_MIC_IN_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL },
1305: { PSS_LINE_IN_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL },
1306: { PSS_DAC_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL },
1307: { PSS_MON_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL },
1308: { PSS_MIC_IN_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL },
1309: { PSS_LINE_IN_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL },
1310: { PSS_DAC_MUTE, AD1848_KIND_MUTE, AD1848_DAC_CHANNEL },
1311: { PSS_REC_LVL, AD1848_KIND_RECORDGAIN, -1 },
1312: { PSS_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1}
1313: };
1314:
1315: static int nummap = sizeof(mappings) / sizeof(mappings[0]);
1316:
1317: int
1318: pss_mixer_set_port(addr, cp)
1319: void *addr;
1320: mixer_ctrl_t *cp;
1321: {
1322: struct ad1848_softc *ac = addr;
1323: struct pss_softc *sc = ac->parent;
1324: struct ad1848_volume vol;
1325: int error = ad1848_mixer_set_port(ac, mappings, nummap, cp);
1326:
1327: if (error != ENXIO)
1328: return (error);
1329:
1330: switch (cp->dev) {
1331: case PSS_MASTER_VOL: /* master volume */
1332: if (cp->type == AUDIO_MIXER_VALUE) {
1333: if (ad1848_to_vol(cp, &vol))
1334: error = pss_set_master_gain(sc, &vol);
1335: }
1336: break;
1337:
1338: case PSS_OUTPUT_MODE:
1339: if (cp->type == AUDIO_MIXER_ENUM)
1340: error = pss_set_master_mode(sc, cp->un.ord);
1341: break;
1342:
1343: case PSS_MASTER_TREBLE: /* master treble */
1344: if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1)
1345: error = pss_set_treble(sc, (u_char)cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1346: break;
1347:
1348: case PSS_MASTER_BASS: /* master bass */
1349: if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1)
1350: error = pss_set_bass(sc, (u_char)cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1351: break;
1352:
1353: default:
1354: return ENXIO;
1355: /*NOTREACHED*/
1356: }
1357:
1358: return 0;
1359: }
1360:
1361: int
1362: pss_mixer_get_port(addr, cp)
1363: void *addr;
1364: mixer_ctrl_t *cp;
1365: {
1366: struct ad1848_softc *ac = addr;
1367: struct pss_softc *sc = ac->parent;
1368: struct ad1848_volume vol;
1369: u_char eq;
1370: int error = ad1848_mixer_get_port(ac, mappings, nummap, cp);
1371:
1372: if (error != ENXIO)
1373: return (error);
1374:
1375: error = EINVAL;
1376:
1377: switch (cp->dev) {
1378: case PSS_MASTER_VOL: /* master volume */
1379: if (cp->type == AUDIO_MIXER_VALUE) {
1380: error = pss_get_master_gain(sc, &vol);
1381: if (!error)
1382: ad1848_from_vol(cp, &vol);
1383: }
1384: break;
1385:
1386: case PSS_MASTER_TREBLE: /* master treble */
1387: if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) {
1388: error = pss_get_treble(sc, &eq);
1389: if (!error)
1390: cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = eq;
1391: }
1392: break;
1393:
1394: case PSS_MASTER_BASS: /* master bass */
1395: if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) {
1396: error = pss_get_bass(sc, &eq);
1397: if (!error)
1398: cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = eq;
1399: }
1400: break;
1401:
1402: case PSS_OUTPUT_MODE:
1403: if (cp->type == AUDIO_MIXER_ENUM)
1404: error = pss_get_master_mode(sc, &cp->un.ord);
1405: break;
1406:
1407: default:
1408: error = ENXIO;
1409: break;
1410: }
1411:
1412: return(error);
1413: }
1414:
1415: int
1416: pss_query_devinfo(addr, dip)
1417: void *addr;
1418: mixer_devinfo_t *dip;
1419: {
1420: DPRINTF(("pss_query_devinfo: index=%d\n", dip->index));
1421:
1422: switch(dip->index) {
1423: case PSS_MIC_IN_LVL: /* Microphone */
1424: dip->type = AUDIO_MIXER_VALUE;
1425: dip->mixer_class = PSS_INPUT_CLASS;
1426: dip->prev = AUDIO_MIXER_LAST;
1427: dip->next = PSS_MIC_IN_MUTE;
1428: strlcpy(dip->label.name, AudioNmicrophone, sizeof dip->label.name);
1429: dip->un.v.num_channels = 2;
1430: strlcpy(dip->un.v.units.name, AudioNvolume,
1431: sizeof dip->un.v.units.name);
1432: break;
1433:
1434: case PSS_LINE_IN_LVL: /* line/CD */
1435: dip->type = AUDIO_MIXER_VALUE;
1436: dip->mixer_class = PSS_INPUT_CLASS;
1437: dip->prev = AUDIO_MIXER_LAST;
1438: dip->next = PSS_LINE_IN_MUTE;
1439: strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
1440: dip->un.v.num_channels = 2;
1441: strlcpy(dip->un.v.units.name, AudioNvolume,
1442: sizeof dip->un.v.units.name);
1443: break;
1444:
1445: case PSS_DAC_LVL: /* dacout */
1446: dip->type = AUDIO_MIXER_VALUE;
1447: dip->mixer_class = PSS_INPUT_CLASS;
1448: dip->prev = AUDIO_MIXER_LAST;
1449: dip->next = PSS_DAC_MUTE;
1450: strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
1451: dip->un.v.num_channels = 2;
1452: strlcpy(dip->un.v.units.name, AudioNvolume,
1453: sizeof dip->un.v.units.name);
1454: break;
1455:
1456: case PSS_REC_LVL: /* record level */
1457: dip->type = AUDIO_MIXER_VALUE;
1458: dip->mixer_class = PSS_RECORD_CLASS;
1459: dip->prev = AUDIO_MIXER_LAST;
1460: dip->next = PSS_RECORD_SOURCE;
1461: strlcpy(dip->label.name, AudioNrecord, sizeof dip->label.name);
1462: dip->un.v.num_channels = 2;
1463: strlcpy(dip->un.v.units.name, AudioNvolume,
1464: sizeof dip->un.v.units.name);
1465: break;
1466:
1467: case PSS_MON_LVL: /* monitor level */
1468: dip->type = AUDIO_MIXER_VALUE;
1469: dip->mixer_class = PSS_MONITOR_CLASS;
1470: dip->next = dip->prev = AUDIO_MIXER_LAST;
1471: strlcpy(dip->label.name, AudioNmonitor, sizeof dip->label.name);
1472: dip->un.v.num_channels = 1;
1473: strlcpy(dip->un.v.units.name, AudioNvolume,
1474: sizeof dip->un.v.units.name);
1475: break;
1476:
1477: case PSS_MASTER_VOL: /* master volume */
1478: dip->type = AUDIO_MIXER_VALUE;
1479: dip->mixer_class = PSS_OUTPUT_CLASS;
1480: dip->prev = AUDIO_MIXER_LAST;
1481: dip->next = PSS_OUTPUT_MODE;
1482: strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
1483: dip->un.v.num_channels = 2;
1484: strlcpy(dip->un.v.units.name, AudioNvolume,
1485: sizeof dip->un.v.units.name);
1486: break;
1487:
1488: case PSS_MASTER_TREBLE: /* master treble */
1489: dip->type = AUDIO_MIXER_VALUE;
1490: dip->mixer_class = PSS_OUTPUT_CLASS;
1491: dip->next = dip->prev = AUDIO_MIXER_LAST;
1492: strlcpy(dip->label.name, AudioNtreble, sizeof dip->label.name);
1493: dip->un.v.num_channels = 1;
1494: strlcpy(dip->un.v.units.name, AudioNtreble,
1495: sizeof dip->un.v.units.name);
1496: break;
1497:
1498: case PSS_MASTER_BASS: /* master bass */
1499: dip->type = AUDIO_MIXER_VALUE;
1500: dip->mixer_class = PSS_OUTPUT_CLASS;
1501: dip->next = dip->prev = AUDIO_MIXER_LAST;
1502: strlcpy(dip->label.name, AudioNbass, sizeof dip->label.name);
1503: dip->un.v.num_channels = 1;
1504: strlcpy(dip->un.v.units.name, AudioNbass, sizeof dip->un.v.units.name);
1505: break;
1506:
1507: case PSS_OUTPUT_CLASS: /* output class descriptor */
1508: dip->type = AUDIO_MIXER_CLASS;
1509: dip->mixer_class = PSS_OUTPUT_CLASS;
1510: dip->next = dip->prev = AUDIO_MIXER_LAST;
1511: strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
1512: break;
1513:
1514: case PSS_INPUT_CLASS: /* input class descriptor */
1515: dip->type = AUDIO_MIXER_CLASS;
1516: dip->mixer_class = PSS_INPUT_CLASS;
1517: dip->next = dip->prev = AUDIO_MIXER_LAST;
1518: strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
1519: break;
1520:
1521: case PSS_MONITOR_CLASS: /* monitor class descriptor */
1522: dip->type = AUDIO_MIXER_CLASS;
1523: dip->mixer_class = PSS_MONITOR_CLASS;
1524: dip->next = dip->prev = AUDIO_MIXER_LAST;
1525: strlcpy(dip->label.name, AudioCmonitor, sizeof dip->label.name);
1526: break;
1527:
1528: case PSS_RECORD_CLASS: /* record source class */
1529: dip->type = AUDIO_MIXER_CLASS;
1530: dip->mixer_class = PSS_RECORD_CLASS;
1531: dip->next = dip->prev = AUDIO_MIXER_LAST;
1532: strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
1533: break;
1534:
1535: case PSS_MIC_IN_MUTE:
1536: dip->mixer_class = PSS_INPUT_CLASS;
1537: dip->type = AUDIO_MIXER_ENUM;
1538: dip->prev = PSS_MIC_IN_LVL;
1539: dip->next = AUDIO_MIXER_LAST;
1540: goto mute;
1541:
1542: case PSS_LINE_IN_MUTE:
1543: dip->mixer_class = PSS_INPUT_CLASS;
1544: dip->type = AUDIO_MIXER_ENUM;
1545: dip->prev = PSS_LINE_IN_LVL;
1546: dip->next = AUDIO_MIXER_LAST;
1547: goto mute;
1548:
1549: case PSS_DAC_MUTE:
1550: dip->mixer_class = PSS_INPUT_CLASS;
1551: dip->type = AUDIO_MIXER_ENUM;
1552: dip->prev = PSS_DAC_LVL;
1553: dip->next = AUDIO_MIXER_LAST;
1554: mute:
1555: strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
1556: dip->un.e.num_mem = 2;
1557: strlcpy(dip->un.e.member[0].label.name, AudioNoff,
1558: sizeof dip->un.e.member[0].label.name);
1559: dip->un.e.member[0].ord = 0;
1560: strlcpy(dip->un.e.member[1].label.name, AudioNon,
1561: sizeof dip->un.e.member[1].label.name);
1562: dip->un.e.member[1].ord = 1;
1563: break;
1564:
1565: case PSS_OUTPUT_MODE:
1566: dip->mixer_class = PSS_OUTPUT_CLASS;
1567: dip->type = AUDIO_MIXER_ENUM;
1568: dip->prev = PSS_MASTER_VOL;
1569: dip->next = AUDIO_MIXER_LAST;
1570: strlcpy(dip->label.name, AudioNmode, sizeof dip->label.name);
1571: dip->un.e.num_mem = 4;
1572: strlcpy(dip->un.e.member[0].label.name, AudioNmono,
1573: sizeof dip->un.e.member[0].label.name);
1574: dip->un.e.member[0].ord = PSS_SPKR_MONO;
1575: strlcpy(dip->un.e.member[1].label.name, AudioNstereo,
1576: sizeof dip->un.e.member[1].label.name);
1577: dip->un.e.member[1].ord = PSS_SPKR_STEREO;
1578: strlcpy(dip->un.e.member[2].label.name, AudioNpseudo,
1579: sizeof dip->un.e.member[2].label.name);
1580: dip->un.e.member[2].ord = PSS_SPKR_PSEUDO;
1581: strlcpy(dip->un.e.member[3].label.name, AudioNspatial,
1582: sizeof dip->un.e.member[3].label.name);
1583: dip->un.e.member[3].ord = PSS_SPKR_SPATIAL;
1584: break;
1585:
1586: case PSS_RECORD_SOURCE:
1587: dip->mixer_class = PSS_RECORD_CLASS;
1588: dip->type = AUDIO_MIXER_ENUM;
1589: dip->prev = PSS_REC_LVL;
1590: dip->next = AUDIO_MIXER_LAST;
1591: strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
1592: dip->un.e.num_mem = 3;
1593: strlcpy(dip->un.e.member[0].label.name, AudioNmicrophone,
1594: sizeof dip->un.e.member[0].label.name);
1595: dip->un.e.member[0].ord = PSS_MIC_IN_LVL;
1596: strlcpy(dip->un.e.member[1].label.name, AudioNcd,
1597: sizeof dip->un.e.member[1].label.name);
1598: dip->un.e.member[1].ord = PSS_LINE_IN_LVL;
1599: strlcpy(dip->un.e.member[2].label.name, AudioNdac,
1600: sizeof dip->un.e.member[2].label.name);
1601: dip->un.e.member[2].ord = PSS_DAC_LVL;
1602: break;
1603:
1604: default:
1605: return ENXIO;
1606: /*NOTREACHED*/
1607: }
1608: DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
1609:
1610: return 0;
1611: }
CVSweb