LCOV - code coverage report
Current view: top level - dev/pci - cmpci.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 822 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 40 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: cmpci.c,v 1.45 2018/09/14 08:37:34 miko Exp $ */
       2             : /*      $NetBSD: cmpci.c,v 1.25 2004/10/26 06:32:20 xtraeme Exp $       */
       3             : 
       4             : /*
       5             :  * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
       6             :  * All rights reserved.
       7             :  *
       8             :  * This code is derived from software contributed to The NetBSD Foundation
       9             :  * by Takuya SHIOZAKI <tshiozak@NetBSD.org> .
      10             :  *
      11             :  * This code is derived from software contributed to The NetBSD Foundation
      12             :  * by ITOH Yasufumi.
      13             :  *
      14             :  * Redistribution and use in source and binary forms, with or without
      15             :  * modification, are permitted provided that the following conditions
      16             :  * are met:
      17             :  * 1. Redistributions of source code must retain the above copyright
      18             :  *    notice, this list of conditions and the following disclaimer.
      19             :  * 2. Redistributions in binary form must reproduce the above copyright
      20             :  *    notice, this list of conditions and the following disclaimer in the
      21             :  *    documentation and/or other materials provided with the distribution.
      22             :  *
      23             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      24             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      25             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      26             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      27             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      28             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      29             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      30             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      31             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      32             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      33             :  * SUCH DAMAGE.
      34             :  *
      35             :  */
      36             : 
      37             : /*
      38             :  * C-Media CMI8x38, CMI8768 Audio Chip Support.
      39             :  *
      40             :  * TODO:
      41             :  *   - Joystick support.
      42             :  *
      43             :  */
      44             : 
      45             : #if defined(AUDIO_DEBUG) || defined(DEBUG)
      46             : #define DPRINTF(x) if (cmpcidebug) printf x
      47             : int cmpcidebug = 0;
      48             : #else
      49             : #define DPRINTF(x)
      50             : #endif
      51             : 
      52             : #include <sys/param.h>
      53             : #include <sys/systm.h>
      54             : #include <sys/kernel.h>
      55             : #include <sys/malloc.h>
      56             : #include <sys/device.h>
      57             : 
      58             : #include <dev/pci/pcidevs.h>
      59             : #include <dev/pci/pcivar.h>
      60             : 
      61             : #include <sys/audioio.h>
      62             : #include <dev/audio_if.h>
      63             : #include <dev/midi_if.h>
      64             : 
      65             : #include <dev/pci/cmpcireg.h>
      66             : #include <dev/pci/cmpcivar.h>
      67             : 
      68             : #include <machine/bus.h>
      69             : #include <machine/intr.h>
      70             : 
      71             : /*
      72             :  * Low-level HW interface
      73             :  */
      74             : uint8_t cmpci_mixerreg_read(struct cmpci_softc *, uint8_t);
      75             : void cmpci_mixerreg_write(struct cmpci_softc *, uint8_t, uint8_t);
      76             : void cmpci_reg_partial_write_1(struct cmpci_softc *, int, int,
      77             :                                                     unsigned, unsigned);
      78             : void cmpci_reg_partial_write_4(struct cmpci_softc *, int, int,
      79             :                                                     uint32_t, uint32_t);
      80             : void cmpci_reg_set_1(struct cmpci_softc *, int, uint8_t);
      81             : void cmpci_reg_clear_1(struct cmpci_softc *, int, uint8_t);
      82             : void cmpci_reg_set_4(struct cmpci_softc *, int, uint32_t);
      83             : void cmpci_reg_clear_4(struct cmpci_softc *, int, uint32_t);
      84             : void cmpci_reg_set_reg_misc(struct cmpci_softc *, uint32_t);
      85             : void cmpci_reg_clear_reg_misc(struct cmpci_softc *, uint32_t);
      86             : int cmpci_rate_to_index(int);
      87             : int cmpci_index_to_rate(int);
      88             : int cmpci_index_to_divider(int);
      89             : 
      90             : int cmpci_adjust(int, int);
      91             : void cmpci_set_mixer_gain(struct cmpci_softc *, int);
      92             : void cmpci_set_out_ports(struct cmpci_softc *);
      93             : int cmpci_set_in_ports(struct cmpci_softc *);
      94             : 
      95             : void cmpci_resume(struct cmpci_softc *);
      96             : 
      97             : /*
      98             :  * autoconf interface
      99             :  */
     100             : int cmpci_match(struct device *, void *, void *);
     101             : void cmpci_attach(struct device *, struct device *, void *);
     102             : int cmpci_activate(struct device *, int);
     103             : 
     104             : struct cfdriver cmpci_cd = {
     105             :         NULL, "cmpci", DV_DULL
     106             : };
     107             : 
     108             : struct cfattach cmpci_ca = {
     109             :         sizeof (struct cmpci_softc), cmpci_match, cmpci_attach, NULL,
     110             :         cmpci_activate
     111             : };
     112             : 
     113             : /* interrupt */
     114             : int cmpci_intr(void *);
     115             : 
     116             : /*
     117             :  * DMA stuff
     118             :  */
     119             : int cmpci_alloc_dmamem(struct cmpci_softc *,
     120             :                                    size_t, int,
     121             :                                    int, caddr_t *);
     122             : int cmpci_free_dmamem(struct cmpci_softc *, caddr_t,
     123             :                                   int);
     124             : struct cmpci_dmanode * cmpci_find_dmamem(struct cmpci_softc *,
     125             :                                                      caddr_t);
     126             : 
     127             : /*
     128             :  * Interface to machine independent layer
     129             :  */
     130             : int cmpci_open(void *, int);
     131             : void cmpci_close(void *);
     132             : int cmpci_set_params(void *, int, int,
     133             :                                  struct audio_params *,
     134             :                                  struct audio_params *);
     135             : int cmpci_round_blocksize(void *, int);
     136             : int cmpci_halt_output(void *);
     137             : int cmpci_halt_input(void *);
     138             : int cmpci_set_port(void *, mixer_ctrl_t *);
     139             : int cmpci_get_port(void *, mixer_ctrl_t *);
     140             : int cmpci_query_devinfo(void *, mixer_devinfo_t *);
     141             : void *cmpci_malloc(void *, int, size_t, int, int);
     142             : void cmpci_free(void *, void *, int);
     143             : size_t cmpci_round_buffersize(void *, int, size_t);
     144             : int cmpci_get_props(void *);
     145             : int cmpci_trigger_output(void *, void *, void *, int,
     146             :                                      void (*)(void *), void *,
     147             :                                      struct audio_params *);
     148             : int cmpci_trigger_input(void *, void *, void *, int,
     149             :                                     void (*)(void *), void *,
     150             :                                     struct audio_params *);
     151             : 
     152             : struct audio_hw_if cmpci_hw_if = {
     153             :         cmpci_open,             /* open */
     154             :         cmpci_close,            /* close */
     155             :         cmpci_set_params,       /* set_params */
     156             :         cmpci_round_blocksize,  /* round_blocksize */
     157             :         NULL,                   /* commit_settings */
     158             :         NULL,                   /* init_output */
     159             :         NULL,                   /* init_input */
     160             :         NULL,                   /* start_output */
     161             :         NULL,                   /* start_input */
     162             :         cmpci_halt_output,      /* halt_output */
     163             :         cmpci_halt_input,       /* halt_input */
     164             :         NULL,                   /* speaker_ctl */
     165             :         NULL,                   /* setfd */
     166             :         cmpci_set_port,         /* set_port */
     167             :         cmpci_get_port,         /* get_port */
     168             :         cmpci_query_devinfo,    /* query_devinfo */
     169             :         cmpci_malloc,           /* malloc */
     170             :         cmpci_free,             /* free */
     171             :         cmpci_round_buffersize,/* round_buffersize */
     172             :         cmpci_get_props,        /* get_props */
     173             :         cmpci_trigger_output,   /* trigger_output */
     174             :         cmpci_trigger_input     /* trigger_input */
     175             : };
     176             : 
     177             : /*
     178             :  * Low-level HW interface
     179             :  */
     180             : 
     181             : /* mixer register read/write */
     182             : uint8_t
     183           0 : cmpci_mixerreg_read(struct cmpci_softc *sc, uint8_t no)
     184             : {
     185             :         uint8_t ret;
     186             : 
     187           0 :         bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
     188           0 :         delay(10);
     189           0 :         ret = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA);
     190           0 :         delay(10);
     191           0 :         return ret;
     192             : }
     193             : 
     194             : void
     195           0 : cmpci_mixerreg_write(struct cmpci_softc *sc, uint8_t no, uint8_t val)
     196             : {
     197           0 :         bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
     198           0 :         delay(10);
     199           0 :         bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA, val);
     200           0 :         delay(10);
     201           0 : }
     202             : 
     203             : /* register partial write */
     204             : void
     205           0 : cmpci_reg_partial_write_1(struct cmpci_softc *sc, int no, int shift,
     206             :     unsigned mask, unsigned val)
     207             : {
     208           0 :         bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
     209             :             (val<<shift) |
     210             :             (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift)));
     211           0 :         delay(10);
     212           0 : }
     213             : 
     214             : void
     215           0 : cmpci_reg_partial_write_4(struct cmpci_softc *sc, int no, int shift,
     216             :     uint32_t mask, uint32_t val)
     217             : {
     218           0 :         bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
     219             :             (val<<shift) |
     220             :             (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift)));
     221           0 :         delay(10);
     222           0 : }
     223             : 
     224             : /* register set/clear bit */
     225             : void
     226           0 : cmpci_reg_set_1(struct cmpci_softc *sc, int no, uint8_t mask)
     227             : {
     228           0 :         bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
     229             :             (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) | mask));
     230           0 :         delay(10);
     231           0 : }
     232             : 
     233             : void
     234           0 : cmpci_reg_clear_1(struct cmpci_softc *sc, int no, uint8_t mask)
     235             : {
     236           0 :         bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
     237             :             (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) & ~mask));
     238           0 :         delay(10);
     239           0 : }
     240             : 
     241             : void
     242           0 : cmpci_reg_set_4(struct cmpci_softc *sc, int no, uint32_t mask)
     243             : {
     244             :         /* use cmpci_reg_set_reg_misc() for CMPCI_REG_MISC */
     245             :         KDASSERT(no != CMPCI_REG_MISC);
     246             : 
     247           0 :         bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
     248             :             (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) | mask));
     249           0 :         delay(10);
     250           0 : }
     251             : 
     252             : void
     253           0 : cmpci_reg_clear_4(struct cmpci_softc *sc, int no, uint32_t mask)
     254             : {
     255             :         /* use cmpci_reg_clear_reg_misc() for CMPCI_REG_MISC */
     256             :         KDASSERT(no != CMPCI_REG_MISC);
     257             : 
     258           0 :         bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
     259             :             (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~mask));
     260           0 :         delay(10);
     261           0 : }
     262             : 
     263             : /*
     264             :  * The CMPCI_REG_MISC register needs special handling, since one of
     265             :  * its bits has different read/write values.
     266             :  */
     267             : void
     268           0 : cmpci_reg_set_reg_misc(struct cmpci_softc *sc, uint32_t mask)
     269             : {
     270           0 :         sc->sc_reg_misc |= mask;
     271           0 :         bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MISC,
     272             :             sc->sc_reg_misc);
     273           0 :         delay(10);
     274           0 : }
     275             : 
     276             : void
     277           0 : cmpci_reg_clear_reg_misc(struct cmpci_softc *sc, uint32_t mask)
     278             : {
     279           0 :         sc->sc_reg_misc &= ~mask;
     280           0 :         bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MISC,
     281             :             sc->sc_reg_misc);
     282           0 :         delay(10);
     283           0 : }
     284             : 
     285             : /* rate */
     286             : static const struct {
     287             :         int rate;
     288             :         int divider;
     289             : } cmpci_rate_table[CMPCI_REG_NUMRATE] = {
     290             : #define _RATE(n) { n, CMPCI_REG_RATE_ ## n }
     291             :         _RATE(5512),
     292             :         _RATE(8000),
     293             :         _RATE(11025),
     294             :         _RATE(16000),
     295             :         _RATE(22050),
     296             :         _RATE(32000),
     297             :         _RATE(44100),
     298             :         _RATE(48000)
     299             : #undef  _RATE
     300             : };
     301             : 
     302             : int
     303           0 : cmpci_rate_to_index(int rate)
     304             : {
     305             :         int i;
     306             : 
     307           0 :         for (i = 0; i < CMPCI_REG_NUMRATE - 1; i++)
     308           0 :                 if (rate <=
     309           0 :                     (cmpci_rate_table[i].rate + cmpci_rate_table[i+1].rate) / 2)
     310           0 :                         return i;
     311           0 :         return i;  /* 48000 */
     312           0 : }
     313             : 
     314             : int
     315           0 : cmpci_index_to_rate(int index)
     316             : {
     317           0 :         return cmpci_rate_table[index].rate;
     318             : }
     319             : 
     320             : int
     321           0 : cmpci_index_to_divider(int index)
     322             : {
     323           0 :         return cmpci_rate_table[index].divider;
     324             : }
     325             : 
     326             : const struct pci_matchid cmpci_devices[] = {
     327             :         { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8338A },
     328             :         { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8338B },
     329             :         { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8738 },
     330             :         { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8738B }
     331             : };
     332             : 
     333             : /*
     334             :  * interface to configure the device.
     335             :  */
     336             : 
     337             : int
     338           0 : cmpci_match(struct device *parent, void *match, void *aux)
     339             : {
     340           0 :         return (pci_matchbyid((struct pci_attach_args *)aux, cmpci_devices,
     341             :             nitems(cmpci_devices)));
     342             : }
     343             : 
     344             : void
     345           0 : cmpci_attach(struct device *parent, struct device *self, void *aux)
     346             : {
     347           0 :         struct cmpci_softc *sc = (struct cmpci_softc *)self;
     348           0 :         struct pci_attach_args *pa = (struct pci_attach_args *)aux;
     349           0 :         struct audio_attach_args aa;
     350           0 :         pci_intr_handle_t ih;
     351             :         char const *intrstr;
     352             :         int i, v, d;
     353             : 
     354           0 :         sc->sc_id = pa->pa_id;
     355           0 :         sc->sc_class = pa->pa_class;
     356           0 :         switch (PCI_PRODUCT(sc->sc_id)) {
     357             :         case PCI_PRODUCT_CMI_CMI8338A:
     358             :                 /*FALLTHROUGH*/
     359             :         case PCI_PRODUCT_CMI_CMI8338B:
     360           0 :                 sc->sc_capable = CMPCI_CAP_CMI8338;
     361           0 :                 break;
     362             :         case PCI_PRODUCT_CMI_CMI8738:
     363             :                 /*FALLTHROUGH*/
     364             :         case PCI_PRODUCT_CMI_CMI8738B:
     365           0 :                 sc->sc_capable = CMPCI_CAP_CMI8738;
     366           0 :                 break;
     367             :         }
     368             : 
     369             :         /* map I/O space */
     370           0 :         if (pci_mapreg_map(pa, CMPCI_PCI_IOBASEREG, PCI_MAPREG_TYPE_IO, 0,
     371           0 :                            &sc->sc_iot, &sc->sc_ioh, NULL, NULL, 0)) {
     372           0 :                 printf(": can't map i/o space\n");
     373           0 :                 return;
     374             :         }
     375             : 
     376             :         /* interrupt */
     377           0 :         if (pci_intr_map(pa, &ih)) {
     378           0 :                 printf(": can't map interrupt\n");
     379           0 :                 return;
     380             :         }
     381           0 :         intrstr = pci_intr_string(pa->pa_pc, ih);
     382           0 :         sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO | IPL_MPSAFE,
     383           0 :             cmpci_intr, sc, sc->sc_dev.dv_xname);
     384           0 :         if (sc->sc_ih == NULL) {
     385           0 :                 printf(": can't establish interrupt");
     386           0 :                 if (intrstr != NULL)
     387           0 :                         printf(" at %s", intrstr);
     388           0 :                 printf("\n");
     389           0 :                 return;
     390             :         }
     391           0 :         printf(": %s\n", intrstr);
     392             : 
     393           0 :         sc->sc_dmat = pa->pa_dmat;
     394             : 
     395           0 :         audio_attach_mi(&cmpci_hw_if, sc, &sc->sc_dev);
     396             : 
     397             :         /* attach OPL device */
     398           0 :         aa.type = AUDIODEV_TYPE_OPL;
     399           0 :         aa.hwif = NULL;
     400           0 :         aa.hdl = NULL;
     401           0 :         (void)config_found(&sc->sc_dev, &aa, audioprint);
     402             : 
     403             :         /* attach MPU-401 device */
     404           0 :         aa.type = AUDIODEV_TYPE_MPU;
     405           0 :         aa.hwif = NULL;
     406           0 :         aa.hdl = NULL;
     407           0 :         if (bus_space_subregion(sc->sc_iot, sc->sc_ioh,
     408           0 :             CMPCI_REG_MPU_BASE, CMPCI_REG_MPU_SIZE, &sc->sc_mpu_ioh) == 0)
     409           0 :                 sc->sc_mpudev = config_found(&sc->sc_dev, &aa, audioprint);
     410             : 
     411             :         /* get initial value (this is 0 and may be omitted but just in case) */
     412           0 :         sc->sc_reg_misc = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
     413           0 :             CMPCI_REG_MISC) & ~CMPCI_REG_SPDIF48K;
     414             : 
     415             :         /* extra capabilitites check */
     416           0 :         d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_INTR_CTRL) &
     417             :             CMPCI_REG_CHIP_MASK2;
     418           0 :         if (d) {
     419           0 :                 if (d & CMPCI_REG_CHIP_8768) {
     420           0 :                         sc->sc_version = 68;
     421           0 :                         sc->sc_capable |= CMPCI_CAP_4CH | CMPCI_CAP_6CH |
     422             :                             CMPCI_CAP_8CH;
     423           0 :                 } else if (d & CMPCI_REG_CHIP_055) {
     424           0 :                         sc->sc_version = 55;
     425           0 :                         sc->sc_capable |= CMPCI_CAP_4CH | CMPCI_CAP_6CH;
     426           0 :                 } else if (d & CMPCI_REG_CHIP_039) {
     427           0 :                         sc->sc_version = 39;
     428           0 :                         sc->sc_capable |= CMPCI_CAP_4CH |
     429           0 :                             ((d & CMPCI_REG_CHIP_039_6CH) ? CMPCI_CAP_6CH : 0);
     430           0 :                 } else {
     431             :                         /* unknown version */
     432           0 :                         sc->sc_version = 0;
     433             :                 }
     434             :         } else {
     435           0 :                 d = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
     436           0 :                     CMPCI_REG_CHANNEL_FORMAT) & CMPCI_REG_CHIP_MASK1;
     437           0 :                 if (d)
     438           0 :                         sc->sc_version = 37;
     439             :                 else
     440           0 :                         sc->sc_version = 33;
     441             :         }
     442             : 
     443           0 :         cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0);
     444           0 :         cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0);
     445           0 :         cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0);
     446           0 :         cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX,
     447             :             CMPCI_SB16_SW_CD|CMPCI_SB16_SW_MIC|CMPCI_SB16_SW_LINE);
     448           0 :         for (i = 0; i < CMPCI_NDEVS; i++) {
     449           0 :                 switch(i) {
     450             :                 /*
     451             :                  * CMI8738 defaults are
     452             :                  *  master:     0xe0    (0x00 - 0xf8)
     453             :                  *  FM, DAC:    0xc0    (0x00 - 0xf8)
     454             :                  *  PC speaker: 0x80    (0x00 - 0xc0)
     455             :                  *  others:     0
     456             :                  */
     457             :                 /* volume */
     458             :                 case CMPCI_MASTER_VOL:
     459             :                         v = 128;        /* 224 */
     460           0 :                         break;
     461             :                 case CMPCI_FM_VOL:
     462             :                 case CMPCI_DAC_VOL:
     463             :                         v = 192;
     464           0 :                         break;
     465             :                 case CMPCI_PCSPEAKER:
     466             :                         v = 128;
     467           0 :                         break;
     468             : 
     469             :                 /* booleans, set to true */
     470             :                 case CMPCI_CD_MUTE:
     471             :                 case CMPCI_MIC_MUTE:
     472             :                 case CMPCI_LINE_IN_MUTE:
     473             :                 case CMPCI_AUX_IN_MUTE:
     474             :                         v = 1;
     475           0 :                         break;
     476             : 
     477             :                 /* volume with inital value 0 */
     478             :                 case CMPCI_CD_VOL:
     479             :                 case CMPCI_LINE_IN_VOL:
     480             :                 case CMPCI_AUX_IN_VOL:
     481             :                 case CMPCI_MIC_VOL:
     482             :                 case CMPCI_MIC_RECVOL:
     483             :                         /* FALLTHROUGH */
     484             : 
     485             :                 /* others are cleared */
     486             :                 case CMPCI_MIC_PREAMP:
     487             :                 case CMPCI_RECORD_SOURCE:
     488             :                 case CMPCI_PLAYBACK_MODE:
     489             :                 case CMPCI_SPDIF_IN_SELECT:
     490             :                 case CMPCI_SPDIF_IN_PHASE:
     491             :                 case CMPCI_SPDIF_LOOP:
     492             :                 case CMPCI_SPDIF_OUT_PLAYBACK:
     493             :                 case CMPCI_SPDIF_OUT_VOLTAGE:
     494             :                 case CMPCI_MONITOR_DAC:
     495             :                 case CMPCI_REAR:
     496             :                 case CMPCI_INDIVIDUAL:
     497             :                 case CMPCI_REVERSE:
     498             :                 case CMPCI_SURROUND:
     499             :                 default:
     500             :                         v = 0;
     501           0 :                         break;
     502             :                 }
     503           0 :                 sc->sc_gain[i][CMPCI_LEFT] = sc->sc_gain[i][CMPCI_RIGHT] = v;
     504           0 :                 cmpci_set_mixer_gain(sc, i);
     505             :         }
     506             : 
     507           0 :         sc->sc_play_channel = 0;
     508           0 : }
     509             : 
     510             : int
     511           0 : cmpci_activate(struct device *self, int act)
     512             : {
     513           0 :         struct cmpci_softc *sc = (struct cmpci_softc *)self;
     514             : 
     515           0 :         switch (act) {
     516             :         case DVACT_RESUME:
     517           0 :                 cmpci_resume(sc);
     518           0 :                 break;
     519             :         default:
     520             :                 break;
     521             :         }
     522           0 :         return (config_activate_children(self, act));
     523             : }
     524             : 
     525             : void
     526           0 : cmpci_resume(struct cmpci_softc *sc)
     527             : {
     528           0 :         cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0);
     529           0 : }
     530             : 
     531             : int
     532           0 : cmpci_intr(void *handle)
     533             : {
     534           0 :         struct cmpci_softc *sc = handle;
     535             :         struct cmpci_channel *chan;
     536             :         uint32_t intrstat;
     537             :         uint16_t hwpos;
     538             : 
     539           0 :         mtx_enter(&audio_lock);
     540           0 :         intrstat = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
     541             :             CMPCI_REG_INTR_STATUS);
     542             : 
     543           0 :         if (!(intrstat & CMPCI_REG_ANY_INTR)) {
     544           0 :                 mtx_leave(&audio_lock);
     545           0 :                 return 0;
     546             :         }
     547             : 
     548           0 :         delay(10);
     549             : 
     550             :         /* disable and reset intr */
     551           0 :         if (intrstat & CMPCI_REG_CH0_INTR)
     552           0 :                 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
     553             :                    CMPCI_REG_CH0_INTR_ENABLE);
     554           0 :         if (intrstat & CMPCI_REG_CH1_INTR)
     555           0 :                 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
     556             :                     CMPCI_REG_CH1_INTR_ENABLE);
     557             : 
     558           0 :         if (intrstat & CMPCI_REG_CH0_INTR) {
     559           0 :                 chan = &sc->sc_ch0;
     560           0 :                 if (chan->intr != NULL) {
     561           0 :                         hwpos = bus_space_read_2(sc->sc_iot, sc->sc_ioh,
     562             :                             CMPCI_REG_DMA0_BYTES);
     563           0 :                         hwpos = hwpos * chan->bps / chan->blksize;
     564           0 :                         hwpos = chan->nblocks - hwpos - 1;
     565           0 :                         while (chan->swpos != hwpos) {
     566           0 :                                 (*chan->intr)(chan->intr_arg);
     567           0 :                                 chan->swpos++;
     568           0 :                                 if (chan->swpos >= chan->nblocks)
     569           0 :                                         chan->swpos = 0;
     570           0 :                                 if (chan->swpos != hwpos) {
     571             :                                         DPRINTF(("%s: DMA0 hwpos=%d swpos=%d\n",
     572             :                                             __func__, hwpos, chan->swpos));
     573             :                                 }
     574             :                         }
     575             :                 }
     576             :         }
     577           0 :         if (intrstat & CMPCI_REG_CH1_INTR) {
     578           0 :                 chan = &sc->sc_ch1;
     579           0 :                 if (chan->intr != NULL) {
     580           0 :                         hwpos = bus_space_read_2(sc->sc_iot, sc->sc_ioh,
     581             :                             CMPCI_REG_DMA1_BYTES);
     582           0 :                         hwpos = hwpos * chan->bps / chan->blksize;
     583           0 :                         hwpos = chan->nblocks - hwpos - 1;
     584           0 :                         while (chan->swpos != hwpos) {
     585           0 :                                 (*chan->intr)(chan->intr_arg);
     586           0 :                                 chan->swpos++;
     587           0 :                                 if (chan->swpos >= chan->nblocks)
     588           0 :                                         chan->swpos = 0;
     589           0 :                                 if (chan->swpos != hwpos) {
     590             :                                         DPRINTF(("%s: DMA1 hwpos=%d swpos=%d\n",
     591             :                                             __func__, hwpos, chan->swpos));
     592             :                                 }
     593             :                         }
     594             :                 }
     595             :         }
     596             : 
     597             :         /* enable intr */
     598           0 :         if (intrstat & CMPCI_REG_CH0_INTR)
     599           0 :                 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
     600             :                     CMPCI_REG_CH0_INTR_ENABLE);
     601           0 :         if (intrstat & CMPCI_REG_CH1_INTR)
     602           0 :                 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
     603             :                     CMPCI_REG_CH1_INTR_ENABLE);
     604             : 
     605             : #if 0
     606             :         if (intrstat & CMPCI_REG_UART_INTR && sc->sc_mpudev != NULL)
     607             :                 mpu_intr(sc->sc_mpudev);
     608             : #endif
     609             : 
     610           0 :         mtx_leave(&audio_lock);
     611           0 :         return 1;
     612           0 : }
     613             : 
     614             : /* open/close */
     615             : int
     616           0 : cmpci_open(void *handle, int flags)
     617             : {
     618           0 :         return 0;
     619             : }
     620             : 
     621             : void
     622           0 : cmpci_close(void *handle)
     623             : {
     624           0 : }
     625             : 
     626             : int
     627           0 : cmpci_set_params(void *handle, int setmode, int usemode,
     628             :     struct audio_params *play, struct audio_params *rec)
     629             : {
     630             :         int i;
     631           0 :         struct cmpci_softc *sc = handle;
     632             : 
     633           0 :         for (i = 0; i < 2; i++) {
     634             :                 int md_format;
     635             :                 int md_divide;
     636             :                 int md_index;
     637             :                 int mode;
     638             :                 struct audio_params *p;
     639             : 
     640           0 :                 switch (i) {
     641             :                 case 0:
     642             :                         mode = AUMODE_PLAY;
     643             :                         p = play;
     644           0 :                         break;
     645             :                 case 1:
     646             :                         mode = AUMODE_RECORD;
     647             :                         p = rec;
     648           0 :                         break;
     649             :                 default:
     650           0 :                         return EINVAL;
     651             :                 }
     652             : 
     653           0 :                 if (!(setmode & mode))
     654           0 :                         continue;
     655             : 
     656           0 :                 if (setmode & AUMODE_RECORD) {
     657           0 :                         if (p->channels > 2)
     658           0 :                                 p->channels = 2;
     659           0 :                         sc->sc_play_channel = 0;
     660           0 :                         cmpci_reg_clear_reg_misc(sc, CMPCI_REG_ENDBDAC);
     661           0 :                         cmpci_reg_clear_reg_misc(sc, CMPCI_REG_XCHGDAC);
     662           0 :                 } else {
     663           0 :                         sc->sc_play_channel = 1;
     664           0 :                         cmpci_reg_set_reg_misc(sc, CMPCI_REG_ENDBDAC);
     665           0 :                         cmpci_reg_set_reg_misc(sc, CMPCI_REG_XCHGDAC);
     666             :                 }
     667             : 
     668           0 :                 cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
     669             :                     CMPCI_REG_NXCHG);
     670           0 :                 if (sc->sc_capable & CMPCI_CAP_4CH)
     671           0 :                         cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT,
     672             :                             CMPCI_REG_CHB3D);
     673           0 :                 if (sc->sc_capable & CMPCI_CAP_6CH) {
     674           0 :                         cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT,
     675             :                             CMPCI_REG_CHB3D5C);
     676           0 :                         cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
     677             :                             CMPCI_REG_CHB3D6C);
     678           0 :                         cmpci_reg_clear_reg_misc(sc, CMPCI_REG_ENCENTER);
     679           0 :                 }
     680           0 :                 if (sc->sc_capable & CMPCI_CAP_8CH)
     681           0 :                         cmpci_reg_clear_4(sc, CMPCI_REG_8768_MISC,
     682             :                             CMPCI_REG_CHB3D8C);
     683             : 
     684             :                 /* format */
     685           0 :                 switch (p->channels) {
     686             :                 case 1:
     687             :                         md_format = CMPCI_REG_FORMAT_MONO;
     688           0 :                         break;
     689             :                 case 2:
     690             :                         md_format = CMPCI_REG_FORMAT_STEREO;
     691           0 :                         break;
     692             :                 case 4:
     693           0 :                         if (mode & AUMODE_PLAY) {
     694           0 :                                 if (sc->sc_capable & CMPCI_CAP_4CH) {
     695           0 :                                         cmpci_reg_clear_reg_misc(sc,
     696             :                                             CMPCI_REG_N4SPK3D);
     697           0 :                                         cmpci_reg_set_4(sc,
     698             :                                             CMPCI_REG_CHANNEL_FORMAT,
     699             :                                             CMPCI_REG_CHB3D);
     700           0 :                                         cmpci_reg_set_4(sc,
     701             :                                             CMPCI_REG_LEGACY_CTRL,
     702             :                                             CMPCI_REG_NXCHG);
     703           0 :                                 } else
     704           0 :                                         p->channels = 2;
     705             :                         }
     706             :                         md_format = CMPCI_REG_FORMAT_STEREO;
     707           0 :                         break;
     708             :                 case 6:
     709           0 :                         if (mode & AUMODE_PLAY) {
     710           0 :                                 if (sc->sc_capable & CMPCI_CAP_6CH) {
     711           0 :                                         cmpci_reg_clear_reg_misc(sc,
     712             :                                             CMPCI_REG_N4SPK3D);
     713           0 :                                         cmpci_reg_set_4(sc,
     714             :                                             CMPCI_REG_CHANNEL_FORMAT,
     715             :                                             CMPCI_REG_CHB3D5C);
     716           0 :                                         cmpci_reg_set_4(sc,
     717             :                                             CMPCI_REG_LEGACY_CTRL,
     718             :                                             CMPCI_REG_CHB3D6C);
     719           0 :                                         cmpci_reg_set_reg_misc(sc,
     720             :                                             CMPCI_REG_ENCENTER);
     721           0 :                                         cmpci_reg_set_4(sc,
     722             :                                             CMPCI_REG_LEGACY_CTRL,
     723             :                                             CMPCI_REG_NXCHG);
     724           0 :                                 } else
     725           0 :                                         p->channels = 2;
     726             :                         }
     727             :                         md_format = CMPCI_REG_FORMAT_STEREO;
     728           0 :                         break;
     729             :                 case 8:
     730           0 :                         if (mode & AUMODE_PLAY) {
     731           0 :                                 if (sc->sc_capable & CMPCI_CAP_8CH) {
     732           0 :                                         cmpci_reg_clear_reg_misc(sc,
     733             :                                             CMPCI_REG_N4SPK3D);
     734           0 :                                         cmpci_reg_set_4(sc,
     735             :                                             CMPCI_REG_CHANNEL_FORMAT,
     736             :                                             CMPCI_REG_CHB3D5C);
     737           0 :                                         cmpci_reg_set_4(sc,
     738             :                                             CMPCI_REG_LEGACY_CTRL,
     739             :                                             CMPCI_REG_CHB3D6C);
     740           0 :                                         cmpci_reg_set_reg_misc(sc,
     741             :                                             CMPCI_REG_ENCENTER);
     742           0 :                                         cmpci_reg_set_4(sc,
     743             :                                             CMPCI_REG_8768_MISC,
     744             :                                             CMPCI_REG_CHB3D8C);
     745           0 :                                         cmpci_reg_set_4(sc,
     746             :                                             CMPCI_REG_LEGACY_CTRL,
     747             :                                             CMPCI_REG_NXCHG);
     748           0 :                                 } else
     749           0 :                                         p->channels = 2;
     750             :                         }
     751             :                         md_format = CMPCI_REG_FORMAT_STEREO;
     752           0 :                         break;
     753             :                 default:
     754           0 :                         return (EINVAL);
     755             :                 }
     756           0 :                 if (p->precision >= 16) {
     757           0 :                         p->precision = 16;
     758           0 :                         p->encoding = AUDIO_ENCODING_SLINEAR_LE;
     759           0 :                         md_format |= CMPCI_REG_FORMAT_16BIT;
     760           0 :                 } else {
     761           0 :                         p->precision = 8;
     762           0 :                         p->encoding = AUDIO_ENCODING_ULINEAR_LE;
     763             :                         md_format |= CMPCI_REG_FORMAT_8BIT;
     764             :                 }
     765           0 :                 p->bps = AUDIO_BPS(p->precision);
     766           0 :                 p->msb = 1;
     767           0 :                 if (mode & AUMODE_PLAY) {
     768           0 :                         if (sc->sc_play_channel == 1) {
     769           0 :                                 cmpci_reg_partial_write_4(sc,
     770             :                                    CMPCI_REG_CHANNEL_FORMAT,
     771             :                                    CMPCI_REG_CH1_FORMAT_SHIFT,
     772             :                                    CMPCI_REG_CH1_FORMAT_MASK, md_format);
     773           0 :                         } else {
     774           0 :                                 cmpci_reg_partial_write_4(sc,
     775             :                                    CMPCI_REG_CHANNEL_FORMAT,
     776             :                                    CMPCI_REG_CH0_FORMAT_SHIFT,
     777             :                                    CMPCI_REG_CH0_FORMAT_MASK, md_format);
     778             :                         }
     779             :                 } else {
     780           0 :                         cmpci_reg_partial_write_4(sc,
     781             :                            CMPCI_REG_CHANNEL_FORMAT,
     782             :                            CMPCI_REG_CH1_FORMAT_SHIFT,
     783             :                            CMPCI_REG_CH1_FORMAT_MASK, md_format);
     784             :                 }
     785             :                 /* sample rate */
     786           0 :                 md_index = cmpci_rate_to_index(p->sample_rate);
     787           0 :                 md_divide = cmpci_index_to_divider(md_index);
     788           0 :                 p->sample_rate = cmpci_index_to_rate(md_index);
     789             :                 DPRINTF(("%s: sample:%d, divider=%d\n",
     790             :                          sc->sc_dev.dv_xname, (int)p->sample_rate, md_divide));
     791           0 :                 if (mode & AUMODE_PLAY) {
     792           0 :                         if (sc->sc_play_channel == 1) {
     793           0 :                                 cmpci_reg_partial_write_4(sc,
     794             :                                     CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT,
     795             :                                     CMPCI_REG_ADC_FS_MASK, md_divide);
     796           0 :                                 sc->sc_ch1.md_divide = md_divide;
     797           0 :                         } else {
     798           0 :                                 cmpci_reg_partial_write_4(sc,
     799             :                                     CMPCI_REG_FUNC_1, CMPCI_REG_DAC_FS_SHIFT,
     800             :                                     CMPCI_REG_DAC_FS_MASK, md_divide);
     801           0 :                                 sc->sc_ch0.md_divide = md_divide;
     802             :                         }
     803             :                 } else {
     804           0 :                         cmpci_reg_partial_write_4(sc,
     805             :                             CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT,
     806             :                             CMPCI_REG_ADC_FS_MASK, md_divide);
     807           0 :                         sc->sc_ch1.md_divide = md_divide;
     808             :                 }
     809           0 :         }
     810             : 
     811           0 :         return 0;
     812           0 : }
     813             : 
     814             : /* ARGSUSED */
     815             : int
     816           0 : cmpci_round_blocksize(void *handle, int block)
     817             : {
     818           0 :         return ((block + 3) & -4);
     819             : }
     820             : 
     821             : int
     822           0 : cmpci_halt_output(void *handle)
     823             : {
     824           0 :         struct cmpci_softc *sc = handle;
     825             :         uint32_t reg_intr, reg_enable, reg_reset;
     826             : 
     827           0 :         mtx_enter(&audio_lock);
     828           0 :         if (sc->sc_play_channel == 1) {
     829           0 :                 sc->sc_ch1.intr = NULL;
     830             :                 reg_intr = CMPCI_REG_CH1_INTR_ENABLE;
     831             :                 reg_enable = CMPCI_REG_CH1_ENABLE;
     832             :                 reg_reset = CMPCI_REG_CH1_RESET;
     833           0 :         } else {
     834           0 :                 sc->sc_ch0.intr = NULL;
     835             :                 reg_intr = CMPCI_REG_CH0_INTR_ENABLE;
     836             :                 reg_enable = CMPCI_REG_CH0_ENABLE;
     837             :                 reg_reset = CMPCI_REG_CH0_RESET;
     838             :         }
     839           0 :         cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, reg_intr);
     840           0 :         cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, reg_enable);
     841             :         /* wait for reset DMA */
     842           0 :         cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, reg_reset);
     843           0 :         delay(10);
     844           0 :         cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, reg_reset);
     845           0 :         mtx_leave(&audio_lock);
     846           0 :         return 0;
     847             : }
     848             : 
     849             : int
     850           0 : cmpci_halt_input(void *handle)
     851             : {
     852           0 :         struct cmpci_softc *sc = handle;
     853             : 
     854           0 :         mtx_enter(&audio_lock);
     855           0 :         sc->sc_ch1.intr = NULL;
     856           0 :         cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
     857           0 :         cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
     858             :         /* wait for reset DMA */
     859           0 :         cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
     860           0 :         delay(10);
     861           0 :         cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
     862           0 :         mtx_leave(&audio_lock);
     863           0 :         return 0;
     864             : }
     865             : 
     866             : /* mixer device information */
     867             : int
     868           0 : cmpci_query_devinfo(void *handle, mixer_devinfo_t *dip)
     869             : {
     870             :         static const char *const mixer_port_names[] = {
     871             :                 AudioNdac, AudioNfmsynth, AudioNcd, AudioNline, AudioNaux,
     872             :                 AudioNmicrophone
     873             :         };
     874             :         static const char *const mixer_classes[] = {
     875             :                 AudioCinputs, AudioCoutputs, AudioCrecord, CmpciCplayback,
     876             :                 CmpciCspdif
     877             :         };
     878           0 :         struct cmpci_softc *sc = handle;
     879             :         int i;
     880             : 
     881           0 :         dip->prev = dip->next = AUDIO_MIXER_LAST;
     882             : 
     883           0 :         switch (dip->index) {
     884             :         case CMPCI_INPUT_CLASS:
     885             :         case CMPCI_OUTPUT_CLASS:
     886             :         case CMPCI_RECORD_CLASS:
     887             :         case CMPCI_PLAYBACK_CLASS:
     888             :         case CMPCI_SPDIF_CLASS:
     889           0 :                 dip->type = AUDIO_MIXER_CLASS;
     890           0 :                 dip->mixer_class = dip->index;
     891           0 :                 strlcpy(dip->label.name,
     892           0 :                     mixer_classes[dip->index - CMPCI_INPUT_CLASS],
     893             :                     sizeof dip->label.name);
     894           0 :                 return 0;
     895             : 
     896             :         case CMPCI_AUX_IN_VOL:
     897           0 :                 dip->un.v.delta = 1 << (8 - CMPCI_REG_AUX_VALBITS);
     898           0 :                 goto vol1;
     899             :         case CMPCI_DAC_VOL:
     900             :         case CMPCI_FM_VOL:
     901             :         case CMPCI_CD_VOL:
     902             :         case CMPCI_LINE_IN_VOL:
     903             :         case CMPCI_MIC_VOL:
     904           0 :                 dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_VALBITS);
     905           0 :         vol1:   dip->mixer_class = CMPCI_INPUT_CLASS;
     906           0 :                 dip->next = dip->index + 6;       /* CMPCI_xxx_MUTE */
     907           0 :                 strlcpy(dip->label.name, mixer_port_names[dip->index],
     908             :                     sizeof dip->label.name);
     909           0 :                 dip->un.v.num_channels = (dip->index == CMPCI_MIC_VOL ? 1 : 2);
     910             :         vol:
     911           0 :                 dip->type = AUDIO_MIXER_VALUE;
     912           0 :                 strlcpy(dip->un.v.units.name, AudioNvolume,
     913             :                     sizeof dip->un.v.units.name);
     914           0 :                 return 0;
     915             : 
     916             :         case CMPCI_MIC_MUTE:
     917           0 :                 dip->next = CMPCI_MIC_PREAMP;
     918             :                 /* FALLTHROUGH */
     919             :         case CMPCI_DAC_MUTE:
     920             :         case CMPCI_FM_MUTE:
     921             :         case CMPCI_CD_MUTE:
     922             :         case CMPCI_LINE_IN_MUTE:
     923             :         case CMPCI_AUX_IN_MUTE:
     924           0 :                 dip->prev = dip->index - 6;       /* CMPCI_xxx_VOL */
     925           0 :                 dip->mixer_class = CMPCI_INPUT_CLASS;
     926           0 :                 strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
     927           0 :                 goto on_off;
     928             :         on_off:
     929           0 :                 dip->type = AUDIO_MIXER_ENUM;
     930           0 :                 dip->un.e.num_mem = 2;
     931           0 :                 strlcpy(dip->un.e.member[0].label.name, AudioNoff,
     932             :                     sizeof dip->un.e.member[0].label.name);
     933           0 :                 dip->un.e.member[0].ord = 0;
     934           0 :                 strlcpy(dip->un.e.member[1].label.name, AudioNon,
     935             :                     sizeof dip->un.e.member[1].label.name);
     936           0 :                 dip->un.e.member[1].ord = 1;
     937           0 :                 return 0;
     938             : 
     939             :         case CMPCI_MIC_PREAMP:
     940           0 :                 dip->mixer_class = CMPCI_INPUT_CLASS;
     941           0 :                 dip->prev = CMPCI_MIC_MUTE;
     942           0 :                 strlcpy(dip->label.name, AudioNpreamp, sizeof dip->label.name);
     943           0 :                 goto on_off;
     944             :         case CMPCI_PCSPEAKER:
     945           0 :                 dip->mixer_class = CMPCI_INPUT_CLASS;
     946           0 :                 strlcpy(dip->label.name, AudioNspeaker, sizeof dip->label.name);
     947           0 :                 dip->un.v.num_channels = 1;
     948           0 :                 dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_SPEAKER_VALBITS);
     949           0 :                 goto vol;
     950             :         case CMPCI_RECORD_SOURCE:
     951           0 :                 dip->mixer_class = CMPCI_RECORD_CLASS;
     952           0 :                 strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
     953           0 :                 dip->type = AUDIO_MIXER_SET;
     954           0 :                 dip->un.s.num_mem = 7;
     955           0 :                 strlcpy(dip->un.s.member[0].label.name, AudioNmicrophone,
     956             :                     sizeof dip->un.s.member[0].label.name);
     957           0 :                 dip->un.s.member[0].mask = CMPCI_RECORD_SOURCE_MIC;
     958           0 :                 strlcpy(dip->un.s.member[1].label.name, AudioNcd,
     959             :                     sizeof dip->un.s.member[1].label.name);
     960           0 :                 dip->un.s.member[1].mask = CMPCI_RECORD_SOURCE_CD;
     961           0 :                 strlcpy(dip->un.s.member[2].label.name, AudioNline,
     962             :                     sizeof dip->un.s.member[2].label.name);
     963           0 :                 dip->un.s.member[2].mask = CMPCI_RECORD_SOURCE_LINE_IN;
     964           0 :                 strlcpy(dip->un.s.member[3].label.name, AudioNaux,
     965             :                     sizeof dip->un.s.member[3].label.name);
     966           0 :                 dip->un.s.member[3].mask = CMPCI_RECORD_SOURCE_AUX_IN;
     967           0 :                 strlcpy(dip->un.s.member[4].label.name, AudioNwave,
     968             :                     sizeof dip->un.s.member[4].label.name);
     969           0 :                 dip->un.s.member[4].mask = CMPCI_RECORD_SOURCE_WAVE;
     970           0 :                 strlcpy(dip->un.s.member[5].label.name, AudioNfmsynth,
     971             :                     sizeof dip->un.s.member[5].label.name);
     972           0 :                 dip->un.s.member[5].mask = CMPCI_RECORD_SOURCE_FM;
     973           0 :                 strlcpy(dip->un.s.member[6].label.name, CmpciNspdif,
     974             :                     sizeof dip->un.s.member[6].label.name);
     975           0 :                 dip->un.s.member[6].mask = CMPCI_RECORD_SOURCE_SPDIF;
     976           0 :                 return 0;
     977             :         case CMPCI_MIC_RECVOL:
     978           0 :                 dip->mixer_class = CMPCI_RECORD_CLASS;
     979           0 :                 strlcpy(dip->label.name, AudioNmicrophone, sizeof dip->label.name);
     980           0 :                 dip->un.v.num_channels = 1;
     981           0 :                 dip->un.v.delta = 1 << (8 - CMPCI_REG_ADMIC_VALBITS);
     982           0 :                 goto vol;
     983             : 
     984             :         case CMPCI_PLAYBACK_MODE:
     985           0 :                 dip->mixer_class = CMPCI_PLAYBACK_CLASS;
     986           0 :                 dip->type = AUDIO_MIXER_ENUM;
     987           0 :                 strlcpy(dip->label.name, AudioNmode, sizeof dip->label.name);
     988           0 :                 dip->un.e.num_mem = 2;
     989           0 :                 strlcpy(dip->un.e.member[0].label.name, AudioNdac,
     990             :                     sizeof dip->un.e.member[0].label.name);
     991           0 :                 dip->un.e.member[0].ord = CMPCI_PLAYBACK_MODE_WAVE;
     992           0 :                 strlcpy(dip->un.e.member[1].label.name, CmpciNspdif,
     993             :                     sizeof dip->un.e.member[1].label.name);
     994           0 :                 dip->un.e.member[1].ord = CMPCI_PLAYBACK_MODE_SPDIF;
     995           0 :                 return 0;
     996             :         case CMPCI_SPDIF_IN_SELECT:
     997           0 :                 dip->mixer_class = CMPCI_SPDIF_CLASS;
     998           0 :                 dip->type = AUDIO_MIXER_ENUM;
     999           0 :                 dip->next = CMPCI_SPDIF_IN_PHASE;
    1000           0 :                 strlcpy(dip->label.name, AudioNinput, sizeof dip->label.name);
    1001             :                 i = 0;
    1002           0 :                 strlcpy(dip->un.e.member[i].label.name, CmpciNspdin1,
    1003             :                     sizeof dip->un.e.member[i].label.name);
    1004           0 :                 dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDIN1;
    1005           0 :                 if (CMPCI_ISCAP(sc, 2ND_SPDIN)) {
    1006           0 :                         strlcpy(dip->un.e.member[i].label.name, CmpciNspdin2,
    1007             :                             sizeof dip->un.e.member[i].label.name);
    1008           0 :                         dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDIN2;
    1009           0 :                 }
    1010           0 :                 strlcpy(dip->un.e.member[i].label.name, CmpciNspdout,
    1011             :                     sizeof dip->un.e.member[i].label.name);
    1012           0 :                 dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDOUT;
    1013           0 :                 dip->un.e.num_mem = i;
    1014           0 :                 return 0;
    1015             :         case CMPCI_SPDIF_IN_PHASE:
    1016           0 :                 dip->mixer_class = CMPCI_SPDIF_CLASS;
    1017           0 :                 dip->prev = CMPCI_SPDIF_IN_SELECT;
    1018           0 :                 strlcpy(dip->label.name, CmpciNphase, sizeof dip->label.name);
    1019           0 :                 dip->type = AUDIO_MIXER_ENUM;
    1020           0 :                 dip->un.e.num_mem = 2;
    1021           0 :                 strlcpy(dip->un.e.member[0].label.name, CmpciNpositive,
    1022             :                     sizeof dip->un.e.member[0].label.name);
    1023           0 :                 dip->un.e.member[0].ord = CMPCI_SPDIF_IN_PHASE_POSITIVE;
    1024           0 :                 strlcpy(dip->un.e.member[1].label.name, CmpciNnegative,
    1025             :                     sizeof dip->un.e.member[1].label.name);
    1026           0 :                 dip->un.e.member[1].ord = CMPCI_SPDIF_IN_PHASE_NEGATIVE;
    1027           0 :                 return 0;
    1028             :         case CMPCI_SPDIF_LOOP:
    1029           0 :                 dip->mixer_class = CMPCI_SPDIF_CLASS;
    1030           0 :                 dip->next = CMPCI_SPDIF_OUT_PLAYBACK;
    1031           0 :                 strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
    1032           0 :                 dip->type = AUDIO_MIXER_ENUM;
    1033           0 :                 dip->un.e.num_mem = 2;
    1034           0 :                 strlcpy(dip->un.e.member[0].label.name, CmpciNplayback,
    1035             :                     sizeof dip->un.e.member[0].label.name);
    1036           0 :                 dip->un.e.member[0].ord = CMPCI_SPDIF_LOOP_OFF;
    1037           0 :                 strlcpy(dip->un.e.member[1].label.name, CmpciNspdin,
    1038             :                     sizeof dip->un.e.member[1].label.name);
    1039           0 :                 dip->un.e.member[1].ord = CMPCI_SPDIF_LOOP_ON;
    1040           0 :                 return 0;
    1041             :         case CMPCI_SPDIF_OUT_PLAYBACK:
    1042           0 :                 dip->mixer_class = CMPCI_SPDIF_CLASS;
    1043           0 :                 dip->prev = CMPCI_SPDIF_LOOP;
    1044           0 :                 dip->next = CMPCI_SPDIF_OUT_VOLTAGE;
    1045           0 :                 strlcpy(dip->label.name, CmpciNplayback, sizeof dip->label.name);
    1046           0 :                 dip->type = AUDIO_MIXER_ENUM;
    1047           0 :                 dip->un.e.num_mem = 2;
    1048           0 :                 strlcpy(dip->un.e.member[0].label.name, AudioNwave,
    1049             :                     sizeof dip->un.e.member[0].label.name);
    1050           0 :                 dip->un.e.member[0].ord = CMPCI_SPDIF_OUT_PLAYBACK_WAVE;
    1051           0 :                 strlcpy(dip->un.e.member[1].label.name, CmpciNlegacy,
    1052             :                     sizeof dip->un.e.member[1].label.name);
    1053           0 :                 dip->un.e.member[1].ord = CMPCI_SPDIF_OUT_PLAYBACK_LEGACY;
    1054           0 :                 return 0;
    1055             :         case CMPCI_SPDIF_OUT_VOLTAGE:
    1056           0 :                 dip->mixer_class = CMPCI_SPDIF_CLASS;
    1057           0 :                 dip->prev = CMPCI_SPDIF_OUT_PLAYBACK;
    1058           0 :                 strlcpy(dip->label.name, CmpciNvoltage, sizeof dip->label.name);
    1059           0 :                 dip->type = AUDIO_MIXER_ENUM;
    1060           0 :                 dip->un.e.num_mem = 2;
    1061           0 :                 strlcpy(dip->un.e.member[0].label.name, CmpciNhigh_v,
    1062             :                     sizeof dip->un.e.member[0].label.name);
    1063           0 :                 dip->un.e.member[0].ord = CMPCI_SPDIF_OUT_VOLTAGE_HIGH;
    1064           0 :                 strlcpy(dip->un.e.member[1].label.name, CmpciNlow_v,
    1065             :                     sizeof dip->un.e.member[1].label.name);
    1066           0 :                 dip->un.e.member[1].ord = CMPCI_SPDIF_OUT_VOLTAGE_LOW;
    1067           0 :                 return 0;
    1068             :         case CMPCI_MONITOR_DAC:
    1069           0 :                 dip->mixer_class = CMPCI_SPDIF_CLASS;
    1070           0 :                 strlcpy(dip->label.name, AudioNmonitor, sizeof dip->label.name);
    1071           0 :                 dip->type = AUDIO_MIXER_ENUM;
    1072           0 :                 dip->un.e.num_mem = 3;
    1073           0 :                 strlcpy(dip->un.e.member[0].label.name, AudioNoff,
    1074             :                     sizeof dip->un.e.member[0].label.name);
    1075           0 :                 dip->un.e.member[0].ord = CMPCI_MONITOR_DAC_OFF;
    1076           0 :                 strlcpy(dip->un.e.member[1].label.name, CmpciNspdin,
    1077             :                     sizeof dip->un.e.member[1].label.name);
    1078           0 :                 dip->un.e.member[1].ord = CMPCI_MONITOR_DAC_SPDIN;
    1079           0 :                 strlcpy(dip->un.e.member[2].label.name, CmpciNspdout,
    1080             :                     sizeof dip->un.e.member[2].label.name);
    1081           0 :                 dip->un.e.member[2].ord = CMPCI_MONITOR_DAC_SPDOUT;
    1082           0 :                 return 0;
    1083             : 
    1084             :         case CMPCI_MASTER_VOL:
    1085           0 :                 dip->mixer_class = CMPCI_OUTPUT_CLASS;
    1086           0 :                 strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
    1087           0 :                 dip->un.v.num_channels = 2;
    1088           0 :                 dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_VALBITS);
    1089           0 :                 goto vol;
    1090             :         case CMPCI_REAR:
    1091           0 :                 dip->mixer_class = CMPCI_OUTPUT_CLASS;
    1092           0 :                 dip->next = CMPCI_INDIVIDUAL;
    1093           0 :                 strlcpy(dip->label.name, CmpciNrear, sizeof dip->label.name);
    1094           0 :                 goto on_off;
    1095             :         case CMPCI_INDIVIDUAL:
    1096           0 :                 dip->mixer_class = CMPCI_OUTPUT_CLASS;
    1097           0 :                 dip->prev = CMPCI_REAR;
    1098           0 :                 dip->next = CMPCI_REVERSE;
    1099           0 :                 strlcpy(dip->label.name, CmpciNindividual, sizeof dip->label.name);
    1100           0 :                 goto on_off;
    1101             :         case CMPCI_REVERSE:
    1102           0 :                 dip->mixer_class = CMPCI_OUTPUT_CLASS;
    1103           0 :                 dip->prev = CMPCI_INDIVIDUAL;
    1104           0 :                 strlcpy(dip->label.name, CmpciNreverse, sizeof dip->label.name);
    1105           0 :                 goto on_off;
    1106             :         case CMPCI_SURROUND:
    1107           0 :                 dip->mixer_class = CMPCI_OUTPUT_CLASS;
    1108           0 :                 strlcpy(dip->label.name, CmpciNsurround, sizeof dip->label.name);
    1109           0 :                 goto on_off;
    1110             :         }
    1111             : 
    1112           0 :         return ENXIO;
    1113           0 : }
    1114             : 
    1115             : int
    1116           0 : cmpci_alloc_dmamem(struct cmpci_softc *sc, size_t size, int type, int flags,
    1117             :     caddr_t *r_addr)
    1118             : {
    1119             :         int error = 0;
    1120             :         struct cmpci_dmanode *n;
    1121             :         int w;
    1122             : 
    1123           0 :         n = malloc(sizeof(struct cmpci_dmanode), type, flags);
    1124           0 :         if (n == NULL) {
    1125             :                 error = ENOMEM;
    1126           0 :                 goto quit;
    1127             :         }
    1128             : 
    1129           0 :         w = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
    1130             : #define CMPCI_DMABUF_ALIGN    0x4
    1131             : #define CMPCI_DMABUF_BOUNDARY 0x0
    1132           0 :         n->cd_tag = sc->sc_dmat;
    1133           0 :         n->cd_size = size;
    1134           0 :         error = bus_dmamem_alloc(n->cd_tag, n->cd_size,
    1135             :             CMPCI_DMABUF_ALIGN, CMPCI_DMABUF_BOUNDARY, n->cd_segs,
    1136             :             nitems(n->cd_segs), &n->cd_nsegs, w);
    1137           0 :         if (error)
    1138             :                 goto mfree;
    1139           0 :         error = bus_dmamem_map(n->cd_tag, n->cd_segs, n->cd_nsegs, n->cd_size,
    1140             :             &n->cd_addr, w | BUS_DMA_COHERENT);
    1141           0 :         if (error)
    1142             :                 goto dmafree;
    1143           0 :         error = bus_dmamap_create(n->cd_tag, n->cd_size, 1, n->cd_size, 0,
    1144             :             w, &n->cd_map);
    1145           0 :         if (error)
    1146             :                 goto unmap;
    1147           0 :         error = bus_dmamap_load(n->cd_tag, n->cd_map, n->cd_addr, n->cd_size,
    1148             :             NULL, w);
    1149           0 :         if (error)
    1150             :                 goto destroy;
    1151             : 
    1152           0 :         n->cd_next = sc->sc_dmap;
    1153           0 :         sc->sc_dmap = n;
    1154           0 :         *r_addr = KVADDR(n);
    1155           0 :         return 0;
    1156             : 
    1157             :  destroy:
    1158           0 :         bus_dmamap_destroy(n->cd_tag, n->cd_map);
    1159             :  unmap:
    1160           0 :         bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
    1161             :  dmafree:
    1162           0 :         bus_dmamem_free(n->cd_tag,
    1163             :                         n->cd_segs, nitems(n->cd_segs));
    1164             :  mfree:
    1165           0 :         free(n, type, 0);
    1166             :  quit:
    1167           0 :         return error;
    1168           0 : }
    1169             : 
    1170             : int
    1171           0 : cmpci_free_dmamem(struct cmpci_softc *sc, caddr_t addr, int type)
    1172             : {
    1173             :         struct cmpci_dmanode **nnp;
    1174             : 
    1175           0 :         for (nnp = &sc->sc_dmap; *nnp; nnp = &(*nnp)->cd_next) {
    1176           0 :                 if ((*nnp)->cd_addr == addr) {
    1177             :                         struct cmpci_dmanode *n = *nnp;
    1178           0 :                         bus_dmamap_unload(n->cd_tag, n->cd_map);
    1179           0 :                         bus_dmamap_destroy(n->cd_tag, n->cd_map);
    1180           0 :                         bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
    1181           0 :                         bus_dmamem_free(n->cd_tag, n->cd_segs,
    1182             :                             nitems(n->cd_segs));
    1183           0 :                         free(n, type, 0);
    1184             :                         return 0;
    1185             :                 }
    1186             :         }
    1187           0 :         return -1;
    1188           0 : }
    1189             : 
    1190             : struct cmpci_dmanode *
    1191           0 : cmpci_find_dmamem(struct cmpci_softc *sc, caddr_t addr)
    1192             : {
    1193             :         struct cmpci_dmanode *p;
    1194             : 
    1195           0 :         for (p = sc->sc_dmap; p; p = p->cd_next) {
    1196           0 :                 if (KVADDR(p) == (void *)addr)
    1197             :                         break;
    1198             :         }
    1199           0 :         return p;
    1200             : }
    1201             : 
    1202             : #if 0
    1203             : void cmpci_print_dmamem(struct cmpci_dmanode *p);
    1204             : 
    1205             : void
    1206             : cmpci_print_dmamem(struct cmpci_dmanode *p)
    1207             : {
    1208             :         DPRINTF(("DMA at virt:%p, dmaseg:%p, mapseg:%p, size:%p\n",
    1209             :                  (void *)p->cd_addr, (void *)p->cd_segs[0].ds_addr,
    1210             :                  (void *)DMAADDR(p), (void *)p->cd_size));
    1211             : }
    1212             : #endif /* DEBUG */
    1213             : 
    1214             : void *
    1215           0 : cmpci_malloc(void *handle, int direction, size_t size, int type,
    1216             :     int flags)
    1217             : {
    1218           0 :         caddr_t addr;
    1219             : 
    1220           0 :         if (cmpci_alloc_dmamem(handle, size, type, flags, &addr))
    1221           0 :                 return NULL;
    1222           0 :         return addr;
    1223           0 : }
    1224             : 
    1225             : void
    1226           0 : cmpci_free(void *handle, void *addr, int type)
    1227             : {
    1228           0 :         cmpci_free_dmamem(handle, addr, type);
    1229           0 : }
    1230             : 
    1231             : #define MAXVAL 256
    1232             : int
    1233           0 : cmpci_adjust(int val, int mask)
    1234             : {
    1235           0 :         val += (MAXVAL - mask) >> 1;
    1236           0 :         if (val >= MAXVAL)
    1237             :                 val = MAXVAL-1;
    1238           0 :         return val & mask;
    1239             : }
    1240             : 
    1241             : void
    1242           0 : cmpci_set_mixer_gain(struct cmpci_softc *sc, int port)
    1243             : {
    1244             :         int src;
    1245             :         int bits, mask;
    1246             : 
    1247           0 :         switch (port) {
    1248             :         case CMPCI_MIC_VOL:
    1249           0 :                 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_MIC,
    1250           0 :                     CMPCI_ADJUST_MIC_GAIN(sc, sc->sc_gain[port][CMPCI_LR]));
    1251           0 :                 return;
    1252             :         case CMPCI_MASTER_VOL:
    1253             :                 src = CMPCI_SB16_MIXER_MASTER_L;
    1254           0 :                 break;
    1255             :         case CMPCI_LINE_IN_VOL:
    1256             :                 src = CMPCI_SB16_MIXER_LINE_L;
    1257           0 :                 break;
    1258             :         case CMPCI_AUX_IN_VOL:
    1259           0 :                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MIXER_AUX,
    1260             :                     CMPCI_ADJUST_AUX_GAIN(sc, sc->sc_gain[port][CMPCI_LEFT],
    1261             :                                               sc->sc_gain[port][CMPCI_RIGHT]));
    1262           0 :                 return;
    1263             :         case CMPCI_MIC_RECVOL:
    1264           0 :                 cmpci_reg_partial_write_1(sc, CMPCI_REG_MIXER25,
    1265             :                     CMPCI_REG_ADMIC_SHIFT, CMPCI_REG_ADMIC_MASK,
    1266           0 :                     CMPCI_ADJUST_ADMIC_GAIN(sc, sc->sc_gain[port][CMPCI_LR]));
    1267           0 :                 return;
    1268             :         case CMPCI_DAC_VOL:
    1269             :                 src = CMPCI_SB16_MIXER_VOICE_L;
    1270           0 :                 break;
    1271             :         case CMPCI_FM_VOL:
    1272             :                 src = CMPCI_SB16_MIXER_FM_L;
    1273           0 :                 break;
    1274             :         case CMPCI_CD_VOL:
    1275             :                 src = CMPCI_SB16_MIXER_CDDA_L;
    1276           0 :                 break;
    1277             :         case CMPCI_PCSPEAKER:
    1278           0 :                 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_SPEAKER,
    1279           0 :                     CMPCI_ADJUST_2_GAIN(sc, sc->sc_gain[port][CMPCI_LR]));
    1280           0 :                 return;
    1281             :         case CMPCI_MIC_PREAMP:
    1282           0 :                 if (sc->sc_gain[port][CMPCI_LR])
    1283           0 :                         cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25,
    1284             :                             CMPCI_REG_MICGAINZ);
    1285             :                 else
    1286           0 :                         cmpci_reg_set_1(sc, CMPCI_REG_MIXER25,
    1287             :                             CMPCI_REG_MICGAINZ);
    1288           0 :                 return;
    1289             : 
    1290             :         case CMPCI_DAC_MUTE:
    1291           0 :                 if (sc->sc_gain[port][CMPCI_LR])
    1292           0 :                         cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
    1293             :                             CMPCI_REG_WSMUTE);
    1294             :                 else
    1295           0 :                         cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
    1296             :                             CMPCI_REG_WSMUTE);
    1297           0 :                 return;
    1298             :         case CMPCI_FM_MUTE:
    1299           0 :                 if (sc->sc_gain[port][CMPCI_LR])
    1300           0 :                         cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
    1301             :                             CMPCI_REG_FMMUTE);
    1302             :                 else
    1303           0 :                         cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
    1304             :                             CMPCI_REG_FMMUTE);
    1305           0 :                 return;
    1306             :         case CMPCI_AUX_IN_MUTE:
    1307           0 :                 if (sc->sc_gain[port][CMPCI_LR])
    1308           0 :                         cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25,
    1309             :                             CMPCI_REG_VAUXRM|CMPCI_REG_VAUXLM);
    1310             :                 else
    1311           0 :                         cmpci_reg_set_1(sc, CMPCI_REG_MIXER25,
    1312             :                             CMPCI_REG_VAUXRM|CMPCI_REG_VAUXLM);
    1313           0 :                 return;
    1314             :         case CMPCI_CD_MUTE:
    1315             :                 mask = CMPCI_SB16_SW_CD;
    1316           0 :                 goto sbmute;
    1317             :         case CMPCI_MIC_MUTE:
    1318             :                 mask = CMPCI_SB16_SW_MIC;
    1319           0 :                 goto sbmute;
    1320             :         case CMPCI_LINE_IN_MUTE:
    1321           0 :                 mask = CMPCI_SB16_SW_LINE;
    1322             :         sbmute:
    1323           0 :                 bits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_OUTMIX);
    1324           0 :                 if (sc->sc_gain[port][CMPCI_LR])
    1325           0 :                         bits = bits & ~mask;
    1326             :                 else
    1327           0 :                         bits = bits | mask;
    1328           0 :                 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX, bits);
    1329           0 :                 return;
    1330             : 
    1331             :         case CMPCI_SPDIF_IN_SELECT:
    1332             :         case CMPCI_MONITOR_DAC:
    1333             :         case CMPCI_PLAYBACK_MODE:
    1334             :         case CMPCI_SPDIF_LOOP:
    1335             :         case CMPCI_SPDIF_OUT_PLAYBACK:
    1336           0 :                 cmpci_set_out_ports(sc);
    1337           0 :                 return;
    1338             :         case CMPCI_SPDIF_OUT_VOLTAGE:
    1339           0 :                 if (CMPCI_ISCAP(sc, SPDOUT_VOLTAGE)) {
    1340           0 :                         if (sc->sc_gain[CMPCI_SPDIF_OUT_VOLTAGE][CMPCI_LR]
    1341           0 :                             == CMPCI_SPDIF_OUT_VOLTAGE_HIGH)
    1342           0 :                                 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_5V);
    1343             :                         else
    1344           0 :                                 cmpci_reg_set_reg_misc(sc, CMPCI_REG_5V);
    1345             :                 }
    1346           0 :                 return;
    1347             :         case CMPCI_SURROUND:
    1348           0 :                 if (CMPCI_ISCAP(sc, SURROUND)) {
    1349           0 :                         if (sc->sc_gain[CMPCI_SURROUND][CMPCI_LR])
    1350           0 :                                 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
    1351             :                                                 CMPCI_REG_SURROUND);
    1352             :                         else
    1353           0 :                                 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
    1354             :                                                   CMPCI_REG_SURROUND);
    1355             :                 }
    1356           0 :                 return;
    1357             :         case CMPCI_REAR:
    1358           0 :                 if (CMPCI_ISCAP(sc, REAR)) {
    1359           0 :                         if (sc->sc_gain[CMPCI_REAR][CMPCI_LR])
    1360           0 :                                 cmpci_reg_set_reg_misc(sc, CMPCI_REG_N4SPK3D);
    1361             :                         else
    1362           0 :                                 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_N4SPK3D);
    1363             :                 }
    1364           0 :                 return;
    1365             :         case CMPCI_INDIVIDUAL:
    1366           0 :                 if (CMPCI_ISCAP(sc, INDIVIDUAL_REAR)) {
    1367           0 :                         if (sc->sc_gain[CMPCI_REAR][CMPCI_LR])
    1368           0 :                                 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
    1369             :                                                 CMPCI_REG_INDIVIDUAL);
    1370             :                         else
    1371           0 :                                 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
    1372             :                                                   CMPCI_REG_INDIVIDUAL);
    1373             :                 }
    1374           0 :                 return;
    1375             :         case CMPCI_REVERSE:
    1376           0 :                 if (CMPCI_ISCAP(sc, REVERSE_FR)) {
    1377           0 :                         if (sc->sc_gain[CMPCI_REVERSE][CMPCI_LR])
    1378           0 :                                 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
    1379             :                                                 CMPCI_REG_REVERSE_FR);
    1380             :                         else
    1381           0 :                                 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
    1382             :                                                   CMPCI_REG_REVERSE_FR);
    1383             :                 }
    1384           0 :                 return;
    1385             :         case CMPCI_SPDIF_IN_PHASE:
    1386           0 :                 if (CMPCI_ISCAP(sc, SPDIN_PHASE)) {
    1387           0 :                         if (sc->sc_gain[CMPCI_SPDIF_IN_PHASE][CMPCI_LR]
    1388           0 :                             == CMPCI_SPDIF_IN_PHASE_POSITIVE)
    1389           0 :                                 cmpci_reg_clear_1(sc, CMPCI_REG_CHANNEL_FORMAT,
    1390             :                                                   CMPCI_REG_SPDIN_PHASE);
    1391             :                         else
    1392           0 :                                 cmpci_reg_set_1(sc, CMPCI_REG_CHANNEL_FORMAT,
    1393             :                                                 CMPCI_REG_SPDIN_PHASE);
    1394             :                 }
    1395           0 :                 return;
    1396             :         default:
    1397           0 :                 return;
    1398             :         }
    1399             : 
    1400           0 :         cmpci_mixerreg_write(sc, src,
    1401           0 :             CMPCI_ADJUST_GAIN(sc, sc->sc_gain[port][CMPCI_LEFT]));
    1402           0 :         cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_L_TO_R(src),
    1403           0 :             CMPCI_ADJUST_GAIN(sc, sc->sc_gain[port][CMPCI_RIGHT]));
    1404           0 : }
    1405             : 
    1406             : void
    1407           0 : cmpci_set_out_ports(struct cmpci_softc *sc)
    1408             : {
    1409             :         struct cmpci_channel *chan;
    1410             :         u_int8_t v;
    1411             :         int enspdout = 0;
    1412             : 
    1413           0 :         if (!CMPCI_ISCAP(sc, SPDLOOP))
    1414           0 :                 return;
    1415             : 
    1416             :         /* SPDIF/out select */
    1417           0 :         if (sc->sc_gain[CMPCI_SPDIF_LOOP][CMPCI_LR] == CMPCI_SPDIF_LOOP_OFF) {
    1418             :                 /* playback */
    1419           0 :                 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF_LOOP);
    1420           0 :         } else {
    1421             :                 /* monitor SPDIF/in */
    1422           0 :                 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF_LOOP);
    1423             :         }
    1424             : 
    1425             :         /* SPDIF in select */
    1426           0 :         v = sc->sc_gain[CMPCI_SPDIF_IN_SELECT][CMPCI_LR];
    1427           0 :         if (v & CMPCI_SPDIFIN_SPDIFIN2)
    1428           0 :                 cmpci_reg_set_reg_misc(sc, CMPCI_REG_2ND_SPDIFIN);
    1429             :         else
    1430           0 :                 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_2ND_SPDIFIN);
    1431           0 :         if (v & CMPCI_SPDIFIN_SPDIFOUT)
    1432           0 :                 cmpci_reg_set_reg_misc(sc, CMPCI_REG_SPDFLOOPI);
    1433             :         else
    1434           0 :                 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_SPDFLOOPI);
    1435             : 
    1436           0 :         if (sc->sc_play_channel == 1)
    1437           0 :                 chan = &sc->sc_ch1;
    1438             :         else
    1439           0 :                 chan = &sc->sc_ch0;
    1440             : 
    1441             :         /* disable ac3 and 24 and 32 bit s/pdif modes */
    1442           0 :         cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT, CMPCI_REG_AC3EN1);
    1443           0 :         cmpci_reg_clear_reg_misc(sc, CMPCI_REG_AC3EN2);
    1444           0 :         cmpci_reg_clear_reg_misc(sc, CMPCI_REG_SPD32SEL);
    1445           0 :         cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT, CMPCI_REG_SPDIF_24);
    1446             : 
    1447             :         /* playback to ... */
    1448           0 :         if (CMPCI_ISCAP(sc, SPDOUT) &&
    1449           0 :             sc->sc_gain[CMPCI_PLAYBACK_MODE][CMPCI_LR]
    1450           0 :                 == CMPCI_PLAYBACK_MODE_SPDIF &&
    1451           0 :             (chan->md_divide == CMPCI_REG_RATE_44100 ||
    1452           0 :                 (CMPCI_ISCAP(sc, SPDOUT_48K) &&
    1453           0 :                     chan->md_divide == CMPCI_REG_RATE_48000))) {
    1454             :                 /* playback to SPDIF */
    1455           0 :                 if (sc->sc_play_channel == 0)
    1456           0 :                         cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
    1457             :                             CMPCI_REG_SPDIF0_ENABLE);
    1458             :                 else
    1459           0 :                         cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
    1460             :                             CMPCI_REG_SPDIF1_ENABLE);
    1461             :                 enspdout = 1;
    1462           0 :                 if (chan->md_divide == CMPCI_REG_RATE_48000)
    1463           0 :                         cmpci_reg_set_reg_misc(sc,
    1464             :                                 CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K);
    1465             :                 else
    1466           0 :                         cmpci_reg_clear_reg_misc(sc,
    1467             :                                 CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K);
    1468             :                 /* XXX assume sample rate <= 48kHz */
    1469           0 :                 cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT,
    1470             :                     CMPCI_REG_DBL_SPD_RATE);
    1471           0 :         } else {
    1472             :                 /* playback to DAC */
    1473           0 :                 if (sc->sc_play_channel == 0)
    1474           0 :                         cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
    1475             :                             CMPCI_REG_SPDIF0_ENABLE);
    1476             :                 else
    1477           0 :                         cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
    1478             :                             CMPCI_REG_SPDIF1_ENABLE);
    1479           0 :                 if (CMPCI_ISCAP(sc, SPDOUT_48K))
    1480           0 :                         cmpci_reg_clear_reg_misc(sc,
    1481             :                                 CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K);
    1482             :         }
    1483             : 
    1484             :         /* legacy to SPDIF/out or not */
    1485           0 :         if (CMPCI_ISCAP(sc, SPDLEGACY)) {
    1486           0 :                 if (sc->sc_gain[CMPCI_SPDIF_OUT_PLAYBACK][CMPCI_LR]
    1487           0 :                     == CMPCI_SPDIF_OUT_PLAYBACK_WAVE)
    1488           0 :                         cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
    1489             :                                         CMPCI_REG_LEGACY_SPDIF_ENABLE);
    1490             :                 else {
    1491           0 :                         cmpci_reg_set_4(sc, CMPCI_REG_LEGACY_CTRL,
    1492             :                                         CMPCI_REG_LEGACY_SPDIF_ENABLE);
    1493             :                         enspdout = 1;
    1494             :                 }
    1495             :         }
    1496             : 
    1497             :         /* enable/disable SPDIF/out */
    1498           0 :         if (CMPCI_ISCAP(sc, XSPDOUT) && enspdout)
    1499           0 :                 cmpci_reg_set_4(sc, CMPCI_REG_LEGACY_CTRL,
    1500             :                                 CMPCI_REG_XSPDIF_ENABLE);
    1501             :         else
    1502           0 :                 cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
    1503             :                                 CMPCI_REG_XSPDIF_ENABLE);
    1504             : 
    1505             :         /* SPDIF monitor (digital to analog output) */
    1506           0 :         if (CMPCI_ISCAP(sc, SPDIN_MONITOR)) {
    1507           0 :                 v = sc->sc_gain[CMPCI_MONITOR_DAC][CMPCI_LR];
    1508           0 :                 if (!(v & CMPCI_MONDAC_ENABLE))
    1509           0 :                         cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
    1510             :                                         CMPCI_REG_SPDIN_MONITOR);
    1511           0 :                 if (v & CMPCI_MONDAC_SPDOUT)
    1512           0 :                         cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
    1513             :                                         CMPCI_REG_SPDIFOUT_DAC);
    1514             :                 else
    1515           0 :                         cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
    1516             :                                         CMPCI_REG_SPDIFOUT_DAC);
    1517           0 :                 if (v & CMPCI_MONDAC_ENABLE)
    1518           0 :                         cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
    1519             :                                         CMPCI_REG_SPDIN_MONITOR);
    1520             :         }
    1521           0 : }
    1522             : 
    1523             : int
    1524           0 : cmpci_set_in_ports(struct cmpci_softc *sc)
    1525             : {
    1526             :         int mask;
    1527             :         int bitsl, bitsr;
    1528             : 
    1529           0 :         mask = sc->sc_in_mask;
    1530             : 
    1531             :         /*
    1532             :          * Note CMPCI_RECORD_SOURCE_CD, CMPCI_RECORD_SOURCE_LINE_IN and
    1533             :          * CMPCI_RECORD_SOURCE_FM are defined to the corresponding bit
    1534             :          * of the mixer register.
    1535             :          */
    1536           0 :         bitsr = mask & (CMPCI_RECORD_SOURCE_CD | CMPCI_RECORD_SOURCE_LINE_IN |
    1537             :             CMPCI_RECORD_SOURCE_FM);
    1538             : 
    1539           0 :         bitsl = CMPCI_SB16_MIXER_SRC_R_TO_L(bitsr);
    1540           0 :         if (mask & CMPCI_RECORD_SOURCE_MIC) {
    1541           0 :                 bitsl |= CMPCI_SB16_MIXER_MIC_SRC;
    1542           0 :                 bitsr |= CMPCI_SB16_MIXER_MIC_SRC;
    1543           0 :         }
    1544           0 :         cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, bitsl);
    1545           0 :         cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, bitsr);
    1546             : 
    1547           0 :         if (mask & CMPCI_RECORD_SOURCE_AUX_IN)
    1548           0 :                 cmpci_reg_set_1(sc, CMPCI_REG_MIXER25,
    1549             :                     CMPCI_REG_RAUXREN | CMPCI_REG_RAUXLEN);
    1550             :         else
    1551           0 :                 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25,
    1552             :                     CMPCI_REG_RAUXREN | CMPCI_REG_RAUXLEN);
    1553             : 
    1554           0 :         if (mask & CMPCI_RECORD_SOURCE_WAVE)
    1555           0 :                 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
    1556             :                     CMPCI_REG_WAVEINL | CMPCI_REG_WAVEINR);
    1557             :         else
    1558           0 :                 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
    1559             :                     CMPCI_REG_WAVEINL | CMPCI_REG_WAVEINR);
    1560             : 
    1561           0 :         if (CMPCI_ISCAP(sc, SPDIN) &&
    1562           0 :             (sc->sc_ch1.md_divide == CMPCI_REG_RATE_44100 ||
    1563           0 :                 (CMPCI_ISCAP(sc, SPDOUT_48K) &&
    1564           0 :                     sc->sc_ch1.md_divide == CMPCI_REG_RATE_48000/* XXX? */))) {
    1565           0 :                 if (mask & CMPCI_RECORD_SOURCE_SPDIF) {
    1566             :                         /* enable SPDIF/in */
    1567           0 :                         cmpci_reg_set_4(sc,
    1568             :                                         CMPCI_REG_FUNC_1,
    1569             :                                         CMPCI_REG_SPDIF1_ENABLE);
    1570           0 :                 } else {
    1571           0 :                         cmpci_reg_clear_4(sc,
    1572             :                                         CMPCI_REG_FUNC_1,
    1573             :                                         CMPCI_REG_SPDIF1_ENABLE);
    1574             :                 }
    1575             :         }
    1576             : 
    1577           0 :         return 0;
    1578             : }
    1579             : 
    1580             : int
    1581           0 : cmpci_set_port(void *handle, mixer_ctrl_t *cp)
    1582             : {
    1583           0 :         struct cmpci_softc *sc = handle;
    1584             :         int lgain, rgain;
    1585             : 
    1586           0 :         switch (cp->dev) {
    1587             :         case CMPCI_MIC_VOL:
    1588             :         case CMPCI_PCSPEAKER:
    1589             :         case CMPCI_MIC_RECVOL:
    1590           0 :                 if (cp->un.value.num_channels != 1)
    1591           0 :                         return EINVAL;
    1592             :                 /* FALLTHROUGH */
    1593             :         case CMPCI_DAC_VOL:
    1594             :         case CMPCI_FM_VOL:
    1595             :         case CMPCI_CD_VOL:
    1596             :         case CMPCI_LINE_IN_VOL:
    1597             :         case CMPCI_AUX_IN_VOL:
    1598             :         case CMPCI_MASTER_VOL:
    1599           0 :                 if (cp->type != AUDIO_MIXER_VALUE)
    1600           0 :                         return EINVAL;
    1601           0 :                 switch (cp->un.value.num_channels) {
    1602             :                 case 1:
    1603             :                         lgain = rgain =
    1604           0 :                             cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
    1605           0 :                         break;
    1606             :                 case 2:
    1607           0 :                         lgain = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
    1608           0 :                         rgain = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
    1609           0 :                         break;
    1610             :                 default:
    1611           0 :                         return EINVAL;
    1612             :                 }
    1613           0 :                 sc->sc_gain[cp->dev][CMPCI_LEFT]  = lgain;
    1614           0 :                 sc->sc_gain[cp->dev][CMPCI_RIGHT] = rgain;
    1615             : 
    1616           0 :                 cmpci_set_mixer_gain(sc, cp->dev);
    1617           0 :                 break;
    1618             : 
    1619             :         case CMPCI_RECORD_SOURCE:
    1620           0 :                 if (cp->type != AUDIO_MIXER_SET)
    1621           0 :                         return EINVAL;
    1622             : 
    1623           0 :                 if (cp->un.mask & ~(CMPCI_RECORD_SOURCE_MIC |
    1624             :                     CMPCI_RECORD_SOURCE_CD | CMPCI_RECORD_SOURCE_LINE_IN |
    1625             :                     CMPCI_RECORD_SOURCE_AUX_IN | CMPCI_RECORD_SOURCE_WAVE |
    1626             :                     CMPCI_RECORD_SOURCE_FM | CMPCI_RECORD_SOURCE_SPDIF))
    1627           0 :                         return EINVAL;
    1628             : 
    1629           0 :                 if (cp->un.mask & CMPCI_RECORD_SOURCE_SPDIF)
    1630           0 :                         cp->un.mask = CMPCI_RECORD_SOURCE_SPDIF;
    1631             : 
    1632           0 :                 sc->sc_in_mask = cp->un.mask;
    1633           0 :                 return cmpci_set_in_ports(sc);
    1634             : 
    1635             :         /* boolean */
    1636             :         case CMPCI_DAC_MUTE:
    1637             :         case CMPCI_FM_MUTE:
    1638             :         case CMPCI_CD_MUTE:
    1639             :         case CMPCI_LINE_IN_MUTE:
    1640             :         case CMPCI_AUX_IN_MUTE:
    1641             :         case CMPCI_MIC_MUTE:
    1642             :         case CMPCI_MIC_PREAMP:
    1643             :         case CMPCI_PLAYBACK_MODE:
    1644             :         case CMPCI_SPDIF_IN_PHASE:
    1645             :         case CMPCI_SPDIF_LOOP:
    1646             :         case CMPCI_SPDIF_OUT_PLAYBACK:
    1647             :         case CMPCI_SPDIF_OUT_VOLTAGE:
    1648             :         case CMPCI_REAR:
    1649             :         case CMPCI_INDIVIDUAL:
    1650             :         case CMPCI_REVERSE:
    1651             :         case CMPCI_SURROUND:
    1652           0 :                 if (cp->type != AUDIO_MIXER_ENUM)
    1653           0 :                         return EINVAL;
    1654           0 :                 sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
    1655           0 :                 cmpci_set_mixer_gain(sc, cp->dev);
    1656           0 :                 break;
    1657             : 
    1658             :         case CMPCI_SPDIF_IN_SELECT:
    1659           0 :                 switch (cp->un.ord) {
    1660             :                 case CMPCI_SPDIF_IN_SPDIN1:
    1661             :                 case CMPCI_SPDIF_IN_SPDIN2:
    1662             :                 case CMPCI_SPDIF_IN_SPDOUT:
    1663             :                         break;
    1664             :                 default:
    1665           0 :                         return EINVAL;
    1666             :                 }
    1667             :                 goto xenum;
    1668             :         case CMPCI_MONITOR_DAC:
    1669           0 :                 switch (cp->un.ord) {
    1670             :                 case CMPCI_MONITOR_DAC_OFF:
    1671             :                 case CMPCI_MONITOR_DAC_SPDIN:
    1672             :                 case CMPCI_MONITOR_DAC_SPDOUT:
    1673             :                         break;
    1674             :                 default:
    1675           0 :                         return EINVAL;
    1676             :                 }
    1677             :         xenum:
    1678           0 :                 if (cp->type != AUDIO_MIXER_ENUM)
    1679           0 :                         return EINVAL;
    1680           0 :                 sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord;
    1681           0 :                 cmpci_set_mixer_gain(sc, cp->dev);
    1682           0 :                 break;
    1683             : 
    1684             :         default:
    1685           0 :             return EINVAL;
    1686             :         }
    1687             : 
    1688           0 :         return 0;
    1689           0 : }
    1690             : 
    1691             : int
    1692           0 : cmpci_get_port(void *handle, mixer_ctrl_t *cp)
    1693             : {
    1694           0 :         struct cmpci_softc *sc = handle;
    1695             : 
    1696           0 :         switch (cp->dev) {
    1697             :         case CMPCI_MIC_VOL:
    1698             :         case CMPCI_PCSPEAKER:
    1699             :         case CMPCI_MIC_RECVOL:
    1700           0 :                 if (cp->un.value.num_channels != 1)
    1701           0 :                         return EINVAL;
    1702             :                 /*FALLTHROUGH*/
    1703             :         case CMPCI_DAC_VOL:
    1704             :         case CMPCI_FM_VOL:
    1705             :         case CMPCI_CD_VOL:
    1706             :         case CMPCI_LINE_IN_VOL:
    1707             :         case CMPCI_AUX_IN_VOL:
    1708             :         case CMPCI_MASTER_VOL:
    1709           0 :                 switch (cp->un.value.num_channels) {
    1710             :                 case 1:
    1711           0 :                         cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
    1712           0 :                                 sc->sc_gain[cp->dev][CMPCI_LEFT];
    1713           0 :                         break;
    1714             :                 case 2:
    1715           0 :                         cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
    1716           0 :                                 sc->sc_gain[cp->dev][CMPCI_LEFT];
    1717           0 :                         cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
    1718           0 :                                 sc->sc_gain[cp->dev][CMPCI_RIGHT];
    1719           0 :                         break;
    1720             :                 default:
    1721           0 :                         return EINVAL;
    1722             :                 }
    1723             :                 break;
    1724             : 
    1725             :         case CMPCI_RECORD_SOURCE:
    1726           0 :                 cp->un.mask = sc->sc_in_mask;
    1727           0 :                 break;
    1728             : 
    1729             :         case CMPCI_DAC_MUTE:
    1730             :         case CMPCI_FM_MUTE:
    1731             :         case CMPCI_CD_MUTE:
    1732             :         case CMPCI_LINE_IN_MUTE:
    1733             :         case CMPCI_AUX_IN_MUTE:
    1734             :         case CMPCI_MIC_MUTE:
    1735             :         case CMPCI_MIC_PREAMP:
    1736             :         case CMPCI_PLAYBACK_MODE:
    1737             :         case CMPCI_SPDIF_IN_SELECT:
    1738             :         case CMPCI_SPDIF_IN_PHASE:
    1739             :         case CMPCI_SPDIF_LOOP:
    1740             :         case CMPCI_SPDIF_OUT_PLAYBACK:
    1741             :         case CMPCI_SPDIF_OUT_VOLTAGE:
    1742             :         case CMPCI_MONITOR_DAC:
    1743             :         case CMPCI_REAR:
    1744             :         case CMPCI_INDIVIDUAL:
    1745             :         case CMPCI_REVERSE:
    1746             :         case CMPCI_SURROUND:
    1747           0 :                 cp->un.ord = sc->sc_gain[cp->dev][CMPCI_LR];
    1748           0 :                 break;
    1749             : 
    1750             :         default:
    1751           0 :                 return EINVAL;
    1752             :         }
    1753             : 
    1754           0 :         return 0;
    1755           0 : }
    1756             : 
    1757             : /* ARGSUSED */
    1758             : size_t
    1759           0 : cmpci_round_buffersize(void *handle, int direction, size_t bufsize)
    1760             : {
    1761           0 :         if (bufsize > 0x10000)
    1762             :                 bufsize = 0x10000;
    1763             : 
    1764           0 :         return bufsize;
    1765             : }
    1766             : 
    1767             : /* ARGSUSED */
    1768             : int
    1769           0 : cmpci_get_props(void *handle)
    1770             : {
    1771           0 :         return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
    1772             : }
    1773             : 
    1774             : int
    1775           0 : cmpci_trigger_output(void *handle, void *start, void *end, int blksize,
    1776             :     void (*intr)(void *), void *arg, struct audio_params *param)
    1777             : {
    1778           0 :         struct cmpci_softc *sc = handle;
    1779             :         struct cmpci_dmanode *p;
    1780             :         struct cmpci_channel *chan;
    1781             :         uint32_t reg_dma_base, reg_dma_bytes, reg_dma_samples, reg_dir,
    1782             :             reg_intr_enable, reg_enable;
    1783             :         uint32_t length;
    1784           0 :         size_t buffer_size = (caddr_t)end - (caddr_t)start;
    1785             : 
    1786           0 :         cmpci_set_out_ports(sc);
    1787             : 
    1788           0 :         if (sc->sc_play_channel == 1) {
    1789           0 :                 chan = &sc->sc_ch1;
    1790             :                 reg_dma_base = CMPCI_REG_DMA1_BASE;
    1791             :                 reg_dma_bytes = CMPCI_REG_DMA1_BYTES;
    1792             :                 reg_dma_samples = CMPCI_REG_DMA1_SAMPLES;
    1793             :                 reg_dir = CMPCI_REG_CH1_DIR;
    1794             :                 reg_intr_enable = CMPCI_REG_CH1_INTR_ENABLE;
    1795             :                 reg_enable = CMPCI_REG_CH1_ENABLE;
    1796           0 :         } else {
    1797           0 :                 chan = &sc->sc_ch0;
    1798             :                 reg_dma_base = CMPCI_REG_DMA0_BASE;
    1799             :                 reg_dma_bytes = CMPCI_REG_DMA0_BYTES;
    1800             :                 reg_dma_samples = CMPCI_REG_DMA0_SAMPLES;
    1801             :                 reg_dir = CMPCI_REG_CH0_DIR;
    1802             :                 reg_intr_enable = CMPCI_REG_CH0_INTR_ENABLE;
    1803             :                 reg_enable = CMPCI_REG_CH0_ENABLE;
    1804             :         }
    1805             : 
    1806           0 :         chan->bps = (param->channels > 1 ? 2 : 1) * param->bps;
    1807           0 :         if (!chan->bps)
    1808           0 :                 return EINVAL;
    1809             : 
    1810           0 :         chan->intr = intr;
    1811           0 :         chan->intr_arg = arg;
    1812           0 :         chan->blksize = blksize;
    1813           0 :         chan->nblocks = buffer_size / chan->blksize;
    1814           0 :         chan->swpos = 0;
    1815             : 
    1816             :         /* set DMA frame */
    1817           0 :         if (!(p = cmpci_find_dmamem(sc, start)))
    1818           0 :                 return EINVAL;
    1819           0 :         bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg_dma_base,
    1820             :             DMAADDR(p));
    1821           0 :         delay(10);
    1822           0 :         length = (buffer_size + 1) / chan->bps - 1;
    1823           0 :         bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg_dma_bytes, length);
    1824           0 :         delay(10);
    1825             : 
    1826             :         /* set interrupt count */
    1827           0 :         length = (chan->blksize + chan->bps - 1) / chan->bps - 1;
    1828           0 :         bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg_dma_samples, length);
    1829           0 :         delay(10);
    1830             : 
    1831             :         /* start DMA */
    1832           0 :         mtx_enter(&audio_lock);
    1833           0 :         cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, reg_dir); /* PLAY */
    1834           0 :         cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, reg_intr_enable);
    1835           0 :         cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, reg_enable);
    1836           0 :         mtx_leave(&audio_lock);
    1837           0 :         return 0;
    1838           0 : }
    1839             : 
    1840             : int
    1841           0 : cmpci_trigger_input(void *handle, void *start, void *end, int blksize,
    1842             :     void (*intr)(void *), void *arg, struct audio_params *param)
    1843             : {
    1844           0 :         struct cmpci_softc *sc = handle;
    1845             :         struct cmpci_dmanode *p;
    1846           0 :         struct cmpci_channel *chan = &sc->sc_ch1;
    1847           0 :         size_t buffer_size = (caddr_t)end - (caddr_t)start;
    1848             : 
    1849           0 :         cmpci_set_in_ports(sc);
    1850             : 
    1851           0 :         chan->bps = param->channels * param->bps;
    1852           0 :         if (!chan->bps)
    1853           0 :                 return EINVAL;
    1854             : 
    1855           0 :         chan->intr = intr;
    1856           0 :         chan->intr_arg = arg;
    1857           0 :         chan->blksize = blksize;
    1858           0 :         chan->nblocks = buffer_size / chan->blksize;
    1859           0 :         chan->swpos = 0;
    1860             : 
    1861             :         /* set DMA frame */
    1862           0 :         if (!(p = cmpci_find_dmamem(sc, start)))
    1863           0 :                 return EINVAL;
    1864           0 :         bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BASE,
    1865             :             DMAADDR(p));
    1866           0 :         delay(10);
    1867           0 :         bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BYTES,
    1868             :             (buffer_size + 1) / chan->bps - 1);
    1869           0 :         delay(10);
    1870             : 
    1871             :         /* set interrupt count */
    1872           0 :         bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_SAMPLES,
    1873             :             (chan->blksize + chan->bps - 1) / chan->bps - 1);
    1874           0 :         delay(10);
    1875             : 
    1876             :         /* start DMA */
    1877           0 :         mtx_enter(&audio_lock);
    1878           0 :         cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); /* REC */
    1879           0 :         cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
    1880           0 :         cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
    1881           0 :         mtx_leave(&audio_lock);
    1882           0 :         return 0;
    1883           0 : }
    1884             : 
    1885             : /* end of file */

Generated by: LCOV version 1.13