The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/pci/auich.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: auich.c,v 1.58.2.1 2004/09/22 20:58:09 jmc Exp $       */
    2 
    3 /*-
    4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Copyright (c) 2000 Michael Shalayeff
   41  * All rights reserved.
   42  *
   43  * Redistribution and use in source and binary forms, with or without
   44  * modification, are permitted provided that the following conditions
   45  * are met:
   46  * 1. Redistributions of source code must retain the above copyright
   47  *    notice, this list of conditions and the following disclaimer.
   48  * 2. Redistributions in binary form must reproduce the above copyright
   49  *    notice, this list of conditions and the following disclaimer in the
   50  *    documentation and/or other materials provided with the distribution.
   51  * 3. The name of the author may not be used to endorse or promote products
   52  *    derived from this software without specific prior written permission.
   53  *
   54  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   55  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   56  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   57  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
   58  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   59  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   60  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   61  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   62  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   63  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   64  * THE POSSIBILITY OF SUCH DAMAGE.
   65  *
   66  *      from OpenBSD: ich.c,v 1.3 2000/08/11 06:17:18 mickey Exp
   67  */
   68 
   69 /*
   70  * Copyright (c) 2000 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp>
   71  * Copyright (c) 2001 Cameron Grant <cg@freebsd.org>
   72  * All rights reserved.
   73  *
   74  * Redistribution and use in source and binary forms, with or without
   75  * modification, are permitted provided that the following conditions
   76  * are met:
   77  * 1. Redistributions of source code must retain the above copyright
   78  *    notice, this list of conditions and the following disclaimer.
   79  * 2. Redistributions in binary form must reproduce the above copyright
   80  *    notice, this list of conditions and the following disclaimer in the
   81  *    documentation and/or other materials provided with the distribution.
   82  *
   83  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   84  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   85  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   86  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   87  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   88  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   89  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   90  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
   91  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   92  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
   93  * SUCH DAMAGE.
   94  *
   95  * auich_calibrate() was from FreeBSD: ich.c,v 1.22 2002/06/27 22:36:01 scottl Exp 
   96  */
   97 
   98 
   99 /* #define      ICH_DEBUG */
  100 /*
  101  * AC'97 audio found on Intel 810/820/440MX chipsets.
  102  *      http://developer.intel.com/design/chipsets/datashts/290655.htm
  103  *      http://developer.intel.com/design/chipsets/manuals/298028.htm
  104  * ICH3:http://www.intel.com/design/chipsets/datashts/290716.htm
  105  * ICH4:http://www.intel.com/design/chipsets/datashts/290744.htm
  106  * ICH5:http://www.intel.com/design/chipsets/datashts/252516.htm
  107  * AMD8111:
  108  *      http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24674.pdf
  109  *      http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25720.pdf
  110  *
  111  * TODO:
  112  *      - Add support for the dedicated microphone input.
  113  *
  114  * NOTE:
  115  *      - The 440MX B-stepping at running 100MHz has a hardware erratum.
  116  *        It causes PCI master abort and hangups until cold reboot.
  117  *        http://www.intel.com/design/chipsets/specupdt/245051.htm
  118  */
  119 
  120 #include <sys/cdefs.h>
  121 __KERNEL_RCSID(0, "$NetBSD: auich.c,v 1.58.2.1 2004/09/22 20:58:09 jmc Exp $");
  122 
  123 #include <sys/param.h>
  124 #include <sys/systm.h>
  125 #include <sys/kernel.h>
  126 #include <sys/malloc.h>
  127 #include <sys/device.h>
  128 #include <sys/fcntl.h>
  129 #include <sys/proc.h>
  130 
  131 #include <uvm/uvm_extern.h>     /* for PAGE_SIZE */
  132 
  133 #include <dev/pci/pcidevs.h>
  134 #include <dev/pci/pcivar.h>
  135 #include <dev/pci/auichreg.h>
  136 
  137 #include <sys/audioio.h>
  138 #include <dev/audio_if.h>
  139 #include <dev/mulaw.h>
  140 #include <dev/auconv.h>
  141 
  142 #include <machine/bus.h>
  143 
  144 #include <dev/ic/ac97reg.h>
  145 #include <dev/ic/ac97var.h>
  146 
  147 struct auich_dma {
  148         bus_dmamap_t map;
  149         caddr_t addr;
  150         bus_dma_segment_t segs[1];
  151         int nsegs;
  152         size_t size;
  153         struct auich_dma *next;
  154 };
  155 
  156 #define DMAADDR(p)      ((p)->map->dm_segs[0].ds_addr)
  157 #define KERNADDR(p)     ((void *)((p)->addr))
  158 
  159 struct auich_cdata {
  160         struct auich_dmalist ic_dmalist_pcmo[ICH_DMALIST_MAX];
  161         struct auich_dmalist ic_dmalist_pcmi[ICH_DMALIST_MAX];
  162         struct auich_dmalist ic_dmalist_mici[ICH_DMALIST_MAX];
  163 };
  164 
  165 #define ICH_CDOFF(x)            offsetof(struct auich_cdata, x)
  166 #define ICH_PCMO_OFF(x)         ICH_CDOFF(ic_dmalist_pcmo[(x)])
  167 #define ICH_PCMI_OFF(x)         ICH_CDOFF(ic_dmalist_pcmi[(x)])
  168 #define ICH_MICI_OFF(x)         ICH_CDOFF(ic_dmalist_mici[(x)])
  169 
  170 struct auich_softc {
  171         struct device sc_dev;
  172         void *sc_ih;
  173 
  174         audio_device_t sc_audev;
  175 
  176         bus_space_tag_t iot;
  177         bus_space_handle_t mix_ioh;
  178         bus_space_handle_t aud_ioh;
  179         bus_dma_tag_t dmat;
  180 
  181         struct ac97_codec_if *codec_if;
  182         struct ac97_host_if host_if;
  183 
  184         /* DMA scatter-gather lists. */
  185         bus_dmamap_t sc_cddmamap;
  186 #define sc_cddma        sc_cddmamap->dm_segs[0].ds_addr
  187 
  188         struct auich_cdata *sc_cdata;
  189 #define dmalist_pcmo    sc_cdata->ic_dmalist_pcmo
  190 #define dmalist_pcmi    sc_cdata->ic_dmalist_pcmi
  191 #define dmalist_mici    sc_cdata->ic_dmalist_mici
  192 
  193         int     ptr_pcmo,
  194                 ptr_pcmi,
  195                 ptr_mici;
  196 
  197         /* i/o buffer pointers */
  198         u_int32_t pcmo_start, pcmo_p, pcmo_end;
  199         int pcmo_blksize, pcmo_fifoe;
  200 
  201         u_int32_t pcmi_start, pcmi_p, pcmi_end;
  202         int pcmi_blksize, pcmi_fifoe;
  203 
  204         u_int32_t mici_start, mici_p, mici_end;
  205         int mici_blksize, mici_fifoe;
  206 
  207         struct auich_dma *sc_dmas;
  208 
  209 #ifdef DIAGNOSTIC
  210         pci_chipset_tag_t sc_pc;
  211         pcitag_t sc_pt;
  212 #endif
  213         /* SiS 7012 hack */
  214         int  sc_sample_size;
  215         int  sc_sts_reg;
  216         /* 440MX workaround */
  217         int  sc_dmamap_flags;
  218 
  219         void (*sc_pintr)(void *);
  220         void *sc_parg;
  221 
  222         void (*sc_rintr)(void *);
  223         void *sc_rarg;
  224 
  225         /* Power Management */
  226         void *sc_powerhook;
  227         int sc_suspend;
  228         u_int16_t ext_status;
  229 };
  230 
  231 #define IS_FIXED_RATE(codec)    !((codec)->vtbl->get_extcaps(codec) \
  232                                 & AC97_EXT_AUDIO_VRA)
  233 #define SUPPORTS_4CH(codec)     ((codec)->vtbl->get_extcaps(codec) \
  234                                 & AC97_EXT_AUDIO_SDAC)
  235 #define AC97_6CH_DACS           (AC97_EXT_AUDIO_SDAC | AC97_EXT_AUDIO_CDAC \
  236                                 | AC97_EXT_AUDIO_LDAC)
  237 #define SUPPORTS_6CH(codec)     (((codec)->vtbl->get_extcaps(codec) \
  238                                 & AC97_6CH_DACS) == AC97_6CH_DACS)
  239 
  240 /* Debug */
  241 #ifdef AUDIO_DEBUG
  242 #define DPRINTF(l,x)    do { if (auich_debug & (l)) printf x; } while(0)
  243 int auich_debug = 0xfffe;
  244 #define ICH_DEBUG_CODECIO       0x0001
  245 #define ICH_DEBUG_DMA           0x0002
  246 #define ICH_DEBUG_PARAM         0x0004
  247 #else
  248 #define DPRINTF(x,y)    /* nothing */
  249 #endif
  250 
  251 int     auich_match(struct device *, struct cfdata *, void *);
  252 void    auich_attach(struct device *, struct device *, void *);
  253 int     auich_intr(void *);
  254 
  255 CFATTACH_DECL(auich, sizeof(struct auich_softc),
  256     auich_match, auich_attach, NULL, NULL);
  257 
  258 int     auich_open(void *, int);
  259 void    auich_close(void *);
  260 int     auich_query_encoding(void *, struct audio_encoding *);
  261 int     auich_set_params(void *, int, int, struct audio_params *,
  262             struct audio_params *);
  263 int     auich_round_blocksize(void *, int);
  264 int     auich_halt_output(void *);
  265 int     auich_halt_input(void *);
  266 int     auich_getdev(void *, struct audio_device *);
  267 int     auich_set_port(void *, mixer_ctrl_t *);
  268 int     auich_get_port(void *, mixer_ctrl_t *);
  269 int     auich_query_devinfo(void *, mixer_devinfo_t *);
  270 void    *auich_allocm(void *, int, size_t, struct malloc_type *, int);
  271 void    auich_freem(void *, void *, struct malloc_type *);
  272 size_t  auich_round_buffersize(void *, int, size_t);
  273 paddr_t auich_mappage(void *, void *, off_t, int);
  274 int     auich_get_props(void *);
  275 int     auich_trigger_output(void *, void *, void *, int, void (*)(void *),
  276             void *, struct audio_params *);
  277 int     auich_trigger_input(void *, void *, void *, int, void (*)(void *),
  278             void *, struct audio_params *);
  279 
  280 int     auich_alloc_cdata(struct auich_softc *);
  281 
  282 int     auich_allocmem(struct auich_softc *, size_t, size_t,
  283             struct auich_dma *);
  284 int     auich_freemem(struct auich_softc *, struct auich_dma *);
  285 
  286 void    auich_powerhook(int, void *);
  287 int     auich_set_rate(struct auich_softc *, int, u_long);
  288 void    auich_finish_attach(struct device *);
  289 void    auich_calibrate(struct auich_softc *);
  290 
  291 
  292 struct audio_hw_if auich_hw_if = {
  293         auich_open,
  294         auich_close,
  295         NULL,                   /* drain */
  296         auich_query_encoding,
  297         auich_set_params,
  298         auich_round_blocksize,
  299         NULL,                   /* commit_setting */
  300         NULL,                   /* init_output */
  301         NULL,                   /* init_input */
  302         NULL,                   /* start_output */
  303         NULL,                   /* start_input */
  304         auich_halt_output,
  305         auich_halt_input,
  306         NULL,                   /* speaker_ctl */
  307         auich_getdev,
  308         NULL,                   /* getfd */
  309         auich_set_port,
  310         auich_get_port,
  311         auich_query_devinfo,
  312         auich_allocm,
  313         auich_freem,
  314         auich_round_buffersize,
  315         auich_mappage,
  316         auich_get_props,
  317         auich_trigger_output,
  318         auich_trigger_input,
  319         NULL,                   /* dev_ioctl */
  320 };
  321 
  322 int     auich_attach_codec(void *, struct ac97_codec_if *);
  323 int     auich_read_codec(void *, u_int8_t, u_int16_t *);
  324 int     auich_write_codec(void *, u_int8_t, u_int16_t);
  325 int     auich_reset_codec(void *);
  326 
  327 static const struct auich_devtype {
  328         int     vendor;
  329         int     product;
  330         const char *name;
  331         const char *shortname;  /* must be less than 11 characters */
  332 } auich_devices[] = {
  333         { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_ACA,
  334             "i82801AA (ICH) AC-97 Audio",       "ICH" },
  335         { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_ACA,
  336             "i82801AB (ICH0) AC-97 Audio",      "ICH0" },
  337         { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_ACA,
  338             "i82801BA (ICH2) AC-97 Audio",      "ICH2" },
  339         { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82440MX_ACA,
  340             "i82440MX AC-97 Audio",             "440MX" },
  341         { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801CA_AC,
  342             "i82801CA (ICH3) AC-97 Audio",      "ICH3" },
  343         { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DB_AC,
  344             "i82801DB/DBM (ICH4/ICH4M) AC-97 Audio",    "ICH4" },
  345         { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801EB_AC,
  346             "i82801EB (ICH5) AC-97 Audio",   "ICH5" },
  347         { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7012_AC,
  348             "SiS 7012 AC-97 Audio",             "SiS7012" },
  349         { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE_MCP_AC,
  350             "nForce MCP AC-97 Audio",           "nForce" },
  351         { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_MCPT_AC,
  352             "nForce2 MCP-T AC-97 Audio",        "nForce2" },
  353         { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_MCPT_AC,
  354             "nForce3 MCP-T AC-97 Audio",        "nForce3" },
  355         { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PBC768_AC,
  356             "AMD768 AC-97 Audio",               "AMD768" },
  357         { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PBC8111_AC,
  358             "AMD8111 AC-97 Audio",              "AMD8111" },
  359         { 0, 0,
  360             NULL,                               NULL },
  361 };
  362 
  363 static const struct auich_devtype *
  364 auich_lookup(struct pci_attach_args *pa)
  365 {
  366         const struct auich_devtype *d;
  367 
  368         for (d = auich_devices; d->name != NULL; d++) {
  369                 if (PCI_VENDOR(pa->pa_id) == d->vendor
  370                         && PCI_PRODUCT(pa->pa_id) == d->product)
  371                         return (d);
  372         }
  373 
  374         return (NULL);
  375 }
  376 
  377 int
  378 auich_match(struct device *parent, struct cfdata *match, void *aux)
  379 {
  380         struct pci_attach_args *pa = aux;
  381 
  382         if (auich_lookup(pa) != NULL)
  383                 return (1);
  384 
  385         return (0);
  386 }
  387 
  388 void
  389 auich_attach(struct device *parent, struct device *self, void *aux)
  390 {
  391         struct auich_softc *sc = (struct auich_softc *)self;
  392         struct pci_attach_args *pa = aux;
  393         pci_intr_handle_t ih;
  394         bus_size_t mix_size, aud_size;
  395         pcireg_t v;
  396         const char *intrstr;
  397         const struct auich_devtype *d;
  398 
  399         aprint_naive(": Audio controller\n");
  400 
  401         d = auich_lookup(pa);
  402         if (d == NULL)
  403                 panic("auich_attach: impossible");
  404 
  405 #ifdef DIAGNOSTIC
  406         sc->sc_pc = pa->pa_pc;
  407         sc->sc_pt = pa->pa_tag;
  408 #endif
  409 
  410         aprint_normal(": %s\n", d->name);
  411 
  412         if ((d->vendor == PCI_VENDOR_INTEL
  413              && d->product == PCI_PRODUCT_INTEL_82801DB_AC)
  414             || (d->vendor == PCI_VENDOR_INTEL
  415                 && d->product == PCI_PRODUCT_INTEL_82801EB_AC)) {
  416                 /*
  417                  * Use native mode for ICH4/ICH5
  418                  */
  419                 if (pci_mapreg_map(pa, ICH_MMBAR, PCI_MAPREG_TYPE_MEM, 0,
  420                                    &sc->iot, &sc->mix_ioh, NULL, &mix_size)) {
  421                         v = pci_conf_read(pa->pa_pc, pa->pa_tag, ICH_CFG);
  422                         pci_conf_write(pa->pa_pc, pa->pa_tag, ICH_CFG,
  423                                        v | ICH_CFG_IOSE);
  424                         if (pci_mapreg_map(pa, ICH_NAMBAR, PCI_MAPREG_TYPE_IO,
  425                                            0, &sc->iot, &sc->mix_ioh, NULL,
  426                                            &mix_size)) {
  427                                 aprint_error("%s: can't map codec i/o space\n",
  428                                              sc->sc_dev.dv_xname);
  429                                 return;
  430                         }
  431                 }
  432                 if (pci_mapreg_map(pa, ICH_MBBAR, PCI_MAPREG_TYPE_MEM, 0,
  433                                    &sc->iot, &sc->aud_ioh, NULL, &aud_size)) {
  434                         v = pci_conf_read(pa->pa_pc, pa->pa_tag, ICH_CFG);
  435                         pci_conf_write(pa->pa_pc, pa->pa_tag, ICH_CFG,
  436                                        v | ICH_CFG_IOSE);
  437                         if (pci_mapreg_map(pa, ICH_NABMBAR, PCI_MAPREG_TYPE_IO,
  438                                            0, &sc->iot, &sc->aud_ioh, NULL,
  439                                            &aud_size)) {
  440                                 aprint_error("%s: can't map device i/o space\n",
  441                                              sc->sc_dev.dv_xname);
  442                                 return;
  443                         }
  444                 }
  445         } else {
  446                 if (pci_mapreg_map(pa, ICH_NAMBAR, PCI_MAPREG_TYPE_IO, 0,
  447                                    &sc->iot, &sc->mix_ioh, NULL, &mix_size)) {
  448                         aprint_error("%s: can't map codec i/o space\n",
  449                                      sc->sc_dev.dv_xname);
  450                         return;
  451                 }
  452                 if (pci_mapreg_map(pa, ICH_NABMBAR, PCI_MAPREG_TYPE_IO, 0,
  453                                    &sc->iot, &sc->aud_ioh, NULL, &aud_size)) {
  454                         aprint_error("%s: can't map device i/o space\n",
  455                                      sc->sc_dev.dv_xname);
  456                         return;
  457                 }
  458         }
  459         sc->dmat = pa->pa_dmat;
  460 
  461         /* enable bus mastering */
  462         v = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
  463         pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
  464             v | PCI_COMMAND_MASTER_ENABLE);
  465 
  466         /* Map and establish the interrupt. */
  467         if (pci_intr_map(pa, &ih)) {
  468                 aprint_error("%s: can't map interrupt\n", sc->sc_dev.dv_xname);
  469                 return;
  470         }
  471         intrstr = pci_intr_string(pa->pa_pc, ih);
  472         sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO,
  473             auich_intr, sc);
  474         if (sc->sc_ih == NULL) {
  475                 aprint_error("%s: can't establish interrupt",
  476                     sc->sc_dev.dv_xname);
  477                 if (intrstr != NULL)
  478                         aprint_normal(" at %s", intrstr);
  479                 aprint_normal("\n");
  480                 return;
  481         }
  482         aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
  483 
  484         snprintf(sc->sc_audev.name, MAX_AUDIO_DEV_LEN, "%s AC97", d->shortname);
  485         snprintf(sc->sc_audev.version, MAX_AUDIO_DEV_LEN,
  486                  "0x%02x", PCI_REVISION(pa->pa_class));
  487         strlcpy(sc->sc_audev.config, sc->sc_dev.dv_xname, MAX_AUDIO_DEV_LEN);
  488 
  489         /* SiS 7012 needs special handling */
  490         if (d->vendor == PCI_VENDOR_SIS
  491             && d->product == PCI_PRODUCT_SIS_7012_AC) {
  492                 sc->sc_sts_reg = ICH_PICB;
  493                 sc->sc_sample_size = 1;
  494         } else {
  495                 sc->sc_sts_reg = ICH_STS;
  496                 sc->sc_sample_size = 2;
  497         }
  498 
  499         /* Workaround for a 440MX B-stepping erratum */
  500         sc->sc_dmamap_flags = BUS_DMA_COHERENT;
  501         if (d->vendor == PCI_VENDOR_INTEL
  502             && d->product == PCI_PRODUCT_INTEL_82440MX_ACA) {
  503                 sc->sc_dmamap_flags |= BUS_DMA_NOCACHE;
  504                 printf("%s: DMA bug workaround enabled\n", sc->sc_dev.dv_xname);
  505         }
  506 
  507         /* Set up DMA lists. */
  508         sc->ptr_pcmo = sc->ptr_pcmi = sc->ptr_mici = 0;
  509         auich_alloc_cdata(sc);
  510 
  511         DPRINTF(ICH_DEBUG_DMA, ("auich_attach: lists %p %p %p\n",
  512             sc->dmalist_pcmo, sc->dmalist_pcmi, sc->dmalist_mici));
  513 
  514         sc->host_if.arg = sc;
  515         sc->host_if.attach = auich_attach_codec;
  516         sc->host_if.read = auich_read_codec;
  517         sc->host_if.write = auich_write_codec;
  518         sc->host_if.reset = auich_reset_codec;
  519 
  520         if (ac97_attach(&sc->host_if) != 0)
  521                 return;
  522 
  523         /* Watch for power change */
  524         sc->sc_suspend = PWR_RESUME;
  525         sc->sc_powerhook = powerhook_establish(auich_powerhook, sc);
  526 
  527         config_interrupts(self, auich_finish_attach);
  528 }
  529 
  530 void
  531 auich_finish_attach(struct device *self)
  532 {
  533         struct auich_softc *sc = (void *)self;
  534 
  535         if (!IS_FIXED_RATE(sc->codec_if))
  536                 auich_calibrate(sc);
  537 
  538         audio_attach_mi(&auich_hw_if, sc, &sc->sc_dev);
  539 }
  540 
  541 #define ICH_CODECIO_INTERVAL    10
  542 int
  543 auich_read_codec(void *v, u_int8_t reg, u_int16_t *val)
  544 {
  545         struct auich_softc *sc = v;
  546         int i;
  547         uint32_t status;
  548 
  549         /* wait for an access semaphore */
  550         for (i = ICH_SEMATIMO / ICH_CODECIO_INTERVAL; i-- &&
  551             bus_space_read_1(sc->iot, sc->aud_ioh, ICH_CAS) & 1;
  552             DELAY(ICH_CODECIO_INTERVAL));
  553 
  554         if (i > 0) {
  555                 *val = bus_space_read_2(sc->iot, sc->mix_ioh, reg);
  556                 DPRINTF(ICH_DEBUG_CODECIO,
  557                     ("auich_read_codec(%x, %x)\n", reg, *val));
  558                 status = bus_space_read_4(sc->iot, sc->aud_ioh, ICH_GSTS);
  559                 if (status & ICH_RCS) {
  560                         bus_space_write_4(sc->iot, sc->aud_ioh, ICH_GSTS,
  561                                           status & ~(ICH_SRI|ICH_PRI|ICH_GSCI));
  562                         *val = 0xffff;
  563                 }
  564                 return 0;
  565         } else {
  566                 DPRINTF(ICH_DEBUG_CODECIO,
  567                     ("%s: read_codec timeout\n", sc->sc_dev.dv_xname));
  568                 return -1;
  569         }
  570 }
  571 
  572 int
  573 auich_write_codec(void *v, u_int8_t reg, u_int16_t val)
  574 {
  575         struct auich_softc *sc = v;
  576         int i;
  577 
  578         DPRINTF(ICH_DEBUG_CODECIO, ("auich_write_codec(%x, %x)\n", reg, val));
  579         /* wait for an access semaphore */
  580         for (i = ICH_SEMATIMO / ICH_CODECIO_INTERVAL; i-- &&
  581             bus_space_read_1(sc->iot, sc->aud_ioh, ICH_CAS) & 1;
  582             DELAY(ICH_CODECIO_INTERVAL));
  583 
  584         if (i > 0) {
  585                 bus_space_write_2(sc->iot, sc->mix_ioh, reg, val);
  586                 return 0;
  587         } else {
  588                 DPRINTF(ICH_DEBUG_CODECIO,
  589                     ("%s: write_codec timeout\n", sc->sc_dev.dv_xname));
  590                 return -1;
  591         }
  592 }
  593 
  594 int
  595 auich_attach_codec(void *v, struct ac97_codec_if *cif)
  596 {
  597         struct auich_softc *sc = v;
  598 
  599         sc->codec_if = cif;
  600         return 0;
  601 }
  602 
  603 int
  604 auich_reset_codec(void *v)
  605 {
  606         struct auich_softc *sc = v;
  607         int i;
  608         uint32_t control, status;
  609 
  610         control = bus_space_read_4(sc->iot, sc->aud_ioh, ICH_GCTRL);
  611         control &= ~(ICH_ACLSO | ICH_PCM246_MASK);
  612         control |= (control & ICH_CRESET) ? ICH_WRESET : ICH_CRESET;
  613         bus_space_write_4(sc->iot, sc->aud_ioh, ICH_GCTRL, control);
  614 
  615         for (i = 500000; i >= 0; i--) {
  616                 status = bus_space_read_4(sc->iot, sc->aud_ioh, ICH_GSTS);
  617                 if (status & (ICH_PCR | ICH_SCR | ICH_S2CR))
  618                         break;
  619                 DELAY(1);
  620         }
  621         if (i <= 0) {
  622                 printf("%s: auich_reset_codec: time out\n", sc->sc_dev.dv_xname);
  623                 return ETIMEDOUT;
  624         }
  625 #ifdef DEBUG
  626         if (status & ICH_SCR)
  627                 printf("%s: The 2nd codec is ready.\n",
  628                        sc->sc_dev.dv_xname);
  629         if (status & ICH_S2CR)
  630                 printf("%s: The 3rd codec is ready.\n",
  631                        sc->sc_dev.dv_xname);
  632 #endif
  633         return 0;
  634 }
  635 
  636 int
  637 auich_open(void *v, int flags)
  638 {
  639         return 0;
  640 }
  641 
  642 void
  643 auich_close(void *v)
  644 {
  645         struct auich_softc *sc = v;
  646 
  647         auich_halt_output(sc);
  648         auich_halt_input(sc);
  649 
  650         sc->sc_pintr = NULL;
  651         sc->sc_rintr = NULL;
  652 }
  653 
  654 int
  655 auich_query_encoding(void *v, struct audio_encoding *aep)
  656 {
  657 
  658         switch (aep->index) {
  659         case 0:
  660                 strcpy(aep->name, AudioEulinear);
  661                 aep->encoding = AUDIO_ENCODING_ULINEAR;
  662                 aep->precision = 8;
  663                 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
  664                 return (0);
  665         case 1:
  666                 strcpy(aep->name, AudioEmulaw);
  667                 aep->encoding = AUDIO_ENCODING_ULAW;
  668                 aep->precision = 8;
  669                 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
  670                 return (0);
  671         case 2:
  672                 strcpy(aep->name, AudioEalaw);
  673                 aep->encoding = AUDIO_ENCODING_ALAW;
  674                 aep->precision = 8;
  675                 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
  676                 return (0);
  677         case 3:
  678                 strcpy(aep->name, AudioEslinear);
  679                 aep->encoding = AUDIO_ENCODING_SLINEAR;
  680                 aep->precision = 8;
  681                 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
  682                 return (0);
  683         case 4:
  684                 strcpy(aep->name, AudioEslinear_le);
  685                 aep->encoding = AUDIO_ENCODING_SLINEAR_LE;
  686                 aep->precision = 16;
  687                 aep->flags = 0;
  688                 return (0);
  689         case 5:
  690                 strcpy(aep->name, AudioEulinear_le);
  691                 aep->encoding = AUDIO_ENCODING_ULINEAR_LE;
  692                 aep->precision = 16;
  693                 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
  694                 return (0);
  695         case 6:
  696                 strcpy(aep->name, AudioEslinear_be);
  697                 aep->encoding = AUDIO_ENCODING_SLINEAR_BE;
  698                 aep->precision = 16;
  699                 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
  700                 return (0);
  701         case 7:
  702                 strcpy(aep->name, AudioEulinear_be);
  703                 aep->encoding = AUDIO_ENCODING_ULINEAR_BE;
  704                 aep->precision = 16;
  705                 aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
  706                 return (0);
  707         default:
  708                 return (EINVAL);
  709         }
  710 }
  711 
  712 int
  713 auich_set_rate(struct auich_softc *sc, int mode, u_long srate)
  714 {
  715         int ret;
  716         u_long ratetmp;
  717 
  718         ratetmp = srate;
  719         if (mode == AUMODE_RECORD)
  720                 return sc->codec_if->vtbl->set_rate(sc->codec_if,
  721                     AC97_REG_PCM_LR_ADC_RATE, &ratetmp);
  722         ret = sc->codec_if->vtbl->set_rate(sc->codec_if,
  723             AC97_REG_PCM_FRONT_DAC_RATE, &ratetmp);
  724         if (ret)
  725                 return ret;
  726         ratetmp = srate;
  727         ret = sc->codec_if->vtbl->set_rate(sc->codec_if,
  728             AC97_REG_PCM_SURR_DAC_RATE, &ratetmp);
  729         if (ret)
  730                 return ret;
  731         ratetmp = srate;
  732         ret = sc->codec_if->vtbl->set_rate(sc->codec_if,
  733             AC97_REG_PCM_LFE_DAC_RATE, &ratetmp);
  734         return ret;
  735 }
  736 
  737 int
  738 auich_set_params(void *v, int setmode, int usemode, struct audio_params *play,
  739     struct audio_params *rec)
  740 {
  741         struct auich_softc *sc = v;
  742         struct audio_params *p;
  743         int mode;
  744         u_int32_t control;
  745 
  746         for (mode = AUMODE_RECORD; mode != -1;
  747              mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
  748                 if ((setmode & mode) == 0)
  749                         continue;
  750 
  751                 p = mode == AUMODE_PLAY ? play : rec;
  752                 if (p == NULL)
  753                         continue;
  754 
  755                 if ((p->sample_rate !=  8000) &&
  756                     (p->sample_rate != 11025) &&
  757                     (p->sample_rate != 12000) &&
  758                     (p->sample_rate != 16000) &&
  759                     (p->sample_rate != 22050) &&
  760                     (p->sample_rate != 24000) &&
  761                     (p->sample_rate != 32000) &&
  762                     (p->sample_rate != 44100) &&
  763                     (p->sample_rate != 48000))
  764                         return (EINVAL);
  765 
  766                 p->factor = 1;
  767                 if (p->precision == 8)
  768                         p->factor *= 2;
  769 
  770                 p->sw_code = NULL;
  771                 /* setup hardware formats */
  772                 p->hw_encoding = AUDIO_ENCODING_SLINEAR_LE;
  773                 p->hw_precision = 16;
  774 
  775                 if (mode == AUMODE_RECORD) {
  776                         if (p->channels < 1 || p->channels > 2)
  777                                 return EINVAL;
  778                 } else {
  779                         switch (p->channels) {
  780                         case 1:
  781                                 break;
  782                         case 2:
  783                                 break;
  784                         case 4:
  785                                 if (!SUPPORTS_4CH(sc->codec_if))
  786                                         return EINVAL;
  787                                 break;
  788                         case 6:
  789                                 if (!SUPPORTS_6CH(sc->codec_if))
  790                                         return EINVAL;
  791                                 break;
  792                         default:
  793                                 return EINVAL;
  794                         }
  795                 }
  796                 /* If monaural is requested, aurateconv expands a monaural
  797                  * stream to stereo. */
  798                 if (p->channels == 1)
  799                         p->hw_channels = 2;
  800 
  801                 switch (p->encoding) {
  802                 case AUDIO_ENCODING_SLINEAR_BE:
  803                         if (p->precision == 16) {
  804                                 p->sw_code = swap_bytes;
  805                         } else {
  806                                 if (mode == AUMODE_PLAY)
  807                                         p->sw_code = linear8_to_linear16_le;
  808                                 else
  809                                         p->sw_code = linear16_to_linear8_le;
  810                         }
  811                         break;
  812 
  813                 case AUDIO_ENCODING_SLINEAR_LE:
  814                         if (p->precision != 16) {
  815                                 if (mode == AUMODE_PLAY)
  816                                         p->sw_code = linear8_to_linear16_le;
  817                                 else
  818                                         p->sw_code = linear16_to_linear8_le;
  819                         }
  820                         break;
  821 
  822                 case AUDIO_ENCODING_ULINEAR_BE:
  823                         if (p->precision == 16) {
  824                                 if (mode == AUMODE_PLAY)
  825                                         p->sw_code =
  826                                             swap_bytes_change_sign16_le;
  827                                 else
  828                                         p->sw_code =
  829                                             change_sign16_swap_bytes_le;
  830                         } else {
  831                                 if (mode == AUMODE_PLAY)
  832                                         p->sw_code =
  833                                             ulinear8_to_slinear16_le;
  834                                 else
  835                                         p->sw_code =
  836                                             slinear16_to_ulinear8_le;
  837                         }
  838                         break;
  839 
  840                 case AUDIO_ENCODING_ULINEAR_LE:
  841                         if (p->precision == 16) {
  842                                 p->sw_code = change_sign16_le;
  843                         } else {
  844                                 if (mode == AUMODE_PLAY)
  845                                         p->sw_code =
  846                                             ulinear8_to_slinear16_le;
  847                                 else
  848                                         p->sw_code =
  849                                             slinear16_to_ulinear8_le;
  850                         }
  851                         break;
  852 
  853                 case AUDIO_ENCODING_ULAW:
  854                         if (mode == AUMODE_PLAY) {
  855                                 p->sw_code = mulaw_to_slinear16_le;
  856                         } else {
  857                                 p->sw_code = slinear16_to_mulaw_le;
  858                         }
  859                         break;
  860 
  861                 case AUDIO_ENCODING_ALAW:
  862                         if (mode == AUMODE_PLAY) {
  863                                 p->sw_code = alaw_to_slinear16_le;
  864                         } else {
  865                                 p->sw_code = slinear16_to_alaw_le;
  866                         }
  867                         break;
  868 
  869                 default:
  870                         return (EINVAL);
  871                 }
  872 
  873                 if (IS_FIXED_RATE(sc->codec_if)) {
  874                         p->hw_sample_rate = AC97_SINGLE_RATE;
  875                         /* If hw_sample_rate is changed, aurateconv works. */
  876                 } else {
  877                         if (auich_set_rate(sc, mode, p->sample_rate))
  878                                 return EINVAL;
  879                 }
  880                 if (mode == AUMODE_PLAY) {
  881                         control = bus_space_read_4(sc->iot, sc->aud_ioh, ICH_GCTRL);
  882                         control &= ~ICH_PCM246_MASK;
  883                         if (p->channels == 4) {
  884                                 control |= ICH_PCM4;
  885                         } else if (p->channels == 6) {
  886                                 control |= ICH_PCM6;
  887                         }
  888                         bus_space_write_4(sc->iot, sc->aud_ioh, ICH_GCTRL, control);
  889                 }
  890         }
  891 
  892         return (0);
  893 }
  894 
  895 int
  896 auich_round_blocksize(void *v, int blk)
  897 {
  898 
  899         return (blk & ~0x3f);           /* keep good alignment */
  900 }
  901 
  902 int
  903 auich_halt_output(void *v)
  904 {
  905         struct auich_softc *sc = v;
  906 
  907         DPRINTF(ICH_DEBUG_DMA, ("%s: halt_output\n", sc->sc_dev.dv_xname));
  908 
  909         bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMO + ICH_CTRL, ICH_RR);
  910 
  911         return (0);
  912 }
  913 
  914 int
  915 auich_halt_input(void *v)
  916 {
  917         struct auich_softc *sc = v;
  918 
  919         DPRINTF(ICH_DEBUG_DMA,
  920             ("%s: halt_input\n", sc->sc_dev.dv_xname));
  921 
  922         /* XXX halt both unless known otherwise */
  923 
  924         bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CTRL, ICH_RR);
  925         bus_space_write_1(sc->iot, sc->aud_ioh, ICH_MICI + ICH_CTRL, ICH_RR);
  926 
  927         return (0);
  928 }
  929 
  930 int
  931 auich_getdev(void *v, struct audio_device *adp)
  932 {
  933         struct auich_softc *sc = v;
  934 
  935         *adp = sc->sc_audev;
  936         return (0);
  937 }
  938 
  939 int
  940 auich_set_port(void *v, mixer_ctrl_t *cp)
  941 {
  942         struct auich_softc *sc = v;
  943 
  944         return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp));
  945 }
  946 
  947 int
  948 auich_get_port(void *v, mixer_ctrl_t *cp)
  949 {
  950         struct auich_softc *sc = v;
  951 
  952         return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp));
  953 }
  954 
  955 int
  956 auich_query_devinfo(void *v, mixer_devinfo_t *dp)
  957 {
  958         struct auich_softc *sc = v;
  959 
  960         return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dp));
  961 }
  962 
  963 void *
  964 auich_allocm(void *v, int direction, size_t size, struct malloc_type *pool,
  965     int flags)
  966 {
  967         struct auich_softc *sc = v;
  968         struct auich_dma *p;
  969         int error;
  970 
  971         if (size > (ICH_DMALIST_MAX * ICH_DMASEG_MAX))
  972                 return (NULL);
  973 
  974         p = malloc(sizeof(*p), pool, flags|M_ZERO);
  975         if (p == NULL)
  976                 return (NULL);
  977 
  978         error = auich_allocmem(sc, size, 0, p);
  979         if (error) {
  980                 free(p, pool);
  981                 return (NULL);
  982         }
  983 
  984         p->next = sc->sc_dmas;
  985         sc->sc_dmas = p;
  986 
  987         return (KERNADDR(p));
  988 }
  989 
  990 void
  991 auich_freem(void *v, void *ptr, struct malloc_type *pool)
  992 {
  993         struct auich_softc *sc = v;
  994         struct auich_dma *p, **pp;
  995 
  996         for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
  997                 if (KERNADDR(p) == ptr) {
  998                         auich_freemem(sc, p);
  999                         *pp = p->next;
 1000                         free(p, pool);
 1001                         return;
 1002                 }
 1003         }
 1004 }
 1005 
 1006 size_t
 1007 auich_round_buffersize(void *v, int direction, size_t size)
 1008 {
 1009 
 1010         if (size > (ICH_DMALIST_MAX * ICH_DMASEG_MAX))
 1011                 size = ICH_DMALIST_MAX * ICH_DMASEG_MAX;
 1012 
 1013         return size;
 1014 }
 1015 
 1016 paddr_t
 1017 auich_mappage(void *v, void *mem, off_t off, int prot)
 1018 {
 1019         struct auich_softc *sc = v;
 1020         struct auich_dma *p;
 1021 
 1022         if (off < 0)
 1023                 return (-1);
 1024 
 1025         for (p = sc->sc_dmas; p && KERNADDR(p) != mem; p = p->next)
 1026                 ;
 1027         if (!p)
 1028                 return (-1);
 1029         return (bus_dmamem_mmap(sc->dmat, p->segs, p->nsegs,
 1030             off, prot, BUS_DMA_WAITOK));
 1031 }
 1032 
 1033 int
 1034 auich_get_props(void *v)
 1035 {
 1036         struct auich_softc *sc = v;
 1037         int props;
 1038 
 1039         props = AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
 1040         /*
 1041          * Even if the codec is fixed-rate, set_param() succeeds for any sample
 1042          * rate because of aurateconv.  Applications can't know what rate the
 1043          * device can process in the case of mmap().
 1044          */
 1045         if (!IS_FIXED_RATE(sc->codec_if))
 1046                 props |= AUDIO_PROP_MMAP;
 1047         return props;
 1048 }
 1049 
 1050 int
 1051 auich_intr(void *v)
 1052 {
 1053         struct auich_softc *sc = v;
 1054         int ret = 0, sts, gsts, i, qptr;
 1055 
 1056 #ifdef DIAGNOSTIC
 1057         int csts;
 1058 #endif
 1059 
 1060 #ifdef DIAGNOSTIC
 1061         csts = pci_conf_read(sc->sc_pc, sc->sc_pt, PCI_COMMAND_STATUS_REG);
 1062         if (csts & PCI_STATUS_MASTER_ABORT) {
 1063                 printf("auich_intr: PCI master abort\n");
 1064         }
 1065 #endif
 1066 
 1067         gsts = bus_space_read_2(sc->iot, sc->aud_ioh, ICH_GSTS);
 1068         DPRINTF(ICH_DEBUG_DMA, ("auich_intr: gsts=0x%x\n", gsts));
 1069 
 1070         if (gsts & ICH_POINT) {
 1071                 sts = bus_space_read_2(sc->iot, sc->aud_ioh, ICH_PCMO+sc->sc_sts_reg);
 1072                 DPRINTF(ICH_DEBUG_DMA,
 1073                     ("auich_intr: osts=0x%x\n", sts));
 1074 
 1075                 if (sts & ICH_FIFOE) {
 1076                         printf("%s: fifo underrun # %u\n",
 1077                             sc->sc_dev.dv_xname, ++sc->pcmo_fifoe);
 1078                 }
 1079 
 1080                 i = bus_space_read_1(sc->iot, sc->aud_ioh, ICH_PCMO + ICH_CIV);
 1081                 if (sts & (ICH_LVBCI | ICH_CELV)) {
 1082                         struct auich_dmalist *q;
 1083 
 1084                         qptr = sc->ptr_pcmo;
 1085 
 1086                         while (qptr != i) {
 1087                                 q = &sc->dmalist_pcmo[qptr];
 1088 
 1089                                 q->base = sc->pcmo_p;
 1090                                 q->len = (sc->pcmo_blksize / sc->sc_sample_size) | ICH_DMAF_IOC;
 1091                                 DPRINTF(ICH_DEBUG_DMA,
 1092                                     ("auich_intr: %p, %p = %x @ 0x%x\n",
 1093                                     &sc->dmalist_pcmo[i], q,
 1094                                     sc->pcmo_blksize / 2, sc->pcmo_p));
 1095 
 1096                                 sc->pcmo_p += sc->pcmo_blksize;
 1097                                 if (sc->pcmo_p >= sc->pcmo_end)
 1098                                         sc->pcmo_p = sc->pcmo_start;
 1099 
 1100                                 if (++qptr == ICH_DMALIST_MAX)
 1101                                         qptr = 0;
 1102                         }
 1103 
 1104                         sc->ptr_pcmo = qptr;
 1105                         bus_space_write_1(sc->iot, sc->aud_ioh,
 1106                             ICH_PCMO + ICH_LVI,
 1107                             (sc->ptr_pcmo - 1) & ICH_LVI_MASK);
 1108                 }
 1109 
 1110                 if (sts & ICH_BCIS && sc->sc_pintr)
 1111                         sc->sc_pintr(sc->sc_parg);
 1112 
 1113                 /* int ack */
 1114                 bus_space_write_2(sc->iot, sc->aud_ioh, ICH_PCMO + sc->sc_sts_reg,
 1115                     sts & (ICH_LVBCI | ICH_CELV | ICH_BCIS | ICH_FIFOE));
 1116                 bus_space_write_2(sc->iot, sc->aud_ioh, ICH_GSTS, ICH_POINT);
 1117                 ret++;
 1118         }
 1119 
 1120         if (gsts & ICH_PIINT) {
 1121                 sts = bus_space_read_2(sc->iot, sc->aud_ioh, ICH_PCMI+sc->sc_sts_reg);
 1122                 DPRINTF(ICH_DEBUG_DMA,
 1123                     ("auich_intr: ists=0x%x\n", sts));
 1124 
 1125                 if (sts & ICH_FIFOE) {
 1126                         printf("%s: fifo overrun # %u\n",
 1127                             sc->sc_dev.dv_xname, ++sc->pcmi_fifoe);
 1128                 }
 1129 
 1130                 i = bus_space_read_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CIV);
 1131                 if (sts & (ICH_LVBCI | ICH_CELV)) {
 1132                         struct auich_dmalist *q;
 1133 
 1134                         qptr = sc->ptr_pcmi;
 1135 
 1136                         while (qptr != i) {
 1137                                 q = &sc->dmalist_pcmi[qptr];
 1138 
 1139                                 q->base = sc->pcmi_p;
 1140                                 q->len = (sc->pcmi_blksize / sc->sc_sample_size) | ICH_DMAF_IOC;
 1141                                 DPRINTF(ICH_DEBUG_DMA,
 1142                                     ("auich_intr: %p, %p = %x @ 0x%x\n",
 1143                                     &sc->dmalist_pcmi[i], q,
 1144                                     sc->pcmi_blksize / 2, sc->pcmi_p));
 1145 
 1146                                 sc->pcmi_p += sc->pcmi_blksize;
 1147                                 if (sc->pcmi_p >= sc->pcmi_end)
 1148                                         sc->pcmi_p = sc->pcmi_start;
 1149 
 1150                                 if (++qptr == ICH_DMALIST_MAX)
 1151                                         qptr = 0;
 1152                         }
 1153 
 1154                         sc->ptr_pcmi = qptr;
 1155                         bus_space_write_1(sc->iot, sc->aud_ioh,
 1156                             ICH_PCMI + ICH_LVI,
 1157                             (sc->ptr_pcmi - 1) & ICH_LVI_MASK);
 1158                 }
 1159 
 1160                 if (sts & ICH_BCIS && sc->sc_rintr)
 1161                         sc->sc_rintr(sc->sc_rarg);
 1162 
 1163                 /* int ack */
 1164                 bus_space_write_2(sc->iot, sc->aud_ioh, ICH_PCMI + sc->sc_sts_reg,
 1165                     sts & (ICH_LVBCI | ICH_CELV | ICH_BCIS | ICH_FIFOE));
 1166                 bus_space_write_2(sc->iot, sc->aud_ioh, ICH_GSTS, ICH_PIINT);
 1167                 ret++;
 1168         }
 1169 
 1170         if (gsts & ICH_MIINT) {
 1171                 sts = bus_space_read_2(sc->iot, sc->aud_ioh, ICH_MICI+sc->sc_sts_reg);
 1172                 DPRINTF(ICH_DEBUG_DMA,
 1173                     ("auich_intr: ists=0x%x\n", sts));
 1174                 if (sts & ICH_FIFOE)
 1175                         printf("%s: fifo overrun\n", sc->sc_dev.dv_xname);
 1176 
 1177                 /* TODO mic input DMA */
 1178 
 1179                 bus_space_write_2(sc->iot, sc->aud_ioh, ICH_GSTS, ICH_MIINT);
 1180         }
 1181 
 1182         return ret;
 1183 }
 1184 
 1185 int
 1186 auich_trigger_output(void *v, void *start, void *end, int blksize,
 1187     void (*intr)(void *), void *arg, struct audio_params *param)
 1188 {
 1189         struct auich_softc *sc = v;
 1190         struct auich_dmalist *q;
 1191         struct auich_dma *p;
 1192         size_t size;
 1193 #ifdef DIAGNOSTIC
 1194         int csts;
 1195 #endif
 1196 
 1197         DPRINTF(ICH_DEBUG_DMA,
 1198             ("auich_trigger_output(%p, %p, %d, %p, %p, %p)\n",
 1199             start, end, blksize, intr, arg, param));
 1200 
 1201         sc->sc_pintr = intr;
 1202         sc->sc_parg = arg;
 1203 #ifdef DIAGNOSTIC
 1204         csts = pci_conf_read(sc->sc_pc, sc->sc_pt, PCI_COMMAND_STATUS_REG);
 1205         if (csts & PCI_STATUS_MASTER_ABORT) {
 1206                 printf("auich_trigger_output: PCI master abort\n");
 1207         }
 1208 #endif
 1209 
 1210         for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next)
 1211                 ;
 1212         if (!p) {
 1213                 printf("auich_trigger_output: bad addr %p\n", start);
 1214                 return (EINVAL);
 1215         }
 1216 
 1217         size = (size_t)((caddr_t)end - (caddr_t)start);
 1218 
 1219         /*
 1220          * The logic behind this is:
 1221          * setup one buffer to play, then LVI dump out the rest
 1222          * to the scatter-gather chain.
 1223          */
 1224         sc->pcmo_start = DMAADDR(p);
 1225         sc->pcmo_p = sc->pcmo_start + blksize;
 1226         sc->pcmo_end = sc->pcmo_start + size;
 1227         sc->pcmo_blksize = blksize;
 1228 
 1229         sc->ptr_pcmo = 0;
 1230         q = &sc->dmalist_pcmo[sc->ptr_pcmo];
 1231         q->base = sc->pcmo_start;
 1232         q->len = (blksize / sc->sc_sample_size) | ICH_DMAF_IOC;
 1233         if (++sc->ptr_pcmo == ICH_DMALIST_MAX)
 1234                 sc->ptr_pcmo = 0;
 1235 
 1236         bus_space_write_4(sc->iot, sc->aud_ioh, ICH_PCMO + ICH_BDBAR,
 1237             sc->sc_cddma + ICH_PCMO_OFF(0));
 1238         bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMO + ICH_CTRL,
 1239             ICH_IOCE | ICH_FEIE | ICH_LVBIE | ICH_RPBM);
 1240         bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMO + ICH_LVI,
 1241             (sc->ptr_pcmo - 1) & ICH_LVI_MASK);
 1242 
 1243         return (0);
 1244 }
 1245 
 1246 int
 1247 auich_trigger_input(v, start, end, blksize, intr, arg, param)
 1248         void *v;
 1249         void *start, *end;
 1250         int blksize;
 1251         void (*intr)(void *);
 1252         void *arg;
 1253         struct audio_params *param;
 1254 {
 1255         struct auich_softc *sc = v;
 1256         struct auich_dmalist *q;
 1257         struct auich_dma *p;
 1258         size_t size;
 1259 #ifdef DIAGNOSTIC
 1260         int csts;
 1261 #endif
 1262 
 1263         DPRINTF(ICH_DEBUG_DMA,
 1264             ("auich_trigger_input(%p, %p, %d, %p, %p, %p)\n",
 1265             start, end, blksize, intr, arg, param));
 1266 
 1267         sc->sc_rintr = intr;
 1268         sc->sc_rarg = arg;
 1269 
 1270 #ifdef DIAGNOSTIC
 1271         csts = pci_conf_read(sc->sc_pc, sc->sc_pt, PCI_COMMAND_STATUS_REG);
 1272         if (csts & PCI_STATUS_MASTER_ABORT) {
 1273                 printf("auich_trigger_input: PCI master abort\n");
 1274         }
 1275 #endif
 1276 
 1277         for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next)
 1278                 ;
 1279         if (!p) {
 1280                 printf("auich_trigger_input: bad addr %p\n", start);
 1281                 return (EINVAL);
 1282         }
 1283 
 1284         size = (size_t)((caddr_t)end - (caddr_t)start);
 1285 
 1286         /*
 1287          * The logic behind this is:
 1288          * setup one buffer to play, then LVI dump out the rest
 1289          * to the scatter-gather chain.
 1290          */
 1291         sc->pcmi_start = DMAADDR(p);
 1292         sc->pcmi_p = sc->pcmi_start + blksize;
 1293         sc->pcmi_end = sc->pcmi_start + size;
 1294         sc->pcmi_blksize = blksize;
 1295 
 1296         sc->ptr_pcmi = 0;
 1297         q = &sc->dmalist_pcmi[sc->ptr_pcmi];
 1298         q->base = sc->pcmi_start;
 1299         q->len = (blksize / sc->sc_sample_size) | ICH_DMAF_IOC;
 1300         if (++sc->ptr_pcmi == ICH_DMALIST_MAX)
 1301                 sc->ptr_pcmi = 0;
 1302 
 1303         bus_space_write_4(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_BDBAR,
 1304             sc->sc_cddma + ICH_PCMI_OFF(0));
 1305         bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CTRL,
 1306             ICH_IOCE | ICH_FEIE | ICH_LVBIE | ICH_RPBM);
 1307         bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_LVI,
 1308             (sc->ptr_pcmi - 1) & ICH_LVI_MASK);
 1309 
 1310         return (0);
 1311 }
 1312 
 1313 int
 1314 auich_allocmem(struct auich_softc *sc, size_t size, size_t align,
 1315     struct auich_dma *p)
 1316 {
 1317         int error;
 1318 
 1319         p->size = size;
 1320         error = bus_dmamem_alloc(sc->dmat, p->size, align, 0,
 1321                                  p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
 1322                                  &p->nsegs, BUS_DMA_NOWAIT);
 1323         if (error)
 1324                 return (error);
 1325 
 1326         error = bus_dmamem_map(sc->dmat, p->segs, p->nsegs, p->size,
 1327                                &p->addr, BUS_DMA_NOWAIT|sc->sc_dmamap_flags);
 1328         if (error)
 1329                 goto free;
 1330 
 1331         error = bus_dmamap_create(sc->dmat, p->size, 1, p->size,
 1332                                   0, BUS_DMA_NOWAIT, &p->map);
 1333         if (error)
 1334                 goto unmap;
 1335 
 1336         error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size, NULL,
 1337                                 BUS_DMA_NOWAIT);
 1338         if (error)
 1339                 goto destroy;
 1340         return (0);
 1341 
 1342  destroy:
 1343         bus_dmamap_destroy(sc->dmat, p->map);
 1344  unmap:
 1345         bus_dmamem_unmap(sc->dmat, p->addr, p->size);
 1346  free:
 1347         bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
 1348         return (error);
 1349 }
 1350 
 1351 int
 1352 auich_freemem(struct auich_softc *sc, struct auich_dma *p)
 1353 {
 1354 
 1355         bus_dmamap_unload(sc->dmat, p->map);
 1356         bus_dmamap_destroy(sc->dmat, p->map);
 1357         bus_dmamem_unmap(sc->dmat, p->addr, p->size);
 1358         bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
 1359         return (0);
 1360 }
 1361 
 1362 int
 1363 auich_alloc_cdata(struct auich_softc *sc)
 1364 {
 1365         bus_dma_segment_t seg;
 1366         int error, rseg;
 1367 
 1368         /*
 1369          * Allocate the control data structure, and create and load the
 1370          * DMA map for it.
 1371          */
 1372         if ((error = bus_dmamem_alloc(sc->dmat,
 1373                                       sizeof(struct auich_cdata),
 1374                                       PAGE_SIZE, 0, &seg, 1, &rseg, 0)) != 0) {
 1375                 printf("%s: unable to allocate control data, error = %d\n",
 1376                     sc->sc_dev.dv_xname, error);
 1377                 goto fail_0;
 1378         }
 1379 
 1380         if ((error = bus_dmamem_map(sc->dmat, &seg, rseg,
 1381                                     sizeof(struct auich_cdata),
 1382                                     (caddr_t *) &sc->sc_cdata,
 1383                                     sc->sc_dmamap_flags)) != 0) {
 1384                 printf("%s: unable to map control data, error = %d\n",
 1385                     sc->sc_dev.dv_xname, error);
 1386                 goto fail_1;
 1387         }
 1388 
 1389         if ((error = bus_dmamap_create(sc->dmat, sizeof(struct auich_cdata), 1,
 1390                                        sizeof(struct auich_cdata), 0, 0,
 1391                                        &sc->sc_cddmamap)) != 0) {
 1392                 printf("%s: unable to create control data DMA map, "
 1393                     "error = %d\n", sc->sc_dev.dv_xname, error);
 1394                 goto fail_2;
 1395         }
 1396 
 1397         if ((error = bus_dmamap_load(sc->dmat, sc->sc_cddmamap,
 1398                                      sc->sc_cdata, sizeof(struct auich_cdata),
 1399                                      NULL, 0)) != 0) {
 1400                 printf("%s: unable tp load control data DMA map, "
 1401                     "error = %d\n", sc->sc_dev.dv_xname, error);
 1402                 goto fail_3;
 1403         }
 1404 
 1405         return (0);
 1406 
 1407  fail_3:
 1408         bus_dmamap_destroy(sc->dmat, sc->sc_cddmamap);
 1409  fail_2:
 1410         bus_dmamem_unmap(sc->dmat, (caddr_t) sc->sc_cdata,
 1411             sizeof(struct auich_cdata));
 1412  fail_1:
 1413         bus_dmamem_free(sc->dmat, &seg, rseg);
 1414  fail_0:
 1415         return (error);
 1416 }
 1417 
 1418 void
 1419 auich_powerhook(int why, void *addr)
 1420 {
 1421         struct auich_softc *sc = (struct auich_softc *)addr;
 1422 
 1423         switch (why) {
 1424         case PWR_SUSPEND:
 1425         case PWR_STANDBY:
 1426                 /* Power down */
 1427                 DPRINTF(1, ("%s: power down\n", sc->sc_dev.dv_xname));
 1428                 sc->sc_suspend = why;
 1429                 auich_read_codec(sc, AC97_REG_EXT_AUDIO_CTRL, &sc->ext_status);
 1430                 break;
 1431 
 1432         case PWR_RESUME:
 1433                 /* Wake up */
 1434                 DPRINTF(1, ("%s: power resume\n", sc->sc_dev.dv_xname));
 1435                 if (sc->sc_suspend == PWR_RESUME) {
 1436                         printf("%s: resume without suspend.\n",
 1437                             sc->sc_dev.dv_xname);
 1438                         sc->sc_suspend = why;
 1439                         return;
 1440                 }
 1441                 sc->sc_suspend = why;
 1442                 auich_reset_codec(sc);
 1443                 DELAY(1000);
 1444                 (sc->codec_if->vtbl->restore_ports)(sc->codec_if);
 1445                 auich_write_codec(sc, AC97_REG_EXT_AUDIO_CTRL, sc->ext_status);
 1446                 break;
 1447 
 1448         case PWR_SOFTSUSPEND:
 1449         case PWR_SOFTSTANDBY:
 1450         case PWR_SOFTRESUME:
 1451                 break;
 1452         }
 1453 }
 1454 
 1455 
 1456 /* -------------------------------------------------------------------- */
 1457 /* Calibrate card (some boards are overclocked and need scaling) */
 1458 
 1459 void
 1460 auich_calibrate(struct auich_softc *sc)
 1461 {
 1462         struct timeval t1, t2;
 1463         uint8_t ociv, nciv;
 1464         uint64_t wait_us;
 1465         uint32_t actual_48k_rate, bytes, ac97rate;
 1466         void *temp_buffer;
 1467         struct auich_dma *p;
 1468         u_long rate;
 1469 
 1470         /*
 1471          * Grab audio from input for fixed interval and compare how
 1472          * much we actually get with what we expect.  Interval needs
 1473          * to be sufficiently short that no interrupts are
 1474          * generated.
 1475          */
 1476 
 1477         /* Force the codec to a known state first. */
 1478         sc->codec_if->vtbl->set_clock(sc->codec_if, 48000);
 1479         rate = 48000;
 1480         sc->codec_if->vtbl->set_rate(sc->codec_if, AC97_REG_PCM_LR_ADC_RATE,
 1481             &rate);
 1482 
 1483         /* Setup a buffer */
 1484         bytes = 64000;
 1485         temp_buffer = auich_allocm(sc, AUMODE_RECORD, bytes, M_DEVBUF, M_WAITOK);
 1486 
 1487         for (p = sc->sc_dmas; p && KERNADDR(p) != temp_buffer; p = p->next)
 1488                 ;
 1489         if (p == NULL) {
 1490                 printf("auich_calibrate: bad address %p\n", temp_buffer);
 1491                 return;
 1492         }
 1493         sc->dmalist_pcmi[0].base = DMAADDR(p);
 1494         sc->dmalist_pcmi[0].len = (bytes / sc->sc_sample_size);
 1495 
 1496         /*
 1497          * our data format is stereo, 16 bit so each sample is 4 bytes.
 1498          * assuming we get 48000 samples per second, we get 192000 bytes/sec.
 1499          * we're going to start recording with interrupts disabled and measure
 1500          * the time taken for one block to complete.  we know the block size,
 1501          * we know the time in microseconds, we calculate the sample rate:
 1502          *
 1503          * actual_rate [bps] = bytes / (time [s] * 4)
 1504          * actual_rate [bps] = (bytes * 1000000) / (time [us] * 4)
 1505          * actual_rate [Hz] = (bytes * 250000) / time [us]
 1506          */
 1507 
 1508         /* prepare */
 1509         ociv = bus_space_read_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CIV);
 1510         bus_space_write_4(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_BDBAR,
 1511                           sc->sc_cddma + ICH_PCMI_OFF(0));
 1512         bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_LVI,
 1513                           (0 - 1) & ICH_LVI_MASK);
 1514 
 1515         /* start */
 1516         microtime(&t1);
 1517         bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CTRL, ICH_RPBM);
 1518 
 1519         /* wait */
 1520         nciv = ociv;
 1521         do {
 1522                 microtime(&t2);
 1523                 if (t2.tv_sec - t1.tv_sec > 1)
 1524                         break;
 1525                 nciv = bus_space_read_1(sc->iot, sc->aud_ioh,
 1526                                         ICH_PCMI + ICH_CIV);
 1527         } while (nciv == ociv);
 1528         microtime(&t2);
 1529 
 1530         /* stop */
 1531         bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CTRL, 0);
 1532 
 1533         /* reset */
 1534         DELAY(100);
 1535         bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CTRL, ICH_RR);
 1536 
 1537         /* turn time delta into us */
 1538         wait_us = ((t2.tv_sec - t1.tv_sec) * 1000000) + t2.tv_usec - t1.tv_usec;
 1539 
 1540         auich_freem(sc, temp_buffer, M_DEVBUF);
 1541 
 1542         if (nciv == ociv) {
 1543                 printf("%s: ac97 link rate calibration timed out after %"
 1544                        PRIu64 " us\n", sc->sc_dev.dv_xname, wait_us);
 1545                 return;
 1546         }
 1547 
 1548         actual_48k_rate = (bytes * UINT64_C(250000)) / wait_us;
 1549 
 1550         if (actual_48k_rate < 50000)
 1551                 ac97rate = 48000;
 1552         else
 1553                 ac97rate = ((actual_48k_rate + 500) / 1000) * 1000;
 1554 
 1555         printf("%s: measured ac97 link rate at %d Hz",
 1556                sc->sc_dev.dv_xname, actual_48k_rate);
 1557         if (ac97rate != actual_48k_rate)
 1558                 printf(", will use %d Hz", ac97rate);
 1559         printf("\n");
 1560 
 1561         sc->codec_if->vtbl->set_clock(sc->codec_if, ac97rate);
 1562 }

Cache object: 5c8f2dff3a941875bcc4c0591c476556


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.