root/dev/pci/cs4281.c

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

DEFINITIONS

This source file includes following definitions.
  1. cs4281_match
  2. cs4281_attach
  3. cs4281_intr
  4. cs4281_query_encoding
  5. cs4281_set_params
  6. cs4281_halt_output
  7. cs4281_halt_input
  8. cs4281_getdev
  9. cs4281_trigger_output
  10. cs4281_trigger_input
  11. cs4281_sr2regval
  12. cs4281_set_dac_rate
  13. cs4281_set_adc_rate
  14. cs4281_init
  15. cs4281_power
  16. cs4281_reset_codec
  17. cs4281_open
  18. cs4281_close
  19. cs4281_round_blocksize
  20. cs4281_mixer_set_port
  21. cs4281_mixer_get_port
  22. cs4281_query_devinfo
  23. cs4281_malloc
  24. cs4281_free
  25. cs4281_round_buffersize
  26. cs4281_mappage
  27. cs4281_get_props
  28. cs4281_attach_codec
  29. cs4281_read_codec
  30. cs4281_write_codec
  31. cs4281_allocmem
  32. cs4281_src_wait

    1 /*      $OpenBSD: cs4281.c,v 1.19 2005/11/29 05:42:17 tedu Exp $ */
    2 /*      $Tera: cs4281.c,v 1.18 2000/12/27 14:24:45 tacha Exp $  */
    3 
    4 /*
    5  * Copyright (c) 2000 Tatoku Ogaito.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by Tatoku Ogaito
   18  *      for the NetBSD Project.
   19  * 4. The name of the author may not be used to endorse or promote products
   20  *    derived from this software without specific prior written permission
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 
   34 /*
   35  * Cirrus Logic CS4281 driver.
   36  * Data sheets can be found
   37  * http://www.cirrus.com/pubs/4281.pdf?DocumentID=30
   38  * ftp://ftp.alsa-project.org/pub/manuals/cirrus/cs4281tm.pdf
   39  *
   40  * TODO:
   41  *   1: midi and FM support
   42  */
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/kernel.h>
   47 #include <sys/malloc.h>
   48 #include <sys/fcntl.h>
   49 #include <sys/device.h>
   50 
   51 #include <dev/pci/pcidevs.h>
   52 #include <dev/pci/pcivar.h>
   53 #include <dev/pci/cs4281reg.h>
   54 
   55 #include <sys/audioio.h>
   56 #include <dev/audio_if.h>
   57 #include <dev/midi_if.h>
   58 #include <dev/mulaw.h>
   59 #include <dev/auconv.h>
   60 
   61 #include <dev/ic/ac97.h>
   62 
   63 #include <machine/bus.h>
   64 
   65 #define CSCC_PCI_BA0 0x10
   66 #define CSCC_PCI_BA1 0x14
   67 
   68 struct cs4281_dma {
   69         bus_dmamap_t map;
   70         caddr_t addr;           /* real dma buffer */
   71         caddr_t dum;            /* dummy buffer for audio driver */
   72         bus_dma_segment_t segs[1];
   73         int nsegs;
   74         size_t size;
   75         struct cs4281_dma *next;
   76 };
   77 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
   78 #define BUFADDR(p)  ((void *)((p)->dum))
   79 #define KERNADDR(p) ((void *)((p)->addr))
   80 
   81 /*
   82  * Software state
   83  */
   84 struct cs4281_softc {
   85         struct device           sc_dev;
   86 
   87         pci_intr_handle_t       *sc_ih;
   88 
   89         /* I/O (BA0) */
   90         bus_space_tag_t         ba0t;
   91         bus_space_handle_t      ba0h;
   92 
   93         /* BA1 */
   94         bus_space_tag_t         ba1t;
   95         bus_space_handle_t      ba1h;
   96 
   97         /* DMA */
   98         bus_dma_tag_t           sc_dmatag;
   99         struct cs4281_dma       *sc_dmas;
  100         size_t dma_size;
  101         size_t dma_align;
  102 
  103         int     hw_blocksize;
  104 
  105         /* playback */
  106         void    (*sc_pintr)(void *);    /* dma completion intr handler */
  107         void    *sc_parg;               /* arg for sc_intr() */
  108         char    *sc_ps, *sc_pe, *sc_pn;
  109         int     sc_pcount;
  110         int     sc_pi;
  111         struct cs4281_dma *sc_pdma;
  112         char    *sc_pbuf;
  113         int     (*halt_output)(void *);
  114 #ifdef DIAGNOSTIC
  115         char    sc_prun;
  116 #endif
  117 
  118         /* capturing */
  119         void    (*sc_rintr)(void *);    /* dma completion intr handler */
  120         void    *sc_rarg;               /* arg for sc_intr() */
  121         char    *sc_rs, *sc_re, *sc_rn;
  122         int     sc_rcount;
  123         int     sc_ri;
  124         struct  cs4281_dma *sc_rdma;
  125         char    *sc_rbuf;
  126         int     sc_rparam;              /* record format */
  127         int     (*halt_input)(void *);
  128 #ifdef DIAGNOSTIC
  129         char    sc_rrun;
  130 #endif
  131 
  132 #if NMIDI > 0
  133         void    (*sc_iintr)(void *, int);       /* midi input ready handler */
  134         void    (*sc_ointr)(void *);            /* midi output ready handler */
  135         void    *sc_arg;
  136 #endif
  137 
  138         /* AC97 CODEC */
  139         struct ac97_codec_if *codec_if;
  140         struct ac97_host_if host_if;
  141 
  142         /* Power Management */
  143         char    sc_suspend;
  144         void    *sc_powerhook;          /* Power hook */
  145         u_int16_t ac97_reg[CS4281_SAVE_REG_MAX + 1];   /* Save ac97 registers */
  146 };
  147 
  148 #define BA0READ4(sc, r) bus_space_read_4((sc)->ba0t, (sc)->ba0h, (r))
  149 #define BA0WRITE4(sc, r, x) bus_space_write_4((sc)->ba0t, (sc)->ba0h, (r), (x))
  150 
  151 #if defined(ENABLE_SECONDARY_CODEC)
  152 #define MAX_CHANNELS  (4)
  153 #define MAX_FIFO_SIZE 32 /* 128/4 channels */
  154 #else
  155 #define MAX_CHANNELS  (2)
  156 #define MAX_FIFO_SIZE 64 /* 128/2 channels */
  157 #endif
  158 
  159 int cs4281_match(struct device *, void *, void *);
  160 void cs4281_attach(struct device *, struct device *, void *);
  161 int cs4281_intr(void *);
  162 int cs4281_query_encoding(void *, struct audio_encoding *);
  163 int cs4281_set_params(void *, int, int, struct audio_params *,
  164                                      struct audio_params *);
  165 int cs4281_halt_output(void *);
  166 int cs4281_halt_input(void *);
  167 int cs4281_getdev(void *, struct audio_device *);
  168 int cs4281_trigger_output(void *, void *, void *, int, void (*)(void *),
  169                           void *, struct audio_params *);
  170 int cs4281_trigger_input(void *, void *, void *, int, void (*)(void *),
  171                          void *, struct audio_params *);
  172 u_int8_t cs4281_sr2regval(int);
  173 void cs4281_set_dac_rate(struct cs4281_softc *, int);
  174 void cs4281_set_adc_rate(struct cs4281_softc *, int);
  175 int cs4281_init(struct cs4281_softc *);
  176 
  177 int cs4281_open(void *, int);
  178 void cs4281_close(void *);
  179 int cs4281_round_blocksize(void *, int);
  180 int cs4281_get_props(void *);
  181 int cs4281_attach_codec(void *, struct ac97_codec_if *);
  182 int cs4281_read_codec(void *, u_int8_t , u_int16_t *);
  183 int cs4281_write_codec(void *, u_int8_t, u_int16_t);
  184 void cs4281_reset_codec(void *);
  185 
  186 void cs4281_power(int, void *);
  187 
  188 int cs4281_mixer_set_port(void *, mixer_ctrl_t *);
  189 int cs4281_mixer_get_port(void *, mixer_ctrl_t *);
  190 int cs4281_query_devinfo(void *, mixer_devinfo_t *);
  191 void *cs4281_malloc(void *, int, size_t, int, int);
  192 size_t cs4281_round_buffersize(void *, int, size_t);
  193 void cs4281_free(void *, void *, int);
  194 paddr_t cs4281_mappage(void *, void *, off_t, int);
  195 
  196 int cs4281_allocmem(struct cs4281_softc *, size_t, int, int,
  197                                      struct cs4281_dma *);
  198 int cs4281_src_wait(struct cs4281_softc *);
  199 
  200 #if defined(CS4281_DEBUG)
  201 #undef DPRINTF
  202 #undef DPRINTFN
  203 #define DPRINTF(x)          if (cs4281_debug) printf x
  204 #define DPRINTFN(n,x)       if (cs4281_debug>(n)) printf x
  205 int cs4281_debug = 5;
  206 #else
  207 #define DPRINTF(x)
  208 #define DPRINTFN(n,x)
  209 #endif
  210 
  211 struct audio_hw_if cs4281_hw_if = {
  212         cs4281_open,
  213         cs4281_close,
  214         NULL,
  215         cs4281_query_encoding,
  216         cs4281_set_params,
  217         cs4281_round_blocksize,
  218         NULL,
  219         NULL,
  220         NULL,
  221         NULL,
  222         NULL,
  223         cs4281_halt_output,
  224         cs4281_halt_input,
  225         NULL,
  226         cs4281_getdev,
  227         NULL,
  228         cs4281_mixer_set_port,
  229         cs4281_mixer_get_port,
  230         cs4281_query_devinfo,
  231         cs4281_malloc,
  232         cs4281_free,
  233         cs4281_round_buffersize,
  234         NULL, /* cs4281_mappage, */
  235         cs4281_get_props,
  236         cs4281_trigger_output,
  237         cs4281_trigger_input,
  238 };
  239 
  240 #if NMIDI > 0
  241 /* Midi Interface */
  242 void cs4281_midi_close(void *);
  243 void cs4281_midi_getinfo(void *, struct midi_info *);
  244 int cs4281_midi_open(void *, int, void (*)(void *, int),
  245                      void (*)(void *), void *);
  246 int cs4281_midi_output(void *, int);
  247 
  248 struct midi_hw_if cs4281_midi_hw_if = {
  249         cs4281_midi_open,
  250         cs4281_midi_close,
  251         cs4281_midi_output,
  252         cs4281_midi_getinfo,
  253         0,
  254 };
  255 #endif
  256 
  257 struct cfattach clct_ca = {
  258         sizeof(struct cs4281_softc), cs4281_match, cs4281_attach
  259 };
  260 
  261 struct cfdriver clct_cd = {
  262         NULL, "clct", DV_DULL
  263 };
  264 
  265 struct audio_device cs4281_device = {
  266         "CS4281",
  267         "",
  268         "cs4281"
  269 };
  270 
  271 
  272 int
  273 cs4281_match(parent, match, aux)
  274         struct device *parent;
  275         void *match;
  276         void *aux;
  277 {
  278         struct pci_attach_args *pa = (struct pci_attach_args *)aux;
  279         
  280         if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CIRRUS ||
  281             PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_CIRRUS_CS4281)
  282                 return (0);
  283 
  284         return (1);
  285 }
  286 
  287 void
  288 cs4281_attach(parent, self, aux)
  289         struct device *parent;
  290         struct device *self;
  291         void *aux;
  292 {
  293         struct cs4281_softc *sc = (struct cs4281_softc *)self;
  294         struct pci_attach_args *pa = (struct pci_attach_args *)aux;
  295         pci_chipset_tag_t pc = pa->pa_pc;
  296         char const *intrstr;
  297         pci_intr_handle_t ih;
  298         int pci_pwrmgmt_cap_reg, pci_pwrmgmt_csr_reg;
  299 
  300         /* Map I/O register */
  301         if (pci_mapreg_map(pa, CSCC_PCI_BA0,
  302             PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba0t,
  303             &sc->ba0h, NULL, NULL, 0)) {
  304                 printf("%s: can't map BA0 space\n", sc->sc_dev.dv_xname);
  305                 return;
  306         }
  307         if (pci_mapreg_map(pa, CSCC_PCI_BA1,
  308             PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba1t,
  309             &sc->ba1h, NULL, NULL, 0)) {
  310                 printf("%s: can't map BA1 space\n", sc->sc_dev.dv_xname);
  311                 return;
  312         }
  313 
  314         sc->sc_dmatag = pa->pa_dmat;
  315 
  316         /*
  317          * Set Power State D0.
  318          * Without doing this, 0xffffffff is read from all registers after
  319          * using Windows and rebooting into OpenBSD.
  320          * On my IBM ThinkPad X20, it is set to D3 after using Windows2000.
  321          */
  322         if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PWRMGMT,
  323             &pci_pwrmgmt_cap_reg, 0)) {
  324                 pcireg_t reg;
  325 
  326                 pci_pwrmgmt_csr_reg = pci_pwrmgmt_cap_reg + PCI_PMCSR;
  327                 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, pci_pwrmgmt_csr_reg);
  328                 if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0) {
  329                         pci_conf_write(pc, pa->pa_tag, pci_pwrmgmt_csr_reg,
  330                             (reg & ~PCI_PMCSR_STATE_MASK) |
  331                             PCI_PMCSR_STATE_D0);
  332                 }
  333         }
  334 
  335         /* Map and establish the interrupt. */
  336         if (pci_intr_map(pa, &ih)) {
  337                 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
  338                 return;
  339         }
  340         intrstr = pci_intr_string(pc, ih);
  341 
  342         sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, cs4281_intr, sc,
  343             sc->sc_dev.dv_xname);
  344         if (sc->sc_ih == NULL) {
  345                 printf("%s: couldn't establish interrupt",sc->sc_dev.dv_xname);
  346                 if (intrstr != NULL)
  347                         printf(" at %s", intrstr);
  348                 printf("\n");
  349                 return;
  350         }
  351         printf(" %s\n", intrstr);
  352 
  353         /*
  354          * Sound System start-up
  355          */
  356         if (cs4281_init(sc) != 0)
  357                 return;
  358 
  359         sc->halt_input  = cs4281_halt_input;
  360         sc->halt_output = cs4281_halt_output;
  361 
  362         sc->dma_size     = CS4281_BUFFER_SIZE / MAX_CHANNELS;
  363         sc->dma_align    = 0x10;
  364         sc->hw_blocksize = sc->dma_size / 2;
  365         
  366         /* AC 97 attachment */
  367         sc->host_if.arg = sc;
  368         sc->host_if.attach = cs4281_attach_codec;
  369         sc->host_if.read   = cs4281_read_codec;
  370         sc->host_if.write  = cs4281_write_codec;
  371         sc->host_if.reset  = cs4281_reset_codec;
  372         if (ac97_attach(&sc->host_if) != 0) {
  373                 printf("%s: ac97_attach failed\n", sc->sc_dev.dv_xname);
  374                 return;
  375         }
  376         audio_attach_mi(&cs4281_hw_if, sc, &sc->sc_dev);
  377 
  378 #if NMIDI > 0
  379         midi_attach_mi(&cs4281_midi_hw_if, sc, &sc->sc_dev);
  380 #endif
  381 
  382         sc->sc_suspend = PWR_RESUME;
  383         sc->sc_powerhook = powerhook_establish(cs4281_power, sc);
  384 }
  385 
  386 
  387 int
  388 cs4281_intr(p)
  389         void *p;
  390 {
  391         struct cs4281_softc *sc = p;
  392         u_int32_t intr, val;
  393         char *empty_dma;
  394         
  395         intr = BA0READ4(sc, CS4281_HISR);
  396         if (!(intr & (HISR_DMA0 | HISR_DMA1 | HISR_MIDI))) {
  397                 BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
  398                 return (0);
  399         }
  400         DPRINTF(("cs4281_intr:"));
  401 
  402         if (intr & HISR_DMA0)
  403                 val = BA0READ4(sc, CS4281_HDSR0); /* clear intr condition */
  404         if (intr & HISR_DMA1)
  405                 val = BA0READ4(sc, CS4281_HDSR1); /* clear intr condition */
  406         BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
  407 
  408         /* Playback Interrupt */
  409         if (intr & HISR_DMA0) {
  410                 DPRINTF((" PB DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA0),
  411                          (int)BA0READ4(sc, CS4281_DCC0)));
  412                 if (sc->sc_pintr) {
  413                         if ((sc->sc_pi%sc->sc_pcount) == 0)
  414                                 sc->sc_pintr(sc->sc_parg);
  415                 } else {
  416                         printf("unexpected play intr\n");
  417                 }
  418                 /* copy buffer */
  419                 ++sc->sc_pi;
  420                 empty_dma = sc->sc_pdma->addr;
  421                 if (sc->sc_pi&1)
  422                         empty_dma += sc->hw_blocksize;
  423                 memcpy(empty_dma, sc->sc_pn, sc->hw_blocksize);
  424                 sc->sc_pn += sc->hw_blocksize;
  425                 if (sc->sc_pn >= sc->sc_pe)
  426                         sc->sc_pn = sc->sc_ps;
  427         }
  428         if (intr & HISR_DMA1) {
  429                 val = BA0READ4(sc, CS4281_HDSR1);
  430                 /* copy from dma */
  431                 DPRINTF((" CP DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA1),
  432                          (int)BA0READ4(sc, CS4281_DCC1)));
  433                 ++sc->sc_ri;
  434                 empty_dma = sc->sc_rdma->addr;
  435                 if ((sc->sc_ri & 1) == 0)
  436                         empty_dma += sc->hw_blocksize;
  437                 memcpy(sc->sc_rn, empty_dma, sc->hw_blocksize);
  438                 if (sc->sc_rn >= sc->sc_re)
  439                         sc->sc_rn = sc->sc_rs;
  440                 if (sc->sc_rintr) {
  441                         if ((sc->sc_ri % sc->sc_rcount) == 0)
  442                                 sc->sc_rintr(sc->sc_rarg);
  443                 } else {
  444                         printf("unexpected record intr\n");
  445                 }
  446         }
  447         DPRINTF(("\n"));
  448         return (1);
  449 }
  450 
  451 int
  452 cs4281_query_encoding(addr, fp)
  453         void *addr;
  454         struct audio_encoding *fp;
  455 {
  456         switch (fp->index) {
  457         case 0:
  458                 strlcpy(fp->name, AudioEulinear, sizeof fp->name);
  459                 fp->encoding = AUDIO_ENCODING_ULINEAR;
  460                 fp->precision = 8;
  461                 fp->flags = 0;
  462                 break;
  463         case 1:
  464                 strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
  465                 fp->encoding = AUDIO_ENCODING_ULAW;
  466                 fp->precision = 8;
  467                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  468                 break;
  469         case 2:
  470                 strlcpy(fp->name, AudioEalaw, sizeof fp->name);
  471                 fp->encoding = AUDIO_ENCODING_ALAW;
  472                 fp->precision = 8;
  473                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  474                 break;
  475         case 3:
  476                 strlcpy(fp->name, AudioEslinear, sizeof fp->name);
  477                 fp->encoding = AUDIO_ENCODING_SLINEAR;
  478                 fp->precision = 8;
  479                 fp->flags = 0;
  480                 break;
  481         case 4:
  482                 strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
  483                 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
  484                 fp->precision = 16;
  485                 fp->flags = 0;
  486                 break;
  487         case 5:
  488                 strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
  489                 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
  490                 fp->precision = 16;
  491                 fp->flags = 0;
  492                 break;
  493         case 6:
  494                 strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
  495                 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
  496                 fp->precision = 16;
  497                 fp->flags = 0;
  498                 break;
  499         case 7:
  500                 strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
  501                 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
  502                 fp->precision = 16;
  503                 fp->flags = 0;
  504                 break;
  505         default:
  506                 return EINVAL;
  507         }
  508         return (0);
  509 }
  510 
  511 int
  512 cs4281_set_params(addr, setmode, usemode, play, rec)
  513         void *addr;
  514         int setmode, usemode;
  515         struct audio_params *play, *rec;
  516 {
  517         struct cs4281_softc *sc = addr;
  518         struct audio_params *p;
  519         int mode;
  520 
  521         for (mode = AUMODE_RECORD; mode != -1;
  522             mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
  523                 if ((setmode & mode) == 0)
  524                         continue;
  525                 
  526                 p = mode == AUMODE_PLAY ? play : rec;
  527                 
  528                 if (p == play) {
  529                         DPRINTFN(5,("play: samp=%ld precision=%d channels=%d\n",
  530                                 p->sample_rate, p->precision, p->channels));
  531                         if (p->sample_rate < 6023 || p->sample_rate > 48000 ||
  532                             (p->precision != 8 && p->precision != 16) ||
  533                             (p->channels != 1  && p->channels != 2)) {
  534                                 return (EINVAL);
  535                         }
  536                 } else {
  537                         DPRINTFN(5,("rec: samp=%ld precision=%d channels=%d\n",
  538                                 p->sample_rate, p->precision, p->channels));
  539                         if (p->sample_rate < 6023 || p->sample_rate > 48000 ||
  540                             (p->precision != 8 && p->precision != 16) ||
  541                             (p->channels != 1 && p->channels != 2)) {
  542                                 return (EINVAL);
  543                         }
  544                 }
  545                 p->factor = 1;
  546                 p->sw_code = 0;
  547 
  548                 switch (p->encoding) {
  549                 case AUDIO_ENCODING_SLINEAR_BE:
  550                         break;
  551                 case AUDIO_ENCODING_SLINEAR_LE:
  552                         break;
  553                 case AUDIO_ENCODING_ULINEAR_BE:
  554                         break;
  555                 case AUDIO_ENCODING_ULINEAR_LE:
  556                         break;
  557                 case AUDIO_ENCODING_ULAW:
  558                         if (mode == AUMODE_PLAY) {
  559                                 p->sw_code = mulaw_to_slinear8;
  560                         } else {
  561                                 p->sw_code = slinear8_to_mulaw;
  562                         }
  563                         break;
  564                 case AUDIO_ENCODING_ALAW:
  565                         if (mode == AUMODE_PLAY) {
  566                                 p->sw_code = alaw_to_slinear8;
  567                         } else {
  568                                 p->sw_code = slinear8_to_alaw;
  569                         }
  570                         break;
  571                 default:
  572                         return (EINVAL);
  573                 }
  574         }
  575 
  576         /* set sample rate */
  577         cs4281_set_dac_rate(sc, play->sample_rate);
  578         cs4281_set_adc_rate(sc, rec->sample_rate);
  579         return (0);
  580 }
  581 
  582 int
  583 cs4281_halt_output(addr)
  584         void *addr;
  585 {
  586         struct cs4281_softc *sc = addr;
  587         
  588         BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
  589 #ifdef DIAGNOSTIC
  590         sc->sc_prun = 0;
  591 #endif
  592         return (0);
  593 }
  594 
  595 int
  596 cs4281_halt_input(addr)
  597         void *addr;
  598 {
  599         struct cs4281_softc *sc = addr;
  600 
  601         BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
  602 #ifdef DIAGNOSTIC
  603         sc->sc_rrun = 0;
  604 #endif
  605         return (0);
  606 }
  607 
  608 /* trivial */
  609 int
  610 cs4281_getdev(addr, retp)
  611      void *addr;
  612      struct audio_device *retp;
  613 {
  614         *retp = cs4281_device;
  615         return (0);
  616 }
  617 
  618 
  619 int
  620 cs4281_trigger_output(addr, start, end, blksize, intr, arg, param)
  621         void *addr;
  622         void *start, *end;
  623         int blksize;
  624         void (*intr)(void *);
  625         void *arg;
  626         struct audio_params *param;
  627 {
  628         struct cs4281_softc *sc = addr;
  629         u_int32_t fmt=0;
  630         struct cs4281_dma *p;
  631         int dma_count;
  632 
  633 #ifdef DIAGNOSTIC
  634         if (sc->sc_prun)
  635                 printf("cs4281_trigger_output: already running\n");
  636         sc->sc_prun = 1;
  637 #endif
  638 
  639         DPRINTF(("cs4281_trigger_output: sc=%p start=%p end=%p "
  640                  "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
  641         sc->sc_pintr = intr;
  642         sc->sc_parg  = arg;
  643 
  644         /* stop playback DMA */
  645         BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
  646 
  647         DPRINTF(("param: precision=%d  factor=%d channels=%d encoding=%d\n",
  648                param->precision, param->factor, param->channels,
  649                param->encoding));
  650         for (p = sc->sc_dmas; p != NULL && BUFADDR(p) != start; p = p->next)
  651                 ;
  652         if (p == NULL) {
  653                 printf("cs4281_trigger_output: bad addr %p\n", start);
  654                 return (EINVAL);
  655         }
  656 
  657         sc->sc_pcount = blksize / sc->hw_blocksize;
  658         sc->sc_ps = (char *)start;
  659         sc->sc_pe = (char *)end;
  660         sc->sc_pdma = p;
  661         sc->sc_pbuf = KERNADDR(p);
  662         sc->sc_pi = 0;
  663         sc->sc_pn = sc->sc_ps;
  664         if (blksize >= sc->dma_size) {
  665                 sc->sc_pn = sc->sc_ps + sc->dma_size;
  666                 memcpy(sc->sc_pbuf, start, sc->dma_size);
  667                 ++sc->sc_pi;
  668         } else {
  669                 sc->sc_pn = sc->sc_ps + sc->hw_blocksize;
  670                 memcpy(sc->sc_pbuf, start, sc->hw_blocksize);
  671         }
  672 
  673         dma_count = sc->dma_size;
  674         if (param->precision * param->factor != 8)
  675                 dma_count /= 2;   /* 16 bit */
  676         if (param->channels > 1)
  677                 dma_count /= 2;   /* Stereo */
  678 
  679         DPRINTF(("cs4281_trigger_output: DMAADDR(p)=0x%x count=%d\n",
  680                  (int)DMAADDR(p), dma_count));
  681         BA0WRITE4(sc, CS4281_DBA0, DMAADDR(p));
  682         BA0WRITE4(sc, CS4281_DBC0, dma_count-1);
  683 
  684         /* set playback format */
  685         fmt = BA0READ4(sc, CS4281_DMR0) & ~DMRn_FMTMSK;
  686         if (param->precision * param->factor == 8)
  687                 fmt |= DMRn_SIZE8;
  688         if (param->channels == 1)
  689                 fmt |= DMRn_MONO;
  690         if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
  691             param->encoding == AUDIO_ENCODING_SLINEAR_BE)
  692                 fmt |= DMRn_BEND;
  693         if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
  694             param->encoding == AUDIO_ENCODING_ULINEAR_LE)
  695                 fmt |= DMRn_USIGN;
  696         BA0WRITE4(sc, CS4281_DMR0, fmt);
  697 
  698         /* set sample rate */
  699         cs4281_set_dac_rate(sc, param->sample_rate);
  700 
  701         /* start DMA */
  702         BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) & ~DCRn_MSK);
  703         /* Enable interrupts */
  704         BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
  705 
  706         BA0WRITE4(sc, CS4281_PPRVC, 7);
  707         BA0WRITE4(sc, CS4281_PPLVC, 7);
  708 
  709         DPRINTF(("HICR =0x%08x(expected 0x00000001)\n", BA0READ4(sc, CS4281_HICR)));
  710         DPRINTF(("HIMR =0x%08x(expected 0x00f0fc3f)\n", BA0READ4(sc, CS4281_HIMR)));
  711         DPRINTF(("DMR0 =0x%08x(expected 0x2???0018)\n", BA0READ4(sc, CS4281_DMR0)));
  712         DPRINTF(("DCR0 =0x%08x(expected 0x00030000)\n", BA0READ4(sc, CS4281_DCR0)));
  713         DPRINTF(("FCR0 =0x%08x(expected 0x81000f00)\n", BA0READ4(sc, CS4281_FCR0)));
  714         DPRINTF(("DACSR=0x%08x(expected 1 for 44kHz 5 for 8kHz)\n",
  715                  BA0READ4(sc, CS4281_DACSR)));
  716         DPRINTF(("SRCSA=0x%08x(expected 0x0b0a0100)\n", BA0READ4(sc, CS4281_SRCSA)));
  717         DPRINTF(("SSPM&SSPM_PSRCEN =0x%08x(expected 0x00000010)\n",
  718                  BA0READ4(sc, CS4281_SSPM) & SSPM_PSRCEN));
  719 
  720         return (0);
  721 }
  722 
  723 int
  724 cs4281_trigger_input(addr, start, end, blksize, intr, arg, param)
  725         void *addr;
  726         void *start, *end;
  727         int blksize;
  728         void (*intr)(void *);
  729         void *arg;
  730         struct audio_params *param;
  731 {
  732         struct cs4281_softc *sc = addr;
  733         struct cs4281_dma *p;
  734         u_int32_t fmt=0;
  735         int dma_count;
  736 
  737         printf("cs4281_trigger_input: not implemented yet\n");
  738 #ifdef DIAGNOSTIC
  739         if (sc->sc_rrun)
  740                 printf("cs4281_trigger_input: already running\n");
  741         sc->sc_rrun = 1;
  742 #endif
  743         DPRINTF(("cs4281_trigger_input: sc=%p start=%p end=%p "
  744             "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
  745         sc->sc_rintr = intr;
  746         sc->sc_rarg  = arg;
  747 
  748         /* stop recording DMA */
  749         BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
  750 
  751         for (p = sc->sc_dmas; p && BUFADDR(p) != start; p = p->next)
  752                 ;
  753         if (!p) {
  754                 printf("cs4281_trigger_input: bad addr %p\n", start);
  755                 return (EINVAL);
  756         }
  757 
  758         sc->sc_rcount = blksize / sc->hw_blocksize;
  759         sc->sc_rs = (char *)start;
  760         sc->sc_re = (char *)end;
  761         sc->sc_rdma = p;
  762         sc->sc_rbuf = KERNADDR(p);
  763         sc->sc_ri = 0;
  764         sc->sc_rn = sc->sc_rs;
  765 
  766         dma_count = sc->dma_size;
  767         if (param->precision * param->factor == 8)
  768                 dma_count /= 2;
  769         if (param->channels > 1)
  770                 dma_count /= 2;
  771 
  772         DPRINTF(("cs4281_trigger_input: DMAADDR(p)=0x%x count=%d\n",
  773                  (int)DMAADDR(p), dma_count));
  774         BA0WRITE4(sc, CS4281_DBA1, DMAADDR(p));
  775         BA0WRITE4(sc, CS4281_DBC1, dma_count-1);
  776 
  777         /* set recording format */
  778         fmt = BA0READ4(sc, CS4281_DMR1) & ~DMRn_FMTMSK;
  779         if (param->precision * param->factor == 8)
  780                 fmt |= DMRn_SIZE8;
  781         if (param->channels == 1)
  782                 fmt |= DMRn_MONO;
  783         if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
  784             param->encoding == AUDIO_ENCODING_SLINEAR_BE)
  785                 fmt |= DMRn_BEND;
  786         if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
  787             param->encoding == AUDIO_ENCODING_ULINEAR_LE)
  788                 fmt |= DMRn_USIGN;
  789         BA0WRITE4(sc, CS4281_DMR1, fmt);
  790 
  791         /* set sample rate */
  792         cs4281_set_adc_rate(sc, param->sample_rate);
  793 
  794         /* Start DMA */
  795         BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) & ~DCRn_MSK);
  796         /* Enable interrupts */
  797         BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
  798 
  799         DPRINTF(("HICR=0x%08x\n", BA0READ4(sc, CS4281_HICR)));
  800         DPRINTF(("HIMR=0x%08x\n", BA0READ4(sc, CS4281_HIMR)));
  801         DPRINTF(("DMR1=0x%08x\n", BA0READ4(sc, CS4281_DMR1)));
  802         DPRINTF(("DCR1=0x%08x\n", BA0READ4(sc, CS4281_DCR1)));
  803 
  804         return (0);
  805 }
  806 
  807 /* convert sample rate to register value */
  808 u_int8_t
  809 cs4281_sr2regval(rate)
  810      int rate;
  811 {
  812         u_int8_t retval;
  813 
  814         /* We don't have to change here. but anyway ... */
  815         if (rate > 48000)
  816                 rate = 48000;
  817         if (rate < 6023)
  818                 rate = 6023;
  819 
  820         switch (rate) {
  821         case 8000:
  822                 retval = 5;
  823                 break;
  824         case 11025:
  825                 retval = 4;
  826                 break;
  827         case 16000:
  828                 retval = 3;
  829                 break;
  830         case 22050:
  831                 retval = 2;
  832                 break;
  833         case 44100:
  834                 retval = 1;
  835                 break;
  836         case 48000:
  837                 retval = 0;
  838                 break;
  839         default:
  840                 retval = 1536000/rate; /* == 24576000/(rate*16) */
  841         }
  842         return (retval);
  843 }
  844 
  845         
  846 void
  847 cs4281_set_dac_rate(sc, rate)
  848         struct cs4281_softc *sc;
  849         int rate;
  850 {
  851         BA0WRITE4(sc, CS4281_DACSR, cs4281_sr2regval(rate));
  852 }
  853 
  854 void
  855 cs4281_set_adc_rate(sc, rate)
  856         struct cs4281_softc *sc;
  857         int rate;
  858 {
  859         BA0WRITE4(sc, CS4281_ADCSR, cs4281_sr2regval(rate));
  860 }
  861 
  862 int
  863 cs4281_init(sc)
  864      struct cs4281_softc *sc;
  865 {
  866         int n;
  867         u_int16_t data;
  868         u_int32_t dat32;
  869 
  870         /* set "Configuration Write Protect" register to
  871          * 0x4281 to allow to write */
  872         BA0WRITE4(sc, CS4281_CWPR, 0x4281);
  873 
  874         /*
  875          * Unset "Full Power-Down bit of Extended PCI Power Management
  876          * Control" register to release the reset state.
  877          */
  878         dat32 = BA0READ4(sc, CS4281_EPPMC);
  879         if (dat32 & EPPMC_FPDN)
  880                 BA0WRITE4(sc, CS4281_EPPMC, dat32 & ~EPPMC_FPDN);
  881 
  882         /* Start PLL out in known state */
  883         BA0WRITE4(sc, CS4281_CLKCR1, 0);
  884         /* Start serial ports out in known state */
  885         BA0WRITE4(sc, CS4281_SERMC, 0);
  886         
  887         /* Reset codec */
  888         BA0WRITE4(sc, CS4281_ACCTL, 0);
  889         delay(50);      /* delay 50us */
  890 
  891         BA0WRITE4(sc, CS4281_SPMC, 0);
  892         delay(100);     /* delay 100us */
  893         BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN);
  894 #if defined(ENABLE_SECONDARY_CODEC)
  895         BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E);
  896         BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID);
  897 #endif
  898         delay(50000);   /* XXX: delay 50ms */
  899 
  900         /* Turn on Sound System clocks based on ABITCLK */
  901         BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_DLLP);
  902         delay(50000);   /* XXX: delay 50ms */
  903         BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_SWCE | CLKCR1_DLLP);
  904 
  905         /* Set enables for sections that are needed in the SSPM registers */
  906         BA0WRITE4(sc, CS4281_SSPM,
  907                   SSPM_MIXEN |          /* Mixer */
  908                   SSPM_CSRCEN |         /* Capture SRC */
  909                   SSPM_PSRCEN |         /* Playback SRC */
  910                   SSPM_JSEN |           /* Joystick */
  911                   SSPM_ACLEN |          /* AC LINK */
  912                   SSPM_FMEN             /* FM */
  913                   );
  914 
  915         /* Wait for clock stabilization */
  916         n = 0;
  917         while ((BA0READ4(sc, CS4281_CLKCR1)& (CLKCR1_DLLRDY | CLKCR1_CLKON))
  918             != (CLKCR1_DLLRDY | CLKCR1_CLKON)) {
  919                 delay(100);
  920                 if (++n > 1000)
  921                         return (-1);
  922         }
  923 
  924         /* Enable ASYNC generation */
  925         BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN);
  926 
  927         /* Wait for Codec ready. Linux driver wait 50ms here */
  928         n = 0;
  929         while((BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY) == 0) {
  930                 delay(100);
  931                 if (++n > 1000)
  932                         return (-1);
  933         }
  934 
  935 #if defined(ENABLE_SECONDARY_CODEC)
  936         /* secondary codec ready*/
  937         n = 0;
  938         while((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) {
  939                 delay(100);
  940                 if (++n > 1000)
  941                         return (-1);
  942         }
  943 #endif
  944 
  945         /* Set the serial timing configuration */
  946         /* XXX: undocumented but the Linux driver do this */
  947         BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
  948         
  949         /* Wait for Codec ready signal */
  950         n = 0;
  951         do {
  952                 delay(1000);
  953                 if (++n > 1000) {
  954                         printf("%s: Timeout waiting for Codec ready\n",
  955                                sc->sc_dev.dv_xname);
  956                         return -1;
  957                 }
  958                 dat32 = BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY;
  959         } while (dat32 == 0);
  960 
  961         /* Enable Valid Frame output on ASDOUT */
  962         BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN | ACCTL_VFRM);
  963         
  964         /* Wait until Codec Calibration is finished. Codec register 26h */
  965         n = 0;
  966         do {
  967                 delay(1);
  968                 if (++n > 1000) {
  969                         printf("%s: Timeout waiting for Codec calibration\n",
  970                                sc->sc_dev.dv_xname);
  971                         return -1;
  972                 }
  973                 cs4281_read_codec(sc, AC97_REG_POWER, &data);
  974         } while ((data & 0x0f) != 0x0f);
  975 
  976         /* Set the serial timing configuration again */
  977         /* XXX: undocumented but the Linux driver do this */
  978         BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
  979 
  980         /* Wait until we've sampled input slots 3 & 4 as valid */
  981         n = 0;
  982         do {
  983                 delay(1000);
  984                 if (++n > 1000) {
  985                         printf("%s: Timeout waiting for sampled input slots as valid\n",
  986                                sc->sc_dev.dv_xname);
  987                         return -1;
  988                 }
  989                 dat32 = BA0READ4(sc, CS4281_ACISV) & (ACISV_ISV3 | ACISV_ISV4);
  990         } while (dat32 != (ACISV_ISV3 | ACISV_ISV4));
  991         
  992         /* Start digital data transfer of audio data to the codec */
  993         BA0WRITE4(sc, CS4281_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4));
  994         
  995         cs4281_write_codec(sc, AC97_REG_HEADPHONE_VOLUME, 0);
  996         cs4281_write_codec(sc, AC97_REG_MASTER_VOLUME, 0);
  997         
  998         /* Power on the DAC */
  999         cs4281_read_codec(sc, AC97_REG_POWER, &data);
 1000         cs4281_write_codec(sc, AC97_REG_POWER, data &= 0xfdff);
 1001 
 1002         /* Wait until we sample a DAC ready state.
 1003          * Not documented, but Linux driver does.
 1004          */
 1005         for (n = 0; n < 32; ++n) {
 1006                 delay(1000);
 1007                 cs4281_read_codec(sc, AC97_REG_POWER, &data);
 1008                 if (data & 0x02)
 1009                         break;
 1010         }
 1011         
 1012         /* Power on the ADC */
 1013         cs4281_read_codec(sc, AC97_REG_POWER, &data);
 1014         cs4281_write_codec(sc, AC97_REG_POWER, data &= 0xfeff);
 1015 
 1016         /* Wait until we sample ADC ready state.
 1017          * Not documented, but Linux driver does.
 1018          */
 1019         for (n = 0; n < 32; ++n) {
 1020                 delay(1000);
 1021                 cs4281_read_codec(sc, AC97_REG_POWER, &data);
 1022                 if (data & 0x01)
 1023                         break;
 1024         }
 1025         
 1026 #if 0
 1027         /* Initialize SSCR register features */
 1028         /* XXX: hardware volume setting */
 1029         BA0WRITE4(sc, CS4281_SSCR, ~SSCR_HVC); /* disable HW volume setting */
 1030 #endif
 1031 
 1032         /* disable Sound Blaster Pro emulation */
 1033         /* XXX:
 1034          * Cannot set since the documents does not describe which bit is
 1035          * correspond to SSCR_SB. Since the reset value of SSCR is 0,
 1036          * we can ignore it.*/
 1037 #if 0
 1038         BA0WRITE4(sc, CS4281_SSCR, SSCR_SB);
 1039 #endif
 1040 
 1041         /* map AC97 PCM playback to DMA Channel 0 */
 1042         /* Reset FEN bit to setup first */
 1043         BA0WRITE4(sc, CS4281_FCR0, (BA0READ4(sc,CS4281_FCR0) & ~FCRn_FEN));
 1044         /*
 1045          *| RS[4:0]/|        |
 1046          *| LS[4:0] |  AC97  | Slot Function
 1047          *|---------+--------+--------------------
 1048          *|     0   |    3   | Left PCM Playback
 1049          *|     1   |    4   | Right PCM Playback
 1050          *|     2   |    5   | Phone Line 1 DAC
 1051          *|     3   |    6   | Center PCM Playback
 1052          *....
 1053          *  quoted from Table 29(p109)
 1054          */
 1055         dat32 = 0x01 << 24 |   /* RS[4:0] =  1 see above */
 1056                 0x00 << 16 |   /* LS[4:0] =  0 see above */
 1057                 0x0f <<  8 |   /* SZ[6:0] = 15 size of buffer */
 1058                 0x00 <<  0 ;   /* OF[6:0] =  0 offset */
 1059         BA0WRITE4(sc, CS4281_FCR0, dat32);
 1060         BA0WRITE4(sc, CS4281_FCR0, dat32 | FCRn_FEN);
 1061 
 1062         /* map AC97 PCM record to DMA Channel 1 */
 1063         /* Reset FEN bit to setup first */
 1064         BA0WRITE4(sc, CS4281_FCR1, (BA0READ4(sc,CS4281_FCR1) & ~FCRn_FEN));
 1065         /*
 1066          *| RS[4:0]/|
 1067          *| LS[4:0] | AC97 | Slot Function
 1068          *|---------+------+-------------------
 1069          *|   10    |   3  | Left PCM Record
 1070          *|   11    |   4  | Right PCM Record
 1071          *|   12    |   5  | Phone Line 1 ADC
 1072          *|   13    |   6  | Mic ADC
 1073          *....
 1074          * quoted from Table 30(p109)
 1075          */
 1076         dat32 = 0x0b << 24 |    /* RS[4:0] = 11 See above */
 1077                 0x0a << 16 |    /* LS[4:0] = 10 See above */
 1078                 0x0f <<  8 |    /* SZ[6:0] = 15 Size of buffer */
 1079                 0x10 <<  0 ;    /* OF[6:0] = 16 offset */
 1080 
 1081         /* XXX: I cannot understand why FCRn_PSH is needed here. */
 1082         BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_PSH);
 1083         BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_FEN);
 1084 
 1085 #if 0
 1086         /* Disable DMA Channel 2, 3 */
 1087         BA0WRITE4(sc, CS4281_FCR2, (BA0READ4(sc,CS4281_FCR2) & ~FCRn_FEN));
 1088         BA0WRITE4(sc, CS4281_FCR3, (BA0READ4(sc,CS4281_FCR3) & ~FCRn_FEN));
 1089 #endif
 1090 
 1091         /* Set the SRC Slot Assignment accordingly */
 1092         /*| PLSS[4:0]/
 1093          *| PRSS[4:0] | AC97 | Slot Function
 1094          *|-----------+------+----------------
 1095          *|     0     |  3   | Left PCM Playback
 1096          *|     1     |  4   | Right PCM Playback
 1097          *|     2     |  5   | phone line 1 DAC
 1098          *|     3     |  6   | Center PCM Playback
 1099          *|     4     |  7   | Left Surround PCM Playback
 1100          *|     5     |  8   | Right Surround PCM Playback
 1101          *......
 1102          *
 1103          *| CLSS[4:0]/
 1104          *| CRSS[4:0] | AC97 | Codec |Slot Function
 1105          *|-----------+------+-------+-----------------
 1106          *|    10     |   3  |Primary| Left PCM Record
 1107          *|    11     |   4  |Primary| Right PCM Record
 1108          *|    12     |   5  |Primary| Phone Line 1 ADC
 1109          *|    13     |   6  |Primary| Mic ADC
 1110          *|.....
 1111          *|    20     |   3  |  Sec. | Left PCM Record
 1112          *|    21     |   4  |  Sec. | Right PCM Record
 1113          *|    22     |   5  |  Sec. | Phone Line 1 ADC
 1114          *|    23     |   6  |  Sec. | Mic ADC
 1115          */
 1116         dat32 = 0x0b << 24 |   /* CRSS[4:0] Right PCM Record(primary) */
 1117                 0x0a << 16 |   /* CLSS[4:0] Left  PCM Record(primary) */
 1118                 0x01 <<  8 |   /* PRSS[4:0] Right PCM Playback */
 1119                 0x00 <<  0;    /* PLSS[4:0] Left  PCM Playback */
 1120         BA0WRITE4(sc, CS4281_SRCSA, dat32);
 1121         
 1122         /* Set interrupt to occurred at Half and Full terminal
 1123          * count interrupt enable for DMA channel 0 and 1.
 1124          * To keep DMA stop, set MSK.
 1125          */
 1126         dat32 = DCRn_HTCIE | DCRn_TCIE | DCRn_MSK;
 1127         BA0WRITE4(sc, CS4281_DCR0, dat32);
 1128         BA0WRITE4(sc, CS4281_DCR1, dat32);
 1129         
 1130         /* Set Auto-Initialize Control enable */
 1131         BA0WRITE4(sc, CS4281_DMR0,
 1132                   DMRn_DMA | DMRn_AUTO | DMRn_TR_READ);
 1133         BA0WRITE4(sc, CS4281_DMR1,
 1134                   DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE);
 1135 
 1136         /* Clear DMA Mask in HIMR */
 1137         dat32 = BA0READ4(sc, CS4281_HIMR) & 0xfffbfcff;
 1138         BA0WRITE4(sc, CS4281_HIMR, dat32);
 1139         return (0);
 1140 }
 1141 
 1142 void
 1143 cs4281_power(why, v)
 1144         int why;
 1145         void *v;
 1146 {
 1147         struct cs4281_softc *sc = (struct cs4281_softc *)v;
 1148         int i;
 1149 
 1150         DPRINTF(("%s: cs4281_power why=%d\n", sc->sc_dev.dv_xname, why));
 1151         if (why != PWR_RESUME) {
 1152                 sc->sc_suspend = why;
 1153 
 1154                 cs4281_halt_output(sc);
 1155                 cs4281_halt_input(sc);
 1156                 /* Save AC97 registers */
 1157                 for (i = 1; i <= CS4281_SAVE_REG_MAX; i++) {
 1158                         if (i == 0x04)  /* AC97_REG_MASTER_TONE */
 1159                                 continue;
 1160                         cs4281_read_codec(sc, 2*i, &sc->ac97_reg[i>>1]);
 1161                 }
 1162                 /* should I powerdown here ? */
 1163                 cs4281_write_codec(sc, AC97_REG_POWER, CS4281_POWER_DOWN_ALL);
 1164         } else {
 1165                 if (sc->sc_suspend == PWR_RESUME) {
 1166                         printf("cs4281_power: odd, resume without suspend.\n");
 1167                         sc->sc_suspend = why;
 1168                         return;
 1169                 }
 1170                 sc->sc_suspend = why;
 1171                 cs4281_init(sc);
 1172                 cs4281_reset_codec(sc);
 1173 
 1174                 /* restore ac97 registers */
 1175                 for (i = 1; i <= CS4281_SAVE_REG_MAX; i++) {
 1176                         if (i == 0x04)  /* AC97_REG_MASTER_TONE */
 1177                                 continue;
 1178                         cs4281_write_codec(sc, 2*i, sc->ac97_reg[i>>1]);
 1179                 }
 1180         }
 1181 }
 1182 
 1183 void
 1184 cs4281_reset_codec(void *addr)
 1185 {
 1186         struct cs4281_softc *sc;
 1187         u_int16_t data;
 1188         u_int32_t dat32;
 1189         int n;
 1190 
 1191         sc = addr;
 1192 
 1193         DPRINTFN(3,("cs4281_reset_codec\n"));
 1194 
 1195         /* Reset codec */
 1196         BA0WRITE4(sc, CS4281_ACCTL, 0);
 1197         delay(50);    /* delay 50us */
 1198 
 1199         BA0WRITE4(sc, CS4281_SPMC, 0);
 1200         delay(100);     /* delay 100us */
 1201         BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN);
 1202 #if defined(ENABLE_SECONDARY_CODEC)
 1203         BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E);
 1204         BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID);
 1205 #endif
 1206         delay(50000);   /* XXX: delay 50ms */
 1207 
 1208         /* Enable ASYNC generation */
 1209         BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN);
 1210 
 1211         /* Wait for Codec ready. Linux driver wait 50ms here */
 1212         n = 0;
 1213         while((BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY) == 0) {
 1214                 delay(100);
 1215                 if (++n > 1000) {
 1216                         printf("reset_codec: AC97 codec ready timeout\n");
 1217                         return;
 1218                 }
 1219         }
 1220 #if defined(ENABLE_SECONDARY_CODEC)
 1221         /* secondary codec ready*/
 1222         n = 0;
 1223         while((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) {
 1224                 delay(100);
 1225                 if (++n > 1000)
 1226                         return;
 1227         }
 1228 #endif
 1229         /* Set the serial timing configuration */
 1230         /* XXX: undocumented but the Linux driver do this */
 1231         BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
 1232         
 1233         /* Wait for Codec ready signal */
 1234         n = 0;
 1235         do {
 1236                 delay(1000);
 1237                 if (++n > 1000) {
 1238                         printf("%s: Timeout waiting for Codec ready\n",
 1239                                sc->sc_dev.dv_xname);
 1240                         return;
 1241                 }
 1242                 dat32 = BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY;
 1243         } while (dat32 == 0);
 1244 
 1245         /* Enable Valid Frame output on ASDOUT */
 1246         BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN | ACCTL_VFRM);
 1247         
 1248         /* Wait until Codec Calibration is finished. Codec register 26h */
 1249         n = 0;
 1250         do {
 1251                 delay(1);
 1252                 if (++n > 1000) {
 1253                         printf("%s: Timeout waiting for Codec calibration\n",
 1254                                sc->sc_dev.dv_xname);
 1255                         return ;
 1256                 }
 1257                 cs4281_read_codec(sc, AC97_REG_POWER, &data);
 1258         } while ((data & 0x0f) != 0x0f);
 1259 
 1260         /* Set the serial timing configuration again */
 1261         /* XXX: undocumented but the Linux driver do this */
 1262         BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
 1263 
 1264         /* Wait until we've sampled input slots 3 & 4 as valid */
 1265         n = 0;
 1266         do {
 1267                 delay(1000);
 1268                 if (++n > 1000) {
 1269                         printf("%s: Timeout waiting for sampled input slots as valid\n",
 1270                                sc->sc_dev.dv_xname);
 1271                         return;
 1272                 }
 1273                 dat32 = BA0READ4(sc, CS4281_ACISV) & (ACISV_ISV3 | ACISV_ISV4) ;
 1274         } while (dat32 != (ACISV_ISV3 | ACISV_ISV4));
 1275         
 1276         /* Start digital data transfer of audio data to the codec */
 1277         BA0WRITE4(sc, CS4281_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4));
 1278 }
 1279 
 1280 int
 1281 cs4281_open(void *addr, int flags)
 1282 {
 1283         return (0);
 1284 }
 1285 
 1286 void
 1287 cs4281_close(void *addr)
 1288 {
 1289         struct cs4281_softc *sc;
 1290 
 1291         sc = addr;
 1292 
 1293         (*sc->halt_output)(sc);
 1294         (*sc->halt_input)(sc);
 1295         
 1296         sc->sc_pintr = 0;
 1297         sc->sc_rintr = 0;
 1298 }
 1299 
 1300 int
 1301 cs4281_round_blocksize(void *addr, int blk)
 1302 {
 1303         struct cs4281_softc *sc;
 1304         int retval;
 1305         
 1306         DPRINTFN(5,("cs4281_round_blocksize blk=%d -> ", blk));
 1307         
 1308         sc=addr;
 1309         if (blk < sc->hw_blocksize)
 1310                 retval = sc->hw_blocksize;
 1311         else
 1312                 retval = blk & -(sc->hw_blocksize);
 1313 
 1314         DPRINTFN(5,("%d\n", retval));
 1315 
 1316         return (retval);
 1317 }
 1318 
 1319 int
 1320 cs4281_mixer_set_port(void *addr, mixer_ctrl_t *cp)
 1321 {
 1322         struct cs4281_softc *sc;
 1323         int val;
 1324 
 1325         sc = addr;
 1326         val = sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
 1327         DPRINTFN(3,("mixer_set_port: val=%d\n", val));
 1328         return (val);
 1329 }
 1330 
 1331 int
 1332 cs4281_mixer_get_port(void *addr, mixer_ctrl_t *cp)
 1333 {
 1334         struct cs4281_softc *sc;
 1335 
 1336         sc = addr;
 1337         return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp));
 1338 }
 1339 
 1340 
 1341 int
 1342 cs4281_query_devinfo(void *addr, mixer_devinfo_t *dip)
 1343 {
 1344         struct cs4281_softc *sc;
 1345 
 1346         sc = addr;
 1347         return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip));
 1348 }
 1349 
 1350 void *
 1351 cs4281_malloc(void *addr, int direction, size_t size, int pool, int flags)
 1352 {
 1353         struct cs4281_softc *sc;
 1354         struct cs4281_dma   *p;
 1355         int error;
 1356 
 1357         sc = addr;
 1358 
 1359         p = malloc(sizeof(*p), pool, flags);
 1360         if (!p)
 1361                 return (0);
 1362 
 1363         error = cs4281_allocmem(sc, size, pool, flags, p);
 1364 
 1365         if (error) {
 1366                 free(p, pool);
 1367                 return (0);
 1368         }
 1369 
 1370         p->next = sc->sc_dmas;
 1371         sc->sc_dmas = p;
 1372         return (BUFADDR(p));
 1373 }
 1374 
 1375 
 1376 
 1377 void
 1378 cs4281_free(void *addr, void *ptr, int pool)
 1379 {
 1380         struct cs4281_softc *sc;
 1381         struct cs4281_dma **pp, *p;
 1382 
 1383         sc = addr;
 1384         for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
 1385                 if (BUFADDR(p) == ptr) {
 1386                         bus_dmamap_unload(sc->sc_dmatag, p->map);
 1387                         bus_dmamap_destroy(sc->sc_dmatag, p->map);
 1388                         bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
 1389                         bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
 1390                         free(p->dum, pool);
 1391                         *pp = p->next;
 1392                         free(p, pool);
 1393                         return;
 1394                 }
 1395         }
 1396 }
 1397 
 1398 size_t
 1399 cs4281_round_buffersize(void *addr, int direction, size_t size)
 1400 {
 1401         /* The real dma buffersize are 4KB for CS4280
 1402          * and 64kB/MAX_CHANNELS for CS4281.
 1403          * But they are too small for high quality audio,
 1404          * let the upper layer(audio) use a larger buffer.
 1405          * (originally suggested by Lennart Augustsson.)
 1406          */
 1407         return (size);
 1408 }
 1409 
 1410 paddr_t
 1411 cs4281_mappage(void *addr, void *mem, off_t off, int prot)
 1412 {
 1413         struct cs4281_softc *sc;
 1414         struct cs4281_dma *p;
 1415         
 1416         sc = addr;
 1417         if (off < 0)
 1418                 return -1;
 1419 
 1420         for (p = sc->sc_dmas; p && BUFADDR(p) != mem; p = p->next)
 1421                 ;
 1422 
 1423         if (!p) {
 1424                 DPRINTF(("cs4281_mappage: bad buffer address\n"));
 1425                 return (-1);
 1426         }
 1427 
 1428         return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs, off, prot,
 1429             BUS_DMA_WAITOK));
 1430 }
 1431 
 1432 
 1433 int
 1434 cs4281_get_props(void *addr)
 1435 {
 1436         int retval;
 1437 
 1438         retval = AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
 1439 #ifdef MMAP_READY
 1440         retval |= AUDIO_PROP_MMAP;
 1441 #endif
 1442         return (retval);
 1443 }
 1444 
 1445 /* AC97 */
 1446 int
 1447 cs4281_attach_codec(void *addr, struct ac97_codec_if *codec_if)
 1448 {
 1449         struct cs4281_softc *sc;
 1450 
 1451         DPRINTF(("cs4281_attach_codec:\n"));
 1452         sc = addr;
 1453         sc->codec_if = codec_if;
 1454         return (0);
 1455 }
 1456 
 1457 
 1458 int
 1459 cs4281_read_codec(void *addr, u_int8_t ac97_addr, u_int16_t *ac97_data)
 1460 {
 1461         struct cs4281_softc *sc;
 1462         u_int32_t acctl;
 1463         int n;
 1464 
 1465         sc = addr;
 1466 
 1467         DPRINTFN(5,("read_codec: add=0x%02x ", ac97_addr));
 1468         /*
 1469          * Make sure that there is not data sitting around from a preivous
 1470          * uncompleted access.
 1471          */
 1472         BA0READ4(sc, CS4281_ACSDA);
 1473 
 1474         /* Set up AC97 control registers. */
 1475         BA0WRITE4(sc, CS4281_ACCAD, ac97_addr);
 1476         BA0WRITE4(sc, CS4281_ACCDA, 0);
 1477 
 1478         acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_CRW  | ACCTL_DCV;
 1479         BA0WRITE4(sc, CS4281_ACCTL, acctl);
 1480 
 1481         if (cs4281_src_wait(sc) < 0) {
 1482                 printf("%s: AC97 read prob. (DCV!=0) for add=0x%0x\n",
 1483                        sc->sc_dev.dv_xname, ac97_addr);
 1484                 return 1;
 1485         }
 1486 
 1487         /* wait for valid status bit is active */
 1488         n = 0;
 1489         while ((BA0READ4(sc, CS4281_ACSTS) & ACSTS_VSTS) == 0) {
 1490                 delay(1);
 1491                 while (++n > 1000) {
 1492                         printf("%s: AC97 read fail (VSTS==0) for add=0x%0x\n",
 1493                                sc->sc_dev.dv_xname, ac97_addr);
 1494                         return 1;
 1495                 }
 1496         }
 1497         *ac97_data = BA0READ4(sc, CS4281_ACSDA);
 1498         DPRINTFN(5,("data=0x%04x\n", *ac97_data));
 1499         return (0);
 1500 }
 1501 
 1502 int
 1503 cs4281_write_codec(void *addr, u_int8_t ac97_addr, u_int16_t ac97_data)
 1504 {
 1505         struct cs4281_softc *sc;
 1506         u_int32_t acctl;
 1507 
 1508         sc = addr;
 1509 
 1510         DPRINTFN(5,("write_codec: add=0x%02x  data=0x%04x\n", ac97_addr, ac97_data));
 1511         BA0WRITE4(sc, CS4281_ACCAD, ac97_addr);
 1512         BA0WRITE4(sc, CS4281_ACCDA, ac97_data);
 1513 
 1514         acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_DCV;
 1515         BA0WRITE4(sc, CS4281_ACCTL, acctl);
 1516 
 1517         if (cs4281_src_wait(sc) < 0) {
 1518                 printf("%s: AC97 write fail (DCV!=0) for add=0x%02x data="
 1519                        "0x%04x\n", sc->sc_dev.dv_xname, ac97_addr, ac97_data);
 1520                 return (1);
 1521         }
 1522         return (0);
 1523 }
 1524 
 1525 int
 1526 cs4281_allocmem(struct cs4281_softc *sc, size_t size, int pool, int flags,
 1527                 struct cs4281_dma *p)
 1528 {
 1529         int error;
 1530         size_t align;
 1531         
 1532         align   = sc->dma_align;
 1533         p->size = sc->dma_size;
 1534         /* allocate memory for upper audio driver */
 1535         p->dum  = malloc(size, pool, flags);
 1536         if (!p->dum)
 1537                 return (1);
 1538         error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
 1539                                  p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
 1540                                  &p->nsegs, BUS_DMA_NOWAIT);
 1541         if (error) {
 1542                 printf("%s: unable to allocate dma. error=%d\n",
 1543                        sc->sc_dev.dv_xname, error);
 1544                 return (error);
 1545         }
 1546 
 1547         error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
 1548                                &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
 1549         if (error) {
 1550                 printf("%s: unable to map dma, error=%d\n",
 1551                        sc->sc_dev.dv_xname, error);
 1552                 goto free;
 1553         }
 1554 
 1555         error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
 1556                                   0, BUS_DMA_NOWAIT, &p->map);
 1557         if (error) {
 1558                 printf("%s: unable to create dma map, error=%d\n",
 1559                        sc->sc_dev.dv_xname, error);
 1560                 goto unmap;
 1561         }
 1562 
 1563         error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
 1564                                 BUS_DMA_NOWAIT);
 1565         if (error) {
 1566                 printf("%s: unable to load dma map, error=%d\n",
 1567                        sc->sc_dev.dv_xname, error);
 1568                 goto destroy;
 1569         }
 1570         return (0);
 1571 
 1572 destroy:
 1573         bus_dmamap_destroy(sc->sc_dmatag, p->map);
 1574 unmap:
 1575         bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
 1576 free:
 1577         bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
 1578         return (error);
 1579 }
 1580 
 1581 
 1582 int
 1583 cs4281_src_wait(sc)
 1584         struct cs4281_softc *sc;
 1585 {
 1586         int n;
 1587 
 1588         n = 0;
 1589         while ((BA0READ4(sc, CS4281_ACCTL) & ACCTL_DCV)) {
 1590                 delay(1000);
 1591                 if (++n > 1000)
 1592                         return (-1);
 1593         }
 1594         return (0);
 1595 }

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