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