The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/pci/cs4281.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: cs4281.c,v 1.16.4.1 2004/09/22 20:58:21 jmc Exp $      */
    2 
    3 /*
    4  * Copyright (c) 2000 Tatoku Ogaito.  All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. All advertising materials mentioning features or use of this software
   15  *    must display the following acknowledgement:
   16  *      This product includes software developed by Tatoku Ogaito
   17  *      for the NetBSD Project.
   18  * 4. The name of the author may not be used to endorse or promote products
   19  *    derived from this software without specific prior written permission
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 /*
   34  * Cirrus Logic CS4281 driver.
   35  * Data sheets can be found
   36  * http://www.cirrus.com/ftp/pub/4281.pdf
   37  * ftp://ftp.alsa-project.org/pub/manuals/cirrus/cs4281tm.pdf
   38  *
   39  * TODO:
   40  *   1: midi and FM support
   41  *   2: ...
   42  *
   43  */
   44 
   45 #include <sys/cdefs.h>
   46 __KERNEL_RCSID(0, "$NetBSD: cs4281.c,v 1.16.4.1 2004/09/22 20:58:21 jmc Exp $");
   47 
   48 #include <sys/param.h>
   49 #include <sys/systm.h>
   50 #include <sys/kernel.h>
   51 #include <sys/malloc.h>
   52 #include <sys/fcntl.h>
   53 #include <sys/device.h>
   54 #include <sys/systm.h>
   55 
   56 #include <dev/pci/pcidevs.h>
   57 #include <dev/pci/pcivar.h>
   58 #include <dev/pci/cs4281reg.h>
   59 #include <dev/pci/cs428xreg.h>
   60 
   61 #include <sys/audioio.h>
   62 #include <dev/audio_if.h>
   63 #include <dev/midi_if.h>
   64 #include <dev/mulaw.h>
   65 #include <dev/auconv.h>
   66 
   67 #include <dev/ic/ac97reg.h>
   68 #include <dev/ic/ac97var.h>
   69 
   70 #include <dev/pci/cs428x.h>
   71 
   72 #include <machine/bus.h>
   73 
   74 #if defined(ENABLE_SECONDARY_CODEC)
   75 #define MAX_CHANNELS  (4)
   76 #define MAX_FIFO_SIZE 32 /* 128/4channels */
   77 #else
   78 #define MAX_CHANNELS  (2)
   79 #define MAX_FIFO_SIZE 64 /* 128/2channels */
   80 #endif
   81 
   82 /* IF functions for audio driver */
   83 int     cs4281_match(struct device *, struct cfdata *, void *);
   84 void    cs4281_attach(struct device *, struct device *, void *);
   85 int     cs4281_intr(void *);
   86 int     cs4281_query_encoding(void *, struct audio_encoding *);
   87 int     cs4281_set_params(void *, int, int, struct audio_params *, struct audio_params *);
   88 int     cs4281_halt_output(void *);
   89 int     cs4281_halt_input(void *);
   90 int     cs4281_getdev(void *, struct audio_device *);
   91 int     cs4281_trigger_output(void *, void *, void *, int, void (*)(void *),
   92                               void *, struct audio_params *);
   93 int     cs4281_trigger_input(void *, void *, void *, int, void (*)(void *),
   94                              void *, struct audio_params *);
   95 
   96 int     cs4281_reset_codec(void *);
   97 
   98 /* Internal functions */
   99 u_int8_t cs4281_sr2regval(int);
  100 void     cs4281_set_dac_rate(struct cs428x_softc *, int);
  101 void     cs4281_set_adc_rate(struct cs428x_softc *, int);
  102 int      cs4281_init(struct cs428x_softc *, int);
  103 
  104 /* Power Management */
  105 void cs4281_power(int, void *);
  106 
  107 struct audio_hw_if cs4281_hw_if = {
  108         cs428x_open,
  109         cs428x_close,
  110         NULL,
  111         cs4281_query_encoding,
  112         cs4281_set_params,
  113         cs428x_round_blocksize,
  114         NULL,
  115         NULL,
  116         NULL,
  117         NULL,
  118         NULL,
  119         cs4281_halt_output,
  120         cs4281_halt_input,
  121         NULL,
  122         cs4281_getdev,
  123         NULL,
  124         cs428x_mixer_set_port,
  125         cs428x_mixer_get_port,
  126         cs428x_query_devinfo,
  127         cs428x_malloc,
  128         cs428x_free,
  129         cs428x_round_buffersize,
  130         cs428x_mappage,
  131         cs428x_get_props,
  132         cs4281_trigger_output,
  133         cs4281_trigger_input,
  134         NULL,
  135 };
  136 
  137 #if NMIDI > 0 && 0
  138 /* Midi Interface */
  139 void    cs4281_midi_close(void*);
  140 void    cs4281_midi_getinfo(void *, struct midi_info *);
  141 int     cs4281_midi_open(void *, int, void (*)(void *, int),
  142                               void (*)(void *), void *);
  143 int     cs4281_midi_output(void *, int);
  144 
  145 struct midi_hw_if cs4281_midi_hw_if = {
  146         cs4281_midi_open,
  147         cs4281_midi_close,
  148         cs4281_midi_output,
  149         cs4281_midi_getinfo,
  150         0,
  151 };
  152 #endif
  153 
  154 CFATTACH_DECL(clct, sizeof(struct cs428x_softc),
  155     cs4281_match, cs4281_attach, NULL, NULL);
  156 
  157 struct audio_device cs4281_device = {
  158         "CS4281",
  159         "",
  160         "cs4281"
  161 };
  162 
  163 
  164 int
  165 cs4281_match(parent, match, aux) 
  166         struct device *parent;
  167         struct cfdata *match;
  168         void *aux;
  169 {
  170         struct pci_attach_args *pa = (struct pci_attach_args *)aux;
  171         
  172         if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CIRRUS)
  173                 return 0;
  174         if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CIRRUS_CS4281)
  175                 return 1;
  176         return 0;
  177 }
  178 
  179 void
  180 cs4281_attach(parent, self, aux)
  181         struct device *parent;
  182         struct device *self;
  183         void *aux;
  184 {
  185         struct cs428x_softc *sc = (struct cs428x_softc *)self;
  186         struct pci_attach_args *pa = (struct pci_attach_args *)aux;
  187         pci_chipset_tag_t pc = pa->pa_pc;
  188         char const *intrstr;
  189         pci_intr_handle_t ih;
  190         pcireg_t reg;
  191         char devinfo[256];
  192         int pci_pwrmgmt_cap_reg, pci_pwrmgmt_csr_reg;
  193 
  194         aprint_naive(": Audio controller\n");
  195 
  196         pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
  197         aprint_normal(": %s (rev. 0x%02x)\n", devinfo,
  198             PCI_REVISION(pa->pa_class));
  199 
  200         /* Map I/O register */
  201         if (pci_mapreg_map(pa, PCI_BA0,
  202             PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
  203             &sc->ba0t, &sc->ba0h, NULL, NULL)) {
  204                 aprint_error("%s: can't map BA0 space\n", sc->sc_dev.dv_xname);
  205                 return;
  206         }
  207         if (pci_mapreg_map(pa, PCI_BA1,
  208             PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
  209             &sc->ba1t, &sc->ba1h, NULL, NULL)) {
  210                 aprint_error("%s: can't map BA1 space\n", sc->sc_dev.dv_xname);
  211                 return;
  212         }
  213 
  214         sc->sc_dmatag = pa->pa_dmat;
  215 
  216         /*
  217          * Set Power State D0.
  218          * Without do this, 0xffffffff is read from all registers after
  219          * using Windows.
  220          * On my IBM Thinkpad X20, it is set to D3 after using Windows2000.
  221          */
  222         if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PWRMGMT,
  223                                &pci_pwrmgmt_cap_reg, 0)) {
  224 
  225                 pci_pwrmgmt_csr_reg = pci_pwrmgmt_cap_reg + PCI_PMCSR;
  226                 reg = pci_conf_read(pa->pa_pc, pa->pa_tag,
  227                                     pci_pwrmgmt_csr_reg);
  228                 if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0) {
  229                         pci_conf_write(pc, pa->pa_tag, pci_pwrmgmt_csr_reg,
  230                                        (reg & ~PCI_PMCSR_STATE_MASK) |
  231                                        PCI_PMCSR_STATE_D0);
  232                 }
  233         }
  234 
  235         /* Enable the device (set bus master flag) */
  236         reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
  237         pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
  238             reg | PCI_COMMAND_MASTER_ENABLE);
  239 
  240 #if 0
  241         /* LATENCY_TIMER setting */
  242         temp1 = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
  243         if (PCI_LATTIMER(temp1) < 32) {
  244                 temp1 &= 0xffff00ff;
  245                 temp1 |= 0x00002000;
  246                 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, temp1);
  247         }
  248 #endif
  249         
  250         /* Map and establish the interrupt. */
  251         if (pci_intr_map(pa, &ih)) { 
  252                 aprint_error("%s: couldn't map interrupt\n",
  253                     sc->sc_dev.dv_xname);
  254                 return;
  255         }
  256         intrstr = pci_intr_string(pc, ih);
  257 
  258         sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, cs4281_intr, sc);
  259         if (sc->sc_ih == NULL) {
  260                 aprint_error("%s: couldn't establish interrupt",
  261                     sc->sc_dev.dv_xname);
  262                 if (intrstr != NULL)
  263                         aprint_normal(" at %s", intrstr);
  264                 aprint_normal("\n");
  265                 return;
  266         }
  267         aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
  268 
  269         /*
  270          * Sound System start-up
  271          */
  272         if (cs4281_init(sc, 1) != 0)
  273                 return;
  274 
  275         sc->type = TYPE_CS4281;
  276         sc->halt_input  = cs4281_halt_input;
  277         sc->halt_output = cs4281_halt_output;
  278 
  279         sc->dma_size     = CS4281_BUFFER_SIZE / MAX_CHANNELS;
  280         sc->dma_align    = 0x10;
  281         sc->hw_blocksize = sc->dma_size / 2;
  282         
  283         /* AC 97 attachment */
  284         sc->host_if.arg = sc;
  285         sc->host_if.attach = cs428x_attach_codec;
  286         sc->host_if.read   = cs428x_read_codec;
  287         sc->host_if.write  = cs428x_write_codec;
  288         sc->host_if.reset  = cs4281_reset_codec;
  289         if (ac97_attach(&sc->host_if) != 0) {
  290                 aprint_error("%s: ac97_attach failed\n", sc->sc_dev.dv_xname);
  291                 return;
  292         }
  293         audio_attach_mi(&cs4281_hw_if, sc, &sc->sc_dev);
  294 
  295 #if NMIDI > 0 && 0
  296         midi_attach_mi(&cs4281_midi_hw_if, sc, &sc->sc_dev);
  297 #endif
  298 
  299         sc->sc_suspend = PWR_RESUME;
  300         sc->sc_powerhook = powerhook_establish(cs4281_power, sc);
  301 }
  302 
  303 int
  304 cs4281_intr(p)
  305         void *p;
  306 {
  307         struct cs428x_softc *sc = p;
  308         u_int32_t intr, hdsr0, hdsr1;
  309         char *empty_dma;
  310         int handled = 0;
  311 
  312         hdsr0 = 0;
  313         hdsr1 = 0;
  314         
  315         /* grab interrupt register */
  316         intr = BA0READ4(sc, CS4281_HISR);
  317 
  318         DPRINTF(("cs4281_intr:"));
  319         /* not for me */
  320         if ((intr & HISR_INTENA) == 0) {
  321                 /* clear the interrupt register */
  322                 BA0WRITE4(sc, CS4281_HICR, HICR_CHGM | HICR_IEV);
  323                 return 0;
  324         }
  325 
  326         if (intr & HISR_DMA0)
  327                 hdsr0 = BA0READ4(sc, CS4281_HDSR0); /* clear intr condition */
  328         if (intr & HISR_DMA1)
  329                 hdsr1 = BA0READ4(sc, CS4281_HDSR1); /* clear intr condition */
  330         /* clear the interrupt register */
  331         BA0WRITE4(sc, CS4281_HICR, HICR_CHGM | HICR_IEV);
  332         
  333         DPRINTF(("intr = 0x%08x, hdsr0 = 0x%08x hdsr1 = 0x%08x\n",
  334                  intr, hdsr0, hdsr1));
  335         
  336         /* Playback Interrupt */
  337         if (intr & HISR_DMA0) {
  338                 handled = 1;
  339                 DPRINTF((" PB DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA0),
  340                          (int)BA0READ4(sc, CS4281_DCC0)));
  341                 if (sc->sc_pintr) {
  342                         if ((sc->sc_pi%sc->sc_pcount) == 0)
  343                                 sc->sc_pintr(sc->sc_parg);
  344                 } else {
  345                         printf("unexpected play intr\n");
  346                 }
  347                 /* copy buffer */
  348                 ++sc->sc_pi;
  349                 empty_dma = sc->sc_pdma->addr;
  350                 if (sc->sc_pi&1)
  351                         empty_dma += sc->hw_blocksize;
  352                 memcpy(empty_dma, sc->sc_pn, sc->hw_blocksize);
  353                 sc->sc_pn += sc->hw_blocksize;
  354                 if (sc->sc_pn >= sc->sc_pe)
  355                         sc->sc_pn = sc->sc_ps;
  356         }
  357         if (intr & HISR_DMA1) {
  358                 handled = 1;
  359                 /* copy from DMA */
  360                 DPRINTF((" CP DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA1),
  361                          (int)BA0READ4(sc, CS4281_DCC1)));
  362                 ++sc->sc_ri;
  363                 empty_dma = sc->sc_rdma->addr;
  364                 if ((sc->sc_ri & 1) == 0)
  365                         empty_dma += sc->hw_blocksize;
  366                 memcpy(sc->sc_rn, empty_dma, sc->hw_blocksize);
  367                 if (sc->sc_rn >= sc->sc_re)
  368                         sc->sc_rn = sc->sc_rs;
  369                 if (sc->sc_rintr) {
  370                         if ((sc->sc_ri % sc->sc_rcount) == 0)
  371                                 sc->sc_rintr(sc->sc_rarg);
  372                 } else {
  373                         printf("unexpected record intr\n");
  374                 }
  375         }
  376         DPRINTF(("\n"));
  377 
  378         return handled;
  379 }
  380 
  381 int
  382 cs4281_query_encoding(addr, fp)
  383         void *addr;
  384         struct audio_encoding *fp;
  385 {
  386 
  387         switch (fp->index) {
  388         case 0:
  389                 strcpy(fp->name, AudioEulinear);
  390                 fp->encoding = AUDIO_ENCODING_ULINEAR;
  391                 fp->precision = 8;
  392                 fp->flags = 0;
  393                 break;
  394         case 1:
  395                 strcpy(fp->name, AudioEmulaw);
  396                 fp->encoding = AUDIO_ENCODING_ULAW;
  397                 fp->precision = 8;
  398                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  399                 break;
  400         case 2:
  401                 strcpy(fp->name, AudioEalaw);
  402                 fp->encoding = AUDIO_ENCODING_ALAW;
  403                 fp->precision = 8;
  404                 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
  405                 break;
  406         case 3:
  407                 strcpy(fp->name, AudioEslinear);
  408                 fp->encoding = AUDIO_ENCODING_SLINEAR;
  409                 fp->precision = 8;
  410                 fp->flags = 0;
  411                 break;
  412         case 4:
  413                 strcpy(fp->name, AudioEslinear_le);
  414                 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
  415                 fp->precision = 16;
  416                 fp->flags = 0;
  417                 break;
  418         case 5:
  419                 strcpy(fp->name, AudioEulinear_le);
  420                 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
  421                 fp->precision = 16;
  422                 fp->flags = 0;
  423                 break;
  424         case 6:
  425                 strcpy(fp->name, AudioEslinear_be);
  426                 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
  427                 fp->precision = 16;
  428                 fp->flags = 0;
  429                 break;
  430         case 7:
  431                 strcpy(fp->name, AudioEulinear_be);
  432                 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
  433                 fp->precision = 16;
  434                 fp->flags = 0;
  435                 break;
  436         default:
  437                 return EINVAL;
  438         }
  439         return 0;
  440 }
  441 
  442 int
  443 cs4281_set_params(addr, setmode, usemode, play, rec)
  444         void *addr;
  445         int setmode, usemode;
  446         struct audio_params *play, *rec;
  447 {
  448         struct cs428x_softc *sc = addr;
  449         struct audio_params *p;
  450         int mode;
  451 
  452         for (mode = AUMODE_RECORD; mode != -1;
  453             mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
  454                 if ((setmode & mode) == 0)
  455                         continue;
  456                 
  457                 p = mode == AUMODE_PLAY ? play : rec;
  458                 
  459                 if (p == play) {
  460                         DPRINTFN(5, ("play: sample=%ld precision=%d channels=%d\n",
  461                                 p->sample_rate, p->precision, p->channels));
  462                         if (p->sample_rate < 6023 || p->sample_rate > 48000 ||
  463                             (p->precision != 8 && p->precision != 16) ||
  464                             (p->channels != 1  && p->channels != 2)) {
  465                                 return (EINVAL);
  466                         }
  467                 } else {
  468                         DPRINTFN(5, ("rec: sample=%ld precision=%d channels=%d\n",
  469                                 p->sample_rate, p->precision, p->channels));
  470                         if (p->sample_rate < 6023 || p->sample_rate > 48000 ||
  471                             (p->precision != 8 && p->precision != 16) ||
  472                             (p->channels != 1 && p->channels != 2)) {
  473                                 return (EINVAL);
  474                         }
  475                 }
  476                 p->factor  = 1;
  477                 p->sw_code = 0;
  478 
  479                 switch (p->encoding) {
  480                 case AUDIO_ENCODING_SLINEAR_BE:
  481                         break;
  482                 case AUDIO_ENCODING_SLINEAR_LE:
  483                         break;
  484                 case AUDIO_ENCODING_ULINEAR_BE:
  485                         break;
  486                 case AUDIO_ENCODING_ULINEAR_LE:
  487                         break;
  488                 case AUDIO_ENCODING_ULAW:
  489                         if (mode == AUMODE_PLAY) {
  490                                 p->sw_code = mulaw_to_slinear8;
  491                         } else {
  492                                 p->sw_code = slinear8_to_mulaw;
  493                         }
  494                         break;
  495                 case AUDIO_ENCODING_ALAW:
  496                         if (mode == AUMODE_PLAY) {
  497                                 p->sw_code = alaw_to_slinear8;
  498                         } else {
  499                                 p->sw_code = slinear8_to_alaw;
  500                         }
  501                         break;
  502                 default:
  503                         return (EINVAL);
  504                 }
  505         }
  506 
  507         /* set sample rate */
  508         cs4281_set_dac_rate(sc, play->sample_rate);
  509         cs4281_set_adc_rate(sc, rec->sample_rate);
  510         return 0;
  511 }
  512 
  513 int
  514 cs4281_halt_output(addr)
  515         void *addr;
  516 {
  517         struct cs428x_softc *sc = addr;
  518         
  519         BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
  520         sc->sc_prun = 0;
  521         return 0;
  522 }
  523 
  524 int
  525 cs4281_halt_input(addr)
  526         void *addr;
  527 {
  528         struct cs428x_softc *sc = addr;
  529 
  530         BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
  531         sc->sc_rrun = 0;
  532         return 0;
  533 }
  534 
  535 int
  536 cs4281_getdev(addr, retp)
  537      void *addr;
  538      struct audio_device *retp;
  539 {
  540 
  541         *retp = cs4281_device;
  542         return 0;
  543 }
  544 
  545 int
  546 cs4281_trigger_output(addr, start, end, blksize, intr, arg, param)
  547         void *addr;
  548         void *start, *end;
  549         int blksize;
  550         void (*intr) __P((void *));
  551         void *arg;
  552         struct audio_params *param;
  553 {
  554         struct cs428x_softc *sc = addr;
  555         u_int32_t fmt=0;
  556         struct cs428x_dma *p;
  557         int dma_count;
  558 
  559 #ifdef DIAGNOSTIC
  560         if (sc->sc_prun)
  561                 printf("cs4281_trigger_output: already running\n");
  562 #endif
  563         sc->sc_prun = 1;
  564 
  565         DPRINTF(("cs4281_trigger_output: sc=%p start=%p end=%p "
  566                  "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
  567         sc->sc_pintr = intr;
  568         sc->sc_parg  = arg;
  569 
  570         /* stop playback DMA */
  571         BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
  572 
  573         DPRINTF(("param: precision=%d  factor=%d channels=%d encoding=%d\n",
  574                param->precision, param->factor, param->channels,
  575                param->encoding));
  576         for (p = sc->sc_dmas; p != NULL && BUFADDR(p) != start; p = p->next)
  577                 ;
  578         if (p == NULL) {
  579                 printf("cs4281_trigger_output: bad addr %p\n", start);
  580                 return (EINVAL);
  581         }
  582 
  583         sc->sc_pcount = blksize / sc->hw_blocksize;
  584         sc->sc_ps = (char *)start;
  585         sc->sc_pe = (char *)end;
  586         sc->sc_pdma = p;
  587         sc->sc_pbuf = KERNADDR(p);
  588         sc->sc_pi = 0;
  589         sc->sc_pn = sc->sc_ps;
  590         if (blksize >= sc->dma_size) {
  591                 sc->sc_pn = sc->sc_ps + sc->dma_size;
  592                 memcpy(sc->sc_pbuf, start, sc->dma_size);
  593                 ++sc->sc_pi;
  594         } else {
  595                 sc->sc_pn = sc->sc_ps + sc->hw_blocksize;
  596                 memcpy(sc->sc_pbuf, start, sc->hw_blocksize);
  597         }
  598 
  599         dma_count = sc->dma_size;
  600         if (param->precision * param->factor != 8)
  601                 dma_count /= 2;   /* 16 bit */
  602         if (param->channels > 1)
  603                 dma_count /= 2;   /* Stereo */
  604 
  605         DPRINTF(("cs4281_trigger_output: DMAADDR(p)=0x%x count=%d\n",
  606                  (int)DMAADDR(p), dma_count));
  607         BA0WRITE4(sc, CS4281_DBA0, DMAADDR(p));
  608         BA0WRITE4(sc, CS4281_DBC0, dma_count-1);
  609 
  610         /* set playback format */
  611         fmt = BA0READ4(sc, CS4281_DMR0) & ~DMRn_FMTMSK;
  612         if (param->precision * param->factor == 8)
  613                 fmt |= DMRn_SIZE8;
  614         if (param->channels == 1)
  615                 fmt |= DMRn_MONO;
  616         if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
  617             param->encoding == AUDIO_ENCODING_SLINEAR_BE)
  618                 fmt |= DMRn_BEND;
  619         if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
  620             param->encoding == AUDIO_ENCODING_ULINEAR_LE)
  621                 fmt |= DMRn_USIGN;
  622         BA0WRITE4(sc, CS4281_DMR0, fmt);
  623 
  624         /* set sample rate */
  625         sc->sc_prate = param->sample_rate;
  626         cs4281_set_dac_rate(sc, param->sample_rate);
  627 
  628         /* start DMA */
  629         BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) & ~DCRn_MSK);
  630         /* Enable interrupts */
  631         BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
  632 
  633         DPRINTF(("HICR =0x%08x(expected 0x00000001)\n", BA0READ4(sc, CS4281_HICR)));
  634         DPRINTF(("HIMR =0x%08x(expected 0x00f0fc3f)\n", BA0READ4(sc, CS4281_HIMR)));
  635         DPRINTF(("DMR0 =0x%08x(expected 0x2???0018)\n", BA0READ4(sc, CS4281_DMR0)));
  636         DPRINTF(("DCR0 =0x%08x(expected 0x00030000)\n", BA0READ4(sc, CS4281_DCR0)));
  637         DPRINTF(("FCR0 =0x%08x(expected 0x81000f00)\n", BA0READ4(sc, CS4281_FCR0)));
  638         DPRINTF(("DACSR=0x%08x(expected 1 for 44kHz 5 for 8kHz)\n",
  639                  BA0READ4(sc, CS4281_DACSR)));
  640         DPRINTF(("SRCSA=0x%08x(expected 0x0b0a0100)\n", BA0READ4(sc, CS4281_SRCSA)));
  641         DPRINTF(("SSPM&SSPM_PSRCEN =0x%08x(expected 0x00000010)\n",
  642                  BA0READ4(sc, CS4281_SSPM) & SSPM_PSRCEN));
  643 
  644         return 0;
  645 }
  646 
  647 int
  648 cs4281_trigger_input(addr, start, end, blksize, intr, arg, param)
  649         void *addr;
  650         void *start, *end;
  651         int blksize;
  652         void (*intr) __P((void *));
  653         void *arg;
  654         struct audio_params *param;
  655 {
  656         struct cs428x_softc *sc = addr;
  657         struct cs428x_dma *p;
  658         u_int32_t fmt=0;
  659         int dma_count;
  660 
  661 #ifdef DIAGNOSTIC
  662         if (sc->sc_rrun)
  663                 printf("cs4281_trigger_input: already running\n");
  664 #endif
  665         sc->sc_rrun = 1;
  666         DPRINTF(("cs4281_trigger_input: sc=%p start=%p end=%p "
  667             "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
  668         sc->sc_rintr = intr;
  669         sc->sc_rarg  = arg;
  670 
  671         /* stop recording DMA */
  672         BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
  673 
  674         for (p = sc->sc_dmas; p && BUFADDR(p) != start; p = p->next)
  675                 ;
  676         if (!p) {
  677                 printf("cs4281_trigger_input: bad addr %p\n", start);
  678                 return (EINVAL);
  679         }
  680 
  681         sc->sc_rcount = blksize / sc->hw_blocksize;
  682         sc->sc_rs = (char *)start;
  683         sc->sc_re = (char *)end;
  684         sc->sc_rdma = p;
  685         sc->sc_rbuf = KERNADDR(p);
  686         sc->sc_ri = 0;
  687         sc->sc_rn = sc->sc_rs;
  688 
  689         dma_count = sc->dma_size;
  690         if (param->precision * param->factor == 8)
  691                 dma_count /= 2;
  692         if (param->channels > 1)
  693                 dma_count /= 2;
  694 
  695         DPRINTF(("cs4281_trigger_input: DMAADDR(p)=0x%x count=%d\n",
  696                  (int)DMAADDR(p), dma_count));
  697         BA0WRITE4(sc, CS4281_DBA1, DMAADDR(p));
  698         BA0WRITE4(sc, CS4281_DBC1, dma_count-1);
  699 
  700         /* set recording format */
  701         fmt = BA0READ4(sc, CS4281_DMR1) & ~DMRn_FMTMSK;
  702         if (param->precision * param->factor == 8)
  703                 fmt |= DMRn_SIZE8;
  704         if (param->channels == 1)
  705                 fmt |= DMRn_MONO;
  706         if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
  707             param->encoding == AUDIO_ENCODING_SLINEAR_BE)
  708                 fmt |= DMRn_BEND;
  709         if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
  710             param->encoding == AUDIO_ENCODING_ULINEAR_LE)
  711                 fmt |= DMRn_USIGN;
  712         BA0WRITE4(sc, CS4281_DMR1, fmt);
  713 
  714         /* set sample rate */
  715         sc->sc_rrate = param->sample_rate;
  716         cs4281_set_adc_rate(sc, param->sample_rate);
  717 
  718         /* Start DMA */
  719         BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) & ~DCRn_MSK);
  720         /* Enable interrupts */
  721         BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
  722 
  723         DPRINTF(("HICR=0x%08x\n", BA0READ4(sc, CS4281_HICR)));
  724         DPRINTF(("HIMR=0x%08x\n", BA0READ4(sc, CS4281_HIMR)));
  725         DPRINTF(("DMR1=0x%08x\n", BA0READ4(sc, CS4281_DMR1)));
  726         DPRINTF(("DCR1=0x%08x\n", BA0READ4(sc, CS4281_DCR1)));
  727 
  728         return 0;
  729 }
  730 
  731 /* Power Hook */
  732 void
  733 cs4281_power(why, v)
  734         int why;
  735         void *v;
  736 {
  737         struct cs428x_softc *sc = (struct cs428x_softc *)v;
  738         static u_int32_t dba0 = 0, dbc0 = 0, dmr0 = 0, dcr0 = 0;
  739         static u_int32_t dba1 = 0, dbc1 = 0, dmr1 = 0, dcr1 = 0;
  740 
  741         DPRINTF(("%s: cs4281_power why=%d\n", sc->sc_dev.dv_xname, why));
  742         switch (why) {
  743         case PWR_SUSPEND:
  744         case PWR_STANDBY:
  745                 sc->sc_suspend = why;
  746 
  747                 /* save current playback status */
  748                 if (sc->sc_prun) {
  749                         dcr0 = BA0READ4(sc, CS4281_DCR0);
  750                         dmr0 = BA0READ4(sc, CS4281_DMR0);
  751                         dbc0 = BA0READ4(sc, CS4281_DBC0);
  752                         dba0 = BA0READ4(sc, CS4281_DBA0);
  753                 }
  754 
  755                 /* save current capture status */
  756                 if (sc->sc_rrun) {
  757                         dcr1 = BA0READ4(sc, CS4281_DCR1);
  758                         dmr1 = BA0READ4(sc, CS4281_DMR1);
  759                         dbc1 = BA0READ4(sc, CS4281_DBC1);
  760                         dba1 = BA0READ4(sc, CS4281_DBA1);
  761                 }
  762                 /* Stop DMA */
  763                 BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
  764                 BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
  765                 break;
  766         case PWR_RESUME:
  767                 if (sc->sc_suspend == PWR_RESUME) {
  768                         printf("cs4281_power: odd, resume without suspend.\n");
  769                         sc->sc_suspend = why;
  770                         return;
  771                 }
  772                 sc->sc_suspend = why;
  773                 cs4281_init(sc, 0);
  774                 cs4281_reset_codec(sc);
  775 
  776                 /* restore ac97 registers */
  777                 (*sc->codec_if->vtbl->restore_ports)(sc->codec_if);
  778 
  779                 /* restore DMA related status */
  780                 if (sc->sc_prun) {
  781                         cs4281_set_dac_rate(sc, sc->sc_prate);
  782                         BA0WRITE4(sc, CS4281_DBA0, dba0);
  783                         BA0WRITE4(sc, CS4281_DBC0, dbc0);
  784                         BA0WRITE4(sc, CS4281_DMR0, dmr0);
  785                         BA0WRITE4(sc, CS4281_DCR0, dcr0);
  786                 }
  787                 if (sc->sc_rrun) {
  788                         cs4281_set_adc_rate(sc, sc->sc_rrate);
  789                         BA0WRITE4(sc, CS4281_DBA1, dba1);
  790                         BA0WRITE4(sc, CS4281_DBC1, dbc1);
  791                         BA0WRITE4(sc, CS4281_DMR1, dmr1);
  792                         BA0WRITE4(sc, CS4281_DCR1, dcr1);
  793                 }
  794                 /* enable intterupts */
  795                 if (sc->sc_prun || sc->sc_rrun)
  796                         BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
  797                 break;
  798         case PWR_SOFTSUSPEND:
  799         case PWR_SOFTSTANDBY:
  800         case PWR_SOFTRESUME:
  801                 break;
  802         }
  803 }
  804 
  805 /* control AC97 codec */
  806 int
  807 cs4281_reset_codec(void *addr)
  808 {
  809         struct cs428x_softc *sc;
  810         u_int16_t data;
  811         u_int32_t dat32;
  812         int n;
  813 
  814         sc = addr;
  815 
  816         DPRINTFN(3, ("cs4281_reset_codec\n"));
  817 
  818         /* Reset codec */
  819         BA0WRITE4(sc, CS428X_ACCTL, 0);
  820         delay(50);    /* delay 50us */
  821 
  822         BA0WRITE4(sc, CS4281_SPMC, 0);
  823         delay(100);     /* delay 100us */
  824         BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN);
  825 #if defined(ENABLE_SECONDARY_CODEC)
  826         BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E);
  827         BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID);
  828 #endif
  829         delay(50000);   /* XXX: delay 50ms */
  830 
  831         /* Enable ASYNC generation */
  832         BA0WRITE4(sc, CS428X_ACCTL, ACCTL_ESYN);
  833 
  834         /* Wait for codec ready. Linux driver waits 50ms here */
  835         n = 0;
  836         while ((BA0READ4(sc, CS428X_ACSTS) & ACSTS_CRDY) == 0) {
  837                 delay(100);
  838                 if (++n > 1000) {
  839                         printf("reset_codec: AC97 codec ready timeout\n");
  840                         return ETIMEDOUT;
  841                 }
  842         }
  843 #if defined(ENABLE_SECONDARY_CODEC)
  844         /* secondary codec ready*/
  845         n = 0;
  846         while ((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) {
  847                 delay(100);
  848                 if (++n > 1000)
  849                         return 0;
  850         }
  851 #endif
  852         /* Set the serial timing configuration */
  853         /* XXX: undocumented but the Linux driver do this */
  854         BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
  855         
  856         /* Wait for codec ready signal */
  857         n = 0;
  858         do {
  859                 delay(1000);
  860                 if (++n > 1000) {
  861                         printf("%s: timeout waiting for codec ready\n",
  862                                sc->sc_dev.dv_xname);
  863                         return ETIMEDOUT;
  864                 }
  865                 dat32 = BA0READ4(sc, CS428X_ACSTS) & ACSTS_CRDY;
  866         } while (dat32 == 0);
  867 
  868         /* Enable Valid Frame output on ASDOUT */
  869         BA0WRITE4(sc, CS428X_ACCTL, ACCTL_ESYN | ACCTL_VFRM);
  870         
  871         /* Wait until codec calibration is finished. Codec register 26h */
  872         n = 0;
  873         do {
  874                 delay(1);
  875                 if (++n > 1000) {
  876                         printf("%s: timeout waiting for codec calibration\n",
  877                                sc->sc_dev.dv_xname);
  878                         return ETIMEDOUT;
  879                 }
  880                 cs428x_read_codec(sc, AC97_REG_POWER, &data);
  881         } while ((data & 0x0f) != 0x0f);
  882 
  883         /* Set the serial timing configuration again */
  884         /* XXX: undocumented but the Linux driver do this */
  885         BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
  886 
  887         /* Wait until we've sampled input slots 3 & 4 as valid */
  888         n = 0;
  889         do {
  890                 delay(1000);
  891                 if (++n > 1000) {
  892                         printf("%s: timeout waiting for sampled input slots as valid\n",
  893                                sc->sc_dev.dv_xname);
  894                         return ETIMEDOUT;
  895                 }
  896                 dat32 = BA0READ4(sc, CS428X_ACISV) & (ACISV_ISV3 | ACISV_ISV4) ;
  897         } while (dat32 != (ACISV_ISV3 | ACISV_ISV4));
  898         
  899         /* Start digital data transfer of audio data to the codec */
  900         BA0WRITE4(sc, CS428X_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4));
  901         return 0;
  902 }
  903 
  904 
  905 /* Internal functions */
  906 
  907 /* convert sample rate to register value */
  908 u_int8_t
  909 cs4281_sr2regval(rate)
  910      int rate;
  911 {
  912         u_int8_t retval;
  913 
  914         /* We don't have to change here. but anyway ... */
  915         if (rate > 48000)
  916                 rate = 48000;
  917         if (rate < 6023)
  918                 rate = 6023;
  919 
  920         switch (rate) {
  921         case 8000:
  922                 retval = 5;
  923                 break;
  924         case 11025:
  925                 retval = 4;
  926                 break;
  927         case 16000:
  928                 retval = 3;
  929                 break;
  930         case 22050:
  931                 retval = 2;
  932                 break;
  933         case 44100:
  934                 retval = 1;
  935                 break;
  936         case 48000:
  937                 retval = 0;
  938                 break;
  939         default:
  940                 retval = 1536000/rate; /* == 24576000/(rate*16) */
  941         }
  942         return retval;
  943 }
  944 
  945 void
  946 cs4281_set_adc_rate(sc, rate)
  947         struct cs428x_softc *sc;
  948         int rate;
  949 {
  950 
  951         BA0WRITE4(sc, CS4281_ADCSR, cs4281_sr2regval(rate));
  952 }
  953 
  954 void
  955 cs4281_set_dac_rate(sc, rate)
  956         struct cs428x_softc *sc;
  957         int rate;
  958 {
  959 
  960         BA0WRITE4(sc, CS4281_DACSR, cs4281_sr2regval(rate));
  961 }
  962 
  963 int
  964 cs4281_init(sc, init)
  965      struct cs428x_softc *sc;
  966      int init;
  967 {
  968         int n;
  969         u_int16_t data;
  970         u_int32_t dat32;
  971 
  972         /* set "Configuration Write Protect" register to
  973          * 0x4281 to allow to write */
  974         BA0WRITE4(sc, CS4281_CWPR, 0x4281);
  975 
  976         /*
  977          * Unset "Full Power-Down bit of Extended PCI Power Management
  978          * Control" register to release the reset state.
  979          */
  980         dat32 = BA0READ4(sc, CS4281_EPPMC);
  981         if (dat32 & EPPMC_FPDN) {
  982                 BA0WRITE4(sc, CS4281_EPPMC, dat32 & ~EPPMC_FPDN);
  983         }
  984 
  985         /* Start PLL out in known state */
  986         BA0WRITE4(sc, CS4281_CLKCR1, 0);
  987         /* Start serial ports out in known state */
  988         BA0WRITE4(sc, CS4281_SERMC, 0);
  989         
  990         /* Reset codec */
  991         BA0WRITE4(sc, CS428X_ACCTL, 0);
  992         delay(50);      /* delay 50us */
  993 
  994         BA0WRITE4(sc, CS4281_SPMC, 0);
  995         delay(100);     /* delay 100us */
  996         BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN);
  997 #if defined(ENABLE_SECONDARY_CODEC)
  998         BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E);
  999         BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID);
 1000 #endif
 1001         delay(50000);   /* XXX: delay 50ms */
 1002 
 1003         /* Turn on Sound System clocks based on ABITCLK */
 1004         BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_DLLP);
 1005         delay(50000);   /* XXX: delay 50ms */
 1006         BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_SWCE | CLKCR1_DLLP);
 1007 
 1008         /* Set enables for sections that are needed in the SSPM registers */
 1009         BA0WRITE4(sc, CS4281_SSPM,
 1010                   SSPM_MIXEN |          /* Mixer */
 1011                   SSPM_CSRCEN |         /* Capture SRC */
 1012                   SSPM_PSRCEN |         /* Playback SRC */
 1013                   SSPM_JSEN |           /* Joystick */
 1014                   SSPM_ACLEN |          /* AC LINK */
 1015                   SSPM_FMEN             /* FM */
 1016                   );
 1017 
 1018         /* Wait for clock stabilization */
 1019         n = 0;
 1020 #if 1
 1021         /* what document says */
 1022         while ((BA0READ4(sc, CS4281_CLKCR1)& (CLKCR1_DLLRDY | CLKCR1_CLKON))
 1023                  != (CLKCR1_DLLRDY | CLKCR1_CLKON)) {
 1024                 delay(100);
 1025                 if (++n > 1000) {
 1026                         printf("%s: timeout waiting for clock stabilization\n",
 1027                                sc->sc_dev.dv_xname);
 1028                         return -1;
 1029                 }
 1030         }
 1031 #else
 1032         /* Cirrus driver for Linux does */
 1033         while (!(BA0READ4(sc, CS4281_CLKCR1) & CLKCR1_DLLRDY)) {
 1034                 delay(1000);
 1035                 if (++n > 1000) {
 1036                         printf("%s: timeout waiting for clock stabilization\n",
 1037                                sc->sc_dev.dv_xname);
 1038                         return -1;
 1039                 }
 1040         }
 1041 #endif
 1042 
 1043         /* Enable ASYNC generation */
 1044         BA0WRITE4(sc, CS428X_ACCTL, ACCTL_ESYN);
 1045 
 1046         /* Wait for codec ready. Linux driver waits 50ms here */
 1047         n = 0;
 1048         while ((BA0READ4(sc, CS428X_ACSTS) & ACSTS_CRDY) == 0) {
 1049                 delay(100);
 1050                 if (++n > 1000) {
 1051                         printf("%s: timeout waiting for codec ready\n",
 1052                                sc->sc_dev.dv_xname);
 1053                         return -1;
 1054                 }
 1055         }
 1056 
 1057 #if defined(ENABLE_SECONDARY_CODEC)
 1058         /* secondary codec ready*/
 1059         n = 0;
 1060         while ((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) {
 1061                 delay(100);
 1062                 if (++n > 1000) {
 1063                         printf("%s: timeout waiting for secondary codec ready\n",
 1064                                sc->sc_dev.dv_xname);
 1065                         return -1;
 1066                 }
 1067         }
 1068 #endif
 1069 
 1070         /* Set the serial timing configuration */
 1071         /* XXX: undocumented but the Linux driver do this */
 1072         BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
 1073         
 1074         /* Wait for codec ready signal */
 1075         n = 0;
 1076         do {
 1077                 delay(1000);
 1078                 if (++n > 1000) {
 1079                         printf("%s: timeout waiting for codec ready\n",
 1080                                sc->sc_dev.dv_xname);
 1081                         return -1;
 1082                 }
 1083                 dat32 = BA0READ4(sc, CS428X_ACSTS) & ACSTS_CRDY;
 1084         } while (dat32 == 0);
 1085 
 1086         /* Enable Valid Frame output on ASDOUT */
 1087         BA0WRITE4(sc, CS428X_ACCTL, ACCTL_ESYN | ACCTL_VFRM);
 1088         
 1089         /* Wait until codec calibration is finished. codec register 26h */
 1090         n = 0;
 1091         do {
 1092                 delay(1);
 1093                 if (++n > 1000) {
 1094                         printf("%s: timeout waiting for codec calibration\n",
 1095                                sc->sc_dev.dv_xname);
 1096                         return -1;
 1097                 }
 1098                 cs428x_read_codec(sc, AC97_REG_POWER, &data);
 1099         } while ((data & 0x0f) != 0x0f);
 1100 
 1101         /* Set the serial timing configuration again */
 1102         /* XXX: undocumented but the Linux driver do this */
 1103         BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
 1104 
 1105         /* Wait until we've sampled input slots 3 & 4 as valid */
 1106         n = 0;
 1107         do {
 1108                 delay(1000);
 1109                 if (++n > 1000) {
 1110                         printf("%s: timeout waiting for sampled input slots as valid\n",
 1111                                sc->sc_dev.dv_xname);
 1112                         return -1;
 1113                 }
 1114                 dat32 = BA0READ4(sc, CS428X_ACISV) & (ACISV_ISV3 | ACISV_ISV4);
 1115         } while (dat32 != (ACISV_ISV3 | ACISV_ISV4));
 1116         
 1117         /* Start digital data transfer of audio data to the codec */
 1118         BA0WRITE4(sc, CS428X_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4));
 1119         
 1120         cs428x_write_codec(sc, AC97_REG_HEADPHONE_VOLUME, 0);
 1121         cs428x_write_codec(sc, AC97_REG_MASTER_VOLUME, 0);
 1122         
 1123         /* Power on the DAC */
 1124         cs428x_read_codec(sc, AC97_REG_POWER, &data);
 1125         cs428x_write_codec(sc, AC97_REG_POWER, data & 0xfdff);
 1126 
 1127         /* Wait until we sample a DAC ready state.
 1128          * Not documented, but Linux driver does.
 1129          */
 1130         for (n = 0; n < 32; ++n) {
 1131                 delay(1000);
 1132                 cs428x_read_codec(sc, AC97_REG_POWER, &data);
 1133                 if (data & 0x02)
 1134                         break;
 1135         }
 1136         
 1137         /* Power on the ADC */
 1138         cs428x_read_codec(sc, AC97_REG_POWER, &data);
 1139         cs428x_write_codec(sc, AC97_REG_POWER, data & 0xfeff);
 1140 
 1141         /* Wait until we sample ADC ready state.
 1142          * Not documented, but Linux driver does.
 1143          */
 1144         for (n = 0; n < 32; ++n) {
 1145                 delay(1000);
 1146                 cs428x_read_codec(sc, AC97_REG_POWER, &data);
 1147                 if (data & 0x01)
 1148                         break;
 1149         }
 1150         
 1151 #if 0
 1152         /* Initialize AC-Link features */
 1153         /* variable sample-rate support */
 1154         mem = BA0READ4(sc, CS4281_SERMC);
 1155         mem |=  (SERMC_ODSEN1 | SERMC_ODSEN2);
 1156         BA0WRITE4(sc, CS4281_SERMC, mem);
 1157         /* XXX: more... */
 1158         
 1159         /* Initialize SSCR register features */
 1160         /* XXX: hardware volume setting */
 1161         BA0WRITE4(sc, CS4281_SSCR, ~SSCR_HVC); /* disable HW volume setting */
 1162 #endif
 1163 
 1164         /* disable Sound Blaster Pro emulation */
 1165         /* XXX: 
 1166          * Cannot set since the documents does not describe which bit is
 1167          * correspond to SSCR_SB. Since the reset value of SSCR is 0,
 1168          * we can ignore it.*/
 1169 #if 0
 1170         BA0WRITE4(sc, CS4281_SSCR, SSCR_SB);
 1171 #endif
 1172 
 1173         /* map AC97 PCM playback to DMA Channel 0 */
 1174         /* Reset FEN bit to setup first */
 1175         BA0WRITE4(sc, CS4281_FCR0, (BA0READ4(sc, CS4281_FCR0) & ~FCRn_FEN));
 1176         /*
 1177          *| RS[4:0]/|        |
 1178          *| LS[4:0] |  AC97  | Slot Function
 1179          *|---------+--------+--------------------
 1180          *|     0   |    3   | Left PCM Playback
 1181          *|     1   |    4   | Right PCM Playback
 1182          *|     2   |    5   | Phone Line 1 DAC
 1183          *|     3   |    6   | Center PCM Playback
 1184          *....
 1185          *  quoted from Table 29(p109)
 1186          */
 1187         dat32 = 0x01 << 24 |   /* RS[4:0] =  1 see above */
 1188                 0x00 << 16 |   /* LS[4:0] =  0 see above */
 1189                 0x0f <<  8 |   /* SZ[6:0] = 15 size of buffer */
 1190                 0x00 <<  0 ;   /* OF[6:0] =  0 offset */
 1191         BA0WRITE4(sc, CS4281_FCR0, dat32);
 1192         BA0WRITE4(sc, CS4281_FCR0, dat32 | FCRn_FEN);
 1193 
 1194         /* map AC97 PCM record to DMA Channel 1 */
 1195         /* Reset FEN bit to setup first */
 1196         BA0WRITE4(sc, CS4281_FCR1, (BA0READ4(sc, CS4281_FCR1) & ~FCRn_FEN));
 1197         /*
 1198          *| RS[4:0]/|
 1199          *| LS[4:0] | AC97 | Slot Function
 1200          *|---------+------+-------------------
 1201          *|   10    |   3  | Left PCM Record
 1202          *|   11    |   4  | Right PCM Record
 1203          *|   12    |   5  | Phone Line 1 ADC
 1204          *|   13    |   6  | Mic ADC
 1205          *....
 1206          * quoted from Table 30(p109)
 1207          */
 1208         dat32 = 0x0b << 24 |    /* RS[4:0] = 11 See above */
 1209                 0x0a << 16 |    /* LS[4:0] = 10 See above */
 1210                 0x0f <<  8 |    /* SZ[6:0] = 15 Size of buffer */
 1211                 0x10 <<  0 ;    /* OF[6:0] = 16 offset */
 1212 
 1213         /* XXX: I cannot understand why FCRn_PSH is needed here. */
 1214         BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_PSH);
 1215         BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_FEN);
 1216 
 1217 #if 0
 1218         /* Disable DMA Channel 2, 3 */
 1219         BA0WRITE4(sc, CS4281_FCR2, (BA0READ4(sc, CS4281_FCR2) & ~FCRn_FEN));
 1220         BA0WRITE4(sc, CS4281_FCR3, (BA0READ4(sc, CS4281_FCR3) & ~FCRn_FEN));
 1221 #endif
 1222 
 1223         /* Set the SRC Slot Assignment accordingly */
 1224         /*| PLSS[4:0]/
 1225          *| PRSS[4:0] | AC97 | Slot Function
 1226          *|-----------+------+----------------
 1227          *|     0     |  3   | Left PCM Playback
 1228          *|     1     |  4   | Right PCM Playback
 1229          *|     2     |  5   | phone line 1 DAC
 1230          *|     3     |  6   | Center PCM Playback
 1231          *|     4     |  7   | Left Surround PCM Playback
 1232          *|     5     |  8   | Right Surround PCM Playback
 1233          *......
 1234          *
 1235          *| CLSS[4:0]/
 1236          *| CRSS[4:0] | AC97 | Codec |Slot Function
 1237          *|-----------+------+-------+-----------------
 1238          *|    10     |   3  |Primary| Left PCM Record
 1239          *|    11     |   4  |Primary| Right PCM Record
 1240          *|    12     |   5  |Primary| Phone Line 1 ADC
 1241          *|    13     |   6  |Primary| Mic ADC
 1242          *|.....
 1243          *|    20     |   3  |  Sec. | Left PCM Record
 1244          *|    21     |   4  |  Sec. | Right PCM Record
 1245          *|    22     |   5  |  Sec. | Phone Line 1 ADC
 1246          *|    23     |   6  |  Sec. | Mic ADC
 1247          */
 1248         dat32 = 0x0b << 24 |   /* CRSS[4:0] Right PCM Record(primary) */
 1249                 0x0a << 16 |   /* CLSS[4:0] Left  PCM Record(primary) */
 1250                 0x01 <<  8 |   /* PRSS[4:0] Right PCM Playback */
 1251                 0x00 <<  0;    /* PLSS[4:0] Left  PCM Playback */
 1252         BA0WRITE4(sc, CS4281_SRCSA, dat32);
 1253         
 1254         /* Set interrupt to occurred at Half and Full terminal
 1255          * count interrupt enable for DMA channel 0 and 1.
 1256          * To keep DMA stop, set MSK.
 1257          */
 1258         dat32 = DCRn_HTCIE | DCRn_TCIE | DCRn_MSK;
 1259         BA0WRITE4(sc, CS4281_DCR0, dat32);
 1260         BA0WRITE4(sc, CS4281_DCR1, dat32);
 1261         
 1262         /* Set Auto-Initialize Contorl enable */
 1263         BA0WRITE4(sc, CS4281_DMR0,
 1264                   DMRn_DMA | DMRn_AUTO | DMRn_TR_READ);
 1265         BA0WRITE4(sc, CS4281_DMR1,
 1266                   DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE);
 1267 
 1268         /* Clear DMA Mask in HIMR */
 1269         dat32 = ~HIMR_DMAIM & ~HIMR_D1IM & ~HIMR_D0IM;
 1270         BA0WRITE4(sc, CS4281_HIMR,
 1271                   BA0READ4(sc, CS4281_HIMR) & dat32);
 1272 
 1273         /* set current status */
 1274         if (init != 0) {
 1275                 sc->sc_prun = 0;
 1276                 sc->sc_rrun = 0;
 1277         }
 1278 
 1279         /* setup playback volume */
 1280         BA0WRITE4(sc, CS4281_PPRVC, 7);
 1281         BA0WRITE4(sc, CS4281_PPLVC, 7);
 1282 
 1283         return 0;
 1284 }

Cache object: 53df822bb3c3c84b565f5dd85ea23619


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.