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/yds.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: yds.c,v 1.18.2.1 2004/09/22 20:58:46 jmc Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2000, 2001 Kazuki Sakamoto and Minoura Makoto.
    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  * Yamaha YMF724[B-F]/740[B-C]/744/754
   30  *
   31  * Documentation links:
   32  * - ftp://ftp.alsa-project.org/pub/manuals/yamaha/
   33  * - ftp://ftp.alsa-project.org/pub/manuals/yamaha/pci/
   34  *
   35  * TODO:
   36  * - FM synth volume (difficult: mixed before ac97)
   37  * - Digital in/out (SPDIF) support
   38  * - Effect??
   39  */
   40 
   41 #include <sys/cdefs.h>
   42 __KERNEL_RCSID(0, "$NetBSD: yds.c,v 1.18.2.1 2004/09/22 20:58:46 jmc Exp $");
   43 
   44 #include "mpu.h"
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/kernel.h>
   49 #include <sys/fcntl.h>
   50 #include <sys/malloc.h>
   51 #include <sys/device.h>
   52 #include <sys/proc.h>
   53 
   54 #include <dev/pci/pcidevs.h>
   55 #include <dev/pci/pcireg.h>
   56 #include <dev/pci/pcivar.h>
   57 
   58 #include <sys/audioio.h>
   59 #include <dev/audio_if.h>
   60 #include <dev/mulaw.h>
   61 #include <dev/auconv.h>
   62 #include <dev/ic/ac97reg.h>
   63 #include <dev/ic/ac97var.h>
   64 #include <dev/ic/mpuvar.h>
   65 
   66 #include <machine/bus.h>
   67 #include <machine/intr.h>
   68 
   69 #include <dev/microcode/yds/yds_hwmcode.h>
   70 #include <dev/pci/ydsreg.h>
   71 #include <dev/pci/ydsvar.h>
   72 
   73 /* Debug */
   74 #undef YDS_USE_REC_SLOT
   75 #define YDS_USE_P44
   76 
   77 #ifdef AUDIO_DEBUG
   78 # define DPRINTF(x)     if (ydsdebug) printf x
   79 # define DPRINTFN(n,x)  if (ydsdebug>(n)) printf x
   80 int     ydsdebug = 0;
   81 #else
   82 # define DPRINTF(x)
   83 # define DPRINTFN(n,x)
   84 #endif
   85 #ifdef YDS_USE_REC_SLOT
   86 # define YDS_INPUT_SLOT 0       /* REC slot = ADC + loopbacks */
   87 #else
   88 # define YDS_INPUT_SLOT 1       /* ADC slot */
   89 #endif
   90 
   91 int     yds_match __P((struct device *, struct cfdata *, void *));
   92 void    yds_attach __P((struct device *, struct device *, void *));
   93 int     yds_intr __P((void *));
   94 
   95 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
   96 #define KERNADDR(p) ((void *)((p)->addr))
   97 
   98 int     yds_allocmem __P((struct yds_softc *, size_t, size_t,
   99                           struct yds_dma *));
  100 int     yds_freemem __P((struct yds_softc *, struct yds_dma *));
  101 
  102 #ifndef AUDIO_DEBUG
  103 #define YWRITE1(sc, r, x) bus_space_write_1((sc)->memt, (sc)->memh, (r), (x))
  104 #define YWRITE2(sc, r, x) bus_space_write_2((sc)->memt, (sc)->memh, (r), (x))
  105 #define YWRITE4(sc, r, x) bus_space_write_4((sc)->memt, (sc)->memh, (r), (x))
  106 #define YREAD1(sc, r) bus_space_read_1((sc)->memt, (sc)->memh, (r))
  107 #define YREAD2(sc, r) bus_space_read_2((sc)->memt, (sc)->memh, (r))
  108 #define YREAD4(sc, r) bus_space_read_4((sc)->memt, (sc)->memh, (r))
  109 #else
  110 
  111 u_int16_t YREAD2(struct yds_softc *sc,bus_size_t r);
  112 u_int32_t YREAD4(struct yds_softc *sc,bus_size_t r);
  113 void YWRITE1(struct yds_softc *sc,bus_size_t r,u_int8_t x);
  114 void YWRITE2(struct yds_softc *sc,bus_size_t r,u_int16_t x);
  115 void YWRITE4(struct yds_softc *sc,bus_size_t r,u_int32_t x);
  116 
  117 u_int16_t YREAD2(struct yds_softc *sc,bus_size_t r)
  118 {
  119   DPRINTFN(5, (" YREAD2(0x%lX)\n",(unsigned long)r));
  120   return bus_space_read_2(sc->memt,sc->memh,r);
  121 }
  122 u_int32_t YREAD4(struct yds_softc *sc,bus_size_t r)
  123 {
  124   DPRINTFN(5, (" YREAD4(0x%lX)\n",(unsigned long)r));
  125   return bus_space_read_4(sc->memt,sc->memh,r);
  126 }
  127 void YWRITE1(struct yds_softc *sc,bus_size_t r,u_int8_t x)
  128 {
  129   DPRINTFN(5, (" YWRITE1(0x%lX,0x%lX)\n",(unsigned long)r,(unsigned long)x));
  130   bus_space_write_1(sc->memt,sc->memh,r,x);
  131 }
  132 void YWRITE2(struct yds_softc *sc,bus_size_t r,u_int16_t x)
  133 {
  134   DPRINTFN(5, (" YWRITE2(0x%lX,0x%lX)\n",(unsigned long)r,(unsigned long)x));
  135   bus_space_write_2(sc->memt,sc->memh,r,x);
  136 }
  137 void YWRITE4(struct yds_softc *sc,bus_size_t r,u_int32_t x)
  138 {
  139   DPRINTFN(5, (" YWRITE4(0x%lX,0x%lX)\n",(unsigned long)r,(unsigned long)x));
  140   bus_space_write_4(sc->memt,sc->memh,r,x);
  141 }
  142 #endif
  143 
  144 #define YWRITEREGION4(sc, r, x, c)      \
  145         bus_space_write_region_4((sc)->memt, (sc)->memh, (r), (x), (c) / 4)
  146 
  147 CFATTACH_DECL(yds, sizeof(struct yds_softc),
  148     yds_match, yds_attach, NULL, NULL);
  149 
  150 int     yds_open __P((void *, int));
  151 void    yds_close __P((void *));
  152 int     yds_query_encoding __P((void *, struct audio_encoding *));
  153 int     yds_set_params __P((void *, int, int,
  154                             struct audio_params *, struct audio_params *));
  155 int     yds_round_blocksize __P((void *, int));
  156 int     yds_trigger_output __P((void *, void *, void *, int, void (*)(void *),
  157                                 void *, struct audio_params *));
  158 int     yds_trigger_input __P((void *, void *, void *, int, void (*)(void *),
  159                                void *, struct audio_params *));
  160 int     yds_halt_output __P((void *));
  161 int     yds_halt_input __P((void *));
  162 int     yds_getdev __P((void *, struct audio_device *));
  163 int     yds_mixer_set_port __P((void *, mixer_ctrl_t *));
  164 int     yds_mixer_get_port __P((void *, mixer_ctrl_t *));
  165 void   *yds_malloc __P((void *, int, size_t, struct malloc_type *, int));
  166 void    yds_free __P((void *, void *, struct malloc_type *));
  167 size_t  yds_round_buffersize __P((void *, int, size_t));
  168 paddr_t yds_mappage __P((void *, void *, off_t, int));
  169 int     yds_get_props __P((void *));
  170 int     yds_query_devinfo __P((void *addr, mixer_devinfo_t *dip));
  171 
  172 int     yds_attach_codec __P((void *sc, struct ac97_codec_if *));
  173 int     yds_read_codec __P((void *sc, u_int8_t a, u_int16_t *d));
  174 int     yds_write_codec __P((void *sc, u_int8_t a, u_int16_t d));
  175 int     yds_reset_codec __P((void *sc));
  176 int     yds_get_portnum_by_name __P((struct yds_softc *, char *, char *,
  177                                      char *));
  178 
  179 static u_int yds_get_dstype __P((int));
  180 static int yds_download_mcode __P((struct yds_softc *));
  181 static int yds_allocate_slots __P((struct yds_softc *));
  182 static void yds_configure_legacy __P((struct device *arg));
  183 static void yds_enable_dsp __P((struct yds_softc *));
  184 static int yds_disable_dsp __P((struct yds_softc *));
  185 static int yds_ready_codec __P((struct yds_codec_softc *));
  186 static int yds_halt __P((struct yds_softc *));
  187 static u_int32_t yds_get_lpfq __P((u_int));
  188 static u_int32_t yds_get_lpfk __P((u_int));
  189 static struct yds_dma *yds_find_dma __P((struct yds_softc *, void *));
  190 
  191 static int yds_init __P((struct yds_softc *));
  192 static void yds_powerhook __P((int, void *));
  193 
  194 #ifdef AUDIO_DEBUG
  195 static void yds_dump_play_slot __P((struct yds_softc *, int));
  196 #define YDS_DUMP_PLAY_SLOT(n,sc,bank) \
  197         if (ydsdebug > (n)) yds_dump_play_slot(sc, bank)
  198 #else
  199 #define YDS_DUMP_PLAY_SLOT(n,sc,bank)
  200 #endif /* AUDIO_DEBUG */
  201 
  202 static struct audio_hw_if yds_hw_if = {
  203         yds_open,
  204         yds_close,
  205         NULL,
  206         yds_query_encoding,
  207         yds_set_params,
  208         yds_round_blocksize,
  209         NULL,
  210         NULL,
  211         NULL,
  212         NULL,
  213         NULL,
  214         yds_halt_output,
  215         yds_halt_input,
  216         NULL,
  217         yds_getdev,
  218         NULL,
  219         yds_mixer_set_port,
  220         yds_mixer_get_port,
  221         yds_query_devinfo,
  222         yds_malloc,
  223         yds_free,
  224         yds_round_buffersize,
  225         yds_mappage,
  226         yds_get_props,
  227         yds_trigger_output,
  228         yds_trigger_input,
  229         NULL,
  230 };
  231 
  232 struct audio_device yds_device = {
  233         "Yamaha DS-1",
  234         "",
  235         "yds"
  236 };
  237 
  238 const static struct {
  239         u_int   id;
  240         u_int   flags;
  241 #define YDS_CAP_MCODE_1                 0x0001
  242 #define YDS_CAP_MCODE_1E                0x0002
  243 #define YDS_CAP_LEGACY_SELECTABLE       0x0004
  244 #define YDS_CAP_LEGACY_FLEXIBLE         0x0008
  245 #define YDS_CAP_HAS_P44                 0x0010
  246 } yds_chip_capabliity_list[] = {
  247         { PCI_PRODUCT_YAMAHA_YMF724,
  248           YDS_CAP_MCODE_1|YDS_CAP_LEGACY_SELECTABLE },
  249         /* 740[C] has only 32 slots.  But anyway we use only 2 */
  250         { PCI_PRODUCT_YAMAHA_YMF740,
  251           YDS_CAP_MCODE_1|YDS_CAP_LEGACY_SELECTABLE },  /* XXX NOT TESTED */
  252         { PCI_PRODUCT_YAMAHA_YMF740C,
  253           YDS_CAP_MCODE_1E|YDS_CAP_LEGACY_SELECTABLE },
  254         { PCI_PRODUCT_YAMAHA_YMF724F,
  255           YDS_CAP_MCODE_1E|YDS_CAP_LEGACY_SELECTABLE },
  256         { PCI_PRODUCT_YAMAHA_YMF744B, 
  257           YDS_CAP_MCODE_1E|YDS_CAP_LEGACY_FLEXIBLE },
  258         { PCI_PRODUCT_YAMAHA_YMF754,
  259           YDS_CAP_MCODE_1E|YDS_CAP_LEGACY_FLEXIBLE|YDS_CAP_HAS_P44 },
  260         { 0, 0 }
  261 };
  262 #ifdef AUDIO_DEBUG
  263 #define YDS_CAP_BITS    "\020\005P44\004LEGFLEX\003LEGSEL\002MCODE1E\001MCODE1"
  264 #endif
  265 
  266 #ifdef AUDIO_DEBUG
  267 static void
  268 yds_dump_play_slot(sc, bank)
  269         struct yds_softc *sc;
  270         int bank;
  271 {
  272         int i, j;
  273         u_int32_t *p;
  274         u_int32_t num;
  275         char *pa;
  276 
  277         for (i = 0; i < N_PLAY_SLOTS; i++) {
  278                 printf("pbankp[%d] = %p,", i*2, sc->pbankp[i*2]);
  279                 printf("pbankp[%d] = %p\n", i*2+1, sc->pbankp[i*2+1]);
  280         }
  281 
  282         pa = (char *)DMAADDR(&sc->sc_ctrldata) + sc->pbankoff;
  283         p = (u_int32_t *)sc->ptbl;
  284         printf("ptbl + 0: %d\n", *p++);
  285         for (i = 0; i < N_PLAY_SLOTS; i++) {
  286                 printf("ptbl + %d: 0x%x, should be %p\n",
  287                        i+1, *p,
  288                        pa + i * sizeof(struct play_slot_ctrl_bank) *
  289                                 N_PLAY_SLOT_CTRL_BANK);
  290                 p++;
  291         }
  292 
  293         num = le32toh(*(u_int32_t*)sc->ptbl);
  294         printf("numofplay = %d\n", num);
  295 
  296         for (i = 0; i < num; i++) {
  297                 p = (u_int32_t *)sc->pbankp[i*2];
  298 
  299                 printf("  pbankp[%d], bank 0 : %p\n", i*2, p);
  300                 for (j = 0; 
  301                      j < sizeof(struct play_slot_ctrl_bank) / sizeof(u_int32_t);
  302                      j++) {
  303                         printf("    0x%02x: 0x%08x\n",
  304                                (unsigned)(j * sizeof(u_int32_t)),
  305                                (unsigned)*p++);
  306                 }
  307 
  308                 p = (u_int32_t *)sc->pbankp[i*2 + 1];
  309                 printf("  pbankp[%d], bank 1 : %p\n", i*2 + 1, p);
  310                 for (j = 0;
  311                      j < sizeof(struct play_slot_ctrl_bank) / sizeof(u_int32_t);
  312                      j++) {
  313                         printf("    0x%02x: 0x%08x\n",
  314                                (unsigned)(j * sizeof(u_int32_t)),
  315                                (unsigned)*p++);
  316                 }       
  317         }
  318 }
  319 #endif /* AUDIO_DEBUG */
  320 
  321 static u_int
  322 yds_get_dstype(id)
  323         int id;
  324 {
  325         int i;
  326 
  327         for (i = 0; yds_chip_capabliity_list[i].id; i++) {
  328                 if (PCI_PRODUCT(id) == yds_chip_capabliity_list[i].id)
  329                         return yds_chip_capabliity_list[i].flags;
  330         }
  331 
  332         return -1;
  333 }
  334 
  335 static int
  336 yds_download_mcode(sc)
  337         struct yds_softc *sc;
  338 {
  339         u_int ctrl;
  340         const u_int32_t *p;
  341         size_t size;
  342         int dstype;
  343 
  344         static struct {
  345                 const u_int32_t *mcode;
  346                 size_t size;
  347         } ctrls[] = {
  348                 {yds_ds1_ctrl_mcode, sizeof(yds_ds1_ctrl_mcode)},
  349                 {yds_ds1e_ctrl_mcode, sizeof(yds_ds1e_ctrl_mcode)},
  350         };
  351 
  352         if (sc->sc_flags & YDS_CAP_MCODE_1)
  353                 dstype = YDS_DS_1;
  354         else if (sc->sc_flags & YDS_CAP_MCODE_1E)
  355                 dstype = YDS_DS_1E;
  356         else
  357                 return 1;       /* unknown */
  358 
  359         if (yds_disable_dsp(sc))
  360                 return 1;
  361 
  362         /* Software reset */
  363         YWRITE4(sc, YDS_MODE, YDS_MODE_RESET);
  364         YWRITE4(sc, YDS_MODE, 0);
  365 
  366         YWRITE4(sc, YDS_MAPOF_REC, 0);
  367         YWRITE4(sc, YDS_MAPOF_EFFECT, 0);
  368         YWRITE4(sc, YDS_PLAY_CTRLBASE, 0);
  369         YWRITE4(sc, YDS_REC_CTRLBASE, 0);
  370         YWRITE4(sc, YDS_EFFECT_CTRLBASE, 0);
  371         YWRITE4(sc, YDS_WORK_BASE, 0);
  372 
  373         ctrl = YREAD2(sc, YDS_GLOBAL_CONTROL);
  374         YWRITE2(sc, YDS_GLOBAL_CONTROL, ctrl & ~0x0007);
  375 
  376         /* Download DSP microcode. */
  377         p = yds_dsp_mcode;
  378         size = sizeof(yds_dsp_mcode);
  379         YWRITEREGION4(sc, YDS_DSP_INSTRAM, p, size);
  380 
  381         /* Download CONTROL microcode. */
  382         p = ctrls[dstype].mcode;
  383         size = ctrls[dstype].size;
  384         YWRITEREGION4(sc, YDS_CTRL_INSTRAM, p, size);
  385 
  386         yds_enable_dsp(sc);
  387         delay(10 * 1000);               /* nessesary on my 724F (??) */
  388 
  389         return 0;
  390 }
  391 
  392 static int
  393 yds_allocate_slots(sc)
  394         struct yds_softc *sc;
  395 {
  396         size_t pcs, rcs, ecs, ws, memsize;
  397         void *mp;
  398         u_int32_t da;           /* DMA address */
  399         char *va;               /* KVA */
  400         off_t cb;
  401         int i;
  402         struct yds_dma *p;
  403 
  404         /* Alloc DSP Control Data */
  405         pcs = YREAD4(sc, YDS_PLAY_CTRLSIZE) * sizeof(u_int32_t);
  406         rcs = YREAD4(sc, YDS_REC_CTRLSIZE) * sizeof(u_int32_t);
  407         ecs = YREAD4(sc, YDS_EFFECT_CTRLSIZE) * sizeof(u_int32_t);
  408         ws = WORK_SIZE;
  409         YWRITE4(sc, YDS_WORK_SIZE, ws / sizeof(u_int32_t));
  410 
  411         DPRINTF(("play control size : %d\n", (unsigned int)pcs));
  412         DPRINTF(("rec control size : %d\n", (unsigned int)rcs));
  413         DPRINTF(("eff control size : %d\n", (unsigned int)ecs));
  414         DPRINTF(("work size : %d\n", (unsigned int)ws));
  415 #ifdef DIAGNOSTIC
  416         if (pcs != sizeof(struct play_slot_ctrl_bank)) {
  417                 printf("%s: invalid play slot ctrldata %d != %d\n",
  418                        sc->sc_dev.dv_xname, (unsigned int)pcs,
  419                        (unsigned int)sizeof(struct play_slot_ctrl_bank));
  420         if (rcs != sizeof(struct rec_slot_ctrl_bank))
  421                 printf("%s: invalid rec slot ctrldata %d != %d\n",
  422                        sc->sc_dev.dv_xname, (unsigned int)rcs,
  423                        (unsigned int)sizeof(struct rec_slot_ctrl_bank));
  424         }
  425 #endif
  426 
  427         memsize = N_PLAY_SLOTS*N_PLAY_SLOT_CTRL_BANK*pcs +
  428                   N_REC_SLOT_CTRL*N_REC_SLOT_CTRL_BANK*rcs + ws;
  429         memsize += (N_PLAY_SLOTS+1)*sizeof(u_int32_t);
  430 
  431         p = &sc->sc_ctrldata;
  432         if (KERNADDR(p) == NULL) {
  433                 i = yds_allocmem(sc, memsize, 16, p);
  434                 if (i) {
  435                         printf("%s: couldn't alloc/map DSP DMA buffer, reason %d\n",
  436                                 sc->sc_dev.dv_xname, i);
  437                         free(p, M_DEVBUF);
  438                         return 1;
  439                 }
  440         }
  441         mp = KERNADDR(p);
  442         da = DMAADDR(p);
  443 
  444         DPRINTF(("mp:%p, DMA addr:%p\n",
  445                  mp, (void *)sc->sc_ctrldata.map->dm_segs[0].ds_addr));
  446 
  447         memset(mp, 0, memsize);
  448 
  449         /* Work space */
  450         cb = 0;
  451         va = (u_int8_t *)mp;
  452         YWRITE4(sc, YDS_WORK_BASE, da + cb);
  453         cb += ws;
  454 
  455         /* Play control data table */
  456         sc->ptbl = (u_int32_t *)(va + cb);
  457         sc->ptbloff = cb;
  458         YWRITE4(sc, YDS_PLAY_CTRLBASE, da + cb);
  459         cb += (N_PLAY_SLOT_CTRL + 1) * sizeof(u_int32_t);
  460 
  461         /* Record slot control data */
  462         sc->rbank = (struct rec_slot_ctrl_bank *)(va + cb);
  463         YWRITE4(sc, YDS_REC_CTRLBASE, da + cb);
  464         sc->rbankoff = cb;
  465         cb += N_REC_SLOT_CTRL * N_REC_SLOT_CTRL_BANK * rcs;
  466 
  467 #if 0
  468         /* Effect slot control data -- unused */
  469         YWRITE4(sc, YDS_EFFECT_CTRLBASE, da + cb);
  470         cb += N_EFFECT_SLOT_CTRL * N_EFFECT_SLOT_CTRL_BANK * ecs;
  471 #endif
  472 
  473         /* Play slot control data */
  474         sc->pbankoff = cb;
  475         for (i=0; i < N_PLAY_SLOT_CTRL; i++) {
  476                 sc->pbankp[i*2] = (struct play_slot_ctrl_bank *)(va + cb);
  477                 *(sc->ptbl + i+1) = htole32(da + cb);
  478                 cb += pcs;
  479 
  480                 sc->pbankp[i*2+1] = (struct play_slot_ctrl_bank *)(va + cb);
  481                 cb += pcs;
  482         }
  483         /* Sync play control data table */
  484         bus_dmamap_sync(sc->sc_dmatag, p->map,
  485                         sc->ptbloff, (N_PLAY_SLOT_CTRL+1) * sizeof(u_int32_t),
  486                         BUS_DMASYNC_PREWRITE);                  
  487 
  488         return 0;
  489 }
  490 
  491 static void
  492 yds_enable_dsp(sc)
  493         struct yds_softc *sc;
  494 {
  495         YWRITE4(sc, YDS_CONFIG, YDS_DSP_SETUP);
  496 }
  497 
  498 static int
  499 yds_disable_dsp(sc)
  500         struct yds_softc *sc;
  501 {
  502         int to;
  503         u_int32_t data;
  504 
  505         data = YREAD4(sc, YDS_CONFIG);
  506         if (data)
  507                 YWRITE4(sc, YDS_CONFIG, YDS_DSP_DISABLE);
  508 
  509         for (to = 0; to < YDS_WORK_TIMEOUT; to++) {
  510                 if ((YREAD4(sc, YDS_STATUS) & YDS_STAT_WORK) == 0)
  511                         return 0;
  512                 delay(1);
  513         }
  514 
  515         return 1;
  516 }
  517 
  518 int
  519 yds_match(parent, match, aux)
  520         struct device *parent;
  521         struct cfdata *match;
  522         void *aux;
  523 {
  524         struct pci_attach_args *pa = (struct pci_attach_args *)aux;
  525 
  526         switch (PCI_VENDOR(pa->pa_id)) {
  527         case PCI_VENDOR_YAMAHA:
  528                 switch (PCI_PRODUCT(pa->pa_id)) {
  529                 case PCI_PRODUCT_YAMAHA_YMF724:
  530                 case PCI_PRODUCT_YAMAHA_YMF740:
  531                 case PCI_PRODUCT_YAMAHA_YMF740C:
  532                 case PCI_PRODUCT_YAMAHA_YMF724F:
  533                 case PCI_PRODUCT_YAMAHA_YMF744B:
  534                 case PCI_PRODUCT_YAMAHA_YMF754:
  535                         return (1);
  536                 }
  537                 break;
  538         }
  539 
  540         return (0);
  541 }
  542 
  543 /*
  544  * This routine is called after all the ISA devices are configured,
  545  * to avoid conflict.
  546  */
  547 static void
  548 yds_configure_legacy (arg)
  549         struct device *arg;
  550 #define FLEXIBLE        (sc->sc_flags & YDS_CAP_LEGACY_FLEXIBLE)
  551 #define SELECTABLE      (sc->sc_flags & YDS_CAP_LEGACY_SELECTABLE)
  552 {
  553         struct yds_softc *sc = (struct yds_softc*) arg;
  554         pcireg_t reg;
  555         struct device *dev;
  556         int i;
  557         bus_addr_t opl_addrs[] = {0x388, 0x398, 0x3A0, 0x3A8};
  558         bus_addr_t mpu_addrs[] = {0x330, 0x300, 0x332, 0x334};
  559 
  560         if (!FLEXIBLE && !SELECTABLE)
  561                 return;
  562 
  563         reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, YDS_PCI_LEGACY);
  564         reg &= ~0x8133c03f;     /* these bits are out of interest */
  565         reg |= ((YDS_PCI_EX_LEGACY_IMOD) |
  566                 (YDS_PCI_LEGACY_FMEN |
  567                  YDS_PCI_LEGACY_MEN /*| YDS_PCI_LEGACY_MIEN*/));
  568         reg |= YDS_PCI_EX_LEGACY_SMOD_DISABLE;
  569         if (FLEXIBLE) {
  570                 pci_conf_write(sc->sc_pc, sc->sc_pcitag, YDS_PCI_LEGACY, reg);
  571                 delay(100*1000);
  572         }
  573 
  574         /* Look for OPL */
  575         dev = 0;
  576         for (i = 0; i < sizeof(opl_addrs) / sizeof(bus_addr_t); i++) {
  577                 if (SELECTABLE) {
  578                         pci_conf_write(sc->sc_pc, sc->sc_pcitag,
  579                                        YDS_PCI_LEGACY, reg | (i << (0+16)));
  580                         delay(100*1000);        /* wait 100ms */
  581                 } else
  582                         pci_conf_write(sc->sc_pc, sc->sc_pcitag,
  583                                        YDS_PCI_FM_BA, opl_addrs[i]);
  584                 if (bus_space_map(sc->sc_opl_iot,
  585                                   opl_addrs[i], 4, 0, &sc->sc_opl_ioh) == 0) {
  586                         struct audio_attach_args aa; 
  587 
  588                         aa.type = AUDIODEV_TYPE_OPL;
  589                         aa.hwif = aa.hdl = NULL;
  590                         dev = config_found(&sc->sc_dev, &aa, audioprint);
  591                         if (dev == 0)
  592                                 bus_space_unmap(sc->sc_opl_iot,
  593                                                 sc->sc_opl_ioh, 4);
  594                         else {
  595                                 if (SELECTABLE)
  596                                         reg |= (i << (0+16));
  597                                 break;
  598                         }
  599                 } 
  600         }
  601         if (dev == 0) {
  602                 reg &= ~YDS_PCI_LEGACY_FMEN;
  603                 pci_conf_write(sc->sc_pc, sc->sc_pcitag,
  604                                YDS_PCI_LEGACY, reg);
  605         } else {
  606                 /* Max. volume */
  607                 YWRITE4(sc, YDS_LEGACY_OUT_VOLUME, 0x3fff3fff);
  608                 YWRITE4(sc, YDS_LEGACY_REC_VOLUME, 0x3fff3fff);
  609         }
  610 
  611         /* Look for MPU */
  612         dev = 0;
  613         for (i = 0; i < sizeof(mpu_addrs) / sizeof(bus_addr_t); i++) {
  614                 if (SELECTABLE)
  615                         pci_conf_write(sc->sc_pc, sc->sc_pcitag,
  616                                        YDS_PCI_LEGACY, reg | (i << (4+16)));
  617                 else
  618                         pci_conf_write(sc->sc_pc, sc->sc_pcitag,
  619                                        YDS_PCI_MPU_BA, mpu_addrs[i]);
  620                 if (bus_space_map(sc->sc_mpu_iot,
  621                                   mpu_addrs[i], 2, 0, &sc->sc_mpu_ioh) == 0) {
  622                         struct audio_attach_args aa; 
  623 
  624                         aa.type = AUDIODEV_TYPE_MPU;
  625                         aa.hwif = aa.hdl = NULL;
  626                         dev = config_found(&sc->sc_dev, &aa, audioprint);
  627                         if (dev == 0)
  628                                 bus_space_unmap(sc->sc_mpu_iot,
  629                                                 sc->sc_mpu_ioh, 2);
  630                         else {
  631                                 if (SELECTABLE)
  632                                         reg |= (i << (4+16));
  633                                 break;
  634                         }
  635                 }
  636         }
  637         if (dev == 0) {
  638                 reg &= ~(YDS_PCI_LEGACY_MEN | YDS_PCI_LEGACY_MIEN);
  639                 pci_conf_write(sc->sc_pc, sc->sc_pcitag, YDS_PCI_LEGACY, reg);
  640         }
  641         sc->sc_mpu = dev;
  642 } 
  643 #undef FLEXIBLE
  644 #undef SELECTABLE
  645 
  646 static int
  647 yds_init(sc)
  648         struct yds_softc *sc;
  649 {
  650         u_int32_t reg;
  651 
  652         DPRINTF(("yds_init()\n"));
  653 
  654         /* Download microcode */
  655         if (yds_download_mcode(sc)) {
  656                 printf("%s: download microcode failed\n", sc->sc_dev.dv_xname);
  657                 return 1;
  658         }
  659 
  660         /* Allocate DMA buffers */
  661         if (yds_allocate_slots(sc)) {
  662                 printf("%s: could not allocate slots\n", sc->sc_dev.dv_xname);
  663                 return 1;
  664         }
  665 
  666         /* Warm reset */
  667         reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, YDS_PCI_DSCTRL);
  668         pci_conf_write(sc->sc_pc, sc->sc_pcitag, YDS_PCI_DSCTRL,
  669                 reg | YDS_DSCTRL_WRST);
  670         delay(50000);
  671 
  672         return 0;
  673 }
  674 
  675 static void
  676 yds_powerhook(why, addr)
  677         int why;
  678         void *addr;
  679 {
  680         struct yds_softc *sc = addr;
  681 
  682         if (why == PWR_RESUME) {
  683                 if (yds_init(sc)) {
  684                         printf("%s: reinitialize failed\n",
  685                                 sc->sc_dev.dv_xname);
  686                         return;
  687                 }
  688                 sc->sc_codec[0].codec_if->vtbl->restore_ports(sc->sc_codec[0].codec_if);
  689         }
  690 }
  691 
  692 void
  693 yds_attach(parent, self, aux)
  694         struct device *parent;
  695         struct device *self;
  696         void *aux;
  697 {
  698         struct yds_softc *sc = (struct yds_softc *)self;
  699         struct pci_attach_args *pa = (struct pci_attach_args *)aux;
  700         pci_chipset_tag_t pc = pa->pa_pc;
  701         char const *intrstr;
  702         pci_intr_handle_t ih;
  703         pcireg_t reg;
  704         struct yds_codec_softc *codec;
  705         char devinfo[256];
  706         mixer_ctrl_t ctl;
  707         int i, r, to;
  708         int revision;
  709         int ac97_id2;
  710 
  711         pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
  712         revision = PCI_REVISION(pa->pa_class);
  713         printf(": %s (rev. 0x%02x)\n", devinfo, revision);
  714 
  715         /* Map register to memory */
  716         if (pci_mapreg_map(pa, YDS_PCI_MBA, PCI_MAPREG_TYPE_MEM, 0,
  717                            &sc->memt, &sc->memh, NULL, NULL)) {
  718                 printf("%s: can't map memory space\n", sc->sc_dev.dv_xname);
  719                 return;
  720         }
  721 
  722         /* Map and establish the interrupt. */
  723         if (pci_intr_map(pa, &ih)) {
  724                 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
  725                 return;
  726         }
  727         intrstr = pci_intr_string(pc, ih);
  728         sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, yds_intr, sc);
  729         if (sc->sc_ih == NULL) {
  730                 printf("%s: couldn't establish interrupt", sc->sc_dev.dv_xname);
  731                 if (intrstr != NULL)
  732                         printf(" at %s", intrstr);
  733                 printf("\n");
  734                 return;
  735         }
  736         printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
  737 
  738         sc->sc_dmatag = pa->pa_dmat;
  739         sc->sc_pc = pc;
  740         sc->sc_pcitag = pa->pa_tag;
  741         sc->sc_id = pa->pa_id;
  742         sc->sc_revision = revision;
  743         sc->sc_flags = yds_get_dstype(sc->sc_id);
  744 #ifdef AUDIO_DEBUG
  745         if (ydsdebug) {
  746                 char bits[80];
  747 
  748                 printf("%s: chip has %s\n", sc->sc_dev.dv_xname,
  749                        bitmask_snprintf(sc->sc_flags, YDS_CAP_BITS, bits,
  750                                         sizeof(bits)));
  751         }
  752 #endif
  753 
  754         /* Disable legacy mode */
  755         reg = pci_conf_read(pc, pa->pa_tag, YDS_PCI_LEGACY);
  756         pci_conf_write(pc, pa->pa_tag, YDS_PCI_LEGACY,
  757                        reg & YDS_PCI_LEGACY_LAD);
  758 
  759         /* Enable the device. */
  760         reg = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
  761         reg |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
  762                 PCI_COMMAND_MASTER_ENABLE);
  763         pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg);
  764         reg = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
  765 
  766         /* Mute all volumes */
  767         for (i = 0x80; i < 0xc0; i += 2)
  768                 YWRITE2(sc, i, 0);
  769 
  770         /* Initialize the device */
  771         if (yds_init(sc)) {
  772                 printf("%s: initialize failed\n", sc->sc_dev.dv_xname);
  773                 return;
  774         }
  775 
  776         /*
  777          * Detect primary/secondary AC97
  778          *      YMF754 Hardware Specification Rev 1.01 page 24
  779          */
  780         reg = pci_conf_read(pc, pa->pa_tag, YDS_PCI_DSCTRL);
  781         pci_conf_write(pc, pa->pa_tag, YDS_PCI_DSCTRL, reg & ~YDS_DSCTRL_CRST);
  782         delay(400000);          /* Needed for 740C. */
  783 
  784         /* Primary */
  785         for (to = 0; to < AC97_TIMEOUT; to++) {
  786                 if ((YREAD2(sc, AC97_STAT_ADDR1) & AC97_BUSY) == 0)
  787                         break;
  788                 delay(1);
  789         }
  790         if (to == AC97_TIMEOUT) {
  791                 printf("%s: no AC97 available\n", sc->sc_dev.dv_xname);
  792                 return;
  793         }
  794 
  795         /* Secondary */
  796         /* Secondary AC97 is used for 4ch audio. Currently unused. */
  797         ac97_id2 = -1;
  798         if ((YREAD2(sc, YDS_ACTIVITY) & YDS_ACTIVITY_DOCKA) == 0)
  799                 goto detected;
  800 #if 0                           /* reset secondary... */
  801         YWRITE2(sc, YDS_GPIO_OCTRL,
  802                 YREAD2(sc, YDS_GPIO_OCTRL) & ~YDS_GPIO_GPO2);
  803         YWRITE2(sc, YDS_GPIO_FUNCE,
  804                 (YREAD2(sc, YDS_GPIO_FUNCE)&(~YDS_GPIO_GPC2))|YDS_GPIO_GPE2);
  805 #endif
  806         for (to = 0; to < AC97_TIMEOUT; to++) {
  807                 if ((YREAD2(sc, AC97_STAT_ADDR2) & AC97_BUSY) == 0)
  808                         break;
  809                 delay(1);
  810         }
  811         if (to < AC97_TIMEOUT) {
  812                 /* detect id */
  813                 for (ac97_id2 = 1; ac97_id2 < 4; ac97_id2++) {
  814                         YWRITE2(sc, AC97_CMD_ADDR,
  815                                 AC97_CMD_READ | AC97_ID(ac97_id2) | 0x28);
  816 
  817                         for (to = 0; to < AC97_TIMEOUT; to++) {
  818                                 if ((YREAD2(sc, AC97_STAT_ADDR2) & AC97_BUSY)
  819                                     == 0)
  820                                         goto detected;
  821                                 delay(1);
  822                         }
  823                 }
  824                 if (ac97_id2 == 4)
  825                         ac97_id2 = -1;
  826 detected:
  827                 ;
  828         }
  829 
  830         pci_conf_write(pc, pa->pa_tag, YDS_PCI_DSCTRL, reg | YDS_DSCTRL_CRST);
  831         delay (20);
  832         pci_conf_write(pc, pa->pa_tag, YDS_PCI_DSCTRL, reg & ~YDS_DSCTRL_CRST);
  833         delay (400000);
  834         for (to = 0; to < AC97_TIMEOUT; to++) {
  835                 if ((YREAD2(sc, AC97_STAT_ADDR1) & AC97_BUSY) == 0)
  836                         break;
  837                 delay(1);
  838         }
  839 
  840         /*
  841          * Attach ac97 codec
  842          */
  843         for (i = 0; i < 2; i++) {
  844                 static struct {
  845                         int data;
  846                         int addr;
  847                 } statregs[] = {
  848                         {AC97_STAT_DATA1, AC97_STAT_ADDR1},
  849                         {AC97_STAT_DATA2, AC97_STAT_ADDR2},
  850                 };
  851 
  852                 if (i == 1 && ac97_id2 == -1)
  853                         break;          /* secondary ac97 not available */
  854 
  855                 codec = &sc->sc_codec[i];
  856                 memcpy(&codec->sc_dev, &sc->sc_dev, sizeof(codec->sc_dev));
  857                 codec->sc = sc;
  858                 codec->id = i == 1 ? ac97_id2 : 0;
  859                 codec->status_data = statregs[i].data;
  860                 codec->status_addr = statregs[i].addr;
  861                 codec->host_if.arg = codec;
  862                 codec->host_if.attach = yds_attach_codec;
  863                 codec->host_if.read = yds_read_codec;
  864                 codec->host_if.write = yds_write_codec;
  865                 codec->host_if.reset = yds_reset_codec;
  866 
  867                 if ((r = ac97_attach(&codec->host_if)) != 0) {
  868                         printf("%s: can't attach codec (error 0x%X)\n",
  869                                sc->sc_dev.dv_xname, r);
  870                         return;
  871                 }
  872         }
  873 
  874         /* Just enable the DAC and master volumes by default */
  875         ctl.type = AUDIO_MIXER_ENUM;
  876         ctl.un.ord = 0;  /* off */
  877         ctl.dev = yds_get_portnum_by_name(sc, AudioCoutputs,
  878                                           AudioNmaster, AudioNmute);
  879         yds_mixer_set_port(sc, &ctl);
  880         ctl.dev = yds_get_portnum_by_name(sc, AudioCinputs,
  881                                           AudioNdac, AudioNmute);
  882         yds_mixer_set_port(sc, &ctl);
  883         ctl.dev = yds_get_portnum_by_name(sc, AudioCinputs,
  884                                           AudioNcd, AudioNmute);
  885         yds_mixer_set_port(sc, &ctl);
  886         ctl.dev = yds_get_portnum_by_name(sc, AudioCrecord,
  887                                           AudioNvolume, AudioNmute);
  888         yds_mixer_set_port(sc, &ctl);
  889         
  890         ctl.dev = yds_get_portnum_by_name(sc, AudioCrecord,
  891                                           AudioNsource, NULL);
  892         ctl.type = AUDIO_MIXER_ENUM;
  893         ctl.un.ord = 0;
  894         yds_mixer_set_port(sc, &ctl);
  895 
  896         /* Set a reasonable default volume */
  897         ctl.type = AUDIO_MIXER_VALUE;
  898         ctl.un.value.num_channels = 2;
  899         ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
  900         ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127;
  901 
  902         ctl.dev = sc->sc_codec[0].codec_if->vtbl->get_portnum_by_name(
  903             sc->sc_codec[0].codec_if, AudioCoutputs, AudioNmaster, NULL);
  904         yds_mixer_set_port(sc, &ctl);
  905 
  906         audio_attach_mi(&yds_hw_if, sc, &sc->sc_dev);
  907 
  908         sc->sc_legacy_iot = pa->pa_iot;
  909         config_defer((struct device*) sc, yds_configure_legacy);
  910 
  911         powerhook_establish(yds_powerhook, sc);
  912 }
  913 
  914 int
  915 yds_attach_codec(sc_, codec_if)
  916         void *sc_;
  917         struct ac97_codec_if *codec_if;
  918 {
  919         struct yds_codec_softc *sc = sc_;
  920 
  921         sc->codec_if = codec_if;
  922         return 0;
  923 }
  924 
  925 static int
  926 yds_ready_codec(sc)
  927         struct yds_codec_softc *sc;
  928 {
  929         int to;
  930 
  931         for (to = 0; to < AC97_TIMEOUT; to++) {
  932                 if ((YREAD2(sc->sc, sc->status_addr) & AC97_BUSY) == 0)
  933                         return 0;
  934                 delay(1);
  935         }
  936 
  937         return 1;
  938 }
  939 
  940 int
  941 yds_read_codec(sc_, reg, data)
  942         void *sc_;
  943         u_int8_t reg;
  944         u_int16_t *data;
  945 {
  946         struct yds_codec_softc *sc = sc_;
  947 
  948         YWRITE2(sc->sc, AC97_CMD_ADDR, AC97_CMD_READ | AC97_ID(sc->id) | reg);
  949 
  950         if (yds_ready_codec(sc)) {
  951                 printf("%s: yds_read_codec timeout\n",
  952                        sc->sc->sc_dev.dv_xname);
  953                 return EIO;
  954         }
  955 
  956         if (PCI_PRODUCT(sc->sc->sc_id) == PCI_PRODUCT_YAMAHA_YMF744B &&
  957             sc->sc->sc_revision < 2) {
  958                 int i;
  959                 for (i=0; i<600; i++)
  960                         YREAD2(sc->sc, sc->status_data);
  961         }
  962 
  963         *data = YREAD2(sc->sc, sc->status_data);
  964 
  965         return 0;
  966 }
  967 
  968 int
  969 yds_write_codec(sc_, reg, data)
  970         void *sc_;
  971         u_int8_t reg;
  972         u_int16_t data;
  973 {
  974         struct yds_codec_softc *sc = sc_;
  975 
  976         YWRITE2(sc->sc, AC97_CMD_ADDR, AC97_CMD_WRITE | AC97_ID(sc->id) | reg);
  977         YWRITE2(sc->sc, AC97_CMD_DATA, data);
  978 
  979         if (yds_ready_codec(sc)) {
  980                 printf("%s: yds_write_codec timeout\n",
  981                         sc->sc->sc_dev.dv_xname);
  982                 return EIO;
  983         }
  984 
  985         return 0;
  986 }
  987 
  988 /*
  989  * XXX: Must handle the secondary differntly!!
  990  */
  991 int
  992 yds_reset_codec(sc_)
  993         void *sc_;
  994 {
  995         struct yds_codec_softc *codec = sc_;
  996         struct yds_softc *sc = codec->sc;
  997         pcireg_t reg;
  998 
  999         /* reset AC97 codec */
 1000         reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, YDS_PCI_DSCTRL);
 1001         if (reg & 0x03) {
 1002                 pci_conf_write(sc->sc_pc, sc->sc_pcitag,
 1003                                YDS_PCI_DSCTRL, reg & ~0x03);
 1004                 pci_conf_write(sc->sc_pc, sc->sc_pcitag,
 1005                                YDS_PCI_DSCTRL, reg | 0x03);
 1006                 pci_conf_write(sc->sc_pc, sc->sc_pcitag,
 1007                                YDS_PCI_DSCTRL, reg & ~0x03);
 1008                 delay(50000);
 1009         }
 1010 
 1011         yds_ready_codec(sc_);
 1012         return 0;
 1013 }
 1014 
 1015 int
 1016 yds_intr(p)
 1017         void *p;
 1018 {
 1019         struct yds_softc *sc = p;
 1020         u_int status;
 1021 
 1022         status = YREAD4(sc, YDS_STATUS);
 1023         DPRINTFN(1, ("yds_intr: status=%08x\n", status));
 1024         if ((status & (YDS_STAT_INT|YDS_STAT_TINT)) == 0) {
 1025 #if NMPU > 0
 1026                 if (sc->sc_mpu)
 1027                         return mpu_intr(sc->sc_mpu);
 1028 #endif
 1029                 return 0;
 1030         }
 1031 
 1032         if (status & YDS_STAT_TINT) {
 1033                 YWRITE4(sc, YDS_STATUS, YDS_STAT_TINT);
 1034                 printf ("yds_intr: timeout!\n");
 1035         }
 1036 
 1037         if (status & YDS_STAT_INT) {
 1038                 int nbank = (YREAD4(sc, YDS_CONTROL_SELECT) == 0);
 1039 
 1040                 /* Clear interrupt flag */
 1041                 YWRITE4(sc, YDS_STATUS, YDS_STAT_INT);
 1042 
 1043                 /* Buffer for the next frame is always ready. */
 1044                 YWRITE4(sc, YDS_MODE, YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV2);
 1045 
 1046                 if (sc->sc_play.intr) {
 1047                         u_int dma, cpu, blk, len;
 1048 
 1049                         /* Sync play slot control data */
 1050                         bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
 1051                                         sc->pbankoff,
 1052                                         sizeof(struct play_slot_ctrl_bank)*
 1053                                             le32toh(*sc->ptbl)*
 1054                                             N_PLAY_SLOT_CTRL_BANK,
 1055                                         BUS_DMASYNC_POSTWRITE|
 1056                                         BUS_DMASYNC_POSTREAD);
 1057                         dma = le32toh(sc->pbankp[nbank]->pgstart) * sc->sc_play.factor;
 1058                         cpu = sc->sc_play.offset;
 1059                         blk = sc->sc_play.blksize;
 1060                         len = sc->sc_play.length;
 1061 
 1062                         if (((dma > cpu) && (dma - cpu > blk * 2)) ||
 1063                             ((cpu > dma) && (dma + len - cpu > blk * 2))) {
 1064                                 /* We can fill the next block */
 1065                                 /* Sync ring buffer for previous write */
 1066                                 bus_dmamap_sync(sc->sc_dmatag,
 1067                                                 sc->sc_play.dma->map,
 1068                                                 cpu, blk,
 1069                                                 BUS_DMASYNC_POSTWRITE);
 1070                                 sc->sc_play.intr(sc->sc_play.intr_arg);
 1071                                 sc->sc_play.offset += blk;
 1072                                 if (sc->sc_play.offset >= len) {
 1073                                         sc->sc_play.offset -= len;
 1074 #ifdef DIAGNOSTIC
 1075                                         if (sc->sc_play.offset != 0)
 1076                                                 printf ("Audio ringbuffer botch\n");
 1077 #endif
 1078                                 }
 1079                                 /* Sync ring buffer for next write */
 1080                                 bus_dmamap_sync(sc->sc_dmatag,
 1081                                                 sc->sc_play.dma->map,
 1082                                                 cpu, blk,
 1083                                                 BUS_DMASYNC_PREWRITE);
 1084                         }
 1085                 }
 1086                 if (sc->sc_rec.intr) {
 1087                         u_int dma, cpu, blk, len;
 1088 
 1089                         /* Sync rec slot control data */
 1090                         bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
 1091                                         sc->rbankoff,
 1092                                         sizeof(struct rec_slot_ctrl_bank)*
 1093                                             N_REC_SLOT_CTRL*
 1094                                             N_REC_SLOT_CTRL_BANK,
 1095                                         BUS_DMASYNC_POSTWRITE|
 1096                                         BUS_DMASYNC_POSTREAD);
 1097                         dma = le32toh(sc->rbank[YDS_INPUT_SLOT*2 + nbank].pgstartadr);
 1098                         cpu = sc->sc_rec.offset;
 1099                         blk = sc->sc_rec.blksize;
 1100                         len = sc->sc_rec.length;
 1101 
 1102                         if (((dma > cpu) && (dma - cpu > blk * 2)) ||
 1103                             ((cpu > dma) && (dma + len - cpu > blk * 2))) {
 1104                                 /* We can drain the current block */
 1105                                 /* Sync ring buffer first */
 1106                                 bus_dmamap_sync(sc->sc_dmatag,
 1107                                                 sc->sc_rec.dma->map,
 1108                                                 cpu, blk,
 1109                                                 BUS_DMASYNC_POSTREAD);
 1110                                 sc->sc_rec.intr(sc->sc_rec.intr_arg);
 1111                                 sc->sc_rec.offset += blk;
 1112                                 if (sc->sc_rec.offset >= len) {
 1113                                         sc->sc_rec.offset -= len;
 1114 #ifdef DIAGNOSTIC
 1115                                         if (sc->sc_rec.offset != 0)
 1116                                                 printf ("Audio ringbuffer botch\n");
 1117 #endif
 1118                                 }
 1119                                 /* Sync ring buffer for next read */
 1120                                 bus_dmamap_sync(sc->sc_dmatag,
 1121                                                 sc->sc_rec.dma->map,
 1122                                                 cpu, blk,
 1123                                                 BUS_DMASYNC_PREREAD);
 1124                         }
 1125                 }
 1126         }
 1127 
 1128         return 1;
 1129 }
 1130 
 1131 int
 1132 yds_allocmem(sc, size, align, p)
 1133         struct yds_softc *sc;
 1134         size_t size;
 1135         size_t align;
 1136         struct yds_dma *p;
 1137 {
 1138         int error;
 1139 
 1140         p->size = size;
 1141         error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
 1142                                  p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
 1143                                  &p->nsegs, BUS_DMA_NOWAIT);
 1144         if (error)
 1145                 return (error);
 1146 
 1147         error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size, 
 1148                                &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
 1149         if (error)
 1150                 goto free;
 1151 
 1152         error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
 1153                                   0, BUS_DMA_NOWAIT, &p->map);
 1154         if (error)
 1155                 goto unmap;
 1156 
 1157         error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL, 
 1158                                 BUS_DMA_NOWAIT);
 1159         if (error)
 1160                 goto destroy;
 1161         return (0);
 1162 
 1163 destroy:
 1164         bus_dmamap_destroy(sc->sc_dmatag, p->map);
 1165 unmap:
 1166         bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
 1167 free:
 1168         bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
 1169         return (error);
 1170 }
 1171 
 1172 int
 1173 yds_freemem(sc, p)
 1174         struct yds_softc *sc;
 1175         struct yds_dma *p;
 1176 {
 1177         bus_dmamap_unload(sc->sc_dmatag, p->map);
 1178         bus_dmamap_destroy(sc->sc_dmatag, p->map);
 1179         bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
 1180         bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
 1181         return 0;
 1182 }
 1183 
 1184 int
 1185 yds_open(addr, flags)
 1186         void *addr;
 1187         int flags;
 1188 {
 1189         struct yds_softc *sc = addr;
 1190         u_int32_t mode;
 1191 
 1192         /* Select bank 0. */
 1193         YWRITE4(sc, YDS_CONTROL_SELECT, 0);
 1194 
 1195         /* Start the DSP operation. */
 1196         mode = YREAD4(sc, YDS_MODE);
 1197         mode |= YDS_MODE_ACTV;
 1198         mode &= ~YDS_MODE_ACTV2;
 1199         YWRITE4(sc, YDS_MODE, mode);
 1200 
 1201         return 0;
 1202 }
 1203 
 1204 /*
 1205  * Close function is called at splaudio().
 1206  */
 1207 void
 1208 yds_close(addr)
 1209         void *addr;
 1210 {
 1211         struct yds_softc *sc = addr;
 1212 
 1213         yds_halt_output(sc);
 1214         yds_halt_input(sc);
 1215         yds_halt(sc);
 1216 }
 1217 
 1218 int
 1219 yds_query_encoding(addr, fp)
 1220         void *addr;
 1221         struct audio_encoding *fp;
 1222 {
 1223         switch (fp->index) {
 1224         case 0:
 1225                 strcpy(fp->name, AudioEulinear);
 1226                 fp->encoding = AUDIO_ENCODING_ULINEAR;
 1227                 fp->precision = 8;
 1228                 fp->flags = 0;
 1229                 return (0);
 1230         case 1:
 1231                 strcpy(fp->name, AudioEmulaw);
 1232                 fp->encoding = AUDIO_ENCODING_ULAW;
 1233                 fp->precision = 8;
 1234                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
 1235                 return (0);
 1236         case 2:
 1237                 strcpy(fp->name, AudioEalaw);
 1238                 fp->encoding = AUDIO_ENCODING_ALAW;
 1239                 fp->precision = 8;
 1240                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
 1241                 return (0);
 1242         case 3:
 1243                 strcpy(fp->name, AudioEslinear);
 1244                 fp->encoding = AUDIO_ENCODING_SLINEAR;
 1245                 fp->precision = 8;
 1246                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
 1247                 return (0);
 1248         case 4:
 1249                 strcpy(fp->name, AudioEslinear_le);
 1250                 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
 1251                 fp->precision = 16;
 1252                 fp->flags = 0;
 1253                 return (0);
 1254         case 5:
 1255                 strcpy(fp->name, AudioEulinear_le);
 1256                 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
 1257                 fp->precision = 16;
 1258                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
 1259                 return (0);
 1260         case 6:
 1261                 strcpy(fp->name, AudioEslinear_be);
 1262                 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
 1263                 fp->precision = 16;
 1264                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
 1265                 return (0);
 1266         case 7:
 1267                 strcpy(fp->name, AudioEulinear_be);
 1268                 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
 1269                 fp->precision = 16;
 1270                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
 1271                 return (0);
 1272         default:
 1273                 return (EINVAL);
 1274         }
 1275 }
 1276 
 1277 int
 1278 yds_set_params(addr, setmode, usemode, play, rec)
 1279         void *addr;
 1280         int setmode, usemode;
 1281         struct audio_params *play, *rec;
 1282 {
 1283         struct audio_params *p;
 1284         int mode;
 1285 
 1286         for (mode = AUMODE_RECORD; mode != -1; 
 1287              mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
 1288                 if ((setmode & mode) == 0)
 1289                         continue;
 1290 
 1291                 p = mode == AUMODE_PLAY ? play : rec;
 1292 
 1293                 if (p->sample_rate < 4000 || p->sample_rate > 48000 ||
 1294                     (p->precision != 8 && p->precision != 16) ||
 1295                     (p->channels != 1 && p->channels != 2))
 1296                         return (EINVAL);
 1297 
 1298                 p->factor = 1;
 1299                 p->sw_code = 0;
 1300                 switch (p->encoding) {
 1301                 case AUDIO_ENCODING_SLINEAR_BE:
 1302                         if (p->precision == 16)
 1303                                 p->sw_code = swap_bytes;
 1304                         else
 1305                                 p->sw_code = change_sign8;
 1306                         break;
 1307                 case AUDIO_ENCODING_SLINEAR_LE:
 1308                         if (p->precision != 16)
 1309                                 p->sw_code = change_sign8;
 1310                         break;
 1311                 case AUDIO_ENCODING_ULINEAR_BE:
 1312                         if (p->precision == 16) {
 1313                                 if (mode == AUMODE_PLAY)
 1314                                         p->sw_code = swap_bytes_change_sign16_le;
 1315                                 else
 1316                                         p->sw_code = change_sign16_swap_bytes_le;
 1317                         }
 1318                         break;
 1319                 case AUDIO_ENCODING_ULINEAR_LE:
 1320                         if (p->precision == 16)
 1321                                 p->sw_code = change_sign16_le;
 1322                         break;
 1323                 case AUDIO_ENCODING_ULAW:
 1324                         if (mode == AUMODE_PLAY) {
 1325                                 p->factor = 2;
 1326                                 p->precision = 16;
 1327                                 p->sw_code = mulaw_to_slinear16_le;
 1328                         } else
 1329                                 p->sw_code = ulinear8_to_mulaw;
 1330                         break;
 1331                 case AUDIO_ENCODING_ALAW:
 1332                         if (mode == AUMODE_PLAY) {
 1333                                 p->factor = 2;
 1334                                 p->precision = 16;
 1335                                 p->sw_code = alaw_to_slinear16_le;
 1336                         } else
 1337                                 p->sw_code = ulinear8_to_alaw;
 1338                         break;
 1339                 default:
 1340                         return (EINVAL);
 1341                 }
 1342         }
 1343 
 1344         return 0;
 1345 }
 1346 
 1347 int
 1348 yds_round_blocksize(addr, blk)
 1349         void *addr;
 1350         int blk;
 1351 {
 1352         /*
 1353          * Block size must be bigger than a frame.
 1354          * That is 1024bytes at most, i.e. for 48000Hz, 16bit, 2ch.
 1355          */
 1356         if (blk < 1024)
 1357                 blk = 1024;
 1358 
 1359         return blk & ~4;
 1360 }
 1361 
 1362 static u_int32_t
 1363 yds_get_lpfq(sample_rate)
 1364         u_int sample_rate;
 1365 {
 1366         int i;
 1367         static struct lpfqt {
 1368                 u_int rate;
 1369                 u_int32_t lpfq;
 1370         } lpfqt[] = {
 1371                 {8000,  0x32020000},
 1372                 {11025, 0x31770000},
 1373                 {16000, 0x31390000},
 1374                 {22050, 0x31c90000},
 1375                 {32000, 0x33d00000},
 1376                 {48000, 0x40000000},
 1377                 {0, 0}
 1378         };
 1379 
 1380         if (sample_rate == 44100)               /* for P44 slot? */
 1381                 return 0x370A0000;
 1382 
 1383         for (i = 0; lpfqt[i].rate != 0; i++)
 1384                 if (sample_rate <= lpfqt[i].rate)
 1385                         break;
 1386 
 1387         return lpfqt[i].lpfq;
 1388 }
 1389 
 1390 static u_int32_t
 1391 yds_get_lpfk(sample_rate)
 1392         u_int sample_rate;
 1393 {
 1394         int i;
 1395         static struct lpfkt {
 1396                 u_int rate;
 1397                 u_int32_t lpfk;
 1398         } lpfkt[] = {
 1399                 {8000,  0x18b20000},
 1400                 {11025, 0x20930000},
 1401                 {16000, 0x2b9a0000},
 1402                 {22050, 0x35a10000},
 1403                 {32000, 0x3eaa0000},
 1404                 {48000, 0x40000000},
 1405                 {0, 0}
 1406         };
 1407 
 1408         if (sample_rate == 44100)               /* for P44 slot? */
 1409                 return 0x46460000;
 1410 
 1411         for (i = 0; lpfkt[i].rate != 0; i++)
 1412                 if (sample_rate <= lpfkt[i].rate)
 1413                         break;
 1414 
 1415         return lpfkt[i].lpfk;
 1416 }
 1417 
 1418 int
 1419 yds_trigger_output(addr, start, end, blksize, intr, arg, param)
 1420         void *addr;
 1421         void *start, *end;
 1422         int blksize;
 1423         void (*intr) __P((void *));
 1424         void *arg;
 1425         struct audio_params *param;
 1426 #define P44             (sc->sc_flags & YDS_CAP_HAS_P44)
 1427 {
 1428         struct yds_softc *sc = addr;
 1429         struct yds_dma *p;
 1430         struct play_slot_ctrl_bank *psb;
 1431         const u_int gain = 0x40000000;
 1432         bus_addr_t s;
 1433         size_t l;
 1434         int i;
 1435         int p44, channels;
 1436         u_int32_t format;
 1437 
 1438 #ifdef DIAGNOSTIC
 1439         if (sc->sc_play.intr)
 1440                 panic("yds_trigger_output: already running");
 1441 #endif
 1442 
 1443         sc->sc_play.intr = intr;
 1444         sc->sc_play.intr_arg = arg;
 1445         sc->sc_play.offset = 0;
 1446         sc->sc_play.blksize = blksize;
 1447 
 1448         DPRINTFN(1, ("yds_trigger_output: sc=%p start=%p end=%p "
 1449             "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
 1450 
 1451         p = yds_find_dma(sc, start);
 1452         if (!p) {
 1453                 printf("yds_trigger_output: bad addr %p\n", start);
 1454                 return (EINVAL);
 1455         }
 1456         sc->sc_play.dma = p;
 1457 
 1458 #ifdef YDS_USE_P44
 1459         /* The document says the P44 SRC supports only stereo, 16bit PCM. */
 1460         if (P44)
 1461                 p44 = ((param->sample_rate == 44100) &&
 1462                        (param->channels == 2) &&
 1463                        (param->precision == 16));
 1464         else
 1465 #endif
 1466                 p44 = 0;
 1467         channels = p44 ? 1 : param->channels;
 1468 
 1469         s = DMAADDR(p);
 1470         l = ((char *)end - (char *)start);
 1471         sc->sc_play.length = l;
 1472 
 1473         *sc->ptbl = htole32(channels);  /* Num of play */
 1474 
 1475         sc->sc_play.factor = 1;
 1476         if (param->channels == 2)
 1477                 sc->sc_play.factor *= 2;
 1478         if (param->precision != 8)
 1479                 sc->sc_play.factor *= 2;
 1480         l /= sc->sc_play.factor;
 1481 
 1482         format = ((channels == 2 ? PSLT_FORMAT_STEREO : 0) |
 1483                   (param->precision == 8 ? PSLT_FORMAT_8BIT : 0) |
 1484                   (p44 ? PSLT_FORMAT_SRC441 : 0));
 1485 
 1486         psb = sc->pbankp[0];
 1487         memset(psb, 0, sizeof(*psb));
 1488         psb->format = htole32(format);
 1489         psb->pgbase = htole32(s);
 1490         psb->pgloopend = htole32(l);
 1491         if (!p44) {
 1492                 psb->pgdeltaend = htole32((param->sample_rate * 65536 / 48000) << 12);
 1493                 psb->lpfkend = htole32(yds_get_lpfk(param->sample_rate));
 1494                 psb->eggainend = htole32(gain);
 1495                 psb->lpfq = htole32(yds_get_lpfq(param->sample_rate));
 1496                 psb->pgdelta = htole32(psb->pgdeltaend);
 1497                 psb->lpfk = htole32(yds_get_lpfk(param->sample_rate));
 1498                 psb->eggain = htole32(gain);
 1499         }
 1500 
 1501         for (i = 0; i < channels; i++) {
 1502                 /* i == 0: left or mono, i == 1: right */
 1503                 psb = sc->pbankp[i*2];
 1504                 if (i)
 1505                         /* copy from left */
 1506                         *psb = *(sc->pbankp[0]);
 1507                 if (channels == 2) {
 1508                         /* stereo */
 1509                         if (i == 0) {
 1510                                 psb->lchgain = psb->lchgainend = htole32(gain);
 1511                         } else {
 1512                                 psb->lchgain = psb->lchgainend = 0;
 1513                                 psb->rchgain = psb->rchgainend = htole32(gain);
 1514                                 psb->format |= htole32(PSLT_FORMAT_RCH);
 1515                         }
 1516                 } else if (!p44) {
 1517                         /* mono */
 1518                         psb->lchgain = psb->rchgain = htole32(gain);
 1519                         psb->lchgainend = psb->rchgainend = htole32(gain);
 1520                 }
 1521                 /* copy to the other bank */
 1522                 *(sc->pbankp[i*2+1]) = *psb;
 1523         }
 1524 
 1525         YDS_DUMP_PLAY_SLOT(5, sc, 0);
 1526         YDS_DUMP_PLAY_SLOT(5, sc, 1);
 1527 
 1528         if (p44)
 1529                 YWRITE4(sc, YDS_P44_OUT_VOLUME, 0x3fff3fff);
 1530         else
 1531                 YWRITE4(sc, YDS_DAC_OUT_VOLUME, 0x3fff3fff);
 1532 
 1533         /* Now the play slot for the next frame is set up!! */
 1534         /* Sync play slot control data for both directions */
 1535         bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
 1536                         sc->ptbloff,
 1537                         sizeof(struct play_slot_ctrl_bank) *
 1538                             channels * N_PLAY_SLOT_CTRL_BANK,
 1539                         BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
 1540         /* Sync ring buffer */
 1541         bus_dmamap_sync(sc->sc_dmatag, p->map, 0, blksize,
 1542                         BUS_DMASYNC_PREWRITE);
 1543         /* HERE WE GO!! */
 1544         YWRITE4(sc, YDS_MODE,
 1545                 YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV | YDS_MODE_ACTV2);
 1546 
 1547         return 0;
 1548 }
 1549 #undef P44
 1550 
 1551 int
 1552 yds_trigger_input(addr, start, end, blksize, intr, arg, param)
 1553         void *addr;
 1554         void *start, *end;
 1555         int blksize;
 1556         void (*intr) __P((void *));
 1557         void *arg;
 1558         struct audio_params *param;
 1559 {
 1560         struct yds_softc *sc = addr;
 1561         struct yds_dma *p;
 1562         u_int srate, format;
 1563         struct rec_slot_ctrl_bank *rsb;
 1564         bus_addr_t s;
 1565         size_t l;
 1566 
 1567 #ifdef DIAGNOSTIC
 1568         if (sc->sc_rec.intr)
 1569                 panic("yds_trigger_input: already running");
 1570 #endif
 1571         sc->sc_rec.intr = intr;
 1572         sc->sc_rec.intr_arg = arg;
 1573         sc->sc_rec.offset = 0;
 1574         sc->sc_rec.blksize = blksize;
 1575 
 1576         DPRINTFN(1, ("yds_trigger_input: "
 1577             "sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n", 
 1578             addr, start, end, blksize, intr, arg));
 1579         DPRINTFN(1, (" parameters: rate=%lu, precision=%u, channels=%u\n",
 1580             param->sample_rate, param->precision, param->channels));
 1581 
 1582         p = yds_find_dma(sc, start);
 1583         if (!p) {
 1584                 printf("yds_trigger_input: bad addr %p\n", start);
 1585                 return (EINVAL);
 1586         }
 1587         sc->sc_rec.dma = p;
 1588 
 1589         s = DMAADDR(p);
 1590         l = ((char *)end - (char *)start);
 1591         sc->sc_rec.length = l;
 1592 
 1593         sc->sc_rec.factor = 1;
 1594         if (param->channels == 2)
 1595                 sc->sc_rec.factor *= 2;
 1596         if (param->precision != 8)
 1597                 sc->sc_rec.factor *= 2;
 1598 
 1599         rsb = &sc->rbank[0];
 1600         memset(rsb, 0, sizeof(*rsb));
 1601         rsb->pgbase = htole32(s);
 1602         rsb->pgloopendadr = htole32(l);
 1603         /* Seems all 4 banks must be set up... */
 1604         sc->rbank[1] = *rsb;
 1605         sc->rbank[2] = *rsb;
 1606         sc->rbank[3] = *rsb;
 1607 
 1608         YWRITE4(sc, YDS_ADC_IN_VOLUME, 0x3fff3fff);
 1609         YWRITE4(sc, YDS_REC_IN_VOLUME, 0x3fff3fff);
 1610         srate = 48000 * 4096 / param->sample_rate - 1;
 1611         format = ((param->precision == 8 ? YDS_FORMAT_8BIT : 0) |
 1612                   (param->channels == 2 ? YDS_FORMAT_STEREO : 0));
 1613         DPRINTF(("srate=%d, format=%08x\n", srate, format));
 1614 #ifdef YDS_USE_REC_SLOT
 1615         YWRITE4(sc, YDS_DAC_REC_VOLUME, 0x3fff3fff);
 1616         YWRITE4(sc, YDS_P44_REC_VOLUME, 0x3fff3fff);
 1617         YWRITE4(sc, YDS_MAPOF_REC, YDS_RECSLOT_VALID);
 1618         YWRITE4(sc, YDS_REC_SAMPLE_RATE, srate);
 1619         YWRITE4(sc, YDS_REC_FORMAT, format);
 1620 #else
 1621         YWRITE4(sc, YDS_MAPOF_REC, YDS_ADCSLOT_VALID);
 1622         YWRITE4(sc, YDS_ADC_SAMPLE_RATE, srate);
 1623         YWRITE4(sc, YDS_ADC_FORMAT, format);
 1624 #endif
 1625         /* Now the rec slot for the next frame is set up!! */
 1626         /* Sync record slot control data */
 1627         bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
 1628                         sc->rbankoff,
 1629                         sizeof(struct rec_slot_ctrl_bank)*
 1630                             N_REC_SLOT_CTRL*
 1631                             N_REC_SLOT_CTRL_BANK,
 1632                         BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
 1633         /* Sync ring buffer */
 1634         bus_dmamap_sync(sc->sc_dmatag, p->map, 0, blksize,
 1635                         BUS_DMASYNC_PREREAD);
 1636         /* HERE WE GO!! */
 1637         YWRITE4(sc, YDS_MODE,
 1638                 YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV | YDS_MODE_ACTV2);
 1639 
 1640         return 0;
 1641 }
 1642 
 1643 static int
 1644 yds_halt(sc)
 1645         struct yds_softc *sc;
 1646 {
 1647         u_int32_t mode;
 1648 
 1649         /* Stop the DSP operation. */
 1650         mode = YREAD4(sc, YDS_MODE);
 1651         YWRITE4(sc, YDS_MODE, mode & ~(YDS_MODE_ACTV|YDS_MODE_ACTV2));
 1652 
 1653         /* Paranoia...  mute all */
 1654         YWRITE4(sc, YDS_P44_OUT_VOLUME, 0);
 1655         YWRITE4(sc, YDS_DAC_OUT_VOLUME, 0);
 1656         YWRITE4(sc, YDS_ADC_IN_VOLUME, 0);
 1657         YWRITE4(sc, YDS_REC_IN_VOLUME, 0);
 1658         YWRITE4(sc, YDS_DAC_REC_VOLUME, 0);
 1659         YWRITE4(sc, YDS_P44_REC_VOLUME, 0);
 1660 
 1661         return 0;
 1662 }
 1663 
 1664 int
 1665 yds_halt_output(addr)
 1666         void *addr;
 1667 {
 1668         struct yds_softc *sc = addr;
 1669 
 1670         DPRINTF(("yds: yds_halt_output\n"));
 1671         if (sc->sc_play.intr) {
 1672                 sc->sc_play.intr = 0;
 1673                 /* Sync play slot control data */
 1674                 bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
 1675                                 sc->pbankoff,
 1676                                 sizeof(struct play_slot_ctrl_bank)*
 1677                                     (*sc->ptbl)*N_PLAY_SLOT_CTRL_BANK,
 1678                                 BUS_DMASYNC_POSTWRITE|BUS_DMASYNC_POSTREAD);
 1679                 /* Stop the play slot operation */
 1680                 sc->pbankp[0]->status =
 1681                 sc->pbankp[1]->status =
 1682                 sc->pbankp[2]->status =
 1683                 sc->pbankp[3]->status = 1;
 1684                 /* Sync ring buffer */
 1685                 bus_dmamap_sync(sc->sc_dmatag, sc->sc_play.dma->map,
 1686                                 0, sc->sc_play.length, BUS_DMASYNC_POSTWRITE);
 1687         }
 1688 
 1689         return 0;
 1690 }
 1691 
 1692 int
 1693 yds_halt_input(addr)
 1694         void *addr;
 1695 {
 1696         struct yds_softc *sc = addr;
 1697 
 1698         DPRINTF(("yds: yds_halt_input\n"));
 1699         sc->sc_rec.intr = NULL;
 1700         if (sc->sc_rec.intr) {
 1701                 /* Stop the rec slot operation */
 1702                 YWRITE4(sc, YDS_MAPOF_REC, 0);
 1703                 sc->sc_rec.intr = 0;
 1704                 /* Sync rec slot control data */
 1705                 bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,
 1706                                 sc->rbankoff,
 1707                                 sizeof(struct rec_slot_ctrl_bank)*
 1708                                     N_REC_SLOT_CTRL*N_REC_SLOT_CTRL_BANK,
 1709                                 BUS_DMASYNC_POSTWRITE|BUS_DMASYNC_POSTREAD);
 1710                 /* Sync ring buffer */
 1711                 bus_dmamap_sync(sc->sc_dmatag, sc->sc_rec.dma->map,
 1712                                 0, sc->sc_rec.length, BUS_DMASYNC_POSTREAD);
 1713         }
 1714 
 1715         return 0;
 1716 }
 1717 
 1718 int
 1719 yds_getdev(addr, retp)
 1720         void *addr;
 1721         struct audio_device *retp;
 1722 {
 1723         *retp = yds_device;
 1724 
 1725         return 0;
 1726 }
 1727 
 1728 int
 1729 yds_mixer_set_port(addr, cp)
 1730         void *addr;
 1731         mixer_ctrl_t *cp;
 1732 {
 1733         struct yds_softc *sc = addr;
 1734 
 1735         return (sc->sc_codec[0].codec_if->vtbl->mixer_set_port(
 1736             sc->sc_codec[0].codec_if, cp));
 1737 }
 1738 
 1739 int
 1740 yds_mixer_get_port(addr, cp)
 1741         void *addr;
 1742         mixer_ctrl_t *cp;
 1743 {
 1744         struct yds_softc *sc = addr;
 1745 
 1746         return (sc->sc_codec[0].codec_if->vtbl->mixer_get_port(
 1747             sc->sc_codec[0].codec_if, cp));
 1748 }
 1749 
 1750 int
 1751 yds_query_devinfo(addr, dip)
 1752         void *addr;
 1753         mixer_devinfo_t *dip;
 1754 {
 1755         struct yds_softc *sc = addr;
 1756 
 1757         return (sc->sc_codec[0].codec_if->vtbl->query_devinfo(
 1758             sc->sc_codec[0].codec_if, dip));
 1759 }
 1760 
 1761 int
 1762 yds_get_portnum_by_name(sc, class, device, qualifier)
 1763         struct yds_softc *sc;
 1764         char *class, *device, *qualifier;
 1765 {
 1766         return (sc->sc_codec[0].codec_if->vtbl->get_portnum_by_name(
 1767             sc->sc_codec[0].codec_if, class, device, qualifier));
 1768 }
 1769 
 1770 void *
 1771 yds_malloc(addr, direction, size, pool, flags)
 1772         void *addr;
 1773         int direction;
 1774         size_t size;
 1775         struct malloc_type *pool;
 1776         int flags;
 1777 {
 1778         struct yds_softc *sc = addr;
 1779         struct yds_dma *p;
 1780         int error;
 1781 
 1782         p = malloc(sizeof(*p), pool, flags);
 1783         if (!p)
 1784                 return (0);
 1785         error = yds_allocmem(sc, size, 16, p);
 1786         if (error) {
 1787                 free(p, pool);
 1788                 return (0);
 1789         }
 1790         p->next = sc->sc_dmas;
 1791         sc->sc_dmas = p;
 1792         return (KERNADDR(p));
 1793 }
 1794 
 1795 void
 1796 yds_free(addr, ptr, pool)
 1797         void *addr;
 1798         void *ptr;
 1799         struct malloc_type *pool;
 1800 {
 1801         struct yds_softc *sc = addr;
 1802         struct yds_dma **pp, *p;
 1803 
 1804         for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
 1805                 if (KERNADDR(p) == ptr) {
 1806                         yds_freemem(sc, p);
 1807                         *pp = p->next;
 1808                         free(p, pool);
 1809                         return;
 1810                 }
 1811         }
 1812 }
 1813 
 1814 static struct yds_dma *
 1815 yds_find_dma(sc, addr)
 1816         struct yds_softc *sc;
 1817         void *addr;
 1818 {
 1819         struct yds_dma *p;
 1820 
 1821         for (p = sc->sc_dmas; p && KERNADDR(p) != addr; p = p->next)
 1822                 ;
 1823 
 1824         return p;
 1825 }
 1826 
 1827 size_t
 1828 yds_round_buffersize(addr, direction, size)
 1829         void *addr;
 1830         int direction;
 1831         size_t size;
 1832 {
 1833         /*
 1834          * Buffer size should be at least twice as bigger as a frame.
 1835          */
 1836         if (size < 1024 * 3)
 1837                 size = 1024 * 3;
 1838         return (size);
 1839 }
 1840 
 1841 paddr_t
 1842 yds_mappage(addr, mem, off, prot)
 1843         void *addr;
 1844         void *mem;
 1845         off_t off;
 1846         int prot;
 1847 {
 1848         struct yds_softc *sc = addr;
 1849         struct yds_dma *p;
 1850 
 1851         if (off < 0)
 1852                 return (-1);
 1853         p = yds_find_dma(sc, mem);
 1854         if (!p)
 1855                 return (-1);
 1856         return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs, 
 1857                                 off, prot, BUS_DMA_WAITOK));
 1858 }
 1859 
 1860 int
 1861 yds_get_props(addr)
 1862         void *addr;
 1863 {
 1864         return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | 
 1865                 AUDIO_PROP_FULLDUPLEX);
 1866 }

Cache object: b065fa2c3c6d521e60de32f168a855a2


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