root/dev/pci/autri.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. autri_reg_set_1
  2. autri_reg_clear_1
  3. autri_reg_set_4
  4. autri_reg_clear_4
  5. autri_attach_codec
  6. autri_read_codec
  7. autri_write_codec
  8. autri_reset_codec
  9. autri_flags_codec
  10. autri_match
  11. autri_attach
  12. autri_powerhook
  13. autri_init
  14. autri_enable_loop_interrupt
  15. autri_disable_loop_interrupt
  16. autri_intr
  17. autri_allocmem
  18. autri_freemem
  19. autri_open
  20. autri_close
  21. autri_query_encoding
  22. autri_set_params
  23. autri_round_blocksize
  24. autri_halt_output
  25. autri_halt_input
  26. autri_getdev
  27. autri_mixer_set_port
  28. autri_mixer_get_port
  29. autri_query_devinfo
  30. autri_get_portnum_by_name
  31. autri_malloc
  32. autri_free
  33. autri_find_dma
  34. autri_mappage
  35. autri_get_props
  36. autri_setup_channel
  37. autri_trigger_output
  38. autri_trigger_input
  39. autri_halt
  40. autri_enable_interrupt
  41. autri_disable_interrupt
  42. autri_startch
  43. autri_stopch
  44. autri_midi_open
  45. autri_midi_close
  46. autri_midi_output
  47. autri_midi_getinfo

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

/* [<][>][^][v][top][bottom][index][help] */