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
pss_dspwrite(sc,data)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
pss_setaddr(addr,configAddr)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
pss_setint(intNum,configAddress)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
pss_setdma(dmaNum,configAddress)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
pss_testirq(struct pss_softc * sc,int intNum)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
pss_testdma(sc,dmaNum)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
pss_reset_dsp(sc)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
pss_download_dsp(sc,block,size)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
wss_dump_regs(sc)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
pss_dump_regs(sc)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
pssprobe(parent,self,aux)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
spprobe(parent,match,aux)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
mpuprobe(parent,match,aux)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
pcdprobe(parent,match,aux)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
pssattach(parent,self,aux)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
spattach(parent,self,aux)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
mpuattach(parent,self,aux)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
pcdattach(parent,self,aux)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
pss_set_master_gain(sc,gp)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
pss_set_master_mode(sc,mode)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
pss_set_treble(sc,treb)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
pss_set_bass(sc,bass)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
pss_get_master_gain(sc,gp)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
pss_get_master_mode(sc,mode)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
pss_get_treble(sc,tp)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
pss_get_bass(sc,bp)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
pss_speaker_ctl(addr,newstate)1245 pss_speaker_ctl(addr, newstate)
1246     void *addr;
1247     int newstate;
1248 {
1249     return(0);
1250 }
1251 
1252 int
pssintr(arg)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
mpuintr(arg)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
pss_getdev(addr,retp)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
pss_mixer_set_port(addr,cp)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
pss_mixer_get_port(addr,cp)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
pss_query_devinfo(addr,dip)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 }
1612