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

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

Generated by: LCOV version 1.13