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

          Line data    Source code
       1             : /*      $OpenBSD: eap.c,v 1.56 2018/09/14 08:37:34 miko Exp $ */
       2             : /*      $NetBSD: eap.c,v 1.46 2001/09/03 15:07:37 reinoud Exp $ */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
       6             :  * All rights reserved.
       7             :  *
       8             :  * This code is derived from software contributed to The NetBSD Foundation
       9             :  * by Lennart Augustsson <augustss@netbsd.org> and Charles M. Hannum.
      10             :  *
      11             :  * Redistribution and use in source and binary forms, with or without
      12             :  * modification, are permitted provided that the following conditions
      13             :  * are met:
      14             :  * 1. Redistributions of source code must retain the above copyright
      15             :  *    notice, this list of conditions and the following disclaimer.
      16             :  * 2. Redistributions in binary form must reproduce the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer in the
      18             :  *    documentation and/or other materials provided with the distribution.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
      21             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      22             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      23             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
      24             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      25             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      26             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      27             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      28             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      29             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      30             :  * POSSIBILITY OF SUCH DAMAGE.
      31             :  */
      32             : 
      33             : /*
      34             :  * Debugging:   Andreas Gustafsson <gson@araneus.fi>
      35             :  * Testing:     Chuck Cranor       <chuck@maria.wustl.edu>
      36             :  *              Phil Nelson        <phil@cs.wwu.edu>
      37             :  *
      38             :  * ES1371/AC97: Ezra Story         <ezy@panix.com>
      39             :  */
      40             : 
      41             : /* 
      42             :  * Ensoniq ES1370 + AK4531 and ES1371/ES1373 + AC97
      43             :  *
      44             :  * Documentation links:
      45             :  * 
      46             :  * ftp://ftp.alsa-project.org/pub/manuals/ensoniq/
      47             :  * ftp://ftp.alsa-project.org/pub/manuals/asahi_kasei/4531.pdf
      48             :  */
      49             : 
      50             : #include "midi.h"
      51             : 
      52             : #include <sys/param.h>
      53             : #include <sys/systm.h>
      54             : #include <sys/kernel.h>
      55             : #include <sys/fcntl.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             : #include <dev/ic/ac97.h>
      65             : 
      66             : #include <machine/bus.h>
      67             : 
      68             : #include <dev/pci/eapreg.h>
      69             : 
      70             : struct        cfdriver eap_cd = {
      71             :       NULL, "eap", DV_DULL
      72             : };
      73             : 
      74             : #define PCI_CBIO                0x10
      75             : 
      76             : /* Debug */
      77             : #ifdef AUDIO_DEBUG
      78             : #define DPRINTF(x)      if (eapdebug) printf x
      79             : #define DPRINTFN(n,x)   if (eapdebug>(n)) printf x
      80             : int     eapdebug = 1;
      81             : #else
      82             : #define DPRINTF(x)
      83             : #define DPRINTFN(n,x)
      84             : #endif
      85             : 
      86             : int     eap_match(struct device *, void *, void *);
      87             : void    eap_attach(struct device *, struct device *, void *);
      88             : int     eap_activate(struct device *, int);
      89             : int     eap_intr(void *);
      90             : 
      91             : struct eap_dma {
      92             :         bus_dmamap_t map;
      93             :         caddr_t addr;
      94             :         bus_dma_segment_t segs[1];
      95             :         int nsegs;
      96             :         size_t size;
      97             :         struct eap_dma *next;
      98             : };
      99             : 
     100             : #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
     101             : #define KERNADDR(p) ((void *)((p)->addr))
     102             : 
     103             : struct eap_softc {
     104             :         struct device sc_dev;           /* base device */
     105             :         void *sc_ih;                    /* interrupt vectoring */
     106             :         bus_space_tag_t iot;
     107             :         bus_space_handle_t ioh;
     108             :         bus_dma_tag_t sc_dmatag;        /* DMA tag */
     109             : 
     110             :         struct eap_dma *sc_dmas;
     111             : 
     112             :         void    (*sc_pintr)(void *);    /* dma completion intr handler */
     113             :         void    *sc_parg;               /* arg for sc_intr() */
     114             : #ifdef DIAGNOSTIC
     115             :         char    sc_prun;
     116             : #endif
     117             : 
     118             :         void    (*sc_rintr)(void *);    /* dma completion intr handler */
     119             :         void    *sc_rarg;               /* arg for sc_intr() */
     120             : #ifdef DIAGNOSTIC
     121             :         char    sc_rrun;
     122             : #endif
     123             : 
     124             : #if NMIDI > 0
     125             :         void    (*sc_iintr)(void *, int); /* midi input ready handler */
     126             :         void    (*sc_ointr)(void *);    /* midi output ready handler */
     127             :         void    *sc_arg;
     128             :         int     sc_uctrl;
     129             :         struct device *sc_mididev;
     130             : #endif
     131             : 
     132             :         u_short sc_port[AK_NPORTS];     /* mirror of the hardware setting */
     133             :         u_int   sc_record_source;       /* recording source mask */
     134             :         u_int   sc_input_source;        /* input source mask */
     135             :         u_int   sc_mic_preamp;
     136             :         char    sc_1371;                /* Using ES1371/AC97 codec */
     137             :         char    sc_ct5880;              /* CT5880 chip */
     138             : 
     139             :         struct ac97_codec_if *codec_if;
     140             :         struct ac97_host_if host_if;
     141             : 
     142             :         int flags;
     143             : };
     144             : 
     145             : enum    ac97_host_flags eap_flags_codec(void *);
     146             : int     eap_allocmem(struct eap_softc *, size_t, size_t, struct eap_dma *);
     147             : int     eap_freemem(struct eap_softc *, struct eap_dma *);
     148             : 
     149             : #define EWRITE1(sc, r, x) bus_space_write_1((sc)->iot, (sc)->ioh, (r), (x))
     150             : #define EWRITE2(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x))
     151             : #define EWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x))
     152             : #define EREAD1(sc, r) bus_space_read_1((sc)->iot, (sc)->ioh, (r))
     153             : #define EREAD2(sc, r) bus_space_read_2((sc)->iot, (sc)->ioh, (r))
     154             : #define EREAD4(sc, r) bus_space_read_4((sc)->iot, (sc)->ioh, (r))
     155             : 
     156             : struct cfattach eap_ca = {
     157             :         sizeof(struct eap_softc), eap_match, eap_attach, NULL, eap_activate
     158             : };
     159             : 
     160             : int     eap_open(void *, int);
     161             : void    eap_close(void *);
     162             : int     eap_set_params(void *, int, int, struct audio_params *, struct audio_params *);
     163             : int     eap_round_blocksize(void *, int);
     164             : int     eap_trigger_output(void *, void *, void *, int, void (*)(void *),
     165             :             void *, struct audio_params *);
     166             : int     eap_trigger_input(void *, void *, void *, int, void (*)(void *),
     167             :             void *, struct audio_params *);
     168             : int     eap_halt_output(void *);
     169             : int     eap_halt_input(void *);
     170             : void    eap_resume(struct eap_softc *);
     171             : void    eap1370_write_codec(struct eap_softc *, int, int);
     172             : int     eap1370_mixer_set_port(void *, mixer_ctrl_t *);
     173             : int     eap1370_mixer_get_port(void *, mixer_ctrl_t *);
     174             : int     eap1371_mixer_set_port(void *, mixer_ctrl_t *);
     175             : int     eap1371_mixer_get_port(void *, mixer_ctrl_t *);
     176             : int     eap1370_query_devinfo(void *, mixer_devinfo_t *);
     177             : void   *eap_malloc(void *, int, size_t, int, int);
     178             : void    eap_free(void *, void *, int);
     179             : int     eap_get_props(void *);
     180             : void    eap1370_set_mixer(struct eap_softc *sc, int a, int d);
     181             : u_int32_t eap1371_src_wait(struct eap_softc *sc);
     182             : void    eap1371_src_write(struct eap_softc *sc, int a, int d);
     183             : int     eap1371_query_devinfo(void *addr, mixer_devinfo_t *dip);
     184             : 
     185             : int     eap1371_attach_codec(void *sc, struct ac97_codec_if *);
     186             : int     eap1371_read_codec(void *sc, u_int8_t a, u_int16_t *d);
     187             : int     eap1371_write_codec(void *sc, u_int8_t a, u_int16_t d);
     188             : void    eap1371_reset_codec(void *sc);
     189             : #if NMIDI > 0
     190             : void    eap_midi_close(void *);
     191             : void    eap_midi_getinfo(void *, struct midi_info *);
     192             : int     eap_midi_open(void *, int, void (*)(void *, int),
     193             :             void (*)(void *), void *);
     194             : int     eap_midi_output(void *, int);
     195             : #endif
     196             : 
     197             : struct audio_hw_if eap1370_hw_if = {
     198             :         eap_open,
     199             :         eap_close,
     200             :         eap_set_params,
     201             :         eap_round_blocksize,
     202             :         NULL,
     203             :         NULL,
     204             :         NULL,
     205             :         NULL,
     206             :         NULL,
     207             :         eap_halt_output,
     208             :         eap_halt_input,
     209             :         NULL,
     210             :         NULL,
     211             :         eap1370_mixer_set_port,
     212             :         eap1370_mixer_get_port,
     213             :         eap1370_query_devinfo,
     214             :         eap_malloc,
     215             :         eap_free,
     216             :         NULL,
     217             :         eap_get_props,
     218             :         eap_trigger_output,
     219             :         eap_trigger_input
     220             : };
     221             : 
     222             : struct audio_hw_if eap1371_hw_if = {
     223             :         eap_open,
     224             :         eap_close,
     225             :         eap_set_params,
     226             :         eap_round_blocksize,
     227             :         NULL,
     228             :         NULL,
     229             :         NULL,
     230             :         NULL,
     231             :         NULL,
     232             :         eap_halt_output,
     233             :         eap_halt_input,
     234             :         NULL,
     235             :         NULL,
     236             :         eap1371_mixer_set_port,
     237             :         eap1371_mixer_get_port,
     238             :         eap1371_query_devinfo,
     239             :         eap_malloc,
     240             :         eap_free,
     241             :         NULL,
     242             :         eap_get_props,
     243             :         eap_trigger_output,
     244             :         eap_trigger_input
     245             : };
     246             : 
     247             : #if NMIDI > 0
     248             : struct midi_hw_if eap_midi_hw_if = {
     249             :         eap_midi_open,
     250             :         eap_midi_close,
     251             :         eap_midi_output,
     252             :         0,                              /* flush */
     253             :         eap_midi_getinfo,
     254             :         0,                              /* ioctl */
     255             : };
     256             : #endif
     257             : 
     258             : const struct pci_matchid eap_devices[] = {
     259             :         { PCI_VENDOR_CREATIVELABS, PCI_PRODUCT_CREATIVELABS_EV1938 },
     260             :         { PCI_VENDOR_ENSONIQ, PCI_PRODUCT_ENSONIQ_AUDIOPCI },
     261             :         { PCI_VENDOR_ENSONIQ, PCI_PRODUCT_ENSONIQ_AUDIOPCI97 },
     262             :         { PCI_VENDOR_ENSONIQ, PCI_PRODUCT_ENSONIQ_CT5880 },
     263             : };
     264             : 
     265             : int
     266           0 : eap_match(struct device *parent, void *match, void *aux)
     267             : {
     268           0 :         return (pci_matchbyid((struct pci_attach_args *)aux, eap_devices,
     269             :             nitems(eap_devices)));
     270             : }
     271             : 
     272             : int
     273           0 : eap_activate(struct device *self, int act)
     274             : {
     275           0 :         struct eap_softc *sc = (struct eap_softc *)self;
     276             : 
     277           0 :         switch (act) {
     278             :         case DVACT_RESUME:
     279           0 :                 eap_resume(sc);
     280           0 :                 break;
     281             :         default:
     282             :                 break;
     283             :         }
     284           0 :         return (config_activate_children(self, act));
     285             : }
     286             : 
     287             : void
     288           0 : eap1370_write_codec(struct eap_softc *sc, int a, int d)
     289             : {
     290             :         int icss, to;
     291             : 
     292             :         to = EAP_WRITE_TIMEOUT;
     293           0 :         do {
     294           0 :                 icss = EREAD4(sc, EAP_ICSS);
     295             :                 DPRINTFN(5,("eap: codec %d prog: icss=0x%08x\n", a, icss));
     296           0 :                 if (!to--) {
     297           0 :                         printf("%s: timeout writing to codec\n",
     298           0 :                             sc->sc_dev.dv_xname);
     299           0 :                         return;
     300             :                 }
     301           0 :         } while (icss & EAP_CWRIP);  /* XXX could use CSTAT here */
     302           0 :         EWRITE4(sc, EAP_CODEC, EAP_SET_CODEC(a, d));
     303           0 : }
     304             : 
     305             : /*
     306             :  * Reading and writing the CODEC is very convoluted.  This mimics the
     307             :  * FreeBSD and Linux drivers.
     308             :  */
     309             : 
     310             : static __inline void
     311           0 : eap1371_ready_codec(struct eap_softc *sc, u_int8_t a, u_int32_t wd)
     312             : {
     313             :         int to;
     314             :         u_int32_t src, t;
     315             : 
     316           0 :         for (to = 0; to < EAP_WRITE_TIMEOUT; to++) {
     317           0 :                 if (!(EREAD4(sc, E1371_CODEC) & E1371_CODEC_WIP))
     318             :                         break;
     319           0 :                 delay(1);
     320             :         }
     321           0 :         if (to == EAP_WRITE_TIMEOUT)
     322           0 :                 printf("%s: eap1371_ready_codec timeout 1\n",
     323           0 :                     sc->sc_dev.dv_xname);
     324             : 
     325           0 :         mtx_enter(&audio_lock);
     326           0 :         src = eap1371_src_wait(sc) & E1371_SRC_CTLMASK;
     327           0 :         EWRITE4(sc, E1371_SRC, src | E1371_SRC_STATE_OK);
     328             : 
     329           0 :         for (to = 0; to < EAP_READ_TIMEOUT; to++) {
     330           0 :                 t = EREAD4(sc, E1371_SRC);
     331           0 :                 if ((t & E1371_SRC_STATE_MASK) == 0)
     332             :                         break;
     333           0 :                 delay(1);
     334             :         }
     335           0 :         if (to == EAP_READ_TIMEOUT)
     336           0 :                 printf("%s: eap1371_ready_codec timeout 2\n",
     337           0 :                     sc->sc_dev.dv_xname);
     338             : 
     339           0 :         for (to = 0; to < EAP_READ_TIMEOUT; to++) {
     340           0 :                 t = EREAD4(sc, E1371_SRC);
     341           0 :                 if ((t & E1371_SRC_STATE_MASK) == E1371_SRC_STATE_OK)
     342             :                         break;
     343           0 :                 delay(1);
     344             :         }
     345           0 :         if (to == EAP_READ_TIMEOUT)
     346           0 :                 printf("%s: eap1371_ready_codec timeout 3\n",
     347           0 :                     sc->sc_dev.dv_xname);
     348             : 
     349           0 :         EWRITE4(sc, E1371_CODEC, wd);
     350             : 
     351           0 :         eap1371_src_wait(sc);
     352           0 :         EWRITE4(sc, E1371_SRC, src);
     353             : 
     354           0 :         mtx_leave(&audio_lock);
     355           0 : }
     356             : 
     357             : int
     358           0 : eap1371_read_codec(void *sc_, u_int8_t a, u_int16_t *d)
     359             : {
     360           0 :         struct eap_softc *sc = sc_;
     361             :         int to;
     362             :         u_int32_t t;
     363             : 
     364           0 :         eap1371_ready_codec(sc, a, E1371_SET_CODEC(a, 0) | E1371_CODEC_READ);
     365             : 
     366           0 :         for (to = 0; to < EAP_WRITE_TIMEOUT; to++) {
     367           0 :                 if (!(EREAD4(sc, E1371_CODEC) & E1371_CODEC_WIP))
     368             :                         break;
     369           0 :                 delay(1);
     370             :         }
     371           0 :         if (to == EAP_WRITE_TIMEOUT)
     372           0 :                 printf("%s: eap1371_read_codec timeout 1\n",
     373           0 :                     sc->sc_dev.dv_xname);
     374             : 
     375           0 :         for (to = 0; to < EAP_WRITE_TIMEOUT; to++) {
     376           0 :                 t = EREAD4(sc, E1371_CODEC);
     377           0 :                 if (t & E1371_CODEC_VALID)
     378             :                         break;
     379           0 :                 delay(1);
     380             :         }
     381           0 :         if (to == EAP_WRITE_TIMEOUT)
     382           0 :                 printf("%s: eap1371_read_codec timeout 2\n",
     383           0 :                     sc->sc_dev.dv_xname);
     384             : 
     385           0 :         *d = (u_int16_t)t;
     386             : 
     387             :         DPRINTFN(10, ("eap1371: reading codec (%x) = %x\n", a, *d));
     388             : 
     389           0 :         return (0);
     390             : }
     391             : 
     392             : int
     393           0 : eap1371_write_codec(void *sc_, u_int8_t a, u_int16_t d)
     394             : {
     395           0 :         struct eap_softc *sc = sc_;
     396             : 
     397           0 :         eap1371_ready_codec(sc, a, E1371_SET_CODEC(a, d));
     398             : 
     399             :         DPRINTFN(10, ("eap1371: writing codec %x --> %x\n", d, a));
     400             : 
     401           0 :         return (0);
     402             : }
     403             : 
     404             : u_int32_t
     405           0 : eap1371_src_wait(struct eap_softc *sc)
     406             : {
     407             :         int to;
     408             :         u_int32_t src = 0;
     409             :         
     410           0 :         for (to = 0; to < EAP_READ_TIMEOUT; to++) {
     411           0 :                 src = EREAD4(sc, E1371_SRC);
     412           0 :                 if (!(src & E1371_SRC_RBUSY))
     413           0 :                         return (src);
     414           0 :                 delay(1);
     415             :         }
     416           0 :         printf("%s: eap1371_src_wait timeout\n", sc->sc_dev.dv_xname);
     417           0 :         return (src);
     418           0 : }
     419             : 
     420             : void
     421           0 : eap1371_src_write(struct eap_softc *sc, int a, int d)
     422             : {
     423             :         u_int32_t r;
     424             : 
     425           0 :         r = eap1371_src_wait(sc) & E1371_SRC_CTLMASK;
     426           0 :         r |= E1371_SRC_RAMWE | E1371_SRC_ADDR(a) | E1371_SRC_DATA(d);
     427           0 :         EWRITE4(sc, E1371_SRC, r);
     428           0 : }
     429             :         
     430             : void
     431           0 : eap_attach(struct device *parent, struct device *self, void *aux)
     432             : {
     433           0 :         struct eap_softc *sc = (struct eap_softc *)self;
     434           0 :         struct pci_attach_args *pa = (struct pci_attach_args *)aux;
     435           0 :         pci_chipset_tag_t pc = pa->pa_pc;
     436             :         struct audio_hw_if *eap_hw_if;
     437             :         char const *intrstr;
     438           0 :         pci_intr_handle_t ih;
     439           0 :         mixer_ctrl_t ctl;
     440             :         int i;
     441             :         int revision;
     442             : 
     443             :         /* Flag if we're "creative" */
     444           0 :         sc->sc_1371 = !(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ENSONIQ &&
     445           0 :             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENSONIQ_AUDIOPCI);
     446             : 
     447           0 :         revision = PCI_REVISION(pa->pa_class);
     448           0 :         if (sc->sc_1371) {
     449           0 :                 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ENSONIQ &&
     450           0 :                     ((PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENSONIQ_AUDIOPCI97 &&
     451           0 :                     (revision == EAP_ES1373_8 || revision == EAP_CT5880_A)) ||
     452           0 :                     PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENSONIQ_CT5880))
     453           0 :                         sc->sc_ct5880 = 1;
     454             :         }
     455             : 
     456             :         /* Map I/O register */
     457           0 :         if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
     458           0 :             &sc->iot, &sc->ioh, NULL, NULL, 0)) {
     459           0 :                 return;
     460             :         }
     461             : 
     462           0 :         sc->sc_dmatag = pa->pa_dmat;
     463             : 
     464             :         /* Map and establish the interrupt. */
     465           0 :         if (pci_intr_map(pa, &ih)) {
     466           0 :                 printf(": couldn't map interrupt\n");
     467           0 :                 return;
     468             :         }
     469           0 :         intrstr = pci_intr_string(pc, ih);
     470           0 :         sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE,
     471           0 :             eap_intr, sc, sc->sc_dev.dv_xname);
     472           0 :         if (sc->sc_ih == NULL) {
     473           0 :                 printf(": couldn't establish interrupt");
     474           0 :                 if (intrstr != NULL)
     475           0 :                         printf(" at %s", intrstr);
     476           0 :                 printf("\n");
     477           0 :                 return;
     478             :         }
     479           0 :         printf(": %s\n", intrstr);
     480             : 
     481           0 :         if (!sc->sc_1371) {
     482             :                 /* Enable interrupts and looping mode. */
     483             :                 /* enable the parts we need */
     484           0 :                 EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN);
     485           0 :                 EWRITE4(sc, EAP_ICSC, EAP_CDC_EN);
     486             : 
     487             :                 /* reset codec */
     488             :                 /* normal operation */
     489             :                 /* select codec clocks */
     490           0 :                 eap1370_write_codec(sc, AK_RESET, AK_PD);
     491           0 :                 eap1370_write_codec(sc, AK_RESET, AK_PD | AK_NRST);
     492           0 :                 eap1370_write_codec(sc, AK_CS, 0x0);
     493             : 
     494             :                 eap_hw_if = &eap1370_hw_if;
     495             : 
     496             :                 /* Enable all relevant mixer switches. */
     497           0 :                 ctl.dev = EAP_INPUT_SOURCE;
     498           0 :                 ctl.type = AUDIO_MIXER_SET;
     499           0 :                 ctl.un.mask = 1 << EAP_VOICE_VOL | 1 << EAP_FM_VOL |
     500             :                     1 << EAP_CD_VOL | 1 << EAP_LINE_VOL | 1 << EAP_AUX_VOL |
     501             :                     1 << EAP_MIC_VOL;
     502           0 :                 eap_hw_if->set_port(sc, &ctl);
     503             : 
     504           0 :                 ctl.type = AUDIO_MIXER_VALUE;
     505           0 :                 ctl.un.value.num_channels = 1;
     506           0 :                 for (ctl.dev = EAP_MASTER_VOL; ctl.dev < EAP_MIC_VOL;
     507           0 :                      ctl.dev++) {
     508           0 :                         ctl.un.value.level[AUDIO_MIXER_LEVEL_MONO] = VOL_0DB;
     509           0 :                         eap_hw_if->set_port(sc, &ctl);
     510             :                 }
     511           0 :                 ctl.un.value.level[AUDIO_MIXER_LEVEL_MONO] = 0;
     512           0 :                 eap_hw_if->set_port(sc, &ctl);
     513           0 :                 ctl.dev = EAP_MIC_PREAMP;
     514           0 :                 ctl.type = AUDIO_MIXER_ENUM;
     515           0 :                 ctl.un.ord = 0;
     516           0 :                 eap_hw_if->set_port(sc, &ctl);
     517           0 :                 ctl.dev = EAP_RECORD_SOURCE;
     518           0 :                 ctl.type = AUDIO_MIXER_SET;
     519           0 :                 ctl.un.mask = 1 << EAP_MIC_VOL;
     520           0 :                 eap_hw_if->set_port(sc, &ctl);
     521           0 :         } else {
     522             :                 /* clean slate */
     523             : 
     524           0 :                 EWRITE4(sc, EAP_SIC, 0);
     525           0 :                 EWRITE4(sc, EAP_ICSC, 0);
     526           0 :                 EWRITE4(sc, E1371_LEGACY, 0);
     527             : 
     528           0 :                 if (sc->sc_ct5880) {
     529           0 :                         EWRITE4(sc, EAP_ICSS, EAP_CT5880_AC97_RESET);
     530             :                         /* Let codec wake up */
     531           0 :                         delay(20000);
     532           0 :                 }
     533             : 
     534             :                 /* Reset from es1371's perspective */
     535           0 :                 EWRITE4(sc, EAP_ICSC, E1371_SYNC_RES);
     536           0 :                 delay(20);
     537           0 :                 EWRITE4(sc, EAP_ICSC, 0);
     538             : 
     539             :                 /*
     540             :                  * Must properly reprogram sample rate converter,
     541             :                  * or it locks up.
     542             :                  *
     543             :                  * We don't know how to program it (no documentation),
     544             :                  * and the linux/oss magic receipe doesn't work (breaks
     545             :                  * full-duplex, by selecting different play and record
     546             :                  * rates). On the other hand, the sample rate converter
     547             :                  * can't be disabled (disabling it would disable DMA),
     548             :                  * so we use these magic defaults that make it "resample"
     549             :                  * 48kHz to 48kHz without breaking full-duplex.
     550             :                  */
     551           0 :                 EWRITE4(sc, E1371_SRC, E1371_SRC_DISABLE);
     552           0 :                 for (i = 0; i < 0x80; i++)
     553           0 :                         eap1371_src_write(sc, i, 0);
     554           0 :                 eap1371_src_write(sc, ESRC_ADC + ESRC_TRUNC_N, ESRC_SET_N(16));
     555           0 :                 eap1371_src_write(sc, ESRC_ADC + ESRC_IREGS, ESRC_SET_VFI(16));
     556           0 :                 eap1371_src_write(sc, ESRC_ADC + ESRC_VFF, 0);
     557           0 :                 eap1371_src_write(sc, ESRC_ADC_VOLL, ESRC_SET_ADC_VOL(16));
     558           0 :                 eap1371_src_write(sc, ESRC_ADC_VOLR, ESRC_SET_ADC_VOL(16));
     559           0 :                 eap1371_src_write(sc, ESRC_DAC1 + ESRC_TRUNC_N, ESRC_SET_N(16));
     560           0 :                 eap1371_src_write(sc, ESRC_DAC1 + ESRC_IREGS, ESRC_SET_VFI(16));
     561           0 :                 eap1371_src_write(sc, ESRC_DAC1 + ESRC_VFF, 0);
     562           0 :                 eap1371_src_write(sc, ESRC_DAC1_VOLL, ESRC_SET_DAC_VOLI(1));
     563           0 :                 eap1371_src_write(sc, ESRC_DAC1_VOLR, ESRC_SET_DAC_VOLI(1));
     564           0 :                 eap1371_src_write(sc, ESRC_DAC2 + ESRC_IREGS, ESRC_SET_VFI(16));
     565           0 :                 eap1371_src_write(sc, ESRC_DAC2 + ESRC_TRUNC_N, ESRC_SET_N(16));
     566           0 :                 eap1371_src_write(sc, ESRC_DAC2 + ESRC_VFF, 0);
     567           0 :                 eap1371_src_write(sc, ESRC_DAC2_VOLL, ESRC_SET_DAC_VOLI(1));
     568           0 :                 eap1371_src_write(sc, ESRC_DAC2_VOLR, ESRC_SET_DAC_VOLI(1));
     569           0 :                 EWRITE4(sc, E1371_SRC, 0);
     570             : 
     571             :                 /* Reset codec */
     572             : 
     573             :                 /* Interrupt enable */
     574           0 :                 sc->host_if.arg = sc;
     575           0 :                 sc->host_if.attach = eap1371_attach_codec;
     576           0 :                 sc->host_if.read = eap1371_read_codec;
     577           0 :                 sc->host_if.write = eap1371_write_codec;
     578           0 :                 sc->host_if.reset = eap1371_reset_codec;
     579           0 :                 sc->host_if.flags = eap_flags_codec;
     580           0 :                 sc->flags = AC97_HOST_DONT_READ;
     581             :         
     582           0 :                 if (ac97_attach(&sc->host_if) == 0) {
     583             :                         /* Interrupt enable */
     584           0 :                         EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN);
     585             :                 } else
     586           0 :                         return;
     587             : 
     588             :                 eap_hw_if = &eap1371_hw_if;
     589             :         }
     590             : 
     591           0 :         audio_attach_mi(eap_hw_if, sc, &sc->sc_dev);
     592             : #if NMIDI > 0
     593           0 :         sc->sc_mididev = midi_attach_mi(&eap_midi_hw_if, sc, &sc->sc_dev);
     594             : #endif
     595           0 : }
     596             : 
     597             : void
     598           0 : eap_resume(struct eap_softc *sc)
     599             : {
     600             :         int i;
     601             : 
     602           0 :         if (!sc->sc_1371) {
     603             :                 /* Enable interrupts and looping mode. */
     604             :                 /* enable the parts we need */
     605           0 :                 EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN);
     606           0 :                 EWRITE4(sc, EAP_ICSC, EAP_CDC_EN);
     607             : 
     608             :                 /* reset codec */
     609             :                 /* normal operation */
     610             :                 /* select codec clocks */
     611           0 :                 eap1370_write_codec(sc, AK_RESET, AK_PD);
     612           0 :                 eap1370_write_codec(sc, AK_RESET, AK_PD | AK_NRST);
     613           0 :                 eap1370_write_codec(sc, AK_CS, 0x0);
     614             : 
     615           0 :         } else {
     616             :                 /* clean slate */
     617             : 
     618           0 :                 EWRITE4(sc, EAP_SIC, 0);
     619           0 :                 EWRITE4(sc, EAP_ICSC, 0);
     620           0 :                 EWRITE4(sc, E1371_LEGACY, 0);
     621             : 
     622           0 :                 if (sc->sc_ct5880) {
     623           0 :                         EWRITE4(sc, EAP_ICSS, EAP_CT5880_AC97_RESET);
     624             :                         /* Let codec wake up */
     625           0 :                         delay(20000);
     626           0 :                 }
     627             : 
     628           0 :                 ac97_resume(&sc->host_if, sc->codec_if);
     629             : 
     630           0 :                 EWRITE4(sc, E1371_SRC, E1371_SRC_DISABLE);
     631           0 :                 for (i = 0; i < 0x80; i++)
     632           0 :                         eap1371_src_write(sc, i, 0);
     633           0 :                 eap1371_src_write(sc, ESRC_ADC + ESRC_TRUNC_N, ESRC_SET_N(16));
     634           0 :                 eap1371_src_write(sc, ESRC_ADC + ESRC_IREGS, ESRC_SET_VFI(16));
     635           0 :                 eap1371_src_write(sc, ESRC_ADC + ESRC_VFF, 0);
     636           0 :                 eap1371_src_write(sc, ESRC_ADC_VOLL, ESRC_SET_ADC_VOL(16));
     637           0 :                 eap1371_src_write(sc, ESRC_ADC_VOLR, ESRC_SET_ADC_VOL(16));
     638           0 :                 eap1371_src_write(sc, ESRC_DAC1 + ESRC_TRUNC_N, ESRC_SET_N(16));
     639           0 :                 eap1371_src_write(sc, ESRC_DAC1 + ESRC_IREGS, ESRC_SET_VFI(16));
     640           0 :                 eap1371_src_write(sc, ESRC_DAC1 + ESRC_VFF, 0);
     641           0 :                 eap1371_src_write(sc, ESRC_DAC1_VOLL, ESRC_SET_DAC_VOLI(1));
     642           0 :                 eap1371_src_write(sc, ESRC_DAC1_VOLR, ESRC_SET_DAC_VOLI(1));
     643           0 :                 eap1371_src_write(sc, ESRC_DAC2 + ESRC_IREGS, ESRC_SET_VFI(16));
     644           0 :                 eap1371_src_write(sc, ESRC_DAC2 + ESRC_TRUNC_N, ESRC_SET_N(16));
     645           0 :                 eap1371_src_write(sc, ESRC_DAC2 + ESRC_VFF, 0);
     646           0 :                 eap1371_src_write(sc, ESRC_DAC2_VOLL, ESRC_SET_DAC_VOLI(1));
     647           0 :                 eap1371_src_write(sc, ESRC_DAC2_VOLR, ESRC_SET_DAC_VOLI(1));
     648           0 :                 EWRITE4(sc, E1371_SRC, 0);
     649             : 
     650             :                 /* Interrupt enable */
     651           0 :                 EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN);
     652             :         }
     653           0 : }
     654             : 
     655             : 
     656             : int
     657           0 : eap1371_attach_codec(void *sc_, struct ac97_codec_if *codec_if)
     658             : {
     659           0 :         struct eap_softc *sc = sc_;
     660             :         
     661           0 :         sc->codec_if = codec_if;
     662           0 :         return (0);
     663             : }
     664             : 
     665             : void
     666           0 : eap1371_reset_codec(void *sc_)
     667             : {
     668           0 :         struct eap_softc *sc = sc_;
     669             :         u_int32_t icsc;
     670             : 
     671           0 :         mtx_enter(&audio_lock);
     672           0 :         icsc = EREAD4(sc, EAP_ICSC);
     673           0 :         EWRITE4(sc, EAP_ICSC, icsc | E1371_SYNC_RES);
     674           0 :         delay(20);
     675           0 :         EWRITE4(sc, EAP_ICSC, icsc & ~E1371_SYNC_RES);
     676           0 :         delay(1);
     677           0 :         mtx_leave(&audio_lock);
     678             : 
     679             :         return;
     680           0 : }
     681             : 
     682             : int
     683           0 : eap_intr(void *p)
     684             : {
     685           0 :         struct eap_softc *sc = p;
     686             :         u_int32_t intr, sic;
     687             : 
     688           0 :         mtx_enter(&audio_lock);
     689           0 :         intr = EREAD4(sc, EAP_ICSS);
     690           0 :         if (!(intr & EAP_INTR)) {
     691           0 :                 mtx_leave(&audio_lock);
     692           0 :                 return (0);
     693             :         }
     694           0 :         sic = EREAD4(sc, EAP_SIC);
     695             :         DPRINTFN(5, ("eap_intr: ICSS=0x%08x, SIC=0x%08x\n", intr, sic));
     696           0 :         if (intr & EAP_I_ADC) {
     697             : #if 0
     698             :                 /*
     699             :                  * XXX This is a hack!
     700             :                  * The EAP chip sometimes generates the recording interrupt
     701             :                  * while it is still transferring the data.  To make sure
     702             :                  * it has all arrived we busy wait until the count is right.
     703             :                  * The transfer we are waiting for is 8 longwords.
     704             :                  */
     705             :                 int s, nw, n;
     706             : 
     707             :                 EWRITE4(sc, EAP_MEMPAGE, EAP_ADC_PAGE);
     708             :                 s = EREAD4(sc, EAP_ADC_CSR);
     709             :                 nw = ((s & 0xffff) + 1) >> 2; /* # of words in DMA */
     710             :                 n = 0;
     711             :                 while (((EREAD4(sc, EAP_ADC_SIZE) >> 16) + 8) % nw == 0) {
     712             :                         delay(10);
     713             :                         if (++n > 100) {
     714             :                                 printf("eapintr: dma fix timeout");
     715             :                                 break;
     716             :                         }
     717             :                 }
     718             :                 /* Continue with normal interrupt handling. */
     719             : #endif
     720           0 :                 EWRITE4(sc, EAP_SIC, sic & ~EAP_R1_INTR_EN);
     721           0 :                 EWRITE4(sc, EAP_SIC, sic | EAP_R1_INTR_EN);
     722           0 :                 if (sc->sc_rintr)
     723           0 :                         sc->sc_rintr(sc->sc_rarg);
     724             :         }
     725           0 :         if (intr & EAP_I_DAC2) {
     726           0 :                 EWRITE4(sc, EAP_SIC, sic & ~EAP_P2_INTR_EN);
     727           0 :                 EWRITE4(sc, EAP_SIC, sic | EAP_P2_INTR_EN);
     728           0 :                 if (sc->sc_pintr)
     729           0 :                         sc->sc_pintr(sc->sc_parg);
     730             :         }
     731             : #if NMIDI > 0
     732           0 :         if (intr & EAP_I_UART) {
     733             :                 u_int32_t data;
     734             : 
     735           0 :                 if (EREAD1(sc, EAP_UART_STATUS) & EAP_US_RXINT) {
     736           0 :                         while (EREAD1(sc, EAP_UART_STATUS) & EAP_US_RXRDY) {
     737           0 :                                 data = EREAD1(sc, EAP_UART_DATA);
     738           0 :                                 if (sc->sc_iintr)
     739           0 :                                         sc->sc_iintr(sc->sc_arg, data);
     740             :                         }
     741             :                 }
     742           0 :                 if (EREAD1(sc, EAP_UART_STATUS) & EAP_US_TXINT) {
     743           0 :                         sc->sc_uctrl &= ~EAP_UC_TXINTEN;
     744           0 :                         EWRITE1(sc, EAP_UART_CONTROL, sc->sc_uctrl);
     745           0 :                         if (sc->sc_ointr) 
     746           0 :                                 sc->sc_ointr(sc->sc_arg);
     747             :                 }
     748           0 :         }
     749             : #endif
     750           0 :         mtx_leave(&audio_lock);
     751           0 :         return (1);
     752           0 : }
     753             : 
     754             : int
     755           0 : eap_allocmem(struct eap_softc *sc, size_t size, size_t align, struct eap_dma *p)
     756             : {
     757             :         int error;
     758             : 
     759           0 :         p->size = size;
     760           0 :         error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
     761             :             p->segs, nitems(p->segs),
     762             :             &p->nsegs, BUS_DMA_NOWAIT);
     763           0 :         if (error)
     764           0 :                 return (error);
     765             : 
     766           0 :         error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
     767             :             &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
     768           0 :         if (error)
     769             :                 goto free;
     770             : 
     771           0 :         error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
     772             :             0, BUS_DMA_NOWAIT, &p->map);
     773           0 :         if (error)
     774             :                 goto unmap;
     775             : 
     776           0 :         error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
     777             :             BUS_DMA_NOWAIT);
     778           0 :         if (error)
     779             :                 goto destroy;
     780           0 :         return (0);
     781             : 
     782             : destroy:
     783           0 :         bus_dmamap_destroy(sc->sc_dmatag, p->map);
     784             : unmap:
     785           0 :         bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
     786             : free:
     787           0 :         bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
     788           0 :         return (error);
     789           0 : }
     790             : 
     791             : int
     792           0 : eap_freemem(struct eap_softc *sc, struct eap_dma *p)
     793             : {
     794           0 :         bus_dmamap_unload(sc->sc_dmatag, p->map);
     795           0 :         bus_dmamap_destroy(sc->sc_dmatag, p->map);
     796           0 :         bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
     797           0 :         bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
     798           0 :         return (0);
     799             : }
     800             : 
     801             : int
     802           0 : eap_open(void *addr, int flags)
     803             : {
     804           0 :         return (0);
     805             : }
     806             : 
     807             : /*
     808             :  * Close function is called at splaudio().
     809             :  */
     810             : void
     811           0 : eap_close(void *addr)
     812             : {
     813           0 :         struct eap_softc *sc = addr;
     814             :     
     815           0 :         eap_halt_output(sc);
     816           0 :         eap_halt_input(sc);
     817             : 
     818           0 :         sc->sc_pintr = 0;
     819           0 :         sc->sc_rintr = 0;
     820           0 : }
     821             : 
     822             : int
     823           0 : eap_set_params(void *addr, int setmode, int usemode,
     824             :     struct audio_params *play, struct audio_params *rec)
     825             : {
     826           0 :         struct eap_softc *sc = addr;
     827             :         struct audio_params *p;
     828             :         int mode;
     829             :         u_int32_t div;
     830             : 
     831             :         /*
     832             :          * The es1370 only has one clock, so make the sample rates match.
     833             :          */
     834           0 :         if (!sc->sc_1371) {
     835           0 :                 if (play->sample_rate != rec->sample_rate &&
     836           0 :                     usemode == (AUMODE_PLAY | AUMODE_RECORD)) {
     837           0 :                         if (setmode == AUMODE_PLAY) {
     838           0 :                                 rec->sample_rate = play->sample_rate;
     839           0 :                                 setmode |= AUMODE_RECORD;
     840           0 :                         } else if (setmode == AUMODE_RECORD) {
     841           0 :                                 play->sample_rate = rec->sample_rate;
     842           0 :                                 setmode |= AUMODE_PLAY;
     843             :                         } else
     844           0 :                                 return (EINVAL);
     845             :                 }
     846             :         }
     847             : 
     848           0 :         for (mode = AUMODE_RECORD; mode != -1;
     849           0 :             mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
     850           0 :                 if ((setmode & mode) == 0)
     851             :                         continue;
     852             : 
     853           0 :                 p = mode == AUMODE_PLAY ? play : rec;
     854             : 
     855           0 :                 if (sc->sc_1371)
     856           0 :                         p->sample_rate = 48000;
     857           0 :                 if (p->sample_rate < 4000)
     858           0 :                         p->sample_rate = 4000;
     859           0 :                 if (p->sample_rate > 48000)
     860           0 :                         p->sample_rate = 48000;
     861           0 :                 if (p->precision > 16)
     862           0 :                         p->precision = 16;
     863           0 :                 if (p->channels > 2)
     864           0 :                         p->channels = 2;
     865           0 :                 switch (p->encoding) {
     866             :                 case AUDIO_ENCODING_SLINEAR_LE:
     867           0 :                         if (p->precision != 16)
     868           0 :                                 return EINVAL;
     869             :                         break;
     870             :                 case AUDIO_ENCODING_ULINEAR_LE:
     871             :                 case AUDIO_ENCODING_ULINEAR_BE:
     872           0 :                         if (p->precision != 8)
     873           0 :                                 return EINVAL;
     874             :                 default:
     875           0 :                         return (EINVAL);
     876             :                 }
     877           0 :                 p->bps = AUDIO_BPS(p->precision);
     878           0 :                 p->msb = 1;
     879           0 :         }
     880             : 
     881           0 :         if (!sc->sc_1371) {
     882             :                 /* Set the speed */
     883             :                 DPRINTFN(2, ("eap_set_params: old ICSC = 0x%08x\n",
     884             :                     EREAD4(sc, EAP_ICSC)));
     885           0 :                 div = EREAD4(sc, EAP_ICSC) & ~EAP_PCLKBITS;
     886             :                 /*
     887             :                  * XXX
     888             :                  * The -2 isn't documented, but seemed to make the wall
     889             :                  * time match
     890             :                  * what I expect.  - mycroft
     891             :                  */
     892           0 :                 if (usemode == AUMODE_RECORD)
     893           0 :                         div |= EAP_SET_PCLKDIV(EAP_XTAL_FREQ /
     894             :                             rec->sample_rate - 2);
     895             :                 else
     896           0 :                         div |= EAP_SET_PCLKDIV(EAP_XTAL_FREQ /
     897             :                             play->sample_rate - 2);
     898           0 :                 div |= EAP_CCB_INTRM;
     899           0 :                 EWRITE4(sc, EAP_ICSC, div);
     900             :                 DPRINTFN(2, ("eap_set_params: set ICSC = 0x%08x\n", div));
     901           0 :         }
     902             : 
     903           0 :         return (0);
     904           0 : }
     905             : 
     906             : int
     907           0 : eap_round_blocksize(void *addr, int blk)
     908             : {
     909           0 :         return ((blk + 31) & -32);  /* keep good alignment */
     910             : }
     911             : 
     912             : int
     913           0 : eap_trigger_output(
     914             :         void *addr,
     915             :         void *start,
     916             :         void *end,
     917             :         int blksize,
     918             :         void (*intr)(void *),
     919             :         void *arg,
     920             :         struct audio_params *param)
     921             : {
     922           0 :         struct eap_softc *sc = addr;
     923             :         struct eap_dma *p;
     924             :         u_int32_t icsc, sic;
     925             :         int sampshift;
     926             : 
     927             : #ifdef DIAGNOSTIC
     928           0 :         if (sc->sc_prun)
     929           0 :                 panic("eap_trigger_output: already running");
     930           0 :         sc->sc_prun = 1;
     931             : #endif
     932             : 
     933             :         DPRINTFN(1, ("eap_trigger_output: sc=%p start=%p end=%p "
     934             :             "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
     935           0 :         sc->sc_pintr = intr;
     936           0 :         sc->sc_parg = arg;
     937           0 :         mtx_enter(&audio_lock);
     938           0 :         sic = EREAD4(sc, EAP_SIC);
     939           0 :         sic &= ~(EAP_P2_S_EB | EAP_P2_S_MB | EAP_INC_BITS);
     940           0 :         sic |= EAP_SET_P2_ST_INC(0) | EAP_SET_P2_END_INC(param->precision / 8);
     941             :         sampshift = 0;
     942           0 :         if (param->precision == 16) {
     943           0 :                 sic |= EAP_P2_S_EB;
     944             :                 sampshift++;
     945           0 :         }
     946           0 :         if (param->channels == 2) {
     947           0 :                 sic |= EAP_P2_S_MB;
     948           0 :                 sampshift++;
     949           0 :         }
     950           0 :         EWRITE4(sc, EAP_SIC, sic & ~EAP_P2_INTR_EN);
     951           0 :         EWRITE4(sc, EAP_SIC, sic | EAP_P2_INTR_EN);
     952             : 
     953           0 :         for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next)
     954             :                 ;
     955           0 :         if (!p) {
     956           0 :                 mtx_leave(&audio_lock);
     957           0 :                 printf("eap_trigger_output: bad addr %p\n", start);
     958           0 :                 return (EINVAL);
     959             :         }
     960             : 
     961             :         DPRINTF(("eap_trigger_output: DAC2_ADDR=0x%x, DAC2_SIZE=0x%x\n",
     962             :             (int)DMAADDR(p),
     963             :             (int)EAP_SET_SIZE(0, (((char *)end - (char *)start) >> 2) - 1)));
     964           0 :         EWRITE4(sc, EAP_MEMPAGE, EAP_DAC_PAGE);
     965           0 :         EWRITE4(sc, EAP_DAC2_ADDR, DMAADDR(p));
     966           0 :         EWRITE4(sc, EAP_DAC2_SIZE,
     967             :             EAP_SET_SIZE(0, (((char *)end - (char *)start) >> 2) - 1));
     968             : 
     969           0 :         EWRITE4(sc, EAP_DAC2_CSR, (blksize >> sampshift) - 1);
     970             : 
     971           0 :         if (sc->sc_1371)
     972           0 :                 EWRITE4(sc, E1371_SRC, 0);
     973             : 
     974           0 :         icsc = EREAD4(sc, EAP_ICSC);
     975           0 :         EWRITE4(sc, EAP_ICSC, icsc | EAP_DAC2_EN);
     976             : 
     977             :         DPRINTFN(1, ("eap_trigger_output: set ICSC = 0x%08x\n", icsc));
     978           0 :         mtx_leave(&audio_lock);
     979           0 :         return (0);
     980           0 : }
     981             : 
     982             : int
     983           0 : eap_trigger_input(
     984             :         void *addr,
     985             :         void *start,
     986             :         void *end,
     987             :         int blksize,
     988             :         void (*intr)(void *),
     989             :         void *arg,
     990             :         struct audio_params *param)
     991             : {
     992           0 :         struct eap_softc *sc = addr;
     993             :         struct eap_dma *p;
     994             :         u_int32_t icsc, sic;
     995             :         int sampshift;
     996             : 
     997             : #ifdef DIAGNOSTIC
     998           0 :         if (sc->sc_rrun)
     999           0 :                 panic("eap_trigger_input: already running");
    1000           0 :         sc->sc_rrun = 1;
    1001             : #endif
    1002             : 
    1003             :         DPRINTFN(1, ("eap_trigger_input: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
    1004             :             addr, start, end, blksize, intr, arg));
    1005           0 :         sc->sc_rintr = intr;
    1006           0 :         sc->sc_rarg = arg;
    1007           0 :         mtx_enter(&audio_lock);
    1008           0 :         sic = EREAD4(sc, EAP_SIC);
    1009           0 :         sic &= ~(EAP_R1_S_EB | EAP_R1_S_MB);
    1010             :         sampshift = 0;
    1011           0 :         if (param->precision == 16) {
    1012           0 :                 sic |= EAP_R1_S_EB;
    1013             :                 sampshift++;
    1014           0 :         }
    1015           0 :         if (param->channels == 2) {
    1016           0 :                 sic |= EAP_R1_S_MB;
    1017           0 :                 sampshift++;
    1018           0 :         }
    1019           0 :         EWRITE4(sc, EAP_SIC, sic & ~EAP_R1_INTR_EN);
    1020           0 :         EWRITE4(sc, EAP_SIC, sic | EAP_R1_INTR_EN);
    1021             : 
    1022           0 :         for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next)
    1023             :                 ;
    1024           0 :         if (!p) {
    1025           0 :                 mtx_leave(&audio_lock);
    1026           0 :                 printf("eap_trigger_input: bad addr %p\n", start);
    1027           0 :                 return (EINVAL);
    1028             :         }
    1029             : 
    1030             :         DPRINTF(("eap_trigger_input: ADC_ADDR=0x%x, ADC_SIZE=0x%x\n",
    1031             :             (int)DMAADDR(p),
    1032             :             (int)EAP_SET_SIZE(0, (((char *)end - (char *)start) >> 2) - 1)));
    1033           0 :         EWRITE4(sc, EAP_MEMPAGE, EAP_ADC_PAGE);
    1034           0 :         EWRITE4(sc, EAP_ADC_ADDR, DMAADDR(p));
    1035           0 :         EWRITE4(sc, EAP_ADC_SIZE,
    1036             :             EAP_SET_SIZE(0, (((char *)end - (char *)start) >> 2) - 1));
    1037             : 
    1038           0 :         EWRITE4(sc, EAP_ADC_CSR, (blksize >> sampshift) - 1);
    1039             : 
    1040           0 :         if (sc->sc_1371)
    1041           0 :                 EWRITE4(sc, E1371_SRC, 0);
    1042             : 
    1043           0 :         icsc = EREAD4(sc, EAP_ICSC);
    1044           0 :         EWRITE4(sc, EAP_ICSC, icsc | EAP_ADC_EN);
    1045             : 
    1046             :         DPRINTFN(1, ("eap_trigger_input: set ICSC = 0x%08x\n", icsc));
    1047           0 :         mtx_leave(&audio_lock);
    1048           0 :         return (0);
    1049           0 : }
    1050             : 
    1051             : int
    1052           0 : eap_halt_output(void *addr)
    1053             : {
    1054           0 :         struct eap_softc *sc = addr;
    1055             :         u_int32_t icsc;
    1056             :         
    1057             :         DPRINTF(("eap: eap_halt_output\n"));
    1058           0 :         mtx_enter(&audio_lock);
    1059           0 :         icsc = EREAD4(sc, EAP_ICSC);
    1060           0 :         EWRITE4(sc, EAP_ICSC, icsc & ~EAP_DAC2_EN);
    1061             : #ifdef DIAGNOSTIC
    1062           0 :         sc->sc_prun = 0;
    1063             : #endif
    1064           0 :         mtx_leave(&audio_lock);
    1065           0 :         return (0);
    1066             : }
    1067             : 
    1068             : int
    1069           0 : eap_halt_input(void *addr)
    1070             : {
    1071           0 :         struct eap_softc *sc = addr;
    1072             :         u_int32_t icsc;
    1073             :     
    1074             :         DPRINTF(("eap: eap_halt_input\n"));
    1075           0 :         mtx_enter(&audio_lock);
    1076           0 :         icsc = EREAD4(sc, EAP_ICSC);
    1077           0 :         EWRITE4(sc, EAP_ICSC, icsc & ~EAP_ADC_EN);
    1078             : #ifdef DIAGNOSTIC
    1079           0 :         sc->sc_rrun = 0;
    1080             : #endif
    1081           0 :         mtx_leave(&audio_lock);
    1082           0 :         return (0);
    1083             : }
    1084             : 
    1085             : int
    1086           0 : eap1371_mixer_set_port(void *addr, mixer_ctrl_t *cp)
    1087             : {
    1088           0 :         struct eap_softc *sc = addr;
    1089             : 
    1090           0 :         return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp));
    1091             : }
    1092             : 
    1093             : int
    1094           0 : eap1371_mixer_get_port(void *addr, mixer_ctrl_t *cp)
    1095             : {
    1096           0 :         struct eap_softc *sc = addr;
    1097             : 
    1098           0 :         return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp));
    1099             : }
    1100             : 
    1101             : int
    1102           0 : eap1371_query_devinfo(void *addr, mixer_devinfo_t *dip)
    1103             : {
    1104           0 :         struct eap_softc *sc = addr;
    1105             : 
    1106           0 :         return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip));
    1107             : }
    1108             : 
    1109             : void
    1110           0 : eap1370_set_mixer(struct eap_softc *sc, int a, int d)
    1111             : {
    1112           0 :         eap1370_write_codec(sc, a, d);
    1113             : 
    1114           0 :         sc->sc_port[a] = d;
    1115             :         DPRINTFN(1, ("eap1370_mixer_set_port port 0x%02x = 0x%02x\n", a, d));
    1116           0 : }
    1117             : 
    1118             : int
    1119           0 : eap1370_mixer_set_port(void *addr, mixer_ctrl_t *cp)
    1120             : {
    1121           0 :         struct eap_softc *sc = addr;
    1122             :         int lval, rval, l, r, la, ra;
    1123             :         int l1, r1, l2, r2, m, o1, o2;
    1124             : 
    1125           0 :         if (cp->dev == EAP_RECORD_SOURCE) {
    1126           0 :                 if (cp->type != AUDIO_MIXER_SET)
    1127           0 :                         return (EINVAL);
    1128           0 :                 m = sc->sc_record_source = cp->un.mask;
    1129             :                 l1 = l2 = r1 = r2 = 0;
    1130           0 :                 if (m & (1 << EAP_VOICE_VOL))
    1131           0 :                         l2 |= AK_M_VOICE, r2 |= AK_M_VOICE;
    1132           0 :                 if (m & (1 << EAP_FM_VOL))
    1133           0 :                         l1 |= AK_M_FM_L, r1 |= AK_M_FM_R;
    1134           0 :                 if (m & (1 << EAP_CD_VOL))
    1135           0 :                         l1 |= AK_M_CD_L, r1 |= AK_M_CD_R;
    1136           0 :                 if (m & (1 << EAP_LINE_VOL))
    1137           0 :                         l1 |= AK_M_LINE_L, r1 |= AK_M_LINE_R;
    1138           0 :                 if (m & (1 << EAP_AUX_VOL))
    1139           0 :                         l2 |= AK_M2_AUX_L, r2 |= AK_M2_AUX_R;
    1140           0 :                 if (m & (1 << EAP_MIC_VOL))
    1141           0 :                         l2 |= AK_M_TMIC, r2 |= AK_M_TMIC;
    1142           0 :                 eap1370_set_mixer(sc, AK_IN_MIXER1_L, l1);
    1143           0 :                 eap1370_set_mixer(sc, AK_IN_MIXER1_R, r1);
    1144           0 :                 eap1370_set_mixer(sc, AK_IN_MIXER2_L, l2);
    1145           0 :                 eap1370_set_mixer(sc, AK_IN_MIXER2_R, r2);
    1146           0 :                 return (0);
    1147             :         }
    1148           0 :         if (cp->dev == EAP_INPUT_SOURCE) {
    1149           0 :                 if (cp->type != AUDIO_MIXER_SET)
    1150           0 :                         return (EINVAL);
    1151           0 :                 m = sc->sc_input_source = cp->un.mask;
    1152             :                 o1 = o2 = 0;
    1153           0 :                 if (m & (1 << EAP_VOICE_VOL))
    1154           0 :                         o2 |= AK_M_VOICE_L | AK_M_VOICE_R;
    1155           0 :                 if (m & (1 << EAP_FM_VOL))
    1156           0 :                         o1 |= AK_M_FM_L | AK_M_FM_R;
    1157           0 :                 if (m & (1 << EAP_CD_VOL))
    1158           0 :                         o1 |= AK_M_CD_L | AK_M_CD_R;
    1159           0 :                 if (m & (1 << EAP_LINE_VOL))
    1160           0 :                         o1 |= AK_M_LINE_L | AK_M_LINE_R;
    1161           0 :                 if (m & (1 << EAP_AUX_VOL))
    1162           0 :                         o2 |= AK_M_AUX_L | AK_M_AUX_R;
    1163           0 :                 if (m & (1 << EAP_MIC_VOL))
    1164           0 :                         o1 |= AK_M_MIC;
    1165           0 :                 eap1370_set_mixer(sc, AK_OUT_MIXER1, o1);
    1166           0 :                 eap1370_set_mixer(sc, AK_OUT_MIXER2, o2);
    1167           0 :                 return (0);
    1168             :         }
    1169           0 :         if (cp->dev == EAP_MIC_PREAMP) {
    1170           0 :                 if (cp->type != AUDIO_MIXER_ENUM)
    1171           0 :                         return (EINVAL);
    1172           0 :                 if (cp->un.ord != 0 && cp->un.ord != 1)
    1173           0 :                         return (EINVAL);
    1174           0 :                 sc->sc_mic_preamp = cp->un.ord;
    1175           0 :                 eap1370_set_mixer(sc, AK_MGAIN, cp->un.ord);
    1176           0 :                 return (0);
    1177             :         }
    1178           0 :         if (cp->type != AUDIO_MIXER_VALUE)
    1179           0 :                 return (EINVAL);
    1180           0 :         if (cp->un.value.num_channels == 1)
    1181           0 :                 lval = rval = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
    1182           0 :         else if (cp->un.value.num_channels == 2) {
    1183           0 :                 lval = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
    1184           0 :                 rval = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
    1185             :         } else
    1186           0 :                 return (EINVAL);
    1187             :         ra = -1;
    1188           0 :         switch (cp->dev) {
    1189             :         case EAP_MASTER_VOL:
    1190           0 :                 l = VOL_TO_ATT5(lval);
    1191           0 :                 r = VOL_TO_ATT5(rval);
    1192             :                 la = AK_MASTER_L;
    1193             :                 ra = AK_MASTER_R;
    1194           0 :                 break;
    1195             :         case EAP_MIC_VOL:
    1196           0 :                 if (cp->un.value.num_channels != 1)
    1197           0 :                         return (EINVAL);
    1198             :                 la = AK_MIC;
    1199           0 :                 goto lr;
    1200             :         case EAP_VOICE_VOL:
    1201             :                 la = AK_VOICE_L;
    1202             :                 ra = AK_VOICE_R;
    1203           0 :                 goto lr;
    1204             :         case EAP_FM_VOL:
    1205             :                 la = AK_FM_L;
    1206             :                 ra = AK_FM_R;
    1207           0 :                 goto lr;
    1208             :         case EAP_CD_VOL:
    1209             :                 la = AK_CD_L;
    1210             :                 ra = AK_CD_R;
    1211           0 :                 goto lr;
    1212             :         case EAP_LINE_VOL:
    1213             :                 la = AK_LINE_L;
    1214             :                 ra = AK_LINE_R;
    1215           0 :                 goto lr;
    1216             :         case EAP_AUX_VOL:
    1217             :                 la = AK_AUX_L;
    1218           0 :                 ra = AK_AUX_R;
    1219             :         lr:
    1220           0 :                 l = VOL_TO_GAIN5(lval);
    1221           0 :                 r = VOL_TO_GAIN5(rval);
    1222           0 :                 break;
    1223             :         default:
    1224           0 :                 return (EINVAL);
    1225             :         }
    1226           0 :         eap1370_set_mixer(sc, la, l);
    1227           0 :         if (ra >= 0) {
    1228           0 :                 eap1370_set_mixer(sc, ra, r);
    1229           0 :         }
    1230           0 :         return (0);
    1231           0 : }
    1232             : 
    1233             : int
    1234           0 : eap1370_mixer_get_port(void *addr, mixer_ctrl_t *cp)
    1235             : {
    1236           0 :         struct eap_softc *sc = addr;
    1237             :         int la, ra, l, r;
    1238             : 
    1239           0 :         switch (cp->dev) {
    1240             :         case EAP_RECORD_SOURCE:
    1241           0 :                 if (cp->type != AUDIO_MIXER_SET)
    1242           0 :                         return (EINVAL);
    1243           0 :                 cp->un.mask = sc->sc_record_source;
    1244           0 :                 return (0);
    1245             :         case EAP_INPUT_SOURCE:
    1246           0 :                 if (cp->type != AUDIO_MIXER_SET)
    1247           0 :                         return (EINVAL);
    1248           0 :                 cp->un.mask = sc->sc_input_source;
    1249           0 :                 return (0);
    1250             :         case EAP_MIC_PREAMP:
    1251           0 :                 if (cp->type != AUDIO_MIXER_ENUM)
    1252           0 :                         return (EINVAL);
    1253           0 :                 cp->un.ord = sc->sc_mic_preamp;
    1254           0 :                 return (0);
    1255             :         case EAP_MASTER_VOL:
    1256           0 :                 l = ATT5_TO_VOL(sc->sc_port[AK_MASTER_L]);
    1257           0 :                 r = ATT5_TO_VOL(sc->sc_port[AK_MASTER_R]);
    1258           0 :                 break;
    1259             :         case EAP_MIC_VOL:
    1260           0 :                 if (cp->un.value.num_channels != 1)
    1261           0 :                         return (EINVAL);
    1262             :                 la = ra = AK_MIC;
    1263           0 :                 goto lr;
    1264             :         case EAP_VOICE_VOL:
    1265             :                 la = AK_VOICE_L;
    1266             :                 ra = AK_VOICE_R;
    1267           0 :                 goto lr;
    1268             :         case EAP_FM_VOL:
    1269             :                 la = AK_FM_L;
    1270             :                 ra = AK_FM_R;
    1271           0 :                 goto lr;
    1272             :         case EAP_CD_VOL:
    1273             :                 la = AK_CD_L;
    1274             :                 ra = AK_CD_R;
    1275           0 :                 goto lr;
    1276             :         case EAP_LINE_VOL:
    1277             :                 la = AK_LINE_L;
    1278             :                 ra = AK_LINE_R;
    1279           0 :                 goto lr;
    1280             :         case EAP_AUX_VOL:
    1281             :                 la = AK_AUX_L;
    1282           0 :                 ra = AK_AUX_R;
    1283             :         lr:
    1284           0 :                 l = GAIN5_TO_VOL(sc->sc_port[la]);
    1285           0 :                 r = GAIN5_TO_VOL(sc->sc_port[ra]);
    1286           0 :                 break;
    1287             :         default:
    1288           0 :                 return (EINVAL);
    1289             :         }
    1290           0 :         if (cp->un.value.num_channels == 1)
    1291           0 :                 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = (l+r) / 2;
    1292           0 :         else if (cp->un.value.num_channels == 2) {
    1293           0 :                 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]  = l;
    1294           0 :                 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
    1295             :         } else
    1296           0 :                 return (EINVAL);
    1297           0 :         return (0);
    1298           0 : }
    1299             : 
    1300             : int
    1301           0 : eap1370_query_devinfo(void *addr, mixer_devinfo_t *dip)
    1302             : {
    1303           0 :         switch (dip->index) {
    1304             :         case EAP_MASTER_VOL:
    1305           0 :                 dip->type = AUDIO_MIXER_VALUE;
    1306           0 :                 dip->mixer_class = EAP_OUTPUT_CLASS;
    1307           0 :                 dip->prev = dip->next = AUDIO_MIXER_LAST;
    1308           0 :                 strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
    1309           0 :                 dip->un.v.num_channels = 2;
    1310           0 :                 strlcpy(dip->un.v.units.name, AudioNvolume,
    1311             :                     sizeof dip->un.v.units.name);
    1312           0 :                 return (0);
    1313             :         case EAP_VOICE_VOL:
    1314           0 :                 dip->type = AUDIO_MIXER_VALUE;
    1315           0 :                 dip->mixer_class = EAP_INPUT_CLASS;
    1316           0 :                 dip->prev = AUDIO_MIXER_LAST;
    1317           0 :                 dip->next = AUDIO_MIXER_LAST;
    1318           0 :                 strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
    1319           0 :                 dip->un.v.num_channels = 2;
    1320           0 :                 strlcpy(dip->un.v.units.name, AudioNvolume,
    1321             :                     sizeof dip->un.v.units.name);
    1322           0 :                 return (0);
    1323             :         case EAP_FM_VOL:
    1324           0 :                 dip->type = AUDIO_MIXER_VALUE;
    1325           0 :                 dip->mixer_class = EAP_INPUT_CLASS;
    1326           0 :                 dip->prev = AUDIO_MIXER_LAST;
    1327           0 :                 dip->next = AUDIO_MIXER_LAST;
    1328           0 :                 strlcpy(dip->label.name, AudioNfmsynth,
    1329             :                     sizeof dip->label.name);
    1330           0 :                 dip->un.v.num_channels = 2;
    1331           0 :                 strlcpy(dip->un.v.units.name, AudioNvolume,
    1332             :                     sizeof dip->un.v.units.name);
    1333           0 :                 return (0);
    1334             :         case EAP_CD_VOL:
    1335           0 :                 dip->type = AUDIO_MIXER_VALUE;
    1336           0 :                 dip->mixer_class = EAP_INPUT_CLASS;
    1337           0 :                 dip->prev = AUDIO_MIXER_LAST;
    1338           0 :                 dip->next = AUDIO_MIXER_LAST;
    1339           0 :                 strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
    1340           0 :                 dip->un.v.num_channels = 2;
    1341           0 :                 strlcpy(dip->un.v.units.name, AudioNvolume,
    1342             :                     sizeof dip->un.v.units.name);
    1343           0 :                 return (0);
    1344             :         case EAP_LINE_VOL:
    1345           0 :                 dip->type = AUDIO_MIXER_VALUE;
    1346           0 :                 dip->mixer_class = EAP_INPUT_CLASS;
    1347           0 :                 dip->prev = AUDIO_MIXER_LAST;
    1348           0 :                 dip->next = AUDIO_MIXER_LAST;
    1349           0 :                 strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
    1350           0 :                 dip->un.v.num_channels = 2;
    1351           0 :                 strlcpy(dip->un.v.units.name, AudioNvolume,
    1352             :                     sizeof dip->un.v.units.name);
    1353           0 :                 return (0);
    1354             :         case EAP_AUX_VOL:
    1355           0 :                 dip->type = AUDIO_MIXER_VALUE;
    1356           0 :                 dip->mixer_class = EAP_INPUT_CLASS;
    1357           0 :                 dip->prev = AUDIO_MIXER_LAST;
    1358           0 :                 dip->next = AUDIO_MIXER_LAST;
    1359           0 :                 strlcpy(dip->label.name, AudioNaux, sizeof dip->label.name);
    1360           0 :                 dip->un.v.num_channels = 2;
    1361           0 :                 strlcpy(dip->un.v.units.name, AudioNvolume,
    1362             :                     sizeof dip->un.v.units.name);
    1363           0 :                 return (0);
    1364             :         case EAP_MIC_VOL:
    1365           0 :                 dip->type = AUDIO_MIXER_VALUE;
    1366           0 :                 dip->mixer_class = EAP_INPUT_CLASS;
    1367           0 :                 dip->prev = AUDIO_MIXER_LAST;
    1368           0 :                 dip->next = EAP_MIC_PREAMP;
    1369           0 :                 strlcpy(dip->label.name, AudioNmicrophone,
    1370             :                     sizeof dip->label.name);
    1371           0 :                 dip->un.v.num_channels = 1;
    1372           0 :                 strlcpy(dip->un.v.units.name, AudioNvolume,
    1373             :                     sizeof dip->un.v.units.name);
    1374           0 :                 return (0);
    1375             :         case EAP_RECORD_SOURCE:
    1376           0 :                 dip->mixer_class = EAP_RECORD_CLASS;
    1377           0 :                 dip->prev = dip->next = AUDIO_MIXER_LAST;
    1378           0 :                 strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
    1379           0 :                 dip->type = AUDIO_MIXER_SET;
    1380           0 :                 dip->un.s.num_mem = 6;
    1381           0 :                 strlcpy(dip->un.s.member[0].label.name, AudioNmicrophone,
    1382             :                     sizeof dip->un.s.member[0].label.name);
    1383           0 :                 dip->un.s.member[0].mask = 1 << EAP_MIC_VOL;
    1384           0 :                 strlcpy(dip->un.s.member[1].label.name, AudioNcd,
    1385             :                     sizeof dip->un.s.member[1].label.name);
    1386           0 :                 dip->un.s.member[1].mask = 1 << EAP_CD_VOL;
    1387           0 :                 strlcpy(dip->un.s.member[2].label.name, AudioNline,
    1388             :                     sizeof dip->un.s.member[2].label.name);
    1389           0 :                 dip->un.s.member[2].mask = 1 << EAP_LINE_VOL;
    1390           0 :                 strlcpy(dip->un.s.member[3].label.name, AudioNfmsynth,
    1391             :                     sizeof dip->un.s.member[3].label.name);
    1392           0 :                 dip->un.s.member[3].mask = 1 << EAP_FM_VOL;
    1393           0 :                 strlcpy(dip->un.s.member[4].label.name, AudioNaux,
    1394             :                     sizeof dip->un.s.member[4].label.name);
    1395           0 :                 dip->un.s.member[4].mask = 1 << EAP_AUX_VOL;
    1396           0 :                 strlcpy(dip->un.s.member[5].label.name, AudioNdac,
    1397             :                     sizeof dip->un.s.member[5].label.name);
    1398           0 :                 dip->un.s.member[5].mask = 1 << EAP_VOICE_VOL;
    1399           0 :                 return (0);
    1400             :         case EAP_INPUT_SOURCE:
    1401           0 :                 dip->mixer_class = EAP_INPUT_CLASS;
    1402           0 :                 dip->prev = dip->next = AUDIO_MIXER_LAST;
    1403           0 :                 strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
    1404           0 :                 dip->type = AUDIO_MIXER_SET;
    1405           0 :                 dip->un.s.num_mem = 6;
    1406           0 :                 strlcpy(dip->un.s.member[0].label.name, AudioNmicrophone,
    1407             :                     sizeof dip->un.s.member[0].label.name);
    1408           0 :                 dip->un.s.member[0].mask = 1 << EAP_MIC_VOL;
    1409           0 :                 strlcpy(dip->un.s.member[1].label.name, AudioNcd,
    1410             :                     sizeof dip->un.s.member[1].label.name);
    1411           0 :                 dip->un.s.member[1].mask = 1 << EAP_CD_VOL;
    1412           0 :                 strlcpy(dip->un.s.member[2].label.name, AudioNline,
    1413             :                     sizeof dip->un.s.member[2].label.name);
    1414           0 :                 dip->un.s.member[2].mask = 1 << EAP_LINE_VOL;
    1415           0 :                 strlcpy(dip->un.s.member[3].label.name, AudioNfmsynth,
    1416             :                     sizeof dip->un.s.member[3].label.name);
    1417           0 :                 dip->un.s.member[3].mask = 1 << EAP_FM_VOL;
    1418           0 :                 strlcpy(dip->un.s.member[4].label.name, AudioNaux,
    1419             :                     sizeof dip->un.s.member[4].label.name);
    1420           0 :                 dip->un.s.member[4].mask = 1 << EAP_AUX_VOL;
    1421           0 :                 strlcpy(dip->un.s.member[5].label.name, AudioNdac,
    1422             :                     sizeof dip->un.s.member[5].label.name);
    1423           0 :                 dip->un.s.member[5].mask = 1 << EAP_VOICE_VOL;
    1424           0 :                 return (0);
    1425             :         case EAP_MIC_PREAMP:
    1426           0 :                 dip->type = AUDIO_MIXER_ENUM;
    1427           0 :                 dip->mixer_class = EAP_INPUT_CLASS;
    1428           0 :                 dip->prev = EAP_MIC_VOL;
    1429           0 :                 dip->next = AUDIO_MIXER_LAST;
    1430           0 :                 strlcpy(dip->label.name, AudioNpreamp, sizeof dip->label.name);
    1431           0 :                 dip->un.e.num_mem = 2;
    1432           0 :                 strlcpy(dip->un.e.member[0].label.name, AudioNoff,
    1433             :                     sizeof dip->un.e.member[0].label.name);
    1434           0 :                 dip->un.e.member[0].ord = 0;
    1435           0 :                 strlcpy(dip->un.e.member[1].label.name, AudioNon,
    1436             :                     sizeof dip->un.e.member[1].label.name);
    1437           0 :                 dip->un.e.member[1].ord = 1;
    1438           0 :                 return (0);
    1439             :         case EAP_OUTPUT_CLASS:
    1440           0 :                 dip->type = AUDIO_MIXER_CLASS;
    1441           0 :                 dip->mixer_class = EAP_OUTPUT_CLASS;
    1442           0 :                 dip->next = dip->prev = AUDIO_MIXER_LAST;
    1443           0 :                 strlcpy(dip->label.name, AudioCoutputs,
    1444             :                     sizeof dip->label.name);
    1445           0 :                 return (0);
    1446             :         case EAP_RECORD_CLASS:
    1447           0 :                 dip->type = AUDIO_MIXER_CLASS;
    1448           0 :                 dip->mixer_class = EAP_RECORD_CLASS;
    1449           0 :                 dip->next = dip->prev = AUDIO_MIXER_LAST;
    1450           0 :                 strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
    1451           0 :                 return (0);
    1452             :         case EAP_INPUT_CLASS:
    1453           0 :                 dip->type = AUDIO_MIXER_CLASS;
    1454           0 :                 dip->mixer_class = EAP_INPUT_CLASS;
    1455           0 :                 dip->next = dip->prev = AUDIO_MIXER_LAST;
    1456           0 :                 strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
    1457           0 :                 return (0);
    1458             :         }
    1459           0 :         return (ENXIO);
    1460           0 : }
    1461             : 
    1462             : void *
    1463           0 : eap_malloc(void *addr, int direction, size_t size, int pool, int flags)
    1464             : {
    1465           0 :         struct eap_softc *sc = addr;
    1466             :         struct eap_dma *p;
    1467             :         int error;
    1468             : 
    1469           0 :         p = malloc(sizeof(*p), pool, flags);
    1470           0 :         if (!p)
    1471           0 :                 return (0);
    1472           0 :         error = eap_allocmem(sc, size, 16, p);
    1473           0 :         if (error) {
    1474           0 :                 free(p, pool, 0);
    1475           0 :                 return (0);
    1476             :         }
    1477           0 :         p->next = sc->sc_dmas;
    1478           0 :         sc->sc_dmas = p;
    1479           0 :         return (KERNADDR(p));
    1480           0 : }
    1481             : 
    1482             : void
    1483           0 : eap_free(void *addr, void *ptr, int pool)
    1484             : {
    1485           0 :         struct eap_softc *sc = addr;
    1486             :         struct eap_dma **pp, *p;
    1487             : 
    1488           0 :         for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
    1489           0 :                 if (KERNADDR(p) == ptr) {
    1490           0 :                         eap_freemem(sc, p);
    1491           0 :                         *pp = p->next;
    1492           0 :                         free(p, pool, 0);
    1493           0 :                         return;
    1494             :                 }
    1495             :         }
    1496           0 : }
    1497             : 
    1498             : int
    1499           0 : eap_get_props(void *addr)
    1500             : {
    1501           0 :         return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
    1502             :             AUDIO_PROP_FULLDUPLEX);
    1503             : }
    1504             : 
    1505             : enum ac97_host_flags
    1506           0 : eap_flags_codec(void *v)
    1507             : {
    1508           0 :       struct eap_softc *sc = v;
    1509             : 
    1510           0 :       return (sc->flags);
    1511             : }
    1512             : #if NMIDI > 0
    1513             : int
    1514           0 : eap_midi_open(void *addr, int flags,
    1515             :     void (*iintr)(void *, int),
    1516             :     void (*ointr)(void *),
    1517             :     void *arg)
    1518             : {
    1519           0 :         struct eap_softc *sc = addr;
    1520             : 
    1521           0 :         sc->sc_iintr = iintr;
    1522           0 :         sc->sc_ointr = ointr;
    1523           0 :         sc->sc_arg = arg;
    1524             : 
    1525           0 :         EWRITE4(sc, EAP_ICSC, EREAD4(sc, EAP_ICSC) | EAP_UART_EN);
    1526           0 :         sc->sc_uctrl = 0;
    1527           0 :         if (flags & FREAD)
    1528           0 :                 sc->sc_uctrl |= EAP_UC_RXINTEN;
    1529           0 :         EWRITE1(sc, EAP_UART_CONTROL, sc->sc_uctrl);
    1530             : 
    1531           0 :         return (0);
    1532             : }
    1533             : 
    1534             : void
    1535           0 : eap_midi_close(void *addr)
    1536             : {
    1537           0 :         struct eap_softc *sc = addr;
    1538             : 
    1539           0 :         tsleep(sc, PWAIT, "eapclm", hz/10); /* give uart a chance to drain */
    1540           0 :         EWRITE1(sc, EAP_UART_CONTROL, 0);
    1541           0 :         EWRITE4(sc, EAP_ICSC, EREAD4(sc, EAP_ICSC) & ~EAP_UART_EN);
    1542             : 
    1543           0 :         sc->sc_iintr = 0;
    1544           0 :         sc->sc_ointr = 0;
    1545           0 : }
    1546             : 
    1547             : int
    1548           0 : eap_midi_output(void *addr, int d)
    1549             : {
    1550           0 :         struct eap_softc *sc = addr;
    1551             : 
    1552           0 :         if (!(EREAD1(sc, EAP_UART_STATUS) & EAP_US_TXRDY))
    1553           0 :                 return 0;
    1554           0 :         EWRITE1(sc, EAP_UART_DATA, d);
    1555           0 :         sc->sc_uctrl |= EAP_UC_TXINTEN;
    1556           0 :         EWRITE1(sc, EAP_UART_CONTROL, sc->sc_uctrl);
    1557           0 :         return 1;
    1558           0 : }
    1559             : 
    1560             : void
    1561           0 : eap_midi_getinfo(void *addr, struct midi_info *mi)
    1562             : {
    1563           0 :         mi->name = "AudioPCI MIDI UART";
    1564           0 :         mi->props = MIDI_PROP_CAN_INPUT | MIDI_PROP_OUT_INTR;
    1565           0 : }
    1566             : 
    1567             : #endif

Generated by: LCOV version 1.13