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

          Line data    Source code
       1             : /*      $OpenBSD: auich.c,v 1.109 2018/09/14 08:45:46 miko Exp $        */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2000,2001 Michael Shalayeff
       5             :  * All rights reserved.
       6             :  *
       7             :  * Redistribution and use in source and binary forms, with or without
       8             :  * modification, are permitted provided that the following conditions
       9             :  * are met:
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  * 2. Redistributions in binary form must reproduce the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer in the
      14             :  *    documentation and/or other materials provided with the distribution.
      15             :  *
      16             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      17             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      18             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      19             :  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
      20             :  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
      21             :  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      22             :  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      23             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
      24             :  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
      25             :  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
      26             :  * THE POSSIBILITY OF SUCH DAMAGE.
      27             :  */
      28             : 
      29             : /*
      30             :  * AC'97 audio found on Intel 810/815/820/440MX chipsets.
      31             :  *      http://developer.intel.com/design/chipsets/datashts/290655.htm
      32             :  *      http://developer.intel.com/design/chipsets/manuals/298028.htm
      33             :  *      http://www.intel.com/design/chipsets/datashts/290714.htm
      34             :  *      http://www.intel.com/design/chipsets/datashts/290744.htm
      35             :  */
      36             : 
      37             : #include <sys/param.h>
      38             : #include <sys/systm.h>
      39             : #include <sys/malloc.h>
      40             : #include <sys/device.h>
      41             : 
      42             : #include <dev/pci/pcidevs.h>
      43             : #include <dev/pci/pcivar.h>
      44             : 
      45             : #include <sys/audioio.h>
      46             : #include <dev/audio_if.h>
      47             : 
      48             : #include <machine/bus.h>
      49             : 
      50             : #include <dev/ic/ac97.h>
      51             : 
      52             : /* 12.1.10 NAMBAR - native audio mixer base address register */
      53             : #define AUICH_NAMBAR    0x10
      54             : /* 12.1.11 NABMBAR - native audio bus mastering base address register */
      55             : #define AUICH_NABMBAR   0x14
      56             : #define AUICH_CFG       0x41
      57             : #define AUICH_CFG_IOSE  0x01
      58             : /* ICH4/ICH5/ICH6/ICH7 native audio mixer BAR */
      59             : #define AUICH_MMBAR     0x18
      60             : /* ICH4/ICH5/ICH6/ICH7 native bus mastering BAR */
      61             : #define AUICH_MBBAR     0x1c
      62             : #define AUICH_S2CR      0x10000000      /* tertiary codec ready */
      63             : 
      64             : /* table 12-3. native audio bus master control registers */
      65             : #define AUICH_BDBAR     0x00    /* 8-byte aligned address */
      66             : #define AUICH_CIV               0x04    /* 5 bits current index value */
      67             : #define AUICH_LVI               0x05    /* 5 bits last valid index value */
      68             : #define         AUICH_LVI_MASK  0x1f
      69             : #define AUICH_STS               0x06    /* 16 bits status */
      70             : #define         AUICH_FIFOE     0x10    /* fifo error */
      71             : #define         AUICH_BCIS      0x08    /* r- buf cmplt int sts; wr ack */
      72             : #define         AUICH_LVBCI     0x04    /* r- last valid bci, wr ack */
      73             : #define         AUICH_CELV      0x02    /* current equals last valid */
      74             : #define         AUICH_DCH       0x01    /* dma halted */
      75             : #define         AUICH_ISTS_BITS "\020\01dch\02celv\03lvbci\04bcis\05fifoe"
      76             : #define AUICH_PICB      0x08    /* 16 bits */
      77             : #define AUICH_PIV               0x0a    /* 5 bits prefetched index value */
      78             : #define AUICH_CTRL      0x0b    /* control */
      79             : #define         AUICH_IOCE      0x10    /* int on completion enable */
      80             : #define         AUICH_FEIE      0x08    /* fifo error int enable */
      81             : #define         AUICH_LVBIE     0x04    /* last valid buf int enable */
      82             : #define         AUICH_RR                0x02    /* 1 - reset regs */
      83             : #define         AUICH_RPBM      0x01    /* 1 - run, 0 - pause */
      84             : 
      85             : #define AUICH_PCMI      0x00
      86             : #define AUICH_PCMO      0x10
      87             : #define AUICH_MICI      0x20
      88             : 
      89             : #define AUICH_GCTRL     0x2c
      90             : #define         AUICH_SSM_78    0x40000000      /* S/PDIF slots 7 and 8 */
      91             : #define         AUICH_SSM_69    0x80000000      /* S/PDIF slots 6 and 9 */
      92             : #define         AUICH_SSM_1011  0xc0000000      /* S/PDIF slots 10 and 11 */
      93             : #define         AUICH_POM16     0x000000        /* PCM out precision 16bit */
      94             : #define         AUICH_POM20     0x400000        /* PCM out precision 20bit */
      95             : #define         AUICH_PCM246_MASK 0x300000
      96             : #define         AUICH_PCM2      0x000000        /* 2ch output */
      97             : #define         AUICH_PCM4      0x100000        /* 4ch output */
      98             : #define         AUICH_PCM6      0x200000        /* 6ch output */
      99             : #define         AUICH_SIS_PCM246_MASK 0x0000c0  /* SiS 7012 */
     100             : #define         AUICH_SIS_PCM2  0x000000        /* SiS 7012 2ch output */
     101             : #define         AUICH_SIS_PCM4  0x000040        /* SiS 7012 4ch output */
     102             : #define         AUICH_SIS_PCM6  0x000080        /* SiS 7012 6ch output */
     103             : #define         AUICH_S2RIE     0x40    /* int when tertiary codec resume */
     104             : #define         AUICH_SRIE      0x20    /* int when 2ndary codec resume */
     105             : #define         AUICH_PRIE      0x10    /* int when primary codec resume */
     106             : #define         AUICH_ACLSO     0x08    /* aclink shut off */
     107             : #define         AUICH_WRESET    0x04    /* warm reset */
     108             : #define         AUICH_CRESET    0x02    /* cold reset */
     109             : #define         AUICH_GIE               0x01    /* gpi int enable */
     110             : #define AUICH_GSTS      0x30
     111             : #define         AUICH_MD3               0x20000 /* pwr-dn semaphore for modem */
     112             : #define         AUICH_AD3               0x10000 /* pwr-dn semaphore for audio */
     113             : #define         AUICH_RCS               0x08000 /* read completion status */
     114             : #define         AUICH_B3S12     0x04000 /* bit 3 of slot 12 */
     115             : #define         AUICH_B2S12     0x02000 /* bit 2 of slot 12 */
     116             : #define         AUICH_B1S12     0x01000 /* bit 1 of slot 12 */
     117             : #define         AUICH_SRI               0x00800 /* secondary resume int */
     118             : #define         AUICH_PRI               0x00400 /* primary resume int */
     119             : #define         AUICH_SCR               0x00200 /* secondary codec ready */
     120             : #define         AUICH_PCR               0x00100 /* primary codec ready */
     121             : #define         AUICH_MINT      0x00080 /* mic in int */
     122             : #define         AUICH_POINT     0x00040 /* pcm out int */
     123             : #define         AUICH_PIINT     0x00020 /* pcm in int */
     124             : #define         AUICH_MOINT     0x00004 /* modem out int */
     125             : #define         AUICH_MIINT     0x00002 /* modem in int */
     126             : #define         AUICH_GSCI      0x00001 /* gpi status change */
     127             : #define         AUICH_GSTS_BITS "\020\01gsci\02miict\03moint\06piint\07point\010mint\011pcr\012scr\013pri\014sri\015b1s12\016b2s12\017b3s12\020rcs\021ad3\022md3"
     128             : #define AUICH_CAS               0x34    /* 1/8 bit */
     129             : #define AUICH_SEMATIMO          1000    /* us */
     130             : #define AUICH_RESETIMO          500000  /* us */
     131             : 
     132             : #define ICH_SIS_NV_CTL  0x4c    /* some SiS/NVIDIA register.  From Linux */
     133             : #define         ICH_SIS_CTL_UNMUTE      0x01    /* un-mute the output */
     134             : 
     135             : /*
     136             :  * There are 32 buffer descriptors.  Each can reference up to 2^16 16-bit
     137             :  * samples.
     138             :  */
     139             : #define AUICH_DMALIST_MAX       32
     140             : #define AUICH_DMASEG_MAX        (65536*2)
     141             : struct auich_dmalist {
     142             :         u_int32_t       base;
     143             :         u_int32_t       len;
     144             : #define AUICH_DMAF_IOC  0x80000000      /* 1-int on complete */
     145             : #define AUICH_DMAF_BUP  0x40000000      /* 0-retrans last, 1-transmit 0 */
     146             : };
     147             : 
     148             : #define AUICH_FIXED_RATE 48000
     149             : 
     150             : struct auich_dma {
     151             :         bus_dmamap_t map;
     152             :         caddr_t addr;
     153             :         bus_dma_segment_t segs[1];
     154             :         int nsegs;
     155             :         size_t size;
     156             : };
     157             : 
     158             : struct auich_cdata {
     159             :         struct auich_dmalist ic_dmalist_pcmo[AUICH_DMALIST_MAX];
     160             :         struct auich_dmalist ic_dmalist_pcmi[AUICH_DMALIST_MAX];
     161             :         struct auich_dmalist ic_dmalist_mici[AUICH_DMALIST_MAX];
     162             : };
     163             : 
     164             : #define AUICH_CDOFF(x)          offsetof(struct auich_cdata, x)
     165             : #define AUICH_PCMO_OFF(x)       AUICH_CDOFF(ic_dmalist_pcmo[(x)])
     166             : #define AUICH_PCMI_OFF(x)       AUICH_CDOFF(ic_dmalist_pcmi[(x)])
     167             : #define AUICH_MICI_OFF(x)       AUICH_CDOFF(ic_dmalist_mici[(x)])
     168             : 
     169             : struct auich_softc {
     170             :         struct device sc_dev;
     171             :         void *sc_ih;
     172             : 
     173             :         pcireg_t pci_id;
     174             :         bus_space_tag_t iot;
     175             :         bus_space_tag_t iot_mix;
     176             :         bus_space_handle_t mix_ioh;
     177             :         bus_space_handle_t aud_ioh;
     178             :         bus_dma_tag_t dmat;
     179             : 
     180             :         struct ac97_codec_if *codec_if;
     181             :         struct ac97_host_if host_if;
     182             :         int sc_spdif;
     183             : 
     184             :         /* dma scatter-gather buffer lists */
     185             : 
     186             :         bus_dmamap_t sc_cddmamap;
     187             : #define sc_cddma        sc_cddmamap->dm_segs[0].ds_addr
     188             : 
     189             :         struct auich_cdata *sc_cdata;
     190             : 
     191             :         struct auich_ring {
     192             :                 int qptr;
     193             :                 struct auich_dmalist *dmalist;
     194             : 
     195             :                 uint32_t start, p, end;
     196             :                 int blksize;
     197             : 
     198             :                 void (*intr)(void *);
     199             :                 void *arg;
     200             :                 int running;
     201             :                 size_t size;
     202             :                 uint32_t ap;
     203             :         } pcmo, pcmi, mici;
     204             : 
     205             :         struct auich_dma *sc_pdma;      /* play */
     206             :         struct auich_dma *sc_rdma;      /* record */
     207             :         struct auich_dma *sc_cdma;      /* calibrate */
     208             : 
     209             : #ifdef AUICH_DEBUG
     210             :         int pcmi_fifoe;
     211             :         int pcmo_fifoe;
     212             : #endif
     213             : 
     214             :         int suspend;
     215             :         u_int16_t ext_ctrl;
     216             :         int sc_sample_size;
     217             :         int sc_sts_reg;
     218             :         int sc_dmamap_flags;
     219             :         int sc_ignore_codecready;
     220             :         int flags;
     221             :         int sc_ac97rate;
     222             : 
     223             :         /* multi-channel control bits */
     224             :         int sc_pcm246_mask;
     225             :         int sc_pcm2;
     226             :         int sc_pcm4;
     227             :         int sc_pcm6;
     228             : 
     229             :         u_int last_rrate;
     230             :         u_int last_prate;
     231             :         u_int last_pchan;
     232             : };
     233             : 
     234             : #ifdef AUICH_DEBUG
     235             : #define DPRINTF(l,x)    do { if (auich_debug & (l)) printf x; } while(0)
     236             : int auich_debug = 0x0002;
     237             : #define AUICH_DEBUG_CODECIO     0x0001
     238             : #define AUICH_DEBUG_DMA         0x0002
     239             : #define AUICH_DEBUG_INTR        0x0004
     240             : #else
     241             : #define DPRINTF(x,y)    /* nothing */
     242             : #endif
     243             : 
     244             : struct cfdriver auich_cd = {
     245             :         NULL, "auich", DV_DULL
     246             : };
     247             : 
     248             : int  auich_match(struct device *, void *, void *);
     249             : void auich_attach(struct device *, struct device *, void *);
     250             : int  auich_intr(void *);
     251             : 
     252             : int auich_activate(struct device *, int);
     253             : 
     254             : struct cfattach auich_ca = {
     255             :         sizeof(struct auich_softc), auich_match, auich_attach,
     256             :         NULL, auich_activate
     257             : };
     258             : 
     259             : static const struct auich_devtype {
     260             :         int     vendor;
     261             :         int     product;
     262             :         int     options;
     263             :         char    name[8];
     264             : } auich_devices[] = {
     265             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_6300ESB_ACA,  0, "ESB" },
     266             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_6321ESB_ACA,  0, "ESB2" },
     267             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801AA_ACA,  0, "ICH" },
     268             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801AB_ACA,  0, "ICH0" },
     269             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801BA_ACA,  0, "ICH2" },
     270             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801CA_ACA,  0, "ICH3" },
     271             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801DB_ACA,  0, "ICH4" },
     272             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801EB_ACA,  0, "ICH5" },
     273             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801FB_ACA,  0, "ICH6" },
     274             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801GB_ACA,  0, "ICH7" },
     275             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82440MX_ACA,  0, "440MX" },
     276             :         { PCI_VENDOR_SIS,       PCI_PRODUCT_SIS_7012_ACA,       0, "SiS7012" },
     277             :         { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_NFORCE_ACA,  0, "nForce" },
     278             :         { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_NFORCE2_ACA, 0, "nForce2" },
     279             :         { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_NFORCE2_400_ACA,
     280             :             0, "nForce2" },
     281             :         { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_NFORCE3_ACA, 0, "nForce3" },
     282             :         { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_NFORCE3_250_ACA,
     283             :             0, "nForce3" },
     284             :         { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_NFORCE4_AC,  0, "nForce4" },
     285             :         { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_MCP04_AC97,  0, "MCP04" },
     286             :         { PCI_VENDOR_NVIDIA,    PCI_PRODUCT_NVIDIA_MCP51_ACA,   0, "MCP51" },
     287             :         { PCI_VENDOR_AMD,       PCI_PRODUCT_AMD_PBC768_ACA,     0, "AMD768" },
     288             :         { PCI_VENDOR_AMD,       PCI_PRODUCT_AMD_8111_ACA,       0, "AMD8111" },
     289             : };
     290             : 
     291             : int auich_open(void *, int);
     292             : void auich_close(void *);
     293             : int auich_set_params(void *, int, int, struct audio_params *,
     294             :     struct audio_params *);
     295             : int auich_round_blocksize(void *, int);
     296             : void auich_halt_pipe(struct auich_softc *, int, struct auich_ring *);
     297             : int auich_halt_output(void *);
     298             : int auich_halt_input(void *);
     299             : int auich_set_port(void *, mixer_ctrl_t *);
     300             : int auich_get_port(void *, mixer_ctrl_t *);
     301             : int auich_query_devinfo(void *, mixer_devinfo_t *);
     302             : void *auich_allocm(void *, int, size_t, int, int);
     303             : void auich_freem(void *, void *, int);
     304             : size_t auich_round_buffersize(void *, int, size_t);
     305             : int auich_get_props(void *);
     306             : void auich_trigger_pipe(struct auich_softc *, int, struct auich_ring *);
     307             : void auich_intr_pipe(struct auich_softc *, int, struct auich_ring *);
     308             : int auich_trigger_output(void *, void *, void *, int, void (*)(void *),
     309             :     void *, struct audio_params *);
     310             : int auich_trigger_input(void *, void *, void *, int, void (*)(void *),
     311             :     void *, struct audio_params *);
     312             : int auich_alloc_cdata(struct auich_softc *);
     313             : int auich_allocmem(struct auich_softc *, size_t, size_t, struct auich_dma *);
     314             : int auich_freemem(struct auich_softc *, struct auich_dma *);
     315             : 
     316             : void auich_resume(struct auich_softc *);
     317             : 
     318             : struct audio_hw_if auich_hw_if = {
     319             :         auich_open,
     320             :         auich_close,
     321             :         auich_set_params,
     322             :         auich_round_blocksize,
     323             :         NULL,                   /* commit_setting */
     324             :         NULL,                   /* init_output */
     325             :         NULL,                   /* init_input */
     326             :         NULL,                   /* start_output */
     327             :         NULL,                   /* start_input */
     328             :         auich_halt_output,
     329             :         auich_halt_input,
     330             :         NULL,                   /* speaker_ctl */
     331             :         NULL,                   /* getfd */
     332             :         auich_set_port,
     333             :         auich_get_port,
     334             :         auich_query_devinfo,
     335             :         auich_allocm,
     336             :         auich_freem,
     337             :         auich_round_buffersize,
     338             :         auich_get_props,
     339             :         auich_trigger_output,
     340             :         auich_trigger_input
     341             : };
     342             : 
     343             : int  auich_attach_codec(void *, struct ac97_codec_if *);
     344             : int  auich_read_codec(void *, u_int8_t, u_int16_t *);
     345             : int  auich_write_codec(void *, u_int8_t, u_int16_t);
     346             : void auich_reset_codec(void *);
     347             : enum ac97_host_flags auich_flags_codec(void *);
     348             : unsigned int auich_calibrate(struct auich_softc *);
     349             : void auich_spdif_event(void *, int);
     350             : 
     351             : int
     352           0 : auich_match(struct device *parent, void *match, void *aux)
     353             : {
     354           0 :         struct pci_attach_args *pa = aux;
     355             :         int i;
     356             : 
     357           0 :         for (i = nitems(auich_devices); i--;)
     358           0 :                 if (PCI_VENDOR(pa->pa_id) == auich_devices[i].vendor &&
     359           0 :                     PCI_PRODUCT(pa->pa_id) == auich_devices[i].product)
     360           0 :                         return 1;
     361             : 
     362           0 :         return 0;
     363           0 : }
     364             : 
     365             : void
     366           0 : auich_attach(struct device *parent, struct device *self, void *aux)
     367             : {
     368           0 :         struct auich_softc *sc = (struct auich_softc *)self;
     369           0 :         struct pci_attach_args *pa = aux;
     370           0 :         pci_intr_handle_t ih;
     371           0 :         bus_size_t mix_size, aud_size;
     372             :         pcireg_t csr;
     373             :         const char *intrstr;
     374             :         u_int32_t status;
     375             :         int i;
     376             : 
     377           0 :         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
     378           0 :             (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801DB_ACA ||
     379           0 :             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801EB_ACA ||
     380           0 :             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801FB_ACA ||
     381           0 :             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801GB_ACA)) {
     382             :                 /*
     383             :                  * Use native mode for ICH4/ICH5/ICH6/ICH7
     384             :                  */
     385           0 :                 if (pci_mapreg_map(pa, AUICH_MMBAR, PCI_MAPREG_TYPE_MEM, 0,
     386           0 :                     &sc->iot_mix, &sc->mix_ioh, NULL, &mix_size, 0)) {
     387           0 :                         csr = pci_conf_read(pa->pa_pc, pa->pa_tag, AUICH_CFG);
     388           0 :                         pci_conf_write(pa->pa_pc, pa->pa_tag, AUICH_CFG,
     389           0 :                             csr | AUICH_CFG_IOSE);
     390           0 :                         if (pci_mapreg_map(pa, AUICH_NAMBAR, PCI_MAPREG_TYPE_IO,
     391             :                             0, &sc->iot_mix, &sc->mix_ioh, NULL, &mix_size, 0)) {
     392           0 :                                 printf(": can't map codec mem/io space\n");
     393           0 :                                 return;
     394             :                         }
     395             :                 }
     396             : 
     397           0 :                 if (pci_mapreg_map(pa, AUICH_MBBAR, PCI_MAPREG_TYPE_MEM, 0,
     398           0 :                     &sc->iot, &sc->aud_ioh, NULL, &aud_size, 0)) {
     399           0 :                         csr = pci_conf_read(pa->pa_pc, pa->pa_tag, AUICH_CFG);
     400           0 :                         pci_conf_write(pa->pa_pc, pa->pa_tag, AUICH_CFG,
     401           0 :                             csr | AUICH_CFG_IOSE);
     402           0 :                         if (pci_mapreg_map(pa, AUICH_NABMBAR,
     403             :                             PCI_MAPREG_TYPE_IO, 0, &sc->iot,
     404             :                             &sc->aud_ioh, NULL, &aud_size, 0)) {
     405           0 :                                 printf(": can't map device mem/io space\n");
     406           0 :                                 bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
     407           0 :                                 return;
     408             :                         }
     409             :                 }
     410             :         } else {
     411           0 :                 if (pci_mapreg_map(pa, AUICH_NAMBAR, PCI_MAPREG_TYPE_IO,
     412           0 :                     0, &sc->iot_mix, &sc->mix_ioh, NULL, &mix_size, 0)) {
     413           0 :                         printf(": can't map codec i/o space\n");
     414           0 :                         return;
     415             :                 }
     416             : 
     417           0 :                 if (pci_mapreg_map(pa, AUICH_NABMBAR, PCI_MAPREG_TYPE_IO,
     418           0 :                     0, &sc->iot, &sc->aud_ioh, NULL, &aud_size, 0)) {
     419           0 :                         printf(": can't map device i/o space\n");
     420           0 :                         bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
     421           0 :                         return;
     422             :                 }
     423             :         }
     424           0 :         sc->dmat = pa->pa_dmat;
     425           0 :         sc->pci_id = pa->pa_id;
     426             : 
     427           0 :         if (pci_intr_map(pa, &ih)) {
     428           0 :                 printf(": can't map interrupt\n");
     429           0 :                 bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);
     430           0 :                 bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
     431           0 :                 return;
     432             :         }
     433           0 :         intrstr = pci_intr_string(pa->pa_pc, ih);
     434           0 :         sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO | IPL_MPSAFE,
     435           0 :             auich_intr, sc, sc->sc_dev.dv_xname);
     436           0 :         if (!sc->sc_ih) {
     437           0 :                 printf(": can't establish interrupt");
     438           0 :                 if (intrstr)
     439           0 :                         printf(" at %s", intrstr);
     440           0 :                 printf("\n");
     441           0 :                 bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);
     442           0 :                 bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
     443           0 :                 return;
     444             :         }
     445             : 
     446           0 :         for (i = nitems(auich_devices); i--;)
     447           0 :                 if (PCI_PRODUCT(pa->pa_id) == auich_devices[i].product)
     448             :                         break;
     449             : 
     450           0 :         printf(": %s, %s\n", intrstr, auich_devices[i].name);
     451             : 
     452             :         /* SiS 7012 needs special handling */
     453           0 :         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SIS &&
     454           0 :             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SIS_7012_ACA) {
     455           0 :                 sc->sc_sts_reg = AUICH_PICB;
     456           0 :                 sc->sc_sample_size = 1;
     457           0 :                 sc->sc_pcm246_mask = AUICH_SIS_PCM246_MASK;
     458           0 :                 sc->sc_pcm2 = AUICH_SIS_PCM2;
     459           0 :                 sc->sc_pcm4 = AUICH_SIS_PCM4;
     460           0 :                 sc->sc_pcm6 = AUICH_SIS_PCM6;
     461             :                 /* un-mute output */
     462           0 :                 bus_space_write_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL,
     463             :                     bus_space_read_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL) |
     464             :                     ICH_SIS_CTL_UNMUTE);
     465           0 :         } else {
     466           0 :                 sc->sc_sts_reg = AUICH_STS;
     467           0 :                 sc->sc_sample_size = 2;
     468           0 :                 sc->sc_pcm246_mask = AUICH_PCM246_MASK;
     469           0 :                 sc->sc_pcm2 = AUICH_PCM2;
     470           0 :                 sc->sc_pcm4 = AUICH_PCM4;
     471           0 :                 sc->sc_pcm6 = AUICH_PCM6;
     472             :         }
     473             : 
     474             :         /* Workaround for a 440MX B-stepping erratum */
     475           0 :         sc->sc_dmamap_flags = BUS_DMA_COHERENT;
     476           0 :         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
     477           0 :             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82440MX_ACA) {
     478           0 :                 sc->sc_dmamap_flags |= BUS_DMA_NOCACHE;
     479           0 :                 printf("%s: DMA bug workaround enabled\n", sc->sc_dev.dv_xname);
     480           0 :         }
     481             : 
     482             :         /* Set up DMA lists. */
     483           0 :         sc->pcmo.qptr = sc->pcmi.qptr = sc->mici.qptr = 0;
     484           0 :         auich_alloc_cdata(sc);
     485             : 
     486             :         DPRINTF(AUICH_DEBUG_DMA, ("auich_attach: lists %p %p %p\n",
     487             :             sc->pcmo.dmalist, sc->pcmi.dmalist, sc->mici.dmalist));
     488             : 
     489             :         /* Reset codec and AC'97 */
     490           0 :         auich_reset_codec(sc);
     491           0 :         status = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS);
     492           0 :         if (!(status & AUICH_PCR)) {        /* reset failure */
     493           0 :                 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
     494           0 :                     (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801DB_ACA ||
     495           0 :                      PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801EB_ACA ||
     496           0 :                      PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801FB_ACA ||
     497           0 :                      PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801GB_ACA)) {
     498             :                         /* MSI 845G Max never return AUICH_PCR */
     499           0 :                         sc->sc_ignore_codecready = 1;
     500             :                 } else {
     501           0 :                         printf("%s: reset failed!\n", sc->sc_dev.dv_xname);
     502           0 :                         return;
     503             :                 }
     504           0 :         }
     505             : 
     506           0 :         sc->host_if.arg = sc;
     507           0 :         sc->host_if.attach = auich_attach_codec;
     508           0 :         sc->host_if.read = auich_read_codec;
     509           0 :         sc->host_if.write = auich_write_codec;
     510           0 :         sc->host_if.reset = auich_reset_codec;
     511           0 :         sc->host_if.flags = auich_flags_codec;
     512           0 :         sc->host_if.spdif_event = auich_spdif_event;
     513           0 :         if (sc->sc_dev.dv_cfdata->cf_flags & 0x0001)
     514           0 :                 sc->flags = AC97_HOST_SWAPPED_CHANNELS;
     515             : 
     516           0 :         if (ac97_attach(&sc->host_if) != 0) {
     517           0 :                 pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
     518           0 :                 bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);
     519           0 :                 bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
     520           0 :                 return;
     521             :         }
     522           0 :         sc->codec_if->vtbl->unlock(sc->codec_if);
     523             : 
     524           0 :         audio_attach_mi(&auich_hw_if, sc, &sc->sc_dev);
     525             : 
     526             :         /* Watch for power changes */
     527           0 :         sc->suspend = DVACT_RESUME;
     528             : 
     529           0 :         sc->sc_ac97rate = -1;
     530           0 : }
     531             : 
     532             : int
     533           0 : auich_activate(struct device *self, int act)
     534             : {
     535           0 :         struct auich_softc *sc = (struct auich_softc *)self;
     536             : 
     537           0 :         switch (act) {
     538             :         case DVACT_RESUME:
     539           0 :                 auich_resume(sc);
     540           0 :                 break;
     541             :         default:
     542             :                 break;
     543             :         }
     544           0 :         return (config_activate_children(self, act));
     545             : }
     546             : 
     547             : int
     548           0 : auich_read_codec(void *v, u_int8_t reg, u_int16_t *val)
     549             : {
     550           0 :         struct auich_softc *sc = v;
     551             :         int i;
     552             : 
     553             :         /* wait for an access semaphore */
     554           0 :         for (i = AUICH_SEMATIMO; i-- &&
     555           0 :             bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1));
     556             : 
     557           0 :         if (!sc->sc_ignore_codecready && i < 0) {
     558             :                 DPRINTF(AUICH_DEBUG_CODECIO,
     559             :                     ("%s: read_codec timeout\n", sc->sc_dev.dv_xname));
     560           0 :                 return (-1);
     561             :         }
     562             : 
     563           0 :         *val = bus_space_read_2(sc->iot_mix, sc->mix_ioh, reg);
     564             :         DPRINTF(AUICH_DEBUG_CODECIO, ("%s: read_codec(%x, %x)\n",
     565             :             sc->sc_dev.dv_xname, reg, *val));
     566           0 :         return (0);
     567           0 : }
     568             : 
     569             : int
     570           0 : auich_write_codec(void *v, u_int8_t reg, u_int16_t val)
     571             : {
     572           0 :         struct auich_softc *sc = v;
     573             :         int i;
     574             : 
     575             :         /* wait for an access semaphore */
     576           0 :         for (i = AUICH_SEMATIMO; i-- &&
     577           0 :             bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1));
     578             : 
     579           0 :         if (sc->sc_ignore_codecready || i >= 0) {
     580             :                 DPRINTF(AUICH_DEBUG_CODECIO, ("%s: write_codec(%x, %x)\n",
     581             :                     sc->sc_dev.dv_xname, reg, val));
     582           0 :                 bus_space_write_2(sc->iot_mix, sc->mix_ioh, reg, val);
     583           0 :                 return (0);
     584             :         } else {
     585             :                 DPRINTF(AUICH_DEBUG_CODECIO,
     586             :                     ("%s: write_codec timeout\n", sc->sc_dev.dv_xname));
     587           0 :                 return (-1);
     588             :         }
     589           0 : }
     590             : 
     591             : int
     592           0 : auich_attach_codec(void *v, struct ac97_codec_if *cif)
     593             : {
     594           0 :         struct auich_softc *sc = v;
     595             : 
     596           0 :         sc->codec_if = cif;
     597           0 :         return 0;
     598             : }
     599             : 
     600             : void
     601           0 : auich_reset_codec(void *v)
     602             : {
     603           0 :         struct auich_softc *sc = v;
     604             :         u_int32_t control;
     605             :         int i;
     606             : 
     607           0 :         control = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GCTRL);
     608           0 :         control &= ~(AUICH_ACLSO | sc->sc_pcm246_mask);
     609           0 :         control |= (control & AUICH_CRESET) ? AUICH_WRESET : AUICH_CRESET;
     610           0 :         bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GCTRL, control);
     611             : 
     612           0 :         for (i = AUICH_RESETIMO; i-- &&
     613           0 :             !(bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS) & AUICH_PCR);
     614           0 :             DELAY(1));
     615             : 
     616             :         if (i < 0)
     617             :                 DPRINTF(AUICH_DEBUG_CODECIO,
     618             :                     ("%s: reset_codec timeout\n", sc->sc_dev.dv_xname));
     619           0 : }
     620             : 
     621             : enum ac97_host_flags
     622           0 : auich_flags_codec(void *v)
     623             : {
     624           0 :         struct auich_softc *sc = v;
     625             : 
     626           0 :         return (sc->flags);
     627             : }
     628             : 
     629             : void
     630           0 : auich_spdif_event(void *v, int flag)
     631             : {
     632           0 :         struct auich_softc *sc = v;
     633           0 :         sc->sc_spdif = flag;
     634           0 : }
     635             : 
     636             : int
     637           0 : auich_open(void *v, int flags)
     638             : {
     639           0 :         struct auich_softc *sc = v;
     640             : 
     641           0 :         if (sc->sc_ac97rate == -1)
     642           0 :                 sc->sc_ac97rate = auich_calibrate(sc);
     643             : 
     644           0 :         sc->codec_if->vtbl->lock(sc->codec_if);
     645             : 
     646           0 :         return 0;
     647             : }
     648             : 
     649             : void
     650           0 : auich_close(void *v)
     651             : {
     652           0 :         struct auich_softc *sc = v;
     653             : 
     654           0 :         sc->codec_if->vtbl->unlock(sc->codec_if);
     655           0 : }
     656             : 
     657             : int
     658           0 : auich_set_params(void *v, int setmode, int usemode,
     659             :     struct audio_params *play, struct audio_params *rec)
     660             : {
     661           0 :         struct auich_softc *sc = v;
     662           0 :         struct ac97_codec_if *codec = sc->codec_if;
     663             :         int error;
     664             :         u_int orate;
     665             :         u_int adj_rate;
     666             :         u_int32_t control;
     667             :         u_int16_t ext_id;
     668             : 
     669           0 :         if (setmode & AUMODE_PLAY) {
     670             :                 /* only 16-bit 48kHz slinear_le if s/pdif enabled */
     671           0 :                 if (sc->sc_spdif) {
     672           0 :                         play->sample_rate = 48000;
     673           0 :                         play->precision = 16;
     674           0 :                         play->encoding = AUDIO_ENCODING_SLINEAR_LE;
     675           0 :                 }
     676             :         }
     677           0 :         if (setmode & AUMODE_PLAY) {
     678           0 :                 play->precision = 16;
     679           0 :                 switch(play->encoding) {
     680             :                 case AUDIO_ENCODING_SLINEAR_LE:
     681           0 :                         if (play->channels > 6)
     682           0 :                                 play->channels = 6;
     683           0 :                         if (play->channels > 1)
     684           0 :                                 play->channels &= ~1;
     685           0 :                         switch (play->channels) {
     686             :                         case 1:
     687           0 :                                 play->channels = 2;
     688           0 :                                 break;
     689             :                         case 2:
     690             :                                 break;
     691             :                         case 4:
     692           0 :                                 ext_id = codec->vtbl->get_caps(codec);
     693           0 :                                 if (!(ext_id & AC97_EXT_AUDIO_SDAC))
     694           0 :                                         play->channels = 2;
     695             :                                 break;
     696             :                         case 6:
     697           0 :                                 ext_id = codec->vtbl->get_caps(codec);
     698           0 :                                 if ((ext_id & AC97_BITS_6CH) !=
     699             :                                     AC97_BITS_6CH)
     700           0 :                                         play->channels = 2;
     701             :                                 break;
     702             :                         default:
     703           0 :                                 return (EINVAL);
     704             :                         }
     705             :                         break;
     706             :                 default:
     707           0 :                         return (EINVAL);
     708             :                 }
     709           0 :                 play->bps = AUDIO_BPS(play->precision);
     710           0 :                 play->msb = 1;
     711             : 
     712           0 :                 orate = adj_rate = play->sample_rate;
     713           0 :                 if (sc->sc_ac97rate != 0)
     714           0 :                         adj_rate = orate * AUICH_FIXED_RATE / sc->sc_ac97rate;
     715             : 
     716           0 :                 play->sample_rate = adj_rate;
     717           0 :                 sc->last_prate = play->sample_rate;
     718             : 
     719           0 :                 error = ac97_set_rate(sc->codec_if,
     720             :                     AC97_REG_PCM_LFE_DAC_RATE, &play->sample_rate);
     721           0 :                 if (error)
     722           0 :                         return (error);
     723             : 
     724           0 :                 play->sample_rate = adj_rate;
     725           0 :                 error = ac97_set_rate(sc->codec_if,
     726             :                     AC97_REG_PCM_SURR_DAC_RATE, &play->sample_rate);
     727           0 :                 if (error)
     728           0 :                         return (error);
     729             : 
     730           0 :                 play->sample_rate = adj_rate;
     731           0 :                 error = ac97_set_rate(sc->codec_if,
     732             :                     AC97_REG_PCM_FRONT_DAC_RATE, &play->sample_rate);
     733           0 :                 if (error)
     734           0 :                         return (error);
     735             : 
     736           0 :                 if (play->sample_rate == adj_rate)
     737           0 :                         play->sample_rate = orate;
     738             : 
     739           0 :                 control = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GCTRL);
     740           0 :                 control &= ~(sc->sc_pcm246_mask);
     741           0 :                 if (play->channels == 4)
     742           0 :                         control |= sc->sc_pcm4;
     743           0 :                 else if (play->channels == 6)
     744           0 :                         control |= sc->sc_pcm6;
     745           0 :                 bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GCTRL, control);
     746             : 
     747           0 :                 sc->last_pchan = play->channels;
     748           0 :         }
     749             : 
     750           0 :         if (setmode & AUMODE_RECORD) {
     751           0 :                 rec->channels = 2;
     752           0 :                 rec->precision = 16;
     753           0 :                 rec->encoding = AUDIO_ENCODING_SLINEAR_LE;
     754           0 :                 rec->bps = AUDIO_BPS(rec->precision);
     755           0 :                 rec->msb = 1;
     756             : 
     757           0 :                 orate = rec->sample_rate;
     758           0 :                 if (sc->sc_ac97rate != 0)
     759           0 :                         rec->sample_rate = orate * AUICH_FIXED_RATE /
     760             :                             sc->sc_ac97rate;
     761           0 :                 sc->last_rrate = rec->sample_rate;
     762           0 :                 error = ac97_set_rate(sc->codec_if, AC97_REG_PCM_LR_ADC_RATE,
     763             :                     &rec->sample_rate);
     764           0 :                 if (error)
     765           0 :                         return (error);
     766           0 :                 rec->sample_rate = orate;
     767           0 :         }
     768             : 
     769           0 :         return (0);
     770           0 : }
     771             : 
     772             : int
     773           0 : auich_round_blocksize(void *v, int blk)
     774             : {
     775           0 :         return (blk + 0x3f) & ~0x3f;
     776             : }
     777             : 
     778             : 
     779             : void
     780           0 : auich_halt_pipe(struct auich_softc *sc, int pipe, struct auich_ring *ring)
     781             : {
     782             :         int i;
     783             :         uint32_t sts;
     784             : 
     785           0 :         bus_space_write_1(sc->iot, sc->aud_ioh, pipe + AUICH_CTRL, 0);
     786             : 
     787             :         /* wait for DMA halted and clear interrupt / event bits if needed */
     788           0 :         for (i = 0; i < 1000; i++) {
     789           0 :                 sts = bus_space_read_2(sc->iot, sc->aud_ioh,
     790             :                     pipe + sc->sc_sts_reg);
     791           0 :                 if (sts & (AUICH_CELV | AUICH_LVBCI | AUICH_BCIS | AUICH_FIFOE))
     792           0 :                         bus_space_write_2(sc->iot, sc->aud_ioh,
     793             :                             pipe + sc->sc_sts_reg,
     794             :                             AUICH_CELV | AUICH_LVBCI |
     795             :                             AUICH_BCIS | AUICH_FIFOE);
     796           0 :                 if (sts & AUICH_DCH)
     797             :                         break;
     798           0 :                 DELAY(100);
     799             :         }
     800           0 :         bus_space_write_1(sc->iot, sc->aud_ioh, pipe + AUICH_CTRL, AUICH_RR);
     801             : 
     802             :         if (i > 0)
     803             :                 DPRINTF(AUICH_DEBUG_DMA,
     804             :                     ("auich_halt_pipe: halt took %d cycles\n", i));
     805             : 
     806           0 :         ring->running = 0;
     807           0 : }
     808             : 
     809             : 
     810             : int
     811           0 : auich_halt_output(void *v)
     812             : {
     813           0 :         struct auich_softc *sc = v;
     814             : 
     815             :         DPRINTF(AUICH_DEBUG_DMA, ("%s: halt_output\n", sc->sc_dev.dv_xname));
     816             : 
     817           0 :         mtx_enter(&audio_lock);
     818           0 :         auich_halt_pipe(sc, AUICH_PCMO, &sc->pcmo);
     819             : 
     820           0 :         sc->pcmo.intr = NULL;
     821           0 :         mtx_leave(&audio_lock);
     822           0 :         return 0;
     823             : }
     824             : 
     825             : int
     826           0 : auich_halt_input(void *v)
     827             : {
     828           0 :         struct auich_softc *sc = v;
     829             : 
     830             :         DPRINTF(AUICH_DEBUG_DMA,
     831             :             ("%s: halt_input\n", sc->sc_dev.dv_xname));
     832             : 
     833             :         /* XXX halt both unless known otherwise */
     834           0 :         mtx_enter(&audio_lock);
     835           0 :         auich_halt_pipe(sc, AUICH_PCMI, &sc->pcmi);
     836           0 :         auich_halt_pipe(sc, AUICH_MICI, &sc->mici);
     837             : 
     838           0 :         sc->pcmi.intr = NULL;
     839           0 :         mtx_leave(&audio_lock);
     840           0 :         return 0;
     841             : }
     842             : 
     843             : int
     844           0 : auich_set_port(void *v, mixer_ctrl_t *cp)
     845             : {
     846           0 :         struct auich_softc *sc = v;
     847           0 :         return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
     848             : }
     849             : 
     850             : int
     851           0 : auich_get_port(void *v, mixer_ctrl_t *cp)
     852             : {
     853           0 :         struct auich_softc *sc = v;
     854           0 :         return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp);
     855             : }
     856             : 
     857             : int
     858           0 : auich_query_devinfo(void *v, mixer_devinfo_t *dp)
     859             : {
     860           0 :         struct auich_softc *sc = v;
     861           0 :         return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dp);
     862             : }
     863             : 
     864             : void *
     865           0 : auich_allocm(void *v, int direction, size_t size, int pool, int flags)
     866             : {
     867           0 :         struct auich_softc *sc = v;
     868             :         struct auich_dma *p;
     869             :         int error;
     870             : 
     871             :         /* can only use 1 segment */
     872           0 :         if (size > AUICH_DMASEG_MAX) {
     873             :                 DPRINTF(AUICH_DEBUG_DMA,
     874             :                     ("%s: requested buffer size too large: %zd", \
     875             :                     sc->sc_dev.dv_xname, size));
     876           0 :                 return NULL;
     877             :         }
     878             : 
     879           0 :         p = malloc(sizeof(*p), pool, flags | M_ZERO);
     880           0 :         if (!p)
     881           0 :                 return NULL;
     882             : 
     883           0 :         error = auich_allocmem(sc, size, PAGE_SIZE, p);
     884           0 :         if (error) {
     885           0 :                 free(p, pool, 0);
     886           0 :                 return NULL;
     887             :         }
     888             : 
     889           0 :         if (direction == AUMODE_PLAY)
     890           0 :                 sc->sc_pdma = p;
     891           0 :         else if (direction == AUMODE_RECORD)
     892           0 :                 sc->sc_rdma = p;
     893             :         else
     894           0 :                 sc->sc_cdma = p;
     895             : 
     896           0 :         return p->addr;
     897           0 : }
     898             : 
     899             : void
     900           0 : auich_freem(void *v, void *ptr, int pool)
     901             : {
     902             :         struct auich_softc *sc;
     903             :         struct auich_dma *p;
     904             : 
     905           0 :         sc = v;
     906           0 :         if (sc->sc_pdma != NULL && sc->sc_pdma->addr == ptr)
     907           0 :                 p = sc->sc_pdma;
     908           0 :         else if (sc->sc_rdma != NULL && sc->sc_rdma->addr == ptr)
     909           0 :                 p = sc->sc_rdma;
     910           0 :         else if (sc->sc_cdma != NULL && sc->sc_cdma->addr == ptr)
     911             :                 p = sc->sc_cdma;
     912             :         else
     913           0 :                 return;
     914             : 
     915           0 :         auich_freemem(sc, p);
     916           0 :         free(p, pool, 0);
     917           0 : }
     918             : 
     919             : size_t
     920           0 : auich_round_buffersize(void *v, int direction, size_t size)
     921             : {
     922           0 :         if (size > AUICH_DMALIST_MAX * AUICH_DMASEG_MAX)
     923             :                 size = AUICH_DMALIST_MAX * AUICH_DMASEG_MAX;
     924             : 
     925           0 :         return size;
     926             : }
     927             : 
     928             : int
     929           0 : auich_get_props(void *v)
     930             : {
     931           0 :         return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
     932             : }
     933             : 
     934             : int
     935           0 : auich_intr(void *v)
     936             : {
     937           0 :         struct auich_softc *sc = v;
     938             :         int ret = 0, sts, gsts;
     939             : 
     940           0 :         mtx_enter(&audio_lock);
     941           0 :         gsts = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS);
     942             :         DPRINTF(AUICH_DEBUG_INTR, ("auich_intr: gsts=%b\n", gsts, AUICH_GSTS_BITS));
     943             : 
     944           0 :         if (gsts & AUICH_POINT) {
     945           0 :                 sts = bus_space_read_2(sc->iot, sc->aud_ioh,
     946             :                     AUICH_PCMO + sc->sc_sts_reg);
     947             :                 DPRINTF(AUICH_DEBUG_INTR,
     948             :                     ("auich_intr: osts=%b\n", sts, AUICH_ISTS_BITS));
     949             : 
     950             : #ifdef AUICH_DEBUG
     951             :                 if (sts & AUICH_FIFOE) {
     952             :                         printf("%s: in fifo underrun # %u civ=%u ctrl=0x%x sts=%b\n",
     953             :                             sc->sc_dev.dv_xname, sc->pcmo_fifoe++,
     954             :                             bus_space_read_1(sc->iot, sc->aud_ioh,
     955             :                                 AUICH_PCMO + AUICH_CIV),
     956             :                             bus_space_read_1(sc->iot, sc->aud_ioh,
     957             :                                 AUICH_PCMO + AUICH_CTRL),
     958             :                             bus_space_read_2(sc->iot, sc->aud_ioh,
     959             :                                 AUICH_PCMO + sc->sc_sts_reg),
     960             :                             AUICH_ISTS_BITS);
     961             :                 }
     962             : #endif
     963             : 
     964           0 :                 if (sts & AUICH_BCIS)
     965           0 :                         auich_intr_pipe(sc, AUICH_PCMO, &sc->pcmo);
     966             : 
     967             :                 /* int ack */
     968           0 :                 bus_space_write_2(sc->iot, sc->aud_ioh,
     969             :                     AUICH_PCMO + sc->sc_sts_reg, sts &
     970             :                     (AUICH_BCIS | AUICH_FIFOE));
     971           0 :                 bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_POINT);
     972             :                 ret++;
     973           0 :         }
     974             : 
     975           0 :         if (gsts & AUICH_PIINT) {
     976           0 :                 sts = bus_space_read_2(sc->iot, sc->aud_ioh,
     977             :                     AUICH_PCMI + sc->sc_sts_reg);
     978             :                 DPRINTF(AUICH_DEBUG_INTR,
     979             :                     ("auich_intr: ists=%b\n", sts, AUICH_ISTS_BITS));
     980             : 
     981             : #ifdef AUICH_DEBUG
     982             :                 if (sts & AUICH_FIFOE) {
     983             :                         printf("%s: in fifo overrun # %u civ=%u ctrl=0x%x sts=%b\n",
     984             :                             sc->sc_dev.dv_xname, sc->pcmi_fifoe++,
     985             :                             bus_space_read_1(sc->iot, sc->aud_ioh,
     986             :                                 AUICH_PCMI + AUICH_CIV),
     987             :                             bus_space_read_1(sc->iot, sc->aud_ioh,
     988             :                                 AUICH_PCMI + AUICH_CTRL),
     989             :                             bus_space_read_2(sc->iot, sc->aud_ioh,
     990             :                                 AUICH_PCMI + sc->sc_sts_reg),
     991             :                             AUICH_ISTS_BITS);
     992             :                 }
     993             : #endif
     994             : 
     995           0 :                 if (sts & AUICH_BCIS)
     996           0 :                         auich_intr_pipe(sc, AUICH_PCMI, &sc->pcmi);
     997             : 
     998             :                 /* int ack */
     999           0 :                 bus_space_write_2(sc->iot, sc->aud_ioh,
    1000             :                     AUICH_PCMI + sc->sc_sts_reg, sts &
    1001             :                     (AUICH_BCIS | AUICH_FIFOE));
    1002           0 :                 bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_PIINT);
    1003           0 :                 ret++;
    1004           0 :         }
    1005             : 
    1006           0 :         if (gsts & AUICH_MINT) {
    1007           0 :                 sts = bus_space_read_2(sc->iot, sc->aud_ioh,
    1008             :                     AUICH_MICI + sc->sc_sts_reg);
    1009             :                 DPRINTF(AUICH_DEBUG_INTR,
    1010             :                     ("auich_intr: ists=%b\n", sts, AUICH_ISTS_BITS));
    1011             : #ifdef AUICH_DEBUG
    1012             :                 if (sts & AUICH_FIFOE) {
    1013             :                         printf("%s: in fifo overrun civ=%u ctrl=0x%x sts=%b\n",
    1014             :                             sc->sc_dev.dv_xname,
    1015             :                             bus_space_read_1(sc->iot, sc->aud_ioh,
    1016             :                                 AUICH_MICI + AUICH_CIV),
    1017             :                             bus_space_read_1(sc->iot, sc->aud_ioh,
    1018             :                                 AUICH_MICI + AUICH_CTRL),
    1019             :                             bus_space_read_2(sc->iot, sc->aud_ioh,
    1020             :                                 AUICH_MICI + sc->sc_sts_reg),
    1021             :                             AUICH_ISTS_BITS);
    1022             :                 }
    1023             : #endif
    1024           0 :                 if (sts & AUICH_BCIS)
    1025           0 :                         auich_intr_pipe(sc, AUICH_MICI, &sc->mici);
    1026             : 
    1027             :                 /* int ack */
    1028           0 :                 bus_space_write_2(sc->iot, sc->aud_ioh,
    1029             :                     AUICH_MICI + sc->sc_sts_reg,
    1030             :                     sts + (AUICH_BCIS | AUICH_FIFOE));
    1031             : 
    1032           0 :                 bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_MINT);
    1033           0 :                 ret++;
    1034           0 :         }
    1035           0 :         mtx_leave(&audio_lock);
    1036           0 :         return ret;
    1037             : }
    1038             : 
    1039             : 
    1040             : void
    1041           0 : auich_trigger_pipe(struct auich_softc *sc, int pipe, struct auich_ring *ring)
    1042             : {
    1043             :         int blksize, qptr, oqptr;
    1044             :         struct auich_dmalist *q;
    1045             : 
    1046           0 :         blksize = ring->blksize;
    1047           0 :         qptr = oqptr = bus_space_read_1(sc->iot, sc->aud_ioh, pipe + AUICH_CIV);
    1048             : 
    1049             :         /* XXX remove this when no one reports problems */
    1050           0 :         if(oqptr >= AUICH_DMALIST_MAX) {
    1051           0 :                 printf("%s: Unexpected CIV: %d\n", sc->sc_dev.dv_xname, oqptr);
    1052             :                 qptr = oqptr = 0;
    1053           0 :         }
    1054             : 
    1055           0 :         do {
    1056           0 :                 q = &ring->dmalist[qptr];
    1057           0 :                 q->base = ring->p;
    1058           0 :                 q->len = (blksize / sc->sc_sample_size) | AUICH_DMAF_IOC;
    1059             : 
    1060             :                 DPRINTF(AUICH_DEBUG_INTR,
    1061             :                     ("auich_trigger_pipe: %p, %p = %x @ 0x%x qptr=%d\n",
    1062             :                         &ring->dmalist[qptr], q, q->len, q->base, qptr));
    1063             : 
    1064           0 :                 ring->p += blksize;
    1065           0 :                 if (ring->p >= ring->end)
    1066           0 :                         ring->p = ring->start;
    1067             : 
    1068           0 :                 qptr = (qptr + 1) & AUICH_LVI_MASK;
    1069           0 :         } while (qptr != oqptr);
    1070             : 
    1071           0 :         ring->qptr = qptr;
    1072             : 
    1073             :         DPRINTF(AUICH_DEBUG_DMA,
    1074             :             ("auich_trigger_pipe: qptr=%d\n", qptr));
    1075             : 
    1076           0 :         bus_space_write_1(sc->iot, sc->aud_ioh, pipe + AUICH_LVI,
    1077             :             (qptr - 1) & AUICH_LVI_MASK);
    1078           0 :         bus_space_write_1(sc->iot, sc->aud_ioh, pipe + AUICH_CTRL,
    1079             :             AUICH_IOCE | AUICH_FEIE | AUICH_RPBM);
    1080             : 
    1081           0 :         ring->running = 1;
    1082           0 : }
    1083             : 
    1084             : void
    1085           0 : auich_intr_pipe(struct auich_softc *sc, int pipe, struct auich_ring *ring)
    1086             : {
    1087             :         int blksize, qptr, nqptr;
    1088             :         struct auich_dmalist *q;
    1089             : 
    1090           0 :         blksize = ring->blksize;
    1091           0 :         qptr = ring->qptr;
    1092           0 :         nqptr = bus_space_read_1(sc->iot, sc->aud_ioh, pipe + AUICH_CIV);
    1093             : 
    1094           0 :         while (qptr != nqptr) {
    1095           0 :                 q = &ring->dmalist[qptr];
    1096           0 :                 q->base = ring->p;
    1097           0 :                 q->len = (blksize / sc->sc_sample_size) | AUICH_DMAF_IOC;
    1098             : 
    1099             :                 DPRINTF(AUICH_DEBUG_INTR,
    1100             :                     ("auich_intr: %p, %p = %x @ 0x%x qptr=%d\n",
    1101             :                     &ring->dmalist[qptr], q, q->len, q->base, qptr));
    1102             : 
    1103           0 :                 ring->p += blksize;
    1104           0 :                 if (ring->p >= ring->end)
    1105           0 :                         ring->p = ring->start;
    1106             : 
    1107           0 :                 qptr = (qptr + 1) & AUICH_LVI_MASK;
    1108           0 :                 if (ring->intr)
    1109           0 :                         ring->intr(ring->arg);
    1110             :                 else
    1111           0 :                         printf("auich_intr: got progress with intr==NULL\n");
    1112             : 
    1113           0 :                 ring->ap += blksize;
    1114           0 :                 if (ring->ap >= ring->size)
    1115           0 :                         ring->ap = 0;
    1116             :         }
    1117           0 :         ring->qptr = qptr;
    1118             : 
    1119           0 :         bus_space_write_1(sc->iot, sc->aud_ioh, pipe + AUICH_LVI,
    1120             :             (qptr - 1) & AUICH_LVI_MASK);
    1121           0 : }
    1122             : 
    1123             : 
    1124             : int
    1125           0 : auich_trigger_output(void *v, void *start, void *end, int blksize,
    1126             :     void (*intr)(void *), void *arg, struct audio_params *param)
    1127             : {
    1128           0 :         struct auich_softc *sc = v;
    1129             :         struct auich_dma *p;
    1130             :         size_t size;
    1131             : #ifdef AUICH_DEBUG
    1132             :         uint16_t sts;
    1133             :         sts = bus_space_read_2(sc->iot, sc->aud_ioh,
    1134             :             AUICH_PCMO + sc->sc_sts_reg);
    1135             :         DPRINTF(AUICH_DEBUG_DMA,
    1136             :             ("auich_trigger_output(%p, %p, %d, %p, %p, %p) sts=%b\n",
    1137             :                 start, end, blksize, intr, arg, param, sts, AUICH_ISTS_BITS));
    1138             : #endif
    1139             : 
    1140           0 :         if (sc->sc_pdma->addr == start)
    1141             :                 p = sc->sc_pdma;
    1142             :         else
    1143           0 :                 return -1;
    1144             : 
    1145           0 :         size = (size_t)((caddr_t)end - (caddr_t)start);
    1146           0 :         sc->pcmo.size = size;
    1147           0 :         sc->pcmo.intr = intr;
    1148           0 :         sc->pcmo.arg = arg;
    1149             : 
    1150             :         /*
    1151             :          * The logic behind this is:
    1152             :          * setup one buffer to play, then LVI dump out the rest
    1153             :          * to the scatter-gather chain.
    1154             :          */
    1155           0 :         sc->pcmo.start = p->segs->ds_addr;
    1156           0 :         sc->pcmo.p = sc->pcmo.start;
    1157           0 :         sc->pcmo.end = sc->pcmo.start + size;
    1158           0 :         sc->pcmo.blksize = blksize;
    1159             : 
    1160           0 :         mtx_enter(&audio_lock);
    1161           0 :         bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_BDBAR,
    1162             :             sc->sc_cddma + AUICH_PCMO_OFF(0));
    1163           0 :         auich_trigger_pipe(sc, AUICH_PCMO, &sc->pcmo);
    1164           0 :         mtx_leave(&audio_lock);
    1165           0 :         return 0;
    1166           0 : }
    1167             : 
    1168             : int
    1169           0 : auich_trigger_input(void *v, void *start, void *end, int blksize,
    1170             :     void (*intr)(void *), void *arg, struct audio_params *param)
    1171             : {
    1172           0 :         struct auich_softc *sc = v;
    1173             :         struct auich_dma *p;
    1174             :         size_t size;
    1175             : 
    1176             :         DPRINTF(AUICH_DEBUG_DMA,
    1177             :             ("auich_trigger_input(%p, %p, %d, %p, %p, %p) sts=%b\n",
    1178             :                 start, end, blksize, intr, arg, param,
    1179             :                 bus_space_read_2(sc->iot, sc->aud_ioh,
    1180             :                     AUICH_PCMI + sc->sc_sts_reg),
    1181             :                 AUICH_ISTS_BITS));
    1182             : 
    1183           0 :         if (sc->sc_rdma->addr == start)
    1184             :                 p = sc->sc_rdma;
    1185             :         else
    1186           0 :                 return -1;
    1187             : 
    1188           0 :         size = (size_t)((caddr_t)end - (caddr_t)start);
    1189           0 :         sc->pcmi.size = size;
    1190           0 :         sc->pcmi.intr = intr;
    1191           0 :         sc->pcmi.arg = arg;
    1192             : 
    1193             :         /*
    1194             :          * The logic behind this is:
    1195             :          * setup one buffer to play, then LVI dump out the rest
    1196             :          * to the scatter-gather chain.
    1197             :          */
    1198           0 :         sc->pcmi.start = p->segs->ds_addr;
    1199           0 :         sc->pcmi.p = sc->pcmi.start;
    1200           0 :         sc->pcmi.end = sc->pcmi.start + size;
    1201           0 :         sc->pcmi.blksize = blksize;
    1202           0 :         mtx_enter(&audio_lock);
    1203           0 :         bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_BDBAR,
    1204             :             sc->sc_cddma + AUICH_PCMI_OFF(0));
    1205           0 :         auich_trigger_pipe(sc, AUICH_PCMI, &sc->pcmi);
    1206           0 :         mtx_leave(&audio_lock);
    1207           0 :         return 0;
    1208           0 : }
    1209             : 
    1210             : 
    1211             : int
    1212           0 : auich_allocmem(struct auich_softc *sc, size_t size, size_t align,
    1213             :     struct auich_dma *p)
    1214             : {
    1215             :         int error;
    1216             : 
    1217           0 :         p->size = size;
    1218           0 :         error = bus_dmamem_alloc(sc->dmat, p->size, align, 0, p->segs, 1,
    1219             :             &p->nsegs, BUS_DMA_NOWAIT);
    1220           0 :         if (error) {
    1221             :                 DPRINTF(AUICH_DEBUG_DMA, 
    1222             :                     ("%s: bus_dmamem_alloc failed: error %d\n",
    1223             :                     sc->sc_dev.dv_xname, error));
    1224           0 :                 return error;
    1225             :         }
    1226             : 
    1227           0 :         error = bus_dmamem_map(sc->dmat, p->segs, 1, p->size, &p->addr,
    1228             :             BUS_DMA_NOWAIT | sc->sc_dmamap_flags);
    1229           0 :         if (error) {
    1230             :                 DPRINTF(AUICH_DEBUG_DMA, 
    1231             :                     ("%s: bus_dmamem_map failed: error %d\n",
    1232             :                     sc->sc_dev.dv_xname, error));
    1233             :                 goto free;
    1234             :         }
    1235             : 
    1236           0 :         error = bus_dmamap_create(sc->dmat, p->size, 1, p->size, 0,
    1237             :             BUS_DMA_NOWAIT, &p->map);
    1238           0 :         if (error) {
    1239             :                 DPRINTF(AUICH_DEBUG_DMA, 
    1240             :                     ("%s: bus_dmamap_create failed: error %d\n",
    1241             :                     sc->sc_dev.dv_xname, error));
    1242             :                 goto unmap;
    1243             :         }
    1244             : 
    1245           0 :         error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size, NULL,
    1246             :             BUS_DMA_NOWAIT);
    1247           0 :         if (error) {
    1248             :                 DPRINTF(AUICH_DEBUG_DMA,
    1249             :                     ("%s: bus_dmamap_load failed: error %d\n",
    1250             :                     sc->sc_dev.dv_xname, error));
    1251             :                 goto destroy;
    1252             :         }
    1253           0 :         return 0;
    1254             : 
    1255             :  destroy:
    1256           0 :         bus_dmamap_destroy(sc->dmat, p->map);
    1257             :  unmap:
    1258           0 :         bus_dmamem_unmap(sc->dmat, p->addr, p->size);
    1259             :  free:
    1260           0 :         bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
    1261           0 :         return error;
    1262           0 : }
    1263             : 
    1264             : 
    1265             : int
    1266           0 : auich_freemem(struct auich_softc *sc, struct auich_dma *p)
    1267             : {
    1268           0 :         bus_dmamap_unload(sc->dmat, p->map);
    1269           0 :         bus_dmamap_destroy(sc->dmat, p->map);
    1270           0 :         bus_dmamem_unmap(sc->dmat, p->addr, p->size);
    1271           0 :         bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
    1272           0 :         return 0;
    1273             : }
    1274             : 
    1275             : 
    1276             : 
    1277             : int
    1278           0 : auich_alloc_cdata(struct auich_softc *sc)
    1279             : {
    1280           0 :         bus_dma_segment_t seg;
    1281           0 :         int error, rseg;
    1282             : 
    1283             :         /*
    1284             :          * Allocate the control data structure, and create and load the
    1285             :          * DMA map for it.
    1286             :          */
    1287           0 :         if ((error = bus_dmamem_alloc(sc->dmat, sizeof(struct auich_cdata),
    1288           0 :             PAGE_SIZE, 0, &seg, 1, &rseg, 0)) != 0) {
    1289           0 :                 printf("%s: unable to allocate control data, error = %d\n",
    1290           0 :                     sc->sc_dev.dv_xname, error);
    1291           0 :                 goto fail_0;
    1292             :         }
    1293             : 
    1294           0 :         if ((error = bus_dmamem_map(sc->dmat, &seg, 1,
    1295             :             sizeof(struct auich_cdata), (caddr_t *) &sc->sc_cdata,
    1296           0 :             sc->sc_dmamap_flags)) != 0) {
    1297           0 :                 printf("%s: unable to map control data, error = %d\n",
    1298           0 :                     sc->sc_dev.dv_xname, error);
    1299           0 :                 goto fail_1;
    1300             :         }
    1301             : 
    1302           0 :         if ((error = bus_dmamap_create(sc->dmat, sizeof(struct auich_cdata), 1,
    1303           0 :             sizeof(struct auich_cdata), 0, 0, &sc->sc_cddmamap)) != 0) {
    1304           0 :                 printf("%s: unable to create control data DMA map, "
    1305           0 :                     "error = %d\n", sc->sc_dev.dv_xname, error);
    1306           0 :                 goto fail_2;
    1307             :         }
    1308             : 
    1309           0 :         if ((error = bus_dmamap_load(sc->dmat, sc->sc_cddmamap, sc->sc_cdata,
    1310           0 :             sizeof(struct auich_cdata), NULL, 0)) != 0) {
    1311           0 :                 printf("%s: unable tp load control data DMA map, "
    1312           0 :                     "error = %d\n", sc->sc_dev.dv_xname, error);
    1313             :                 goto fail_3;
    1314             :         }
    1315             : 
    1316           0 :         sc->pcmo.dmalist = sc->sc_cdata->ic_dmalist_pcmo;
    1317           0 :         sc->pcmi.dmalist = sc->sc_cdata->ic_dmalist_pcmi;
    1318           0 :         sc->mici.dmalist = sc->sc_cdata->ic_dmalist_mici;
    1319             : 
    1320           0 :         return 0;
    1321             : 
    1322             :  fail_3:
    1323           0 :         bus_dmamap_destroy(sc->dmat, sc->sc_cddmamap);
    1324             :  fail_2:
    1325           0 :         bus_dmamem_unmap(sc->dmat, (caddr_t) sc->sc_cdata,
    1326             :             sizeof(struct auich_cdata));
    1327             :  fail_1:
    1328           0 :         bus_dmamem_free(sc->dmat, &seg, rseg);
    1329             :  fail_0:
    1330           0 :         return error;
    1331           0 : }
    1332             : 
    1333             : void
    1334           0 : auich_resume(struct auich_softc *sc)
    1335             : {
    1336             :         /* SiS 7012 needs special handling */
    1337           0 :         if (PCI_VENDOR(sc->pci_id) == PCI_VENDOR_SIS &&
    1338           0 :             PCI_PRODUCT(sc->pci_id) == PCI_PRODUCT_SIS_7012_ACA) {
    1339             :                 /* un-mute output */
    1340           0 :                 bus_space_write_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL,
    1341             :                     bus_space_read_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL) |
    1342             :                     ICH_SIS_CTL_UNMUTE);
    1343           0 :         }
    1344             : 
    1345           0 :         ac97_resume(&sc->host_if, sc->codec_if);
    1346           0 : }
    1347             : 
    1348             : /* -------------------------------------------------------------------- */
    1349             : /* Calibrate card (some boards are overclocked and need scaling) */
    1350             : 
    1351             : unsigned int
    1352           0 : auich_calibrate(struct auich_softc *sc)
    1353             : {
    1354           0 :         struct timeval t1, t2;
    1355             :         u_int8_t civ, ociv;
    1356             :         uint16_t sts, osts;
    1357             :         u_int32_t wait_us, actual_48k_rate, bytes, ac97rate;
    1358             :         void *temp_buffer;
    1359             :         struct auich_dma *p;
    1360             : 
    1361             :         ac97rate = AUICH_FIXED_RATE;
    1362             :         /*
    1363             :          * Grab audio from input for fixed interval and compare how
    1364             :          * much we actually get with what we expect.  Interval needs
    1365             :          * to be sufficiently short that no interrupts are
    1366             :          * generated.
    1367             :          * XXX: Is this true? We don't request any interrupts,
    1368             :          * so why should the chip issue any?
    1369             :          */
    1370             : 
    1371             :         /* Setup a buffer */
    1372             :         bytes = 16000;
    1373           0 :         temp_buffer = auich_allocm(sc, 0, bytes, M_DEVBUF, M_NOWAIT);
    1374           0 :         if (temp_buffer == NULL)
    1375           0 :                 return (ac97rate);
    1376           0 :         if (sc->sc_cdma->addr == temp_buffer) {
    1377             :                 p = sc->sc_cdma;
    1378             :         } else {
    1379           0 :                 printf("auich_calibrate: bad address %p\n", temp_buffer);
    1380           0 :                 return (ac97rate);
    1381             :         }
    1382             : 
    1383             :         /* get current CIV (usually 0 after reboot) */
    1384           0 :         ociv = civ = bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CIV);
    1385           0 :         sc->pcmi.dmalist[civ].base = p->map->dm_segs[0].ds_addr;
    1386           0 :         sc->pcmi.dmalist[civ].len = bytes / sc->sc_sample_size;
    1387             : 
    1388             : 
    1389             :         /*
    1390             :          * our data format is stereo, 16 bit so each sample is 4 bytes.
    1391             :          * assuming we get 48000 samples per second, we get 192000 bytes/sec.
    1392             :          * we're going to start recording with interrupts disabled and measure
    1393             :          * the time taken for one block to complete.  we know the block size,
    1394             :          * we know the time in microseconds, we calculate the sample rate:
    1395             :          *
    1396             :          * actual_rate [bps] = bytes / (time [s] * 4)
    1397             :          * actual_rate [bps] = (bytes * 1000000) / (time [us] * 4)
    1398             :          * actual_rate [Hz] = (bytes * 250000) / time [us]
    1399             :          */
    1400             : 
    1401             :         /* prepare */
    1402           0 :         bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_BDBAR,
    1403             :             sc->sc_cddma + AUICH_PCMI_OFF(0));
    1404             :         /* we got only one valid sample, so set LVI to CIV
    1405             :          * otherwise we provoke a AUICH_FIFOE FIFO error
    1406             :          * which will confuse the chip later on. */
    1407           0 :         bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_LVI,
    1408             :             civ & AUICH_LVI_MASK);
    1409             : 
    1410             :         /* start, but don't request any interupts */
    1411           0 :         microuptime(&t1);
    1412           0 :         bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL,
    1413             :             AUICH_RPBM);
    1414             : 
    1415             :         /* XXX remove this sometime */
    1416           0 :         osts = bus_space_read_2(sc->iot, sc->aud_ioh,
    1417             :             AUICH_PCMI + sc->sc_sts_reg);
    1418             :         /* wait */
    1419           0 :         while(1) {
    1420           0 :                 microuptime(&t2);
    1421           0 :                 sts = bus_space_read_2(sc->iot, sc->aud_ioh,
    1422             :                     AUICH_PCMI + sc->sc_sts_reg);
    1423           0 :                 civ = bus_space_read_1(sc->iot, sc->aud_ioh,
    1424             :                     AUICH_PCMI + AUICH_CIV);
    1425             :           
    1426             :                 /* turn time delta into us */
    1427           0 :                 wait_us = ((t2.tv_sec - t1.tv_sec) * 1000000) +
    1428           0 :                     t2.tv_usec - t1.tv_usec;
    1429             : 
    1430             :                 /* this should actually never happen because civ==lvi */
    1431           0 :                 if ((civ & AUICH_LVI_MASK) != (ociv & AUICH_LVI_MASK)) {
    1432           0 :                         printf("%s: ac97 CIV progressed after %d us sts=%b civ=%u\n",
    1433           0 :                             sc->sc_dev.dv_xname, wait_us, sts,
    1434             :                             AUICH_ISTS_BITS, civ);
    1435             :                         ociv = civ;
    1436           0 :                 }
    1437             :                 /* normal completion */
    1438           0 :                 if (sts & (AUICH_DCH | AUICH_CELV | AUICH_LVBCI))
    1439             :                         break;
    1440             :                 /*
    1441             :                  * check for strange changes in STS -
    1442             :                  * XXX remove it when everythings fine
    1443             :                  */
    1444           0 :                 if (sts != osts) {
    1445           0 :                         printf("%s: ac97 sts changed after %d us sts=%b civ=%u\n",
    1446           0 :                             sc->sc_dev.dv_xname, wait_us, sts,
    1447             :                             AUICH_ISTS_BITS, civ);
    1448             :                         osts = sts;
    1449           0 :                 }
    1450             :                 /*
    1451             :                  * timeout: we expect 83333 us for 48k sampling rate,
    1452             :                  * 600000 us will be enough even for 8k sampling rate
    1453             :                  */
    1454           0 :                 if (wait_us > 600000) {
    1455           0 :                         printf("%s: ac97 link rate timed out %d us sts=%b civ=%u\n",
    1456           0 :                             sc->sc_dev.dv_xname, wait_us, sts,
    1457             :                             AUICH_ISTS_BITS, civ);
    1458             :                         /* reset and clean up*/
    1459           0 :                         auich_halt_pipe(sc, AUICH_PCMI, &sc->pcmi);
    1460           0 :                         auich_halt_pipe(sc, AUICH_MICI, &sc->mici);
    1461           0 :                         auich_freem(sc, temp_buffer, M_DEVBUF);
    1462             :                         /* return default sample rate */
    1463           0 :                         return (ac97rate);
    1464             :                 }
    1465             :         }
    1466             : 
    1467             :         DPRINTF(AUICH_DEBUG_CODECIO,
    1468             :             ("%s: ac97 link rate calibration took %d us sts=%b civ=%u\n",
    1469             :                 sc->sc_dev.dv_xname, wait_us, sts, AUICH_ISTS_BITS, civ));
    1470             : 
    1471             :         /* reset and clean up */
    1472           0 :         auich_halt_pipe(sc, AUICH_PCMI, &sc->pcmi);
    1473           0 :         auich_halt_pipe(sc, AUICH_MICI, &sc->mici);
    1474           0 :         auich_freem(sc, temp_buffer, M_DEVBUF);
    1475             : 
    1476             : #ifdef AUICH_DEBUG
    1477             :         sts = bus_space_read_2(sc->iot, sc->aud_ioh,
    1478             :             AUICH_PCMI + sc->sc_sts_reg);
    1479             :         civ = bus_space_read_4(sc->iot, sc->aud_ioh,
    1480             :             AUICH_PCMI + AUICH_CIV);
    1481             :         printf("%s: after calibration and reset sts=%b civ=%u\n",
    1482             :             sc->sc_dev.dv_xname, sts, AUICH_ISTS_BITS, civ);
    1483             : #endif
    1484             : 
    1485             :         /* now finally calculate measured samplerate */
    1486           0 :         actual_48k_rate = (bytes * 250000) / wait_us;
    1487             : 
    1488           0 :         if (actual_48k_rate <= 48500)
    1489           0 :                 ac97rate = AUICH_FIXED_RATE;
    1490             :         else
    1491             :                 ac97rate = actual_48k_rate;
    1492             : 
    1493             :         DPRINTF(AUICH_DEBUG_CODECIO, ("%s: measured ac97 link rate at %d Hz",
    1494             :                 sc->sc_dev.dv_xname, actual_48k_rate));
    1495             :         if (ac97rate != actual_48k_rate)
    1496             :                 DPRINTF(AUICH_DEBUG_CODECIO, (", will use %d Hz", ac97rate));
    1497             :         DPRINTF(AUICH_DEBUG_CODECIO, ("\n"));
    1498             : 
    1499           0 :         return (ac97rate);
    1500           0 : }

Generated by: LCOV version 1.13