root/dev/isa/pss.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pss_dspwrite
  2. pss_setaddr
  3. pss_setint
  4. pss_setdma
  5. pss_testirq
  6. pss_testdma
  7. pss_reset_dsp
  8. pss_download_dsp
  9. wss_dump_regs
  10. pss_dump_regs
  11. pssprobe
  12. spprobe
  13. mpuprobe
  14. pcdprobe
  15. pssattach
  16. spattach
  17. mpuattach
  18. pcdattach
  19. pss_set_master_gain
  20. pss_set_master_mode
  21. pss_set_treble
  22. pss_set_bass
  23. pss_get_master_gain
  24. pss_get_master_mode
  25. pss_get_treble
  26. pss_get_bass
  27. pss_speaker_ctl
  28. pssintr
  29. mpuintr
  30. pss_getdev
  31. pss_mixer_set_port
  32. pss_mixer_get_port
  33. pss_query_devinfo

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

/* [<][>][^][v][top][bottom][index][help] */