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/autri.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: autri.c,v 1.18.2.1 2004/09/22 20:58:12 jmc Exp $       */
    2 
    3 /*
    4  * Copyright (c) 2001 SOMEYA Yoshihiko and KUROSAWA Takahiro.
    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 BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  */
   27 
   28 /* 
   29  * Trident 4DWAVE-DX/NX, SiS 7018, ALi M5451 Sound Driver
   30  * 
   31  * The register information is taken from the ALSA driver.
   32  *
   33  * Documentation links:
   34  * - ftp://ftp.alsa-project.org/pub/manuals/trident/
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __KERNEL_RCSID(0, "$NetBSD: autri.c,v 1.18.2.1 2004/09/22 20:58:12 jmc Exp $");
   39 
   40 #include "midi.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/fcntl.h>
   46 #include <sys/malloc.h>
   47 #include <sys/device.h>
   48 #include <sys/proc.h>
   49 
   50 #include <dev/pci/pcidevs.h>
   51 #include <dev/pci/pcireg.h>
   52 #include <dev/pci/pcivar.h>
   53 
   54 #include <sys/audioio.h>
   55 #include <dev/audio_if.h>
   56 #include <dev/midi_if.h>
   57 #include <dev/mulaw.h>
   58 #include <dev/auconv.h>
   59 #include <dev/ic/ac97reg.h>
   60 #include <dev/ic/ac97var.h>
   61 #include <dev/ic/mpuvar.h>
   62 
   63 #include <machine/bus.h>
   64 #include <machine/intr.h>
   65 
   66 #include <dev/pci/autrireg.h>
   67 #include <dev/pci/autrivar.h>
   68 
   69 #ifdef AUDIO_DEBUG
   70 # define DPRINTF(x)     if (autridebug) printf x
   71 # define DPRINTFN(n,x)  if (autridebug > (n)) printf x
   72 int autridebug = 0;
   73 #else
   74 # define DPRINTF(x)
   75 # define DPRINTFN(n,x)
   76 #endif
   77 
   78 int     autri_match(struct device *, struct cfdata *, void *);
   79 void    autri_attach(struct device *, struct device *, void *);
   80 int     autri_intr(void *);
   81 
   82 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
   83 #define KERNADDR(p) ((void *)((p)->addr))
   84 
   85 int     autri_allocmem(struct autri_softc *, size_t,
   86                        size_t, struct autri_dma *);
   87 int     autri_freemem(struct autri_softc *, struct autri_dma *);
   88 
   89 #define TWRITE1(sc, r, x) bus_space_write_1((sc)->memt, (sc)->memh, (r), (x))
   90 #define TWRITE2(sc, r, x) bus_space_write_2((sc)->memt, (sc)->memh, (r), (x))
   91 #define TWRITE4(sc, r, x) bus_space_write_4((sc)->memt, (sc)->memh, (r), (x))
   92 #define TREAD1(sc, r) bus_space_read_1((sc)->memt, (sc)->memh, (r))
   93 #define TREAD2(sc, r) bus_space_read_2((sc)->memt, (sc)->memh, (r))
   94 #define TREAD4(sc, r) bus_space_read_4((sc)->memt, (sc)->memh, (r))
   95 
   96 static __inline void autri_reg_set_1(struct autri_softc *, int, uint8_t);
   97 static __inline void autri_reg_clear_1(struct autri_softc *, int, uint8_t);
   98 static __inline void autri_reg_set_4(struct autri_softc *, int, uint32_t);
   99 static __inline void autri_reg_clear_4(struct autri_softc *, int, uint32_t);
  100 
  101 int     autri_attach_codec(void *sc, struct ac97_codec_if *);
  102 int     autri_read_codec(void *sc, u_int8_t a, u_int16_t *d);
  103 int     autri_write_codec(void *sc, u_int8_t a, u_int16_t d);
  104 int     autri_reset_codec(void *sc);
  105 enum ac97_host_flags    autri_flags_codec(void *sc);
  106 
  107 static void autri_powerhook(int why,void *addr);
  108 static int  autri_init(void *sc);
  109 static struct autri_dma *autri_find_dma(struct autri_softc *, void *);
  110 static void autri_setup_channel(struct autri_softc *sc,int mode,
  111                                 struct audio_params *param);
  112 static void autri_enable_interrupt(struct autri_softc *sc, int ch);
  113 static void autri_disable_interrupt(struct autri_softc *sc, int ch);
  114 static void autri_startch(struct autri_softc *sc, int ch, int ch_intr);
  115 static void autri_stopch(struct autri_softc *sc, int ch, int ch_intr);
  116 static void autri_enable_loop_interrupt(void *sc);
  117 #if 0
  118 static void autri_disable_loop_interrupt(void *sc);
  119 #endif
  120 
  121 CFATTACH_DECL(autri, sizeof(struct autri_softc),
  122     autri_match, autri_attach, NULL, NULL);
  123 
  124 int     autri_open(void *, int);
  125 void    autri_close(void *);
  126 int     autri_query_encoding(void *, struct audio_encoding *);
  127 int     autri_set_params(void *, int, int,
  128                          struct audio_params *, struct audio_params *);
  129 int     autri_round_blocksize(void *, int);
  130 int     autri_trigger_output(void *, void *, void *, int, void (*)(void *),
  131                              void *, struct audio_params *);
  132 int     autri_trigger_input(void *, void *, void *, int, void (*)(void *),
  133                             void *, struct audio_params *);
  134 int     autri_halt_output(void *);
  135 int     autri_halt_input(void *);
  136 int     autri_getdev(void *, struct audio_device *);
  137 int     autri_mixer_set_port(void *, mixer_ctrl_t *);
  138 int     autri_mixer_get_port(void *, mixer_ctrl_t *);
  139 void*   autri_malloc(void *, int, size_t, struct malloc_type *, int);
  140 void    autri_free(void *, void *, struct malloc_type *);
  141 size_t  autri_round_buffersize(void *, int, size_t);
  142 paddr_t autri_mappage(void *, void *, off_t, int);
  143 int     autri_get_props(void *);
  144 int     autri_query_devinfo(void *addr, mixer_devinfo_t *dip);
  145 
  146 int     autri_get_portnum_by_name(struct autri_softc *, char *, char *, char *);
  147 
  148 static struct audio_hw_if autri_hw_if = {
  149         autri_open,
  150         autri_close,
  151         NULL,                   /* drain */
  152         autri_query_encoding,
  153         autri_set_params,
  154         autri_round_blocksize,
  155         NULL,                   /* commit_settings */
  156         NULL,                   /* init_output */
  157         NULL,                   /* init_input */
  158         NULL,                   /* start_output */
  159         NULL,                   /* start_input */
  160         autri_halt_output,
  161         autri_halt_input,
  162         NULL,                   /* speaker_ctl */
  163         autri_getdev,
  164         NULL,                   /* setfd */
  165         autri_mixer_set_port,
  166         autri_mixer_get_port,
  167         autri_query_devinfo,
  168         autri_malloc,
  169         autri_free,
  170         autri_round_buffersize,
  171         autri_mappage,
  172         autri_get_props,
  173         autri_trigger_output,
  174         autri_trigger_input,
  175         NULL,                   /* dev_ioctl */
  176 };
  177 
  178 #if NMIDI > 0
  179 void    autri_midi_close(void *);
  180 void    autri_midi_getinfo(void *, struct midi_info *);
  181 int     autri_midi_open(void *, int, void (*)(void *, int),
  182                            void (*)(void *), void *);
  183 int     autri_midi_output(void *, int);
  184 
  185 struct midi_hw_if autri_midi_hw_if = {
  186         autri_midi_open,
  187         autri_midi_close,
  188         autri_midi_output,
  189         autri_midi_getinfo,
  190         NULL,                   /* ioctl */
  191 };
  192 #endif
  193 
  194 /*
  195  * register set/clear bit
  196  */
  197 static __inline void
  198 autri_reg_set_1(struct autri_softc *sc, int no, uint8_t mask)
  199 {
  200         bus_space_write_1(sc->memt, sc->memh, no,
  201             (bus_space_read_1(sc->memt, sc->memh, no) | mask));
  202 }
  203 
  204 static __inline void
  205 autri_reg_clear_1(struct autri_softc *sc, int no, uint8_t mask)
  206 {
  207         bus_space_write_1(sc->memt, sc->memh, no,
  208             (bus_space_read_1(sc->memt, sc->memh, no) & ~mask));
  209 }
  210 
  211 static __inline void
  212 autri_reg_set_4(struct autri_softc *sc, int no, uint32_t mask)
  213 {
  214         bus_space_write_4(sc->memt, sc->memh, no,
  215             (bus_space_read_4(sc->memt, sc->memh, no) | mask));
  216 }
  217 
  218 static __inline void
  219 autri_reg_clear_4(struct autri_softc *sc, int no, uint32_t mask)
  220 {
  221         bus_space_write_4(sc->memt, sc->memh, no,
  222             (bus_space_read_4(sc->memt, sc->memh, no) & ~mask));
  223 }
  224 
  225 /*
  226  * AC'97 codec
  227  */
  228 int
  229 autri_attach_codec(void *sc_, struct ac97_codec_if *codec_if)
  230 {
  231         struct autri_codec_softc *sc = sc_;
  232 
  233         DPRINTF(("autri_attach_codec()\n"));
  234 
  235         sc->codec_if = codec_if;
  236         return 0;
  237 }
  238 
  239 int
  240 autri_read_codec(void *sc_, u_int8_t index, u_int16_t *data)
  241 {
  242         struct autri_codec_softc *codec = sc_;
  243         struct autri_softc *sc = codec->sc;
  244         u_int32_t status, addr, cmd, busy;
  245         u_int16_t count;
  246 
  247         /*DPRINTF(("sc->sc->type : 0x%X",sc->sc->type));*/
  248 
  249         switch (sc->sc_devid) {
  250         case AUTRI_DEVICE_ID_4DWAVE_DX:
  251                 addr = AUTRI_DX_ACR1;
  252                 cmd  = AUTRI_DX_ACR1_CMD_READ;
  253                 busy = AUTRI_DX_ACR1_BUSY_READ;
  254                 break;
  255         case AUTRI_DEVICE_ID_4DWAVE_NX:
  256                 addr = AUTRI_NX_ACR2;
  257                 cmd  = AUTRI_NX_ACR2_CMD_READ;
  258                 busy = AUTRI_NX_ACR2_BUSY_READ | AUTRI_NX_ACR2_RECV_WAIT;
  259                 break;
  260         case AUTRI_DEVICE_ID_SIS_7018:
  261                 addr = AUTRI_SIS_ACRD;
  262                 cmd  = AUTRI_SIS_ACRD_CMD_READ;
  263                 busy = AUTRI_SIS_ACRD_BUSY_READ | AUTRI_SIS_ACRD_AUDIO_BUSY;
  264                 break;
  265         case AUTRI_DEVICE_ID_ALI_M5451:
  266                 if (sc->sc_revision > 0x01)
  267                         addr = AUTRI_ALI_ACWR;
  268                 else
  269                         addr = AUTRI_ALI_ACRD;
  270                 cmd  = AUTRI_ALI_ACRD_CMD_READ;
  271                 busy = AUTRI_ALI_ACRD_BUSY_READ;
  272                 break;
  273         default:
  274                 printf("%s: autri_read_codec : unknown device\n",
  275                        sc->sc_dev.dv_xname);
  276                 return -1;
  277         }
  278 
  279         /* wait for 'Ready to Read' */
  280         for (count=0; count<0xffff; count++) {
  281                 if ((TREAD4(sc, addr) & busy) == 0)
  282                         break;
  283         }
  284 
  285         if (count == 0xffff) {
  286                 printf("%s: Codec timeout. Busy reading AC'97 codec.\n",
  287                        sc->sc_dev.dv_xname);
  288                 return -1;
  289         }
  290 
  291         /* send Read Command to AC'97 */
  292         TWRITE4(sc, addr, (index & 0x7f) | cmd);
  293 
  294         /* wait for 'Returned data is avalable' */
  295         for (count=0; count<0xffff; count++) {
  296                 status = TREAD4(sc, addr);
  297                 if ((status & busy) == 0)
  298                         break;
  299         }
  300 
  301         if (count == 0xffff) {
  302                 printf("%s: Codec timeout. Busy reading AC'97 codec.\n",
  303                        sc->sc_dev.dv_xname);
  304                 return -1;
  305         }
  306 
  307         *data =  (status >> 16) & 0x0000ffff;
  308         /*DPRINTF(("autri_read_codec(0x%X) return 0x%X\n",reg,*data));*/
  309         return 0;
  310 }
  311 
  312 int
  313 autri_write_codec(void *sc_, u_int8_t index, u_int16_t data)
  314 {
  315         struct autri_codec_softc *codec = sc_;
  316         struct autri_softc *sc = codec->sc;
  317         u_int32_t addr, cmd, busy;
  318         u_int16_t count;
  319 
  320         /*DPRINTF(("autri_write_codec(0x%X,0x%X)\n",index,data));*/
  321 
  322         switch (sc->sc_devid) {
  323         case AUTRI_DEVICE_ID_4DWAVE_DX:
  324                 addr = AUTRI_DX_ACR0;
  325                 cmd  = AUTRI_DX_ACR0_CMD_WRITE;
  326                 busy = AUTRI_DX_ACR0_BUSY_WRITE;
  327                 break;
  328         case AUTRI_DEVICE_ID_4DWAVE_NX:
  329                 addr = AUTRI_NX_ACR1;
  330                 cmd  = AUTRI_NX_ACR1_CMD_WRITE;
  331                 busy = AUTRI_NX_ACR1_BUSY_WRITE;
  332                 break;
  333         case AUTRI_DEVICE_ID_SIS_7018:
  334                 addr = AUTRI_SIS_ACWR;
  335                 cmd  = AUTRI_SIS_ACWR_CMD_WRITE;
  336                 busy = AUTRI_SIS_ACWR_BUSY_WRITE | AUTRI_SIS_ACWR_AUDIO_BUSY;
  337                 break;
  338         case AUTRI_DEVICE_ID_ALI_M5451:
  339                 addr = AUTRI_ALI_ACWR;
  340                 cmd  = AUTRI_ALI_ACWR_CMD_WRITE;
  341                 if (sc->sc_revision > 0x01)
  342                         cmd  |= 0x0100;
  343                 busy = AUTRI_ALI_ACWR_BUSY_WRITE;
  344                 break;
  345         default:
  346                 printf("%s: autri_write_codec : unknown device.\n",
  347                        sc->sc_dev.dv_xname);
  348                 return -1;
  349         }
  350 
  351         /* wait for 'Ready to Write' */
  352         for (count=0; count<0xffff; count++) {
  353                 if ((TREAD4(sc, addr) & busy) == 0)
  354                         break;
  355         }
  356 
  357         if (count == 0xffff) {
  358                 printf("%s: Codec timeout. Busy writing AC'97 codec\n",
  359                        sc->sc_dev.dv_xname);
  360                 return -1;
  361         }
  362 
  363         /* send Write Command to AC'97 */
  364         TWRITE4(sc, addr, (data << 16) | (index & 0x7f) | cmd);
  365 
  366         return 0;
  367 }
  368 
  369 int
  370 autri_reset_codec(void *sc_)
  371 {
  372         struct autri_codec_softc *codec = sc_;
  373         struct autri_softc *sc = codec->sc;
  374         u_int32_t reg, ready;
  375         int addr, count = 200;
  376 
  377         DPRINTF(("autri_reset_codec(codec=%p,sc=%p)\n",codec,sc));
  378         DPRINTF(("sc->sc_devid=%X\n",sc->sc_devid));
  379 
  380         switch (sc->sc_devid) {
  381         case AUTRI_DEVICE_ID_4DWAVE_DX:
  382                 /* warm reset AC'97 codec */
  383                 autri_reg_set_4(sc, AUTRI_DX_ACR2, 1);
  384                 delay(100);
  385                 /* release reset */
  386                 autri_reg_clear_4(sc, AUTRI_DX_ACR2, 1);
  387                 delay(100);
  388 
  389                 addr = AUTRI_DX_ACR2;
  390                 ready = AUTRI_DX_ACR2_CODEC_READY;
  391                 break;
  392         case AUTRI_DEVICE_ID_4DWAVE_NX:
  393                 /* warm reset AC'97 codec */
  394                 autri_reg_set_4(sc, AUTRI_NX_ACR0, 1);
  395                 delay(100);
  396                 /* release reset */
  397                 autri_reg_clear_4(sc, AUTRI_NX_ACR0, 1);
  398                 delay(100);
  399 
  400                 addr = AUTRI_NX_ACR0;
  401                 ready = AUTRI_NX_ACR0_CODEC_READY;
  402                 break;
  403         case AUTRI_DEVICE_ID_SIS_7018:
  404                 /* cold reset AC'97 codec */
  405                 autri_reg_set_4(sc, AUTRI_SIS_SCTRL, 2);
  406                 delay(1000);
  407                 /* release reset (warm & cold) */
  408                 autri_reg_clear_4(sc, AUTRI_SIS_SCTRL, 3);
  409                 delay(2000);
  410 
  411                 addr = AUTRI_SIS_SCTRL;
  412                 ready = AUTRI_SIS_SCTRL_CODEC_READY;
  413                 break;
  414         case AUTRI_DEVICE_ID_ALI_M5451:
  415                 /* warm reset AC'97 codec */
  416                 autri_reg_set_4(sc, AUTRI_ALI_SCTRL, 1);
  417                 delay(100);
  418                 /* release reset (warm & cold) */
  419                 autri_reg_clear_4(sc, AUTRI_ALI_SCTRL, 3);
  420                 delay(100);
  421 
  422                 addr = AUTRI_ALI_SCTRL;
  423                 ready = AUTRI_ALI_SCTRL_CODEC_READY;
  424                 break;
  425         default:
  426                 printf("%s: autri_reset_codec : unknown device\n",
  427                        sc->sc_dev.dv_xname);
  428                 return EOPNOTSUPP;
  429         }
  430 
  431         /* wait for 'Codec Ready' */
  432         while (count--) {
  433                 reg = TREAD4(sc, addr);
  434                 if (reg & ready)
  435                         break;
  436                 delay(1000);
  437         }
  438 
  439         if (count == 0) {
  440                 printf("%s: Codec timeout. AC'97 is not ready for operation.\n",
  441                        sc->sc_dev.dv_xname);
  442                 return ETIMEDOUT;
  443         }
  444         return 0;
  445 }
  446 
  447 enum ac97_host_flags
  448 autri_flags_codec(void *sc_)
  449 {
  450         return AC97_HOST_DONT_READ;
  451 }
  452 
  453 /*
  454  *
  455  */
  456 
  457 int
  458 autri_match(struct device *parent, struct cfdata *match, void *aux)
  459 {
  460         struct pci_attach_args *pa = (struct pci_attach_args *) aux;
  461 
  462         switch (PCI_VENDOR(pa->pa_id)) {
  463         case PCI_VENDOR_TRIDENT:
  464                 switch (PCI_PRODUCT(pa->pa_id)) {
  465                 case PCI_PRODUCT_TRIDENT_4DWAVE_DX:
  466                 case PCI_PRODUCT_TRIDENT_4DWAVE_NX:
  467                         return 1;
  468                 }
  469                 break;
  470         case PCI_VENDOR_SIS:
  471                 switch (PCI_PRODUCT(pa->pa_id)) {
  472                 case PCI_PRODUCT_SIS_7018:
  473                         return 1;
  474                 }
  475                 break;
  476         case PCI_VENDOR_ALI:
  477                 switch (PCI_PRODUCT(pa->pa_id)) {
  478                 case PCI_PRODUCT_ALI_M5451:
  479                         return 1;
  480                 }
  481                 break;
  482         }
  483 
  484         return 0;
  485 }
  486 
  487 void
  488 autri_attach(struct device *parent, struct device *self, void *aux)
  489 {
  490         struct autri_softc *sc = (struct autri_softc *)self;
  491         struct pci_attach_args *pa = (struct pci_attach_args *)aux;
  492         pci_chipset_tag_t pc = pa->pa_pc;
  493         struct autri_codec_softc *codec;
  494         pci_intr_handle_t ih;
  495         char const *intrstr;
  496         char devinfo[256];
  497         mixer_ctrl_t ctl;
  498         int i, r;
  499         u_int32_t reg;
  500 
  501         aprint_naive(": Audio controller\n");
  502 
  503         sc->sc_devid = pa->pa_id;
  504         sc->sc_class = pa->pa_class;
  505 
  506         pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
  507         sc->sc_revision = PCI_REVISION(pa->pa_class);
  508         aprint_normal(": %s (rev. 0x%02x)\n", devinfo, sc->sc_revision);
  509 
  510         /* map register to memory */
  511         if (pci_mapreg_map(pa, AUTRI_PCI_MEMORY_BASE,
  512             PCI_MAPREG_TYPE_MEM, 0, &sc->memt, &sc->memh, NULL, NULL)) {
  513                 aprint_error("%s: can't map memory space\n",
  514                     sc->sc_dev.dv_xname);
  515                 return;
  516         }
  517 
  518         /* map and establish the interrupt */
  519         if (pci_intr_map(pa, &ih)) {
  520                 aprint_error("%s: couldn't map interrupt\n",
  521                     sc->sc_dev.dv_xname);
  522                 return;
  523         }
  524         intrstr = pci_intr_string(pc, ih);
  525         sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, autri_intr, sc);
  526         if (sc->sc_ih == NULL) {
  527                 aprint_error("%s: couldn't establish interrupt",
  528                     sc->sc_dev.dv_xname);
  529                 if (intrstr != NULL)
  530                         aprint_normal(" at %s", intrstr);
  531                 aprint_normal("\n");
  532                 return;
  533         }
  534         aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
  535 
  536         sc->sc_dmatag = pa->pa_dmat;
  537         sc->sc_pc = pc;
  538         sc->sc_pt = pa->pa_tag;
  539 
  540         /* enable the device */
  541         reg = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
  542         reg |= (PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE);
  543         pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg);
  544 
  545         /* initialize the device */
  546         autri_init(sc);
  547 
  548         /* attach AC'97 codec */
  549         codec = &sc->sc_codec;
  550         memcpy(&codec->sc_dev, &sc->sc_dev, sizeof(codec->sc_dev));
  551         codec->sc = sc;
  552 
  553         codec->host_if.arg = codec;
  554         codec->host_if.attach = autri_attach_codec;
  555         codec->host_if.reset = autri_reset_codec;
  556         codec->host_if.read = autri_read_codec;
  557         codec->host_if.write = autri_write_codec;
  558         codec->host_if.flags = autri_flags_codec;
  559 
  560         if ((r = ac97_attach(&codec->host_if)) != 0) {
  561                 aprint_error("%s: can't attach codec (error 0x%X)\n",
  562                     sc->sc_dev.dv_xname, r);
  563                 return;
  564         }
  565 
  566         /* disable mutes */
  567         for (i = 0; i < 4; i++) {
  568                 static struct {
  569                         char *class, *device;
  570                 } d[] = {
  571                         { AudioCoutputs, AudioNmaster},
  572                         { AudioCinputs, AudioNdac},
  573                         { AudioCinputs, AudioNcd},
  574                         { AudioCrecord, AudioNvolume},
  575                 };
  576 
  577                 ctl.type = AUDIO_MIXER_ENUM;
  578                 ctl.un.ord = 0;
  579 
  580 #if 0
  581                 ctl.dev = sc->sc_codec.codec_if->vtbl->get_portnum_by_name(sc->sc_codec.codec_if,
  582                     d[i].class, d[i].device, AudioNmute);
  583 #endif
  584                 ctl.dev = autri_get_portnum_by_name(sc,d[i].class, 
  585                                                    d[i].device, AudioNmute);
  586                 autri_mixer_set_port(sc, &ctl);
  587         }
  588 
  589         /* set a reasonable default volume */
  590         ctl.type = AUDIO_MIXER_VALUE;
  591         ctl.un.value.num_channels = 2;
  592         ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
  593         ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127;
  594 
  595         ctl.dev = autri_get_portnum_by_name(sc,AudioCoutputs,AudioNmaster,NULL);
  596         autri_mixer_set_port(sc, &ctl);
  597 
  598         audio_attach_mi(&autri_hw_if, sc, &sc->sc_dev);
  599 
  600 #if NMIDI > 0
  601         midi_attach_mi(&autri_midi_hw_if, sc, &sc->sc_dev);
  602 #endif
  603 
  604         sc->sc_old_power = PWR_RESUME;
  605         powerhook_establish(autri_powerhook, sc);
  606 }
  607 
  608 static void
  609 autri_powerhook(int why, void *addr)
  610 {
  611         struct autri_softc *sc = addr;
  612 
  613         if (why == PWR_RESUME && sc->sc_old_power == PWR_SUSPEND) {
  614                 DPRINTF(("PWR_RESUME\n"));
  615                 autri_init(sc);
  616                 /*autri_reset_codec(&sc->sc_codec);*/
  617                 (sc->sc_codec.codec_if->vtbl->restore_ports)(sc->sc_codec.codec_if);
  618         }
  619         sc->sc_old_power = why;
  620 }
  621 
  622 int
  623 autri_init(void *sc_)
  624 {
  625         struct autri_softc *sc = sc_;
  626         u_int32_t reg;
  627 
  628         pci_chipset_tag_t pc = sc->sc_pc;
  629         pcitag_t pt = sc->sc_pt;
  630 
  631         DPRINTF(("in autri_init()\n"));
  632         DPRINTFN(5,("pci_conf_read(0x40) : 0x%X\n",pci_conf_read(pc,pt,0x40)));
  633         DPRINTFN(5,("pci_conf_read(0x44) : 0x%X\n",pci_conf_read(pc,pt,0x44)));
  634 
  635         switch (sc->sc_devid) {
  636         case AUTRI_DEVICE_ID_4DWAVE_DX:
  637                 /* disable Legacy Control */
  638                 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
  639                 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
  640                 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
  641                 delay(100);
  642                 /* audio engine reset */
  643                 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
  644                 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00040000);
  645                 delay(100);
  646                 /* release reset */
  647                 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
  648                 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
  649                 delay(100);
  650                 /* DAC on */
  651                 autri_reg_set_4(sc,AUTRI_DX_ACR2,0x02);
  652                 break;
  653         case AUTRI_DEVICE_ID_4DWAVE_NX:
  654                 /* disable Legacy Control */
  655                 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
  656                 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
  657                 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
  658                 delay(100);
  659                 /* audio engine reset */
  660                 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
  661                 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00010000);
  662                 delay(100);
  663                 /* release reset */
  664                 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
  665                 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00010000);
  666                 delay(100);
  667                 /* DAC on */
  668                 autri_reg_set_4(sc,AUTRI_NX_ACR0,0x02);
  669                 break;
  670         case AUTRI_DEVICE_ID_SIS_7018:
  671                 /* disable Legacy Control */
  672                 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
  673                 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
  674                 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
  675                 delay(100);
  676                 /* reset Digital Controller */
  677                 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
  678                 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000);
  679                 delay(100);
  680                 /* release reset */
  681                 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
  682                 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
  683                 delay(100);
  684                 /* disable AC97 GPIO interrupt */
  685                 TWRITE1(sc, AUTRI_SIS_ACGPIO, 0);
  686                 /* enable 64 channel mode */
  687                 autri_reg_set_4(sc, AUTRI_LFO_GC_CIR, BANK_B_EN);
  688                 break;
  689         case AUTRI_DEVICE_ID_ALI_M5451:
  690                 /* disable Legacy Control */
  691                 pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
  692                 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
  693                 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
  694                 delay(100);
  695                 /* reset Digital Controller */
  696                 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
  697                 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000);
  698                 delay(100);
  699                 /* release reset */
  700                 reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
  701                 pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
  702                 delay(100);
  703                 /* enable PCM input */
  704                 autri_reg_set_4(sc, AUTRI_ALI_GCONTROL, AUTRI_ALI_GCONTROL_PCM_IN);
  705                 break;
  706         }
  707 
  708         if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) {
  709                 sc->sc_play.ch      = 0;
  710                 sc->sc_play.ch_intr = 1;
  711                 sc->sc_rec.ch       = 31;
  712                 sc->sc_rec.ch_intr  = 2;
  713         } else {
  714                 sc->sc_play.ch      = 0x20;
  715                 sc->sc_play.ch_intr = 0x21;
  716                 sc->sc_rec.ch       = 0x22;
  717                 sc->sc_rec.ch_intr  = 0x23;
  718         }
  719 
  720         /* clear channel status */
  721         TWRITE4(sc, AUTRI_STOP_A, 0xffffffff);
  722         TWRITE4(sc, AUTRI_STOP_B, 0xffffffff);
  723 
  724         /* disable channel interrupt */
  725         TWRITE4(sc, AUTRI_AINTEN_A, 0);
  726         TWRITE4(sc, AUTRI_AINTEN_B, 0);
  727 
  728 #if 0
  729         /* TLB */
  730         if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
  731                 TWRITE4(sc,AUTRI_NX_TLBC,0);
  732         }
  733 #endif
  734 
  735         autri_enable_loop_interrupt(sc);
  736 
  737         DPRINTF(("out autri_init()\n"));
  738         return 0;
  739 }
  740 
  741 static void
  742 autri_enable_loop_interrupt(void *sc_)
  743 {
  744         struct autri_softc *sc = sc_;
  745         u_int32_t reg;
  746 
  747         /*reg = (ENDLP_IE | MIDLP_IE);*/
  748         reg = ENDLP_IE;
  749 
  750         if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018)
  751                 reg |= BANK_B_EN;
  752 
  753         autri_reg_set_4(sc,AUTRI_LFO_GC_CIR,reg);
  754 }
  755 
  756 #if 0
  757 static void
  758 autri_disable_loop_interrupt(void *sc_)
  759 {
  760         struct autri_softc *sc = sc_;
  761         u_int32_t reg;
  762 
  763         reg = (ENDLP_IE | MIDLP_IE);
  764         autri_reg_clear_4(sc,AUTRI_LFO_GC_CIR,reg);
  765 }
  766 #endif
  767 
  768 int
  769 autri_intr(void *p)
  770 {
  771         struct autri_softc *sc = p;
  772         u_int32_t intsrc;
  773         u_int32_t mask, active[2];
  774         int ch, endch;
  775 /*
  776         u_int32_t reg;
  777         u_int32_t cso,eso;
  778 */
  779 
  780         intsrc = TREAD4(sc,AUTRI_MISCINT);
  781         if ((intsrc & (ADDRESS_IRQ|MPU401_IRQ)) == 0)
  782                 return 0;
  783 
  784         if (intsrc & ADDRESS_IRQ) {
  785 
  786                 active[0] = TREAD4(sc,AUTRI_AIN_A);
  787                 active[1] = TREAD4(sc,AUTRI_AIN_B);
  788 
  789                 if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) {
  790                         endch = 32;
  791                 } else {
  792                         endch = 64;
  793                 }
  794 
  795                 for (ch=0; ch<endch; ch++) {
  796                         mask = 1 << (ch & 0x1f);
  797                         if (active[(ch & 0x20) ? 1 : 0] & mask) {
  798 
  799                                 /* clear interrupt */
  800                                 TWRITE4(sc, (ch & 0x20) ? AUTRI_AIN_B : AUTRI_AIN_A, mask);
  801                                 /* disable interrupt */
  802                                 autri_reg_clear_4(sc,(ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask);
  803 #if 0
  804                                 reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f;
  805                                 TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | ch);
  806 
  807                                 if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
  808                                   cso = TREAD4(sc, 0xe0) & 0x00ffffff;
  809                                   eso = TREAD4(sc, 0xe8) & 0x00ffffff;
  810                                 } else {
  811                                   cso = (TREAD4(sc, 0xe0) >> 16) & 0x0000ffff;
  812                                   eso = (TREAD4(sc, 0xe8) >> 16) & 0x0000ffff;
  813                                 }
  814                                 /*printf("cso=%d, eso=%d\n",cso,eso);*/
  815 #endif
  816                                 if (ch == sc->sc_play.ch_intr) {
  817                                         if (sc->sc_play.intr)
  818                                                 sc->sc_play.intr(sc->sc_play.intr_arg);
  819                                 }
  820 
  821                                 if (ch == sc->sc_rec.ch_intr) {
  822                                         if (sc->sc_rec.intr)
  823                                                 sc->sc_rec.intr(sc->sc_rec.intr_arg);
  824                                 }
  825 
  826                                 /* enable interrupt */
  827                                 autri_reg_set_4(sc, (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask);
  828                         }
  829                 }
  830         }
  831 
  832         if (intsrc & MPU401_IRQ) {
  833                 /* XXX */
  834         }
  835 
  836         autri_reg_set_4(sc,AUTRI_MISCINT,
  837                 ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW);
  838 
  839         return 1;
  840 }
  841 
  842 /*
  843  *
  844  */
  845 
  846 int
  847 autri_allocmem(struct autri_softc *sc, size_t size, size_t align, 
  848                struct autri_dma *p)
  849 {
  850         int error;
  851 
  852         p->size = size;
  853         error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
  854             p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
  855             &p->nsegs, BUS_DMA_NOWAIT);
  856         if (error)
  857                 return (error);
  858 
  859         error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
  860             &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
  861         if (error)
  862                 goto free;
  863 
  864         error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
  865             0, BUS_DMA_NOWAIT, &p->map);
  866         if (error)
  867                 goto unmap;
  868 
  869         error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
  870             BUS_DMA_NOWAIT);
  871         if (error)
  872                 goto destroy;
  873         return (0);
  874 
  875 destroy:
  876         bus_dmamap_destroy(sc->sc_dmatag, p->map);
  877 unmap:
  878         bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
  879 free:
  880         bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
  881         return (error);
  882 }
  883 
  884 int
  885 autri_freemem(struct autri_softc *sc, struct autri_dma *p)
  886 {
  887         bus_dmamap_unload(sc->sc_dmatag, p->map);
  888         bus_dmamap_destroy(sc->sc_dmatag, p->map);
  889         bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
  890         bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
  891         return 0;
  892 }
  893 
  894 int
  895 autri_open(void *addr, int flags)
  896 {
  897         DPRINTF(("autri_open()\n"));
  898         DPRINTFN(5,("MISCINT    : 0x%08X\n",
  899                     TREAD4((struct autri_softc *)addr, AUTRI_MISCINT)));
  900         DPRINTFN(5,("LFO_GC_CIR : 0x%08X\n",
  901                     TREAD4((struct autri_softc *)addr, AUTRI_LFO_GC_CIR)));
  902         return 0;
  903 }
  904 
  905 void
  906 autri_close(void *addr)
  907 {
  908         DPRINTF(("autri_close()\n"));
  909 }
  910 
  911 int
  912 autri_query_encoding(void *addr, struct audio_encoding *fp)
  913 {
  914         switch (fp->index) {
  915         case 0:
  916                 strcpy(fp->name, AudioEulinear);
  917                 fp->encoding = AUDIO_ENCODING_ULINEAR;
  918                 fp->precision = 8;
  919                 fp->flags = 0;
  920                 break;
  921         case 1:
  922                 strcpy(fp->name, AudioEmulaw);
  923                 fp->encoding = AUDIO_ENCODING_ULAW;
  924                 fp->precision = 8;
  925                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  926                 break;
  927         case 2:
  928                 strcpy(fp->name, AudioEalaw);
  929                 fp->encoding = AUDIO_ENCODING_ALAW;
  930                 fp->precision = 8;
  931                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  932                 break;
  933         case 3:
  934                 strcpy(fp->name, AudioEslinear);
  935                 fp->encoding = AUDIO_ENCODING_SLINEAR;
  936                 fp->precision = 8;
  937                 fp->flags = 0;
  938                 break;
  939         case 4:
  940                 strcpy(fp->name, AudioEslinear_le);
  941                 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
  942                 fp->precision = 16;
  943                 fp->flags = 0;
  944                 break;
  945         case 5:
  946                 strcpy(fp->name, AudioEulinear_le);
  947                 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
  948                 fp->precision = 16;
  949                 fp->flags = 0;
  950                 break;
  951         case 6:
  952                 strcpy(fp->name, AudioEslinear_be);
  953                 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
  954                 fp->precision = 16;
  955                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  956                 break;
  957         case 7:
  958                 strcpy(fp->name, AudioEulinear_be);
  959                 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
  960                 fp->precision = 16;
  961                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  962                 break;
  963         default:
  964                 return (EINVAL);
  965         }
  966 
  967         return 0;
  968 }
  969 
  970 int
  971 autri_set_params(void *addr, int setmode, int usemode,
  972                  struct audio_params *play, struct audio_params *rec)
  973 {
  974         struct audio_params *p;
  975         int mode;
  976 
  977         for (mode = AUMODE_RECORD; mode != -1;
  978             mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
  979                 if ((setmode & mode) == 0)
  980                         continue;
  981 
  982                 p = mode == AUMODE_PLAY ? play : rec;
  983 
  984                 if (p->sample_rate < 4000 || p->sample_rate > 48000 ||
  985                     (p->precision != 8 && p->precision != 16) ||
  986                     (p->channels != 1 && p->channels != 2))
  987                         return (EINVAL);
  988 
  989                 p->factor = 1;
  990                 p->sw_code = 0;
  991                 switch (p->encoding) {
  992                 case AUDIO_ENCODING_SLINEAR_BE:
  993                 case AUDIO_ENCODING_ULINEAR_BE:
  994                         if (p->precision == 16)
  995                                 p->sw_code = swap_bytes;
  996                         break;
  997                 case AUDIO_ENCODING_SLINEAR_LE:
  998                 case AUDIO_ENCODING_ULINEAR_LE:
  999                         break;
 1000                 case AUDIO_ENCODING_ULAW:
 1001                         if (mode == AUMODE_PLAY)
 1002                                 p->sw_code = mulaw_to_ulinear8;
 1003                         else
 1004                                 p->sw_code = ulinear8_to_mulaw;
 1005 
 1006                         break;
 1007                 case AUDIO_ENCODING_ALAW:
 1008                         if (mode == AUMODE_PLAY)
 1009                                 p->sw_code = alaw_to_ulinear8;
 1010                         else
 1011                                 p->sw_code = ulinear8_to_alaw;
 1012 
 1013                         break;
 1014                 default:
 1015                         return (EINVAL);
 1016                 }
 1017         }
 1018 
 1019         return 0;
 1020 }
 1021 
 1022 int
 1023 autri_round_blocksize(void *addr, int block)
 1024 {
 1025         return (block & -4);
 1026 }
 1027 
 1028 int
 1029 autri_halt_output(void *addr)
 1030 {
 1031         struct autri_softc *sc = addr;
 1032 
 1033         DPRINTF(("autri_halt_output()\n"));
 1034 
 1035         sc->sc_play.intr = NULL;
 1036         autri_stopch(sc, sc->sc_play.ch, sc->sc_play.ch_intr);
 1037         autri_disable_interrupt(sc, sc->sc_play.ch_intr);
 1038 
 1039         return 0;
 1040 }
 1041 
 1042 int
 1043 autri_halt_input(void *addr)
 1044 {
 1045         struct autri_softc *sc = addr;
 1046 
 1047         DPRINTF(("autri_halt_input()\n"));
 1048 
 1049         sc->sc_rec.intr = NULL;
 1050         autri_stopch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr);
 1051         autri_disable_interrupt(sc, sc->sc_rec.ch_intr);
 1052 
 1053         return 0;
 1054 }
 1055 
 1056 int
 1057 autri_getdev(void *addr, struct audio_device *retp)
 1058 {
 1059         struct autri_softc *sc = addr;
 1060 
 1061         DPRINTF(("autri_getdev().\n"));
 1062 
 1063         strncpy(retp->name, "Trident 4DWAVE", sizeof(retp->name));
 1064         snprintf(retp->version, sizeof(retp->version), "0x%02x",
 1065              PCI_REVISION(sc->sc_class));
 1066 
 1067         switch (sc->sc_devid) {
 1068         case AUTRI_DEVICE_ID_4DWAVE_DX:
 1069                 strncpy(retp->config, "4DWAVE-DX", sizeof(retp->config));
 1070                 break;
 1071         case AUTRI_DEVICE_ID_4DWAVE_NX:
 1072                 strncpy(retp->config, "4DWAVE-NX", sizeof(retp->config));
 1073                 break;
 1074         case AUTRI_DEVICE_ID_SIS_7018:
 1075                 strncpy(retp->config, "SiS 7018", sizeof(retp->config));
 1076                 break;
 1077         case AUTRI_DEVICE_ID_ALI_M5451:
 1078                 strncpy(retp->config, "ALi M5451", sizeof(retp->config));
 1079                 break;
 1080         default:
 1081                 strncpy(retp->config, "unknown", sizeof(retp->config));
 1082         }
 1083 
 1084         return 0;
 1085 }
 1086 
 1087 int
 1088 autri_mixer_set_port(void *addr, mixer_ctrl_t *cp)
 1089 {
 1090         struct autri_softc *sc = addr;
 1091 
 1092         return (sc->sc_codec.codec_if->vtbl->mixer_set_port(
 1093             sc->sc_codec.codec_if, cp));
 1094 }
 1095 
 1096 int
 1097 autri_mixer_get_port(void *addr, mixer_ctrl_t *cp)
 1098 {
 1099         struct autri_softc *sc = addr;
 1100 
 1101         return (sc->sc_codec.codec_if->vtbl->mixer_get_port(
 1102             sc->sc_codec.codec_if, cp));
 1103 }
 1104 
 1105 int
 1106 autri_query_devinfo(void *addr, mixer_devinfo_t *dip)
 1107 {
 1108         struct autri_softc *sc = addr;
 1109 
 1110         return (sc->sc_codec.codec_if->vtbl->query_devinfo(
 1111             sc->sc_codec.codec_if, dip));
 1112 }
 1113 
 1114 int
 1115 autri_get_portnum_by_name(struct autri_softc *sc, char *class,
 1116                           char *device, char *qualifier)
 1117 {
 1118         return (sc->sc_codec.codec_if->vtbl->get_portnum_by_name(
 1119             sc->sc_codec.codec_if, class, device, qualifier));
 1120 }
 1121 
 1122 void *
 1123 autri_malloc(void *addr, int direction, size_t size,
 1124     struct malloc_type *pool, int flags)
 1125 {
 1126         struct autri_softc *sc = addr;
 1127         struct autri_dma *p;
 1128         int error;
 1129 
 1130         p = malloc(sizeof(*p), pool, flags);
 1131         if (!p)
 1132                 return NULL;
 1133 
 1134 #if 0
 1135         error = autri_allocmem(sc, size, 16, p);
 1136 #endif
 1137         error = autri_allocmem(sc, size, 0x10000, p);
 1138         if (error) {
 1139                 free(p, pool);
 1140                 return NULL;
 1141         }
 1142 
 1143         p->next = sc->sc_dmas;
 1144         sc->sc_dmas = p;
 1145         return KERNADDR(p);
 1146 }
 1147 
 1148 void
 1149 autri_free(void *addr, void *ptr, struct malloc_type *pool)
 1150 {
 1151         struct autri_softc *sc = addr;
 1152         struct autri_dma **pp, *p;
 1153 
 1154         for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
 1155                 if (KERNADDR(p) == ptr) {
 1156                         autri_freemem(sc, p);
 1157                         *pp = p->next;
 1158                         free(p, pool);
 1159                         return;
 1160                 }
 1161         }
 1162 }
 1163 
 1164 static struct autri_dma *
 1165 autri_find_dma(struct autri_softc *sc, void *addr)
 1166 {
 1167         struct autri_dma *p;
 1168 
 1169         for (p = sc->sc_dmas; p && KERNADDR(p) != addr; p = p->next)
 1170                 ;
 1171 
 1172         return p;
 1173 }
 1174 
 1175 size_t
 1176 autri_round_buffersize(void *addr, int direction, size_t size)
 1177 {
 1178         return size;
 1179 }
 1180 
 1181 paddr_t
 1182 autri_mappage(void *addr, void *mem, off_t off, int prot)
 1183 {
 1184         struct autri_softc *sc = addr;
 1185         struct autri_dma *p;
 1186 
 1187         if (off < 0)
 1188                 return (-1);
 1189 
 1190         p = autri_find_dma(sc, mem);
 1191         if (!p)
 1192                 return (-1);
 1193 
 1194         return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs,
 1195             off, prot, BUS_DMA_WAITOK));
 1196 }
 1197 
 1198 int
 1199 autri_get_props(void *addr)
 1200 {
 1201         return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
 1202                 AUDIO_PROP_FULLDUPLEX);
 1203 }
 1204 
 1205 static void
 1206 autri_setup_channel(struct autri_softc *sc, int mode,
 1207                     struct audio_params *param)
 1208 {
 1209         int i, ch, channel;
 1210         u_int32_t reg, cr[5];
 1211         u_int32_t cso, eso;
 1212         u_int32_t delta, dch[2], ctrl;
 1213         u_int32_t alpha_fms, fm_vol, attribute;
 1214 
 1215         u_int32_t dmaaddr, dmalen;
 1216         int factor, rvol, cvol;
 1217         struct autri_chstatus *chst;
 1218 
 1219         ctrl = AUTRI_CTRL_LOOPMODE;
 1220         switch (param->encoding) {
 1221         case AUDIO_ENCODING_SLINEAR_BE:
 1222         case AUDIO_ENCODING_SLINEAR_LE:
 1223                 ctrl |= AUTRI_CTRL_SIGNED;
 1224                 break;
 1225         }
 1226 
 1227         factor = 0;
 1228         if (param->precision == 16) {
 1229                 ctrl |= AUTRI_CTRL_16BIT;
 1230                 factor++;
 1231         }
 1232 
 1233         if (param->channels == 2) {
 1234                 ctrl |= AUTRI_CTRL_STEREO;
 1235                 factor++;
 1236         }
 1237 
 1238         delta = (u_int32_t)param->sample_rate;
 1239         if (delta < 4000)
 1240                 delta = 4000;
 1241         if (delta > 48000)
 1242                 delta = 48000;
 1243 
 1244         attribute = 0;
 1245 
 1246         dch[1] = ((delta << 12) / 48000) & 0x0000ffff;
 1247         if (mode == AUMODE_PLAY) {
 1248                 chst = &sc->sc_play;
 1249                 dch[0] = ((delta << 12) / 48000) & 0x0000ffff;
 1250                 ctrl |= AUTRI_CTRL_WAVEVOL;
 1251         } else {
 1252                 chst = &sc->sc_rec;
 1253                 dch[0] = ((48000 << 12) / delta) & 0x0000ffff;
 1254                 if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018) {
 1255                         ctrl |= AUTRI_CTRL_MUTEVOL_SIS;
 1256                         attribute = AUTRI_ATTR_PCMREC_SIS;
 1257                         if (delta != 48000)
 1258                                 attribute |= AUTRI_ATTR_ENASRC_SIS;
 1259                 } else
 1260                         ctrl |= AUTRI_CTRL_MUTEVOL;
 1261         }
 1262 
 1263         dmaaddr = DMAADDR(chst->dma);
 1264         cso = alpha_fms = 0;
 1265         rvol = cvol = 0x7f;
 1266         fm_vol = 0x0 | ((rvol & 0x7f) << 7) | (cvol & 0x7f);
 1267 
 1268         for (ch=0; ch<2; ch++) {
 1269 
 1270                 if (ch == 0)
 1271                         dmalen = (chst->length >> factor);
 1272                 else {
 1273                         /* channel for interrupt */
 1274                         dmalen = (chst->blksize >> factor);
 1275                         if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018)
 1276                                 ctrl |= AUTRI_CTRL_MUTEVOL_SIS;
 1277                         else
 1278                                 ctrl |= AUTRI_CTRL_MUTEVOL;
 1279                         attribute = 0;
 1280                 }
 1281 
 1282                 eso = dmalen - 1;
 1283 
 1284                 switch (sc->sc_devid) {
 1285                 case AUTRI_DEVICE_ID_4DWAVE_DX:
 1286                         cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
 1287                         cr[1] = dmaaddr;
 1288                         cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff); 
 1289                         cr[3] = fm_vol;
 1290                         cr[4] = ctrl;
 1291                         break;
 1292                 case AUTRI_DEVICE_ID_4DWAVE_NX:
 1293                         cr[0] = (dch[ch] << 24) | (cso & 0x00ffffff);
 1294                         cr[1] = dmaaddr;
 1295                         cr[2] = ((dch[ch] << 16) & 0xff000000) | (eso & 0x00ffffff);
 1296                         cr[3] = (alpha_fms << 16) | (fm_vol & 0x0000ffff);
 1297                         cr[4] = ctrl;
 1298                         break;
 1299                 case AUTRI_DEVICE_ID_SIS_7018:
 1300                         cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
 1301                         cr[1] = dmaaddr;
 1302                         cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff); 
 1303                         cr[3] = attribute;
 1304                         cr[4] = ctrl;
 1305                         break;
 1306                 case AUTRI_DEVICE_ID_ALI_M5451:
 1307                         cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
 1308                         cr[1] = dmaaddr;
 1309                         cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
 1310                         cr[3] = 0;
 1311                         cr[4] = ctrl;
 1312                         break;
 1313                 }
 1314 
 1315                 /* write channel data */
 1316                 channel = (ch == 0) ? chst->ch : chst->ch_intr;
 1317 
 1318                 reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f;
 1319                 TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | channel);
 1320 
 1321                 for (i=0; i<5; i++) {
 1322                         TWRITE4(sc, AUTRI_ARAM_CR + i*sizeof(cr[0]), cr[i]);
 1323                         DPRINTFN(5,("cr[%d] : 0x%08X\n", i, cr[i]));
 1324                 }
 1325 
 1326                 /* Bank A only */  
 1327                 if (channel < 0x20) {
 1328                         TWRITE4(sc, AUTRI_EBUF1, AUTRI_EMOD_STILL);
 1329                         TWRITE4(sc, AUTRI_EBUF2, AUTRI_EMOD_STILL);
 1330                 }
 1331         }
 1332 
 1333 }
 1334 
 1335 int
 1336 autri_trigger_output(void *addr, void *start, void *end, int blksize,
 1337                      void (*intr)(void *), void *arg,
 1338                      struct audio_params *param)
 1339 {
 1340         struct autri_softc *sc = addr;
 1341         struct autri_dma *p;
 1342 
 1343         DPRINTFN(5,("autri_trigger_output: sc=%p start=%p end=%p "
 1344             "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
 1345 
 1346         sc->sc_play.intr = intr;
 1347         sc->sc_play.intr_arg = arg;
 1348         sc->sc_play.offset = 0;
 1349         sc->sc_play.blksize = blksize;
 1350         sc->sc_play.length = (char *)end - (char *)start;
 1351 
 1352         p = autri_find_dma(sc, start);
 1353         if (!p) {
 1354                 printf("autri_trigger_output: bad addr %p\n", start);
 1355                 return (EINVAL);
 1356         }
 1357 
 1358         sc->sc_play.dma = p;
 1359 
 1360         /* */
 1361         autri_setup_channel(sc, AUMODE_PLAY, param);
 1362 
 1363         /* volume set to no attenuation */
 1364         TWRITE4(sc, AUTRI_MUSICVOL_WAVEVOL, 0);
 1365 
 1366         /* enable interrupt */
 1367         autri_enable_interrupt(sc, sc->sc_play.ch_intr);
 1368 
 1369         /* start channel */
 1370         autri_startch(sc, sc->sc_play.ch, sc->sc_play.ch_intr);
 1371 
 1372         return 0;
 1373 }
 1374 
 1375 int
 1376 autri_trigger_input(void *addr, void *start, void *end, int blksize,
 1377                     void (*intr)(void *), void *arg,
 1378                     struct audio_params *param)
 1379 {
 1380         struct autri_softc *sc = addr;
 1381         struct autri_dma *p;
 1382 
 1383         DPRINTFN(5,("autri_trigger_input: sc=%p start=%p end=%p "
 1384             "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
 1385 
 1386         sc->sc_rec.intr = intr;
 1387         sc->sc_rec.intr_arg = arg;
 1388         sc->sc_rec.offset = 0;
 1389         sc->sc_rec.blksize = blksize;
 1390         sc->sc_rec.length = (char *)end - (char *)start;
 1391 
 1392         /* */
 1393         p = autri_find_dma(sc, start);
 1394         if (!p) {
 1395                 printf("autri_trigger_input: bad addr %p\n", start);
 1396                 return (EINVAL);
 1397         }
 1398 
 1399         sc->sc_rec.dma = p;
 1400 
 1401         /* */
 1402         if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
 1403                 autri_reg_set_4(sc, AUTRI_NX_ACR0, AUTRI_NX_ACR0_PSB_CAPTURE);
 1404                 TWRITE1(sc, AUTRI_NX_RCI3, AUTRI_NX_RCI3_ENABLE | sc->sc_rec.ch);
 1405         }
 1406 
 1407 #if 0
 1408         /* 4DWAVE only allows capturing at a 48KHz rate */
 1409         if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_DX ||
 1410             sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX)
 1411                 param->sample_rate = 48000;
 1412 #endif
 1413 
 1414         autri_setup_channel(sc, AUMODE_RECORD, param);
 1415 
 1416         /* enable interrupt */
 1417         autri_enable_interrupt(sc, sc->sc_rec.ch_intr);
 1418 
 1419         /* start channel */
 1420         autri_startch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr);
 1421 
 1422         return 0;
 1423 }
 1424 
 1425 #if 0
 1426 static int
 1427 autri_halt(struct autri_softc *sc)
 1428 {
 1429         DPRINTF(("autri_halt().\n"));
 1430         /*autri_stopch(sc);*/
 1431         autri_disable_interrupt(sc, sc->sc_play.channel);
 1432         autri_disable_interrupt(sc, sc->sc_rec.channel);
 1433         return 0;
 1434 }
 1435 #endif
 1436 
 1437 static void
 1438 autri_enable_interrupt(struct autri_softc *sc, int ch)
 1439 {
 1440         int reg;
 1441 
 1442         reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A;
 1443         ch &= 0x1f;
 1444 
 1445         autri_reg_set_4(sc, reg, 1 << ch);
 1446 }
 1447 
 1448 static void
 1449 autri_disable_interrupt(struct autri_softc *sc, int ch)
 1450 {
 1451         int reg;
 1452 
 1453         reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A;
 1454         ch &= 0x1f;
 1455 
 1456         autri_reg_clear_4(sc, reg, 1 << ch);
 1457 }
 1458 
 1459 static void
 1460 autri_startch(struct autri_softc *sc, int ch, int ch_intr)
 1461 {
 1462         int reg;
 1463         u_int32_t chmask;
 1464 
 1465         reg = (ch & 0x20) ? AUTRI_START_B : AUTRI_START_A;
 1466         ch &= 0x1f;
 1467         ch_intr &= 0x1f;
 1468         chmask = (1 << ch) | (1 << ch_intr);
 1469 
 1470         autri_reg_set_4(sc, reg, chmask);
 1471 }
 1472 
 1473 static void
 1474 autri_stopch(struct autri_softc *sc, int ch, int ch_intr)
 1475 {
 1476         int reg;
 1477         u_int32_t chmask;
 1478 
 1479         reg = (ch & 0x20) ? AUTRI_STOP_B : AUTRI_STOP_A;
 1480         ch &= 0x1f;
 1481         ch_intr &= 0x1f;
 1482         chmask = (1 << ch) | (1 << ch_intr);
 1483 
 1484         autri_reg_set_4(sc, reg, chmask);
 1485 }
 1486 
 1487 #if NMIDI > 0
 1488 int
 1489 autri_midi_open(void *addr, int flags, void (*iintr)(void *, int),
 1490                 void (*ointr)(void *), void *arg)
 1491 {
 1492         struct autri_softc *sc = addr;
 1493 
 1494         DPRINTF(("autri_midi_open()\n"));
 1495 
 1496         DPRINTFN(5,("MPUR1 : 0x%02X\n",TREAD1(sc,AUTRI_MPUR1)));
 1497         DPRINTFN(5,("MPUR2 : 0x%02X\n",TREAD1(sc,AUTRI_MPUR2)));
 1498 
 1499         sc->sc_iintr = iintr;
 1500         sc->sc_ointr = ointr;
 1501         sc->sc_arg = arg;
 1502 
 1503         if (flags & FREAD)
 1504                 autri_reg_clear_1(sc, AUTRI_MPUR2, AUTRI_MIDIIN_ENABLE_INTR);
 1505 
 1506         if (flags & FWRITE)
 1507                 autri_reg_set_1(sc, AUTRI_MPUR2, AUTRI_MIDIOUT_CONNECT);
 1508         
 1509         return (0);
 1510 }
 1511 
 1512 void
 1513 autri_midi_close(void *addr)
 1514 {
 1515         struct autri_softc *sc = addr;
 1516 
 1517         DPRINTF(("autri_midi_close()\n"));
 1518 
 1519         tsleep(sc, PWAIT, "autri", hz/10); /* give uart a chance to drain */
 1520 
 1521         sc->sc_iintr = NULL;
 1522         sc->sc_ointr = NULL;
 1523 }
 1524 
 1525 int
 1526 autri_midi_output(void *addr, int d)
 1527 {
 1528         struct autri_softc *sc = addr;
 1529         int x;
 1530 
 1531         for (x = 0; x != MIDI_BUSY_WAIT; x++) {
 1532                 if ((TREAD1(sc, AUTRI_MPUR1) & AUTRI_MIDIOUT_READY) == 0) {
 1533                         TWRITE1(sc, AUTRI_MPUR0, d);
 1534                         return (0);
 1535                 }
 1536                 delay(MIDI_BUSY_DELAY);
 1537         }
 1538         return (EIO);
 1539 }
 1540 
 1541 void
 1542 autri_midi_getinfo(void *addr, struct midi_info *mi)
 1543 {
 1544         mi->name = "4DWAVE MIDI UART";
 1545         mi->props = MIDI_PROP_CAN_INPUT;
 1546 }
 1547 
 1548 #endif

Cache object: 39807cb1453ce42dcc91d52740614c53


[ 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.