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