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

          Line data    Source code
       1             : /*      $OpenBSD: cs4280.c,v 1.52 2018/09/03 05:37:32 miko Exp $        */
       2             : /*      $NetBSD: cs4280.c,v 1.5 2000/06/26 04:56:23 simonb Exp $        */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1999, 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 CS4280 (and maybe CS461x) driver.
      36             :  * Data sheets can be found
      37             :  * http://www.cirrus.com/ftp/pubs/4280.pdf
      38             :  * http://www.cirrus.com/ftp/pubs/4297.pdf
      39             :  * ftp://ftp.alsa-project.org/pub/manuals/cirrus/embedded_audio_spec.pdf
      40             :  * ftp://ftp.alsa-project.org/pub/manuals/cirrus/embedded_audio_spec.doc
      41             :  */
      42             : 
      43             : /*
      44             :  * TODO
      45             :  * Implement MIDI
      46             :  * Joystick support
      47             :  */
      48             : 
      49             : #ifdef CS4280_DEBUG
      50             : #ifndef MIDI_READY
      51             : #define MIDI_READY
      52             : #endif /* ! MIDI_READY */
      53             : #endif
      54             : 
      55             : #ifdef MIDI_READY
      56             : #include "midi.h"
      57             : #endif
      58             : 
      59             : #if defined(CS4280_DEBUG)
      60             : #define DPRINTF(x)          if (cs4280debug) printf x
      61             : #define DPRINTFN(n,x)       if (cs4280debug>(n)) printf x
      62             : int cs4280debug = 0;
      63             : #else
      64             : #define DPRINTF(x)
      65             : #define DPRINTFN(n,x)
      66             : #endif
      67             : 
      68             : #include <sys/param.h>
      69             : #include <sys/systm.h>
      70             : #include <sys/kernel.h>
      71             : #include <sys/fcntl.h>
      72             : #include <sys/malloc.h>
      73             : #include <sys/device.h>
      74             : 
      75             : #include <dev/pci/pcidevs.h>
      76             : #include <dev/pci/pcivar.h>
      77             : #include <dev/pci/cs4280reg.h>
      78             : 
      79             : #include <sys/audioio.h>
      80             : #include <dev/audio_if.h>
      81             : 
      82             : #include <dev/ic/ac97.h>
      83             : 
      84             : #include <machine/bus.h>
      85             : 
      86             : #define CSCC_PCI_BA0 0x10
      87             : #define CSCC_PCI_BA1 0x14
      88             : 
      89             : struct cs4280_dma {
      90             :         bus_dmamap_t map;
      91             :         caddr_t addr;           /* real dma buffer */
      92             :         caddr_t dum;            /* dummy buffer for audio driver */
      93             :         bus_dma_segment_t segs[1];
      94             :         int nsegs;
      95             :         size_t size;
      96             :         struct cs4280_dma *next;
      97             : };
      98             : #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
      99             : #define BUFADDR(p)  ((void *)((p)->dum))
     100             : #define KERNADDR(p) ((void *)((p)->addr))
     101             : 
     102             : /*
     103             :  * Software state
     104             :  */
     105             : struct cs4280_softc {
     106             :         struct device         sc_dev;
     107             : 
     108             :         pci_intr_handle_t *   sc_ih;
     109             : 
     110             :         /* I/O (BA0) */
     111             :         bus_space_tag_t       ba0t;
     112             :         bus_space_handle_t    ba0h;
     113             :         
     114             :         /* BA1 */
     115             :         bus_space_tag_t       ba1t;
     116             :         bus_space_handle_t    ba1h;
     117             :         
     118             :         /* DMA */
     119             :         bus_dma_tag_t    sc_dmatag;
     120             :         struct cs4280_dma *sc_dmas;
     121             : 
     122             :         void    (*sc_pintr)(void *);    /* dma completion intr handler */
     123             :         void    *sc_parg;               /* arg for sc_intr() */
     124             :         char    *sc_ps, *sc_pe, *sc_pn;
     125             :         int     sc_pcount;
     126             :         int     sc_pi;
     127             :         struct  cs4280_dma *sc_pdma;
     128             :         char    *sc_pbuf;
     129             : #ifdef DIAGNOSTIC
     130             :         char    sc_prun;
     131             : #endif
     132             : 
     133             :         void    (*sc_rintr)(void *);    /* dma completion intr handler */
     134             :         void    *sc_rarg;               /* arg for sc_intr() */
     135             :         char    *sc_rs, *sc_re, *sc_rn;
     136             :         int     sc_rcount;
     137             :         int     sc_ri;
     138             :         struct  cs4280_dma *sc_rdma;
     139             :         char    *sc_rbuf;
     140             :         int     sc_rparam;              /* record format */
     141             : #ifdef DIAGNOSTIC
     142             :         char    sc_rrun;
     143             : #endif
     144             : 
     145             : #if NMIDI > 0
     146             :         void    (*sc_iintr)(void *, int); /* midi input ready handler */
     147             :         void    (*sc_ointr)(void *);      /* midi output ready handler */
     148             :         void    *sc_arg;
     149             : #endif
     150             : 
     151             :         u_int32_t pctl;
     152             :         u_int32_t cctl;
     153             : 
     154             :         struct ac97_codec_if *codec_if;
     155             :         struct ac97_host_if host_if;    
     156             : 
     157             :         u_int16_t  ac97_reg[CS4280_SAVE_REG_MAX + 1];   /* Save ac97 registers */
     158             : };
     159             : 
     160             : #define BA0READ4(sc, r) bus_space_read_4((sc)->ba0t, (sc)->ba0h, (r))
     161             : #define BA0WRITE4(sc, r, x) bus_space_write_4((sc)->ba0t, (sc)->ba0h, (r), (x))
     162             : #define BA1READ4(sc, r) bus_space_read_4((sc)->ba1t, (sc)->ba1h, (r))
     163             : #define BA1WRITE4(sc, r, x) bus_space_write_4((sc)->ba1t, (sc)->ba1h, (r), (x))
     164             : 
     165             : int     cs4280_match(struct device *, void *, void *);
     166             : void    cs4280_attach(struct device *, struct device *, void *);
     167             : int     cs4280_activate(struct device *, int);
     168             : void    cs4280_attachhook(struct device *);
     169             : int     cs4280_intr(void *);
     170             : void    cs4280_reset(void *);
     171             : int     cs4280_download_image(struct cs4280_softc *);
     172             : 
     173             : int cs4280_download(struct cs4280_softc *, const u_int32_t *, u_int32_t, u_int32_t);
     174             : int cs4280_allocmem(struct cs4280_softc *, size_t, size_t,
     175             :                          struct cs4280_dma *);
     176             : int cs4280_freemem(struct cs4280_softc *, struct cs4280_dma *);
     177             : 
     178             : #ifdef CS4280_DEBUG
     179             : int     cs4280_check_images(struct cs4280_softc *);
     180             : int     cs4280_checkimage(struct cs4280_softc *, u_int32_t *, u_int32_t,
     181             :                           u_int32_t);
     182             : #endif
     183             : 
     184             : struct  cfdriver clcs_cd = {
     185             :         NULL, "clcs", DV_DULL
     186             : };
     187             : 
     188             : struct cfattach clcs_ca = {
     189             :         sizeof(struct cs4280_softc), cs4280_match, cs4280_attach, NULL,
     190             :         cs4280_activate
     191             : };
     192             : 
     193             : int     cs4280_init(struct cs4280_softc *, int);
     194             : int     cs4280_init2(struct cs4280_softc *, int);
     195             : int     cs4280_open(void *, int);
     196             : void    cs4280_close(void *);
     197             : 
     198             : int     cs4280_set_params(void *, int, int, struct audio_params *, struct audio_params *);
     199             : int     cs4280_round_blocksize(void *, int);
     200             : 
     201             : int     cs4280_halt_output(void *);
     202             : int     cs4280_halt_input(void *);
     203             : 
     204             : int     cs4280_mixer_set_port(void *, mixer_ctrl_t *);
     205             : int     cs4280_mixer_get_port(void *, mixer_ctrl_t *);
     206             : int     cs4280_query_devinfo(void *addr, mixer_devinfo_t *dip);
     207             : void   *cs4280_malloc(void *, int, size_t, int, int);
     208             : void    cs4280_free(void *, void *, int);
     209             : int     cs4280_get_props(void *);
     210             : int     cs4280_trigger_output(void *, void *, void *, int, void (*)(void *),
     211             :             void *, struct audio_params *);
     212             : int     cs4280_trigger_input(void *, void *, void *, int, void (*)(void *),
     213             :             void *, struct audio_params *);
     214             : 
     215             : 
     216             : void    cs4280_set_dac_rate(struct cs4280_softc *, int );
     217             : void    cs4280_set_adc_rate(struct cs4280_softc *, int );
     218             : int     cs4280_get_portnum_by_name(struct cs4280_softc *, char *, char *,
     219             :                                          char *);
     220             : int     cs4280_src_wait(struct cs4280_softc *);
     221             : int     cs4280_attach_codec(void *sc, struct ac97_codec_if *);
     222             : int     cs4280_read_codec(void *sc, u_int8_t a, u_int16_t *d);
     223             : int     cs4280_write_codec(void *sc, u_int8_t a, u_int16_t d);
     224             : void    cs4280_reset_codec(void *sc);
     225             : 
     226             : void    cs4280_clear_fifos(struct cs4280_softc *);
     227             : 
     228             : #if NMIDI > 0
     229             : void    cs4280_midi_close(void *);
     230             : void    cs4280_midi_getinfo(void *, struct midi_info *);
     231             : int     cs4280_midi_open(void *, int, void (*)(void *, int),
     232             :             void (*)(void *), void *);
     233             : int     cs4280_midi_output(void *, int);
     234             : #endif
     235             : 
     236             : struct audio_hw_if cs4280_hw_if = {
     237             :         cs4280_open,
     238             :         cs4280_close,
     239             :         cs4280_set_params,
     240             :         cs4280_round_blocksize,
     241             :         NULL,
     242             :         NULL,
     243             :         NULL,
     244             :         NULL,
     245             :         NULL,
     246             :         cs4280_halt_output,
     247             :         cs4280_halt_input,
     248             :         NULL,
     249             :         NULL,
     250             :         cs4280_mixer_set_port,
     251             :         cs4280_mixer_get_port,
     252             :         cs4280_query_devinfo,
     253             :         cs4280_malloc,
     254             :         cs4280_free,
     255             :         NULL,
     256             :         cs4280_get_props,
     257             :         cs4280_trigger_output,
     258             :         cs4280_trigger_input
     259             : };
     260             : 
     261             : #if NMIDI > 0
     262             : struct midi_hw_if cs4280_midi_hw_if = {
     263             :         cs4280_midi_open,
     264             :         cs4280_midi_close,
     265             :         cs4280_midi_output,
     266             :         0,                      /* flush */
     267             :         cs4280_midi_getinfo,
     268             :         0,                      /* ioctl */
     269             : };
     270             : #endif
     271             : 
     272             :         
     273             : const struct pci_matchid cs4280_devices[] = {
     274             :         { PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CS4280 },
     275             :         { PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CS4610 },
     276             :         { PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CS4615 },
     277             : };
     278             : 
     279             : int
     280           0 : cs4280_match(struct device *parent, void *ma, void *aux) 
     281             : {
     282           0 :         return (pci_matchbyid((struct pci_attach_args *)aux, cs4280_devices,
     283             :             nitems(cs4280_devices)));
     284             : }
     285             : 
     286             : int
     287           0 : cs4280_read_codec(void *sc_, u_int8_t add, u_int16_t *data)
     288             : {
     289           0 :         struct cs4280_softc *sc = sc_;
     290             :         int n;
     291             :         
     292             :         DPRINTFN(5,("read_codec: add=0x%02x ", add));
     293             :         /* 
     294             :          * Make sure that there is not data sitting around from a preivous
     295             :          * uncompleted access.
     296             :          */
     297           0 :         BA0READ4(sc, CS4280_ACSDA);
     298             : 
     299             :         /* Set up AC97 control registers. */
     300           0 :         BA0WRITE4(sc, CS4280_ACCAD, add);
     301           0 :         BA0WRITE4(sc, CS4280_ACCDA, 0);
     302           0 :         BA0WRITE4(sc, CS4280_ACCTL, 
     303             :             ACCTL_RSTN | ACCTL_ESYN | ACCTL_VFRM | ACCTL_CRW  | ACCTL_DCV );
     304             : 
     305           0 :         if (cs4280_src_wait(sc) < 0) {
     306           0 :                 printf("%s: AC97 read prob. (DCV!=0) for add=0x%02x\n",
     307           0 :                        sc->sc_dev.dv_xname, add);
     308           0 :                 return (1);
     309             :         }
     310             : 
     311             :         /* wait for valid status bit is active */
     312             :         n = 0;
     313           0 :         while (!(BA0READ4(sc, CS4280_ACSTS) & ACSTS_VSTS)) {
     314           0 :                 delay(1);
     315           0 :                 while (++n > 1000) {
     316           0 :                         printf("%s: AC97 read fail (VSTS==0) for add=0x%02x\n", 
     317           0 :                                sc->sc_dev.dv_xname, add);
     318           0 :                         return (1);
     319             :                 }
     320             :         }
     321           0 :         *data = BA0READ4(sc, CS4280_ACSDA);
     322             :         DPRINTFN(5,("data=0x%04x\n", *data));
     323           0 :         return (0);
     324           0 : }
     325             : 
     326             : int
     327           0 : cs4280_write_codec(void *sc_, u_int8_t add, u_int16_t data)
     328             : {
     329           0 :         struct cs4280_softc *sc = sc_;
     330             : 
     331             :         DPRINTFN(5,("write_codec: add=0x%02x  data=0x%04x\n", add, data));
     332           0 :         BA0WRITE4(sc, CS4280_ACCAD, add);
     333           0 :         BA0WRITE4(sc, CS4280_ACCDA, data);
     334           0 :         BA0WRITE4(sc, CS4280_ACCTL, 
     335             :             ACCTL_RSTN | ACCTL_ESYN | ACCTL_VFRM | ACCTL_DCV );
     336             : 
     337           0 :         if (cs4280_src_wait(sc) < 0) {
     338           0 :                 printf("%s: AC97 write fail (DCV!=0) for add=0x%02x data="
     339           0 :                        "0x%04x\n", sc->sc_dev.dv_xname, add, data);
     340           0 :                 return (1);
     341             :         }
     342           0 :         return (0);
     343           0 : }
     344             : 
     345             : int
     346           0 : cs4280_src_wait(struct cs4280_softc *sc)
     347             : {
     348             :         int n;
     349             : 
     350             :         n = 0;
     351           0 :         while ((BA0READ4(sc, CS4280_ACCTL) & ACCTL_DCV)) {
     352           0 :                 delay(1000);
     353           0 :                 if (++n > 1000)
     354           0 :                         return (-1);
     355             :         }
     356           0 :         return (0);
     357           0 : }
     358             : 
     359             : 
     360             : void
     361           0 : cs4280_set_adc_rate(struct cs4280_softc *sc, int rate)
     362             : {
     363             :         /* calculate capture rate:
     364             :          *
     365             :          * capture_coefficient_increment = -round(rate*128*65536/48000;
     366             :          * capture_phase_increment       = floor(48000*65536*1024/rate);
     367             :          * cx = round(48000*65536*1024 - capture_phase_increment*rate);
     368             :          * cy = floor(cx/200);
     369             :          * capture_sample_rate_correction = cx - 200*cy;
     370             :          * capture_delay = ceil(24*48000/rate);
     371             :          * capture_num_triplets = floor(65536*rate/24000);
     372             :          * capture_group_length = 24000/GCD(rate, 24000);
     373             :          * where GCD means "Greatest Common Divisor".
     374             :          *
     375             :          * capture_coefficient_increment, capture_phase_increment and
     376             :          * capture_num_triplets are 32-bit signed quantities.
     377             :          * capture_sample_rate_correction and capture_group_length are
     378             :          * 16-bit signed quantities.
     379             :          * capture_delay is a 14-bit unsigned quantity.
     380             :          */
     381             :         u_int32_t cci,cpi,cnt,cx,cy,  tmp1;
     382             :         u_int16_t csrc, cgl, cdlay;
     383             :         
     384             :         /* XXX
     385             :          * Even though, embedded_audio_spec says capture rate range 11025 to
     386             :          * 48000, dhwiface.cpp says,
     387             :          *
     388             :          * "We can only decimate by up to a factor of 1/9th the hardware rate.
     389             :          *  Return an error if an attempt is made to stray outside that limit."
     390             :          *
     391             :          * so assume range as 48000/9 to 48000
     392             :          */ 
     393             : 
     394           0 :         if (rate < 8000)
     395           0 :                 rate = 8000;
     396           0 :         if (rate > 48000)
     397           0 :                 rate = 48000;
     398             : 
     399           0 :         cx = rate << 16;
     400           0 :         cci = cx / 48000;
     401           0 :         cx -= cci * 48000;
     402           0 :         cx <<= 7;
     403           0 :         cci <<= 7;
     404           0 :         cci += cx / 48000;
     405           0 :         cci = - cci;
     406             : 
     407             :         cx = 48000 << 16;
     408           0 :         cpi = cx / rate;
     409           0 :         cx -= cpi * rate;
     410           0 :         cx <<= 10;
     411           0 :         cpi <<= 10;
     412           0 :         cy = cx / rate;
     413           0 :         cpi += cy;
     414           0 :         cx -= cy * rate;
     415             : 
     416           0 :         cy   = cx / 200;
     417           0 :         csrc = cx - 200*cy;
     418             : 
     419           0 :         cdlay = ((48000 * 24) + rate - 1) / rate;
     420             : #if 0
     421             :         cdlay &= 0x3fff; /* make sure cdlay is 14-bit */
     422             : #endif
     423             : 
     424             :         cnt  = rate << 16;
     425           0 :         cnt  /= 24000;
     426             : 
     427             :         cgl = 1;
     428           0 :         for (tmp1 = 2; tmp1 <= 64; tmp1 *= 2) {
     429           0 :                 if (((rate / tmp1) * tmp1) != rate)
     430           0 :                         cgl *= 2;
     431             :         }
     432           0 :         if (((rate / 3) * 3) != rate)
     433           0 :                 cgl *= 3;
     434           0 :         for (tmp1 = 5; tmp1 <= 125; tmp1 *= 5) {
     435           0 :                 if (((rate / tmp1) * tmp1) != rate) 
     436           0 :                         cgl *= 5;
     437             :         }
     438             : #if 0
     439             :         /* XXX what manual says */
     440             :         tmp1 = BA1READ4(sc, CS4280_CSRC) & ~CSRC_MASK;
     441             :         tmp1 |= csrc<<16;
     442             :         BA1WRITE4(sc, CS4280_CSRC, tmp1);
     443             : #else
     444             :         /* suggested by cs461x.c (ALSA driver) */
     445           0 :         BA1WRITE4(sc, CS4280_CSRC, CS4280_MK_CSRC(csrc, cy));
     446             : #endif
     447             : 
     448             : #if 0
     449             :         /* I am confused.  The sample rate calculation section says
     450             :          * cci *is* 32-bit signed quantity but in the parameter description
     451             :          * section, CCI only assigned 16bit.
     452             :          * I believe size of the variable.
     453             :          */
     454             :         tmp1 = BA1READ4(sc, CS4280_CCI) & ~CCI_MASK;
     455             :         tmp1 |= cci<<16;
     456             :         BA1WRITE4(sc, CS4280_CCI, tmp1);
     457             : #else
     458           0 :         BA1WRITE4(sc, CS4280_CCI, cci);
     459             : #endif
     460             : 
     461           0 :         tmp1 = BA1READ4(sc, CS4280_CD) & ~CD_MASK;
     462           0 :         tmp1 |= cdlay <<18;
     463           0 :         BA1WRITE4(sc, CS4280_CD, tmp1);
     464             :         
     465           0 :         BA1WRITE4(sc, CS4280_CPI, cpi);
     466             :         
     467           0 :         tmp1 = BA1READ4(sc, CS4280_CGL) & ~CGL_MASK;
     468           0 :         tmp1 |= cgl;
     469           0 :         BA1WRITE4(sc, CS4280_CGL, tmp1);
     470             : 
     471           0 :         BA1WRITE4(sc, CS4280_CNT, cnt);
     472             :         
     473           0 :         tmp1 = BA1READ4(sc, CS4280_CGC) & ~CGC_MASK;
     474           0 :         tmp1 |= cgl;
     475           0 :         BA1WRITE4(sc, CS4280_CGC, tmp1);
     476           0 : }
     477             : 
     478             : void
     479           0 : cs4280_set_dac_rate(struct cs4280_softc *sc, int rate)
     480             : {
     481             :         /*
     482             :          * playback rate may range from 8000Hz to 48000Hz
     483             :          *
     484             :          * play_phase_increment = floor(rate*65536*1024/48000)
     485             :          * px = round(rate*65536*1024 - play_phase_incremnt*48000)
     486             :          * py=floor(px/200)
     487             :          * play_sample_rate_correction = px - 200*py
     488             :          *
     489             :          * play_phase_increment is a 32bit signed quantity.
     490             :          * play_sample_rate_correction is a 16bit signed quantity.
     491             :          */
     492             :         int32_t ppi;
     493             :         int16_t psrc;
     494             :         u_int32_t px, py;
     495             :         
     496           0 :         if (rate < 8000)
     497           0 :                 rate = 8000;
     498           0 :         if (rate > 48000)
     499           0 :                 rate = 48000;
     500           0 :         px = rate << 16;
     501           0 :         ppi = px/48000;
     502           0 :         px -= ppi*48000;
     503           0 :         ppi <<= 10;
     504           0 :         px  <<= 10;
     505           0 :         py  = px / 48000;
     506           0 :         ppi += py;
     507           0 :         px -= py*48000;
     508           0 :         py  = px/200;
     509           0 :         px -= py*200;
     510           0 :         psrc = px;
     511             : #if 0
     512             :         /* what manual says */
     513             :         px = BA1READ4(sc, CS4280_PSRC) & ~PSRC_MASK;
     514             :         BA1WRITE4(sc, CS4280_PSRC,
     515             :                           ( ((psrc<<16) & PSRC_MASK) | px ));
     516             : #else   
     517             :         /* suggested by cs461x.c (ALSA driver) */
     518           0 :         BA1WRITE4(sc, CS4280_PSRC, CS4280_MK_PSRC(psrc,py));
     519             : #endif
     520           0 :         BA1WRITE4(sc, CS4280_PPI, ppi);
     521           0 : }
     522             : 
     523             : void
     524           0 : cs4280_attachhook(struct device *self)
     525             : {
     526           0 :         struct cs4280_softc *sc = (struct cs4280_softc *)self;
     527           0 :         mixer_ctrl_t ctl;
     528             : 
     529             :         /* Initialization */
     530           0 :         if (cs4280_init2(sc, 1) != 0)
     531           0 :                 return;
     532             : 
     533           0 :         printf("%s: firmware loaded\n", sc->sc_dev.dv_xname);
     534             : 
     535             :         /* Turn mute off of DAC, CD and master volumes by default */
     536           0 :         ctl.type = AUDIO_MIXER_ENUM;
     537           0 :         ctl.un.ord = 0;  /* off */
     538             : 
     539           0 :         ctl.dev = cs4280_get_portnum_by_name(sc, AudioCoutputs,
     540             :                                              AudioNmaster, AudioNmute);
     541           0 :         cs4280_mixer_set_port(sc, &ctl);
     542             : 
     543           0 :         ctl.dev = cs4280_get_portnum_by_name(sc, AudioCinputs,
     544             :                                              AudioNdac, AudioNmute);
     545           0 :         cs4280_mixer_set_port(sc, &ctl);
     546             : 
     547           0 :         ctl.dev = cs4280_get_portnum_by_name(sc, AudioCinputs,
     548             :                                              AudioNcd, AudioNmute);
     549           0 :         cs4280_mixer_set_port(sc, &ctl);
     550             : 
     551           0 :         audio_attach_mi(&cs4280_hw_if, sc, &sc->sc_dev);
     552             : 
     553             : #if NMIDI > 0
     554             :         midi_attach_mi(&cs4280_midi_hw_if, sc, &sc->sc_dev);
     555             : #endif
     556           0 : }
     557             : 
     558             : void
     559           0 : cs4280_attach(struct device *parent, struct device *self, void *aux)
     560             : {
     561           0 :         struct cs4280_softc *sc = (struct cs4280_softc *) self;
     562           0 :         struct pci_attach_args *pa = (struct pci_attach_args *) aux;
     563           0 :         pci_chipset_tag_t pc = pa->pa_pc;
     564             :         char const *intrstr;
     565           0 :         pci_intr_handle_t ih;
     566             :         u_int32_t mem;
     567             :     
     568             :         /* Map I/O register */
     569           0 :         if (pci_mapreg_map(pa, CSCC_PCI_BA0, 
     570             :             PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
     571           0 :             &sc->ba0t, &sc->ba0h, NULL, NULL, 0)) {
     572           0 :                 printf(": can't map BA0 space\n");
     573           0 :                 return;
     574             :         }
     575           0 :         if (pci_mapreg_map(pa, CSCC_PCI_BA1,
     576             :             PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
     577           0 :             &sc->ba1t, &sc->ba1h, NULL, NULL, 0)) {
     578           0 :                 printf(": can't map BA1 space\n");
     579           0 :                 return;
     580             :         }
     581             : 
     582           0 :         sc->sc_dmatag = pa->pa_dmat;
     583             : 
     584             :         /* Get out of power save mode if needed. */
     585           0 :         pci_set_powerstate(pc, pa->pa_tag, PCI_PMCSR_STATE_D0);
     586             : 
     587             :         /* LATENCY_TIMER setting */
     588           0 :         mem = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
     589           0 :         if ( PCI_LATTIMER(mem) < 32 ) {
     590           0 :                 mem &= 0xffff00ff;
     591           0 :                 mem |= 0x00002000;
     592           0 :                 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, mem);
     593           0 :         }
     594             :         
     595             :         /* Map and establish the interrupt. */
     596           0 :         if (pci_intr_map(pa, &ih)) {
     597           0 :                 printf(": couldn't map interrupt\n");
     598           0 :                 return;
     599             :         }
     600           0 :         intrstr = pci_intr_string(pc, ih);
     601             : 
     602           0 :         sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE,
     603           0 :             cs4280_intr, sc, sc->sc_dev.dv_xname);
     604           0 :         if (sc->sc_ih == NULL) {
     605           0 :                 printf(": couldn't establish interrupt");
     606           0 :                 if (intrstr != NULL)
     607           0 :                         printf(" at %s", intrstr);
     608           0 :                 printf("\n");
     609           0 :                 return;
     610             :         }
     611           0 :         printf(": %s\n", intrstr);
     612             : 
     613             :         /* Initialization */
     614           0 :         if (cs4280_init(sc, 1) != 0)
     615           0 :                 return;
     616             : 
     617           0 :         config_mountroot(self, cs4280_attachhook);
     618             : 
     619             :         /* AC 97 attachement */
     620           0 :         sc->host_if.arg = sc;
     621           0 :         sc->host_if.attach = cs4280_attach_codec;
     622           0 :         sc->host_if.read   = cs4280_read_codec;
     623           0 :         sc->host_if.write  = cs4280_write_codec;
     624           0 :         sc->host_if.reset  = cs4280_reset_codec;
     625             : 
     626           0 :         if (ac97_attach(&sc->host_if) != 0) {
     627           0 :                 printf("%s: ac97_attach failed\n", sc->sc_dev.dv_xname);
     628           0 :                 return;
     629             :         }
     630           0 : }
     631             : 
     632             : int
     633           0 : cs4280_intr(void *p)
     634             : {
     635             :         /*
     636             :          * XXX
     637             :          *
     638             :          * Since CS4280 has only 4kB dma buffer and
     639             :          * interrupt occurs every 2kB block, I create dummy buffer
     640             :          * which returns to audio driver and actual dma buffer
     641             :          * using in DMA transfer.
     642             :          *
     643             :          *
     644             :          *  ring buffer in audio.c is pointed by BUFADDR
     645             :          *       <------ ring buffer size == 64kB ------>
     646             :          *       <-----> blksize == 2048*(sc->sc_[pr]count) kB 
     647             :          *      |= = = =|= = = =|= = = =|= = = =|= = = =|
     648             :          *      |       |       |       |       |       | <- call audio_intp every
     649             :          *                                                   sc->sc_[pr]_count time.
     650             :          *
     651             :          *  actual dma buffer is pointed by KERNADDR
     652             :          *       <-> dma buffer size = 4kB
     653             :          *      |= =|
     654             :          *
     655             :          *
     656             :          */
     657           0 :         struct cs4280_softc *sc = p;
     658             :         u_int32_t intr, mem;
     659             :         char * empty_dma;
     660             :         int handled = 0;
     661             : 
     662           0 :         mtx_enter(&audio_lock);
     663             :         /* grab interrupt register then clear it */
     664           0 :         intr = BA0READ4(sc, CS4280_HISR);
     665           0 :         BA0WRITE4(sc, CS4280_HICR, HICR_CHGM | HICR_IEV);
     666             : 
     667             :         /* Playback Interrupt */
     668           0 :         if (intr & HISR_PINT) {
     669             :                 handled = 1;
     670           0 :                 mem = BA1READ4(sc, CS4280_PFIE);
     671           0 :                 BA1WRITE4(sc, CS4280_PFIE, (mem & ~PFIE_PI_MASK) | PFIE_PI_DISABLE);
     672           0 :                 if (sc->sc_pintr) {
     673           0 :                         if ((sc->sc_pi%sc->sc_pcount) == 0)
     674           0 :                                 sc->sc_pintr(sc->sc_parg);
     675             :                 } else {
     676           0 :                         printf("unexpected play intr\n");
     677             :                 }
     678             :                 /* copy buffer */
     679           0 :                 ++sc->sc_pi;
     680           0 :                 empty_dma = sc->sc_pdma->addr;
     681           0 :                 if (sc->sc_pi&1)
     682           0 :                         empty_dma += CS4280_ICHUNK;
     683           0 :                 memcpy(empty_dma, sc->sc_pn, CS4280_ICHUNK);
     684           0 :                 sc->sc_pn += CS4280_ICHUNK;
     685           0 :                 if (sc->sc_pn >= sc->sc_pe)
     686           0 :                         sc->sc_pn = sc->sc_ps;
     687           0 :                 BA1WRITE4(sc, CS4280_PFIE, mem);
     688           0 :         }
     689             :         /* Capture Interrupt */
     690           0 :         if (intr & HISR_CINT) {
     691             :                 int  i;
     692             :                 int16_t rdata;
     693             : 
     694             :                 handled = 1;
     695           0 :                 mem = BA1READ4(sc, CS4280_CIE);
     696           0 :                 BA1WRITE4(sc, CS4280_CIE, (mem & ~CIE_CI_MASK) | CIE_CI_DISABLE);
     697           0 :                 ++sc->sc_ri;
     698           0 :                 empty_dma = sc->sc_rdma->addr;
     699           0 :                 if ((sc->sc_ri&1) == 0)
     700           0 :                         empty_dma += CS4280_ICHUNK;
     701             : 
     702             :                 /*
     703             :                  * XXX
     704             :                  * I think this audio data conversion should be
     705             :                  * happened in upper layer, but I put this here
     706             :                  * since there is no conversion function available.
     707             :                  */
     708           0 :                 switch(sc->sc_rparam) {
     709             :                 case CF_16BIT_STEREO:
     710             :                         /* just copy it */
     711           0 :                         memcpy(sc->sc_rn, empty_dma, CS4280_ICHUNK);
     712           0 :                         sc->sc_rn += CS4280_ICHUNK;
     713           0 :                         break;
     714             :                 case CF_16BIT_MONO:
     715           0 :                         for (i = 0; i < 512; i++) {
     716           0 :                                 rdata  = *((int16_t *)empty_dma)>>1;
     717           0 :                                 empty_dma += 2;
     718           0 :                                 rdata += *((int16_t *)empty_dma)>>1;
     719           0 :                                 empty_dma += 2;
     720           0 :                                 *((int16_t *)sc->sc_rn) = rdata;
     721           0 :                                 sc->sc_rn += 2;
     722             :                         }
     723             :                         break;
     724             :                 case CF_8BIT_STEREO:
     725           0 :                         for (i = 0; i < 512; i++) {
     726           0 :                                 rdata = *((int16_t*)empty_dma);
     727           0 :                                 empty_dma += 2;
     728           0 :                                 *sc->sc_rn++ = rdata >> 8;
     729           0 :                                 rdata = *((int16_t*)empty_dma);
     730           0 :                                 empty_dma += 2;
     731           0 :                                 *sc->sc_rn++ = rdata >> 8;
     732             :                         }
     733             :                         break;
     734             :                 case CF_8BIT_MONO:
     735           0 :                         for (i = 0; i < 512; i++) {
     736           0 :                                 rdata =  *((int16_t*)empty_dma) >>1;
     737           0 :                                 empty_dma += 2;
     738           0 :                                 rdata += *((int16_t*)empty_dma) >>1;
     739           0 :                                 empty_dma += 2;
     740           0 :                                 *sc->sc_rn++ = rdata >>8;
     741             :                         }
     742             :                         break;
     743             :                 default:
     744             :                         /* Should not reach here */
     745           0 :                         printf("unknown sc->sc_rparam: %d\n", sc->sc_rparam);
     746           0 :                 }
     747           0 :                 if (sc->sc_rn >= sc->sc_re)
     748           0 :                         sc->sc_rn = sc->sc_rs;
     749           0 :                 BA1WRITE4(sc, CS4280_CIE, mem);
     750           0 :                 if (sc->sc_rintr) {
     751           0 :                         if ((sc->sc_ri%(sc->sc_rcount)) == 0)
     752           0 :                                 sc->sc_rintr(sc->sc_rarg);
     753             :                 } else {
     754           0 :                         printf("unexpected record intr\n");
     755             :                 }
     756           0 :         }
     757             : 
     758             : #if NMIDI > 0
     759             :         /* Midi port Interrupt */
     760             :         if (intr & HISR_MIDI) {
     761             :                 int data;
     762             : 
     763             :                 handled = 1;
     764             :                 DPRINTF(("i: %d: ", 
     765             :                          BA0READ4(sc, CS4280_MIDSR)));
     766             :                 /* Read the received data */
     767             :                 while ((sc->sc_iintr != NULL) &&
     768             :                        ((BA0READ4(sc, CS4280_MIDSR) & MIDSR_RBE) == 0)) {
     769             :                         data = BA0READ4(sc, CS4280_MIDRP) & MIDRP_MASK;
     770             :                         DPRINTF(("r:%x\n",data));
     771             :                         sc->sc_iintr(sc->sc_arg, data);
     772             :                 }
     773             :                 
     774             :                 /* Write the data */
     775             : #if 1
     776             :                 /* XXX:
     777             :                  * It seems "Transmit Buffer Full" never activate until EOI
     778             :                  * is delivered.  Shall I throw EOI top of this routine ?
     779             :                  */
     780             :                 if ((BA0READ4(sc, CS4280_MIDSR) & MIDSR_TBF) == 0) {
     781             :                         DPRINTF(("w: "));
     782             :                         if (sc->sc_ointr != NULL)
     783             :                                 sc->sc_ointr(sc->sc_arg);
     784             :                 }
     785             : #else
     786             :                 while ((sc->sc_ointr != NULL) && 
     787             :                        ((BA0READ4(sc, CS4280_MIDSR) & MIDSR_TBF) == 0)) {
     788             :                         DPRINTF(("w: "));
     789             :                         sc->sc_ointr(sc->sc_arg);
     790             :                 }
     791             : #endif
     792             :                 DPRINTF(("\n"));
     793             :         }
     794             : #endif
     795           0 :         mtx_leave(&audio_lock);
     796           0 :         return handled;
     797             : }
     798             : 
     799             : 
     800             : /* Download Proceessor Code and Data image */
     801             : 
     802             : int
     803           0 : cs4280_download(struct cs4280_softc *sc, const u_int32_t *src, u_int32_t offset,
     804             :     u_int32_t len)
     805             : {
     806             :         u_int32_t ctr;
     807             : 
     808             : #ifdef CS4280_DEBUG
     809             :         u_int32_t con, data;
     810             :         u_int8_t c0,c1,c2,c3;
     811             : #endif
     812           0 :         if ((offset&3) || (len&3))
     813           0 :                 return (-1);
     814             : 
     815           0 :         len /= sizeof(u_int32_t);
     816           0 :         for (ctr = 0; ctr < len; ctr++) {
     817             :                 /* XXX:
     818             :                  * I cannot confirm this is the right thing or not
     819             :                  * on BIG-ENDIAN machines.
     820             :                  */
     821           0 :                 BA1WRITE4(sc, offset+ctr*4, htole32(*(src+ctr)));
     822             : #ifdef CS4280_DEBUG
     823             :                 data = htole32(*(src+ctr));
     824             :                 c0 = bus_space_read_1(sc->ba1t, sc->ba1h, offset+ctr*4+0);
     825             :                 c1 = bus_space_read_1(sc->ba1t, sc->ba1h, offset+ctr*4+1);
     826             :                 c2 = bus_space_read_1(sc->ba1t, sc->ba1h, offset+ctr*4+2);
     827             :                 c3 = bus_space_read_1(sc->ba1t, sc->ba1h, offset+ctr*4+3);
     828             :                 con = ( (c3<<24) | (c2<<16) | (c1<<8) | c0 );
     829             :                 if (data != con ) {
     830             :                         printf("0x%06x: write=0x%08x read=0x%08x\n",
     831             :                                offset+ctr*4, data, con);
     832             :                         return (-1);
     833             :                 }
     834             : #endif
     835             :         }
     836           0 :         return (0);
     837           0 : }
     838             : 
     839             : struct BA1struct *BA1Struct;
     840             : 
     841             : int
     842           0 : cs4280_download_image(struct cs4280_softc *sc)
     843             : {
     844             :         int idx, err = 0;
     845             :         u_int32_t offset = 0;
     846             :         static u_char *cs4280_firmware;
     847             :         static size_t cs4280_firmwarelen;
     848             : 
     849           0 :         if (cs4280_firmware == NULL) {
     850           0 :                 err = loadfirmware("cs4280", &cs4280_firmware,
     851             :                     &cs4280_firmwarelen);
     852           0 :                 if (err)
     853           0 :                         return (err);
     854             :         }
     855             : 
     856           0 :         BA1Struct = (struct BA1struct *)cs4280_firmware;
     857             : 
     858           0 :         for (idx = 0; idx < BA1_MEMORY_COUNT; ++idx) {
     859           0 :                 err = cs4280_download(sc, &BA1Struct->map[offset],
     860           0 :                     BA1Struct->memory[idx].offset, BA1Struct->memory[idx].size);
     861           0 :                 if (err != 0) {
     862           0 :                         printf("%s: load_image failed at %d\n",
     863           0 :                                sc->sc_dev.dv_xname, idx);
     864           0 :                         return (-1);
     865             :                 }
     866           0 :                 offset += BA1Struct->memory[idx].size / sizeof(u_int32_t);
     867             :         }
     868           0 :         return (err);
     869           0 : }
     870             : 
     871             : #ifdef CS4280_DEBUG
     872             : int
     873             : cs4280_checkimage(struct cs4280_softc *sc, u_int32_t *src, u_int32_t offset,
     874             :     u_int32_t len)
     875             : {
     876             :         u_int32_t ctr, data;
     877             :         int err = 0;
     878             : 
     879             :         if ((offset&3) || (len&3))
     880             :                 return -1;
     881             : 
     882             :         len /= sizeof(u_int32_t);
     883             :         for (ctr = 0; ctr < len; ctr++) {
     884             :                 /* I cannot confirm this is the right thing
     885             :                  * on BIG-ENDIAN machines
     886             :                  */
     887             :                 data = BA1READ4(sc, offset+ctr*4);
     888             :                 if (data != htole32(*(src+ctr))) {
     889             :                         printf("0x%06x: 0x%08x(0x%08x)\n",
     890             :                                offset+ctr*4, data, *(src+ctr));
     891             :                         *(src+ctr) = data;
     892             :                         ++err;
     893             :                 }
     894             :         }
     895             :         return (err);
     896             : }
     897             : 
     898             : int
     899             : cs4280_check_images(struct cs4280_softc *sc)
     900             : {
     901             :         int idx, err;
     902             :         u_int32_t offset = 0;
     903             : 
     904             :         err = 0;
     905             :         /*for (idx=0; idx < BA1_MEMORY_COUNT; ++idx) { */
     906             :         for (idx = 0; idx < 1; ++idx) {
     907             :                 err = cs4280_checkimage(sc, &BA1Struct->map[offset],
     908             :                     BA1Struct->memory[idx].offset,
     909             :                     BA1Struct->memory[idx].size);
     910             :                 if (err != 0) {
     911             :                         printf("%s: check_image failed at %d\n",
     912             :                                sc->sc_dev.dv_xname, idx);
     913             :                 }
     914             :                 offset += BA1Struct->memory[idx].size / sizeof(u_int32_t);
     915             :         }
     916             :         return (err);
     917             : }
     918             : 
     919             : #endif
     920             : 
     921             : int
     922           0 : cs4280_attach_codec(void *sc_, struct ac97_codec_if *codec_if)
     923             : {
     924           0 :         struct cs4280_softc *sc = sc_;
     925             : 
     926           0 :         sc->codec_if = codec_if;
     927           0 :         return (0);
     928             : }
     929             : 
     930             : void
     931           0 : cs4280_reset_codec(void *sc_)
     932             : {
     933           0 :         struct cs4280_softc *sc = sc_;
     934             :         int n;
     935             : 
     936             :         /* Reset codec */
     937           0 :         BA0WRITE4(sc, CS4280_ACCTL, 0);
     938           0 :         delay(100);    /* delay 100us */
     939           0 :         BA0WRITE4(sc, CS4280_ACCTL, ACCTL_RSTN);
     940             : 
     941             :         /* 
     942             :          * It looks like we do the following procedure, too
     943             :          */
     944             : 
     945             :         /* Enable AC-link sync generation */
     946           0 :         BA0WRITE4(sc, CS4280_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
     947           0 :         delay(50*1000); /* XXX delay 50ms */
     948             :         
     949             :         /* Assert valid frame signal */
     950           0 :         BA0WRITE4(sc, CS4280_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
     951             : 
     952             :         /* Wait for valid AC97 input slot */
     953             :         n = 0;
     954           0 :         while (BA0READ4(sc, CS4280_ACISV) != (ACISV_ISV3 | ACISV_ISV4)) {
     955           0 :                 delay(1000);
     956           0 :                 if (++n > 1000) {
     957           0 :                         printf("reset_codec: AC97 inputs slot ready timeout\n");
     958           0 :                         return;
     959             :                 }
     960             :         }
     961           0 : }
     962             : 
     963             : 
     964             : /* Processor Soft Reset */
     965             : void
     966           0 : cs4280_reset(void *sc_)
     967             : {
     968           0 :         struct cs4280_softc *sc = sc_;
     969             : 
     970             :         /* Set RSTSP bit in SPCR (also clear RUN, RUNFR, and DRQEN) */
     971           0 :         BA1WRITE4(sc, CS4280_SPCR, SPCR_RSTSP);
     972           0 :         delay(100);
     973             :         /* Clear RSTSP bit in SPCR */
     974           0 :         BA1WRITE4(sc, CS4280_SPCR, 0);
     975             :         /* enable DMA reqest */
     976           0 :         BA1WRITE4(sc, CS4280_SPCR, SPCR_DRQEN);
     977           0 : }
     978             : 
     979             : int
     980           0 : cs4280_open(void *addr, int flags)
     981             : {
     982           0 :         return (0);
     983             : }
     984             : 
     985             : void
     986           0 : cs4280_close(void *addr)
     987             : {
     988           0 :         struct cs4280_softc *sc = addr;
     989             :         
     990             :         /* XXX: already called in audio_close() */
     991           0 :         cs4280_halt_output(sc);
     992           0 :         cs4280_halt_input(sc);
     993             :         
     994           0 :         sc->sc_pintr = 0;
     995           0 :         sc->sc_rintr = 0;
     996           0 : }
     997             : 
     998             : int
     999           0 : cs4280_set_params(void *addr, int setmode, int usemode,
    1000             :     struct audio_params *play, struct audio_params *rec)
    1001             : {
    1002           0 :         struct cs4280_softc *sc = addr;
    1003             :         struct audio_params *p;
    1004             :         int mode;
    1005             : 
    1006           0 :         for (mode = AUMODE_RECORD; mode != -1;
    1007           0 :             mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1 ) {
    1008           0 :                 if ((setmode & mode) == 0)
    1009             :                         continue;
    1010             :                 
    1011           0 :                 p = mode == AUMODE_PLAY ? play : rec;           
    1012             :                 if (p == play) {
    1013             :                         DPRINTFN(5,("play: sample=%ld precision=%d channels=%d\n",
    1014             :                                 p->sample_rate, p->precision, p->channels));
    1015             :                 } else {
    1016             :                         DPRINTFN(5,("rec: sample=%ld precision=%d channels=%d\n",
    1017             :                                 p->sample_rate, p->precision, p->channels));
    1018             :                 }
    1019             :                 /* play back data format may be 8- or 16-bit and
    1020             :                  * either stereo or mono.
    1021             :                  * playback rate may range from 8000Hz to 48000Hz 
    1022             :                  *
    1023             :                  * capture data format must be 16bit stereo
    1024             :                  * and sample rate range from 11025Hz to 48000Hz.
    1025             :                  *
    1026             :                  * XXX: it looks like to work with 8000Hz,
    1027             :                  *      although data sheets say lower limit is
    1028             :                  *      11025 Hz.
    1029             :                  */
    1030           0 :                 if (p->sample_rate < 8000)
    1031           0 :                         p->sample_rate = 8000;
    1032           0 :                 if (p->sample_rate > 48000)
    1033           0 :                         p->sample_rate = 48000;
    1034           0 :                 if (p->precision > 16)
    1035           0 :                         p->precision = 16;
    1036           0 :                 if (p->channels > 2)
    1037           0 :                         p->channels = 2;
    1038             : 
    1039             :                 /* capturing data is slinear */
    1040           0 :                 switch (p->encoding) {
    1041             :                 case AUDIO_ENCODING_SLINEAR_LE:
    1042             :                         break;
    1043             :                 default:
    1044           0 :                         return (EINVAL);
    1045             :                 }
    1046           0 :                 p->bps = AUDIO_BPS(p->precision);
    1047           0 :                 p->msb = 1;
    1048           0 :         }
    1049             : 
    1050             :         /* set sample rate */
    1051           0 :         cs4280_set_dac_rate(sc, play->sample_rate);
    1052           0 :         cs4280_set_adc_rate(sc, rec->sample_rate);
    1053           0 :         return (0);
    1054           0 : }
    1055             : 
    1056             : int
    1057           0 : cs4280_round_blocksize(void *hdl, int blk)
    1058             : {
    1059           0 :         return (blk < CS4280_ICHUNK ? CS4280_ICHUNK : blk & -CS4280_ICHUNK);
    1060             : }
    1061             : 
    1062             : int
    1063           0 : cs4280_get_props(void *hdl)
    1064             : {
    1065           0 :         return (AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX); 
    1066             : #ifdef notyet
    1067             :         /* XXX 
    1068             :          * How can I mmap ?
    1069             :          */
    1070             :                 AUDIO_PROP_MMAP 
    1071             : #endif
    1072             :             
    1073             : }
    1074             : 
    1075             : int
    1076           0 : cs4280_mixer_get_port(void *addr, mixer_ctrl_t *cp)
    1077             : {
    1078           0 :         struct cs4280_softc *sc = addr;
    1079             : 
    1080           0 :         return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp));
    1081             : }
    1082             : 
    1083             : int
    1084           0 : cs4280_query_devinfo(void *addr, mixer_devinfo_t *dip)
    1085             : {
    1086           0 :         struct cs4280_softc *sc = addr;
    1087             : 
    1088           0 :         return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip));
    1089             : }
    1090             : 
    1091             : int
    1092           0 : cs4280_get_portnum_by_name(struct cs4280_softc *sc, char *class, char *device,
    1093             :     char *qualifier)
    1094             : {
    1095           0 :         return (sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if, class,
    1096             :              device, qualifier));
    1097             : }
    1098             : 
    1099             : int
    1100           0 : cs4280_halt_output(void *addr)
    1101             : {
    1102           0 :         struct cs4280_softc *sc = addr;
    1103             :         u_int32_t mem;
    1104             :         
    1105           0 :         mtx_enter(&audio_lock);
    1106           0 :         mem = BA1READ4(sc, CS4280_PCTL);
    1107           0 :         BA1WRITE4(sc, CS4280_PCTL, mem & ~PCTL_MASK);
    1108             : #ifdef DIAGNOSTIC
    1109           0 :         sc->sc_prun = 0;
    1110             : #endif
    1111           0 :         mtx_leave(&audio_lock);
    1112           0 :         return (0);
    1113             : }
    1114             : 
    1115             : int
    1116           0 : cs4280_halt_input(void *addr)
    1117             : {
    1118           0 :         struct cs4280_softc *sc = addr;
    1119             :         u_int32_t mem;
    1120             : 
    1121           0 :         mtx_enter(&audio_lock);
    1122           0 :         mem = BA1READ4(sc, CS4280_CCTL);
    1123           0 :         BA1WRITE4(sc, CS4280_CCTL, mem & ~CCTL_MASK);
    1124             : #ifdef DIAGNOSTIC
    1125           0 :         sc->sc_rrun = 0;
    1126             : #endif
    1127           0 :         mtx_leave(&audio_lock);
    1128           0 :         return (0);
    1129             : }
    1130             : 
    1131             : int
    1132           0 : cs4280_mixer_set_port(void *addr, mixer_ctrl_t *cp)
    1133             : {
    1134           0 :         struct cs4280_softc *sc = addr;
    1135             :         int val;
    1136             : 
    1137           0 :         val = sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
    1138             :         DPRINTFN(3,("mixer_set_port: val=%d\n", val));
    1139           0 :         return (val);
    1140             : }
    1141             : 
    1142             : 
    1143             : int
    1144           0 : cs4280_freemem(struct cs4280_softc *sc, struct cs4280_dma *p)
    1145             : {
    1146           0 :         bus_dmamap_unload(sc->sc_dmatag, p->map);
    1147           0 :         bus_dmamap_destroy(sc->sc_dmatag, p->map);
    1148           0 :         bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
    1149           0 :         bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
    1150           0 :         return (0);
    1151             : }
    1152             : 
    1153             : int
    1154           0 : cs4280_allocmem(struct cs4280_softc *sc, size_t size, size_t align,
    1155             :     struct cs4280_dma *p)
    1156             : {
    1157             :         int error;
    1158             : 
    1159             :         /* XXX */
    1160           0 :         p->size = size;
    1161           0 :         error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
    1162             :                                  p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
    1163             :                                  &p->nsegs, BUS_DMA_NOWAIT);
    1164           0 :         if (error) {
    1165           0 :                 printf("%s: unable to allocate dma, error=%d\n",
    1166           0 :                        sc->sc_dev.dv_xname, error);
    1167           0 :                 return (error);
    1168             :         }
    1169             :         
    1170           0 :         error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size, 
    1171             :                                &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
    1172           0 :         if (error) {
    1173           0 :                 printf("%s: unable to map dma, error=%d\n",
    1174           0 :                        sc->sc_dev.dv_xname, error);
    1175           0 :                 goto free;
    1176             :         }
    1177             : 
    1178           0 :         error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
    1179             :                                   0, BUS_DMA_NOWAIT, &p->map);
    1180           0 :         if (error) {
    1181           0 :                 printf("%s: unable to create dma map, error=%d\n",
    1182           0 :                        sc->sc_dev.dv_xname, error);
    1183           0 :                 goto unmap;
    1184             :         }
    1185             : 
    1186           0 :         error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL, 
    1187             :                                 BUS_DMA_NOWAIT);
    1188           0 :         if (error) {
    1189           0 :                 printf("%s: unable to load dma map, error=%d\n",
    1190           0 :                        sc->sc_dev.dv_xname, error);
    1191             :                 goto destroy;
    1192             :         }
    1193           0 :         return (0);
    1194             : 
    1195             : destroy:
    1196           0 :         bus_dmamap_destroy(sc->sc_dmatag, p->map);
    1197             : unmap:
    1198           0 :         bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
    1199             : free:
    1200           0 :         bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
    1201           0 :         return (error);
    1202           0 : }
    1203             : 
    1204             : 
    1205             : void *
    1206           0 : cs4280_malloc(void *addr, int direction, size_t size, int pool, int flags)
    1207             : {
    1208           0 :         struct cs4280_softc *sc = addr;
    1209             :         struct cs4280_dma *p;
    1210             :         caddr_t q;
    1211             :         int error;
    1212             :         
    1213             :         DPRINTFN(5,("cs4280_malloc: size=%d pool=%d flags=%d\n", size, pool, flags));
    1214           0 :         q = malloc(size, pool, flags);
    1215           0 :         if (!q) 
    1216           0 :                 return (0);
    1217           0 :         p = malloc(sizeof(*p), pool, flags);
    1218           0 :         if (!p) {
    1219           0 :                 free(q,pool, 0);
    1220           0 :                 return (0);
    1221             :         }
    1222             :         /* 
    1223             :          * cs4280 has fixed 4kB buffer
    1224             :          */
    1225           0 :         error = cs4280_allocmem(sc, CS4280_DCHUNK, CS4280_DALIGN, p);
    1226             : 
    1227           0 :         if (error) {
    1228           0 :                 free(q, pool, 0);
    1229           0 :                 free(p, pool, 0);
    1230           0 :                 return (0);
    1231             :         }
    1232             : 
    1233           0 :         p->next = sc->sc_dmas;
    1234           0 :         sc->sc_dmas = p;
    1235           0 :         p->dum = q; /* return to audio driver */
    1236             : 
    1237           0 :         return (p->dum);
    1238           0 : }
    1239             : 
    1240             : void
    1241           0 : cs4280_free(void *addr, void *ptr, int pool)
    1242             : {
    1243           0 :         struct cs4280_softc *sc = addr;
    1244             :         struct cs4280_dma **pp, *p;
    1245             :         
    1246           0 :         for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
    1247           0 :                 if (BUFADDR(p) == ptr) {
    1248           0 :                         cs4280_freemem(sc, p);
    1249           0 :                         *pp = p->next;
    1250           0 :                         free(p->dum, pool, 0);
    1251           0 :                         free(p, pool, 0);
    1252           0 :                         return;
    1253             :                 }
    1254             :         }
    1255           0 : }
    1256             : 
    1257             : int
    1258           0 : cs4280_trigger_output(void *addr, void *start, void *end, int blksize,
    1259             :     void (*intr)(void *), void *arg, struct audio_params *param)
    1260             : {
    1261           0 :         struct cs4280_softc *sc = addr;
    1262             :         u_int32_t pfie, pctl, mem, pdtc;
    1263             :         struct cs4280_dma *p;
    1264             :         
    1265             : #ifdef DIAGNOSTIC
    1266           0 :         if (sc->sc_prun)
    1267           0 :                 printf("cs4280_trigger_output: already running\n");
    1268           0 :         sc->sc_prun = 1;
    1269             : #endif
    1270             :         DPRINTF(("cs4280_trigger_output: sc=%p start=%p end=%p "
    1271             :             "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
    1272           0 :         sc->sc_pintr = intr;
    1273           0 :         sc->sc_parg  = arg;
    1274             : 
    1275             :         /* stop playback DMA */
    1276           0 :         mem = BA1READ4(sc, CS4280_PCTL);
    1277           0 :         BA1WRITE4(sc, CS4280_PCTL, mem & ~PCTL_MASK);
    1278             : 
    1279             :         /* setup PDTC */
    1280           0 :         pdtc = BA1READ4(sc, CS4280_PDTC);
    1281           0 :         pdtc &= ~PDTC_MASK;
    1282           0 :         pdtc |= CS4280_MK_PDTC(param->precision * param->channels);
    1283           0 :         BA1WRITE4(sc, CS4280_PDTC, pdtc);
    1284             :         
    1285             :         DPRINTF(("param: precision=%d  channels=%d encoding=%d\n",
    1286             :                param->precision, param->channels,
    1287             :                param->encoding));
    1288           0 :         for (p = sc->sc_dmas; p != NULL && BUFADDR(p) != start; p = p->next)
    1289             :                 ;
    1290           0 :         if (p == NULL) {
    1291           0 :                 printf("cs4280_trigger_output: bad addr %p\n", start);
    1292           0 :                 return (EINVAL);
    1293             :         }
    1294           0 :         if (DMAADDR(p) % CS4280_DALIGN != 0 ) {
    1295           0 :                 printf("cs4280_trigger_output: DMAADDR(p)=0x%lx does not start"
    1296             :                        "4kB align\n", DMAADDR(p));
    1297           0 :                 return (EINVAL);
    1298             :         }
    1299             : 
    1300           0 :         sc->sc_pcount = blksize / CS4280_ICHUNK; /* CS4280_ICHUNK is fixed hardware blksize*/
    1301           0 :         sc->sc_ps = (char *)start;
    1302           0 :         sc->sc_pe = (char *)end;
    1303           0 :         sc->sc_pdma = p;
    1304           0 :         sc->sc_pbuf = KERNADDR(p);
    1305           0 :         sc->sc_pi = 0;
    1306           0 :         sc->sc_pn = sc->sc_ps;
    1307           0 :         if (blksize >= CS4280_DCHUNK) {
    1308           0 :                 sc->sc_pn = sc->sc_ps + CS4280_DCHUNK;
    1309           0 :                 memcpy(sc->sc_pbuf, start, CS4280_DCHUNK);
    1310           0 :                 ++sc->sc_pi;
    1311           0 :         } else {
    1312           0 :                 sc->sc_pn = sc->sc_ps + CS4280_ICHUNK;
    1313           0 :                 memcpy(sc->sc_pbuf, start, CS4280_ICHUNK);
    1314             :         }
    1315             : 
    1316             :         /* initiate playback dma */
    1317           0 :         mtx_enter(&audio_lock);
    1318           0 :         BA1WRITE4(sc, CS4280_PBA, DMAADDR(p));
    1319             : 
    1320             :         /* set PFIE */
    1321           0 :         pfie = BA1READ4(sc, CS4280_PFIE) & ~PFIE_MASK;
    1322             : 
    1323           0 :         if (param->precision == 8)
    1324           0 :                 pfie |= PFIE_8BIT;
    1325           0 :         if (param->channels == 1)
    1326           0 :                 pfie |= PFIE_MONO;
    1327             : 
    1328           0 :         if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
    1329           0 :             param->encoding == AUDIO_ENCODING_SLINEAR_BE)
    1330           0 :                 pfie |= PFIE_SWAPPED;
    1331           0 :         if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
    1332           0 :             param->encoding == AUDIO_ENCODING_ULINEAR_LE)
    1333           0 :                 pfie |= PFIE_UNSIGNED;
    1334             : 
    1335           0 :         BA1WRITE4(sc, CS4280_PFIE, pfie | PFIE_PI_ENABLE);
    1336             : 
    1337           0 :         cs4280_set_dac_rate(sc, param->sample_rate);
    1338             : 
    1339           0 :         pctl = BA1READ4(sc, CS4280_PCTL) & ~PCTL_MASK;
    1340           0 :         pctl |= sc->pctl;
    1341           0 :         BA1WRITE4(sc, CS4280_PCTL, pctl);
    1342           0 :         mtx_leave(&audio_lock);
    1343           0 :         return (0);
    1344           0 : }
    1345             : 
    1346             : int
    1347           0 : cs4280_trigger_input(void *addr, void *start, void *end, int blksize,
    1348             :     void (*intr)(void *), void *arg, struct audio_params *param)
    1349             : {
    1350           0 :         struct cs4280_softc *sc = addr;
    1351             :         u_int32_t cctl, cie;
    1352             :         struct cs4280_dma *p;
    1353             :         
    1354             : #ifdef DIAGNOSTIC
    1355           0 :         if (sc->sc_rrun)
    1356           0 :                 printf("cs4280_trigger_input: already running\n");
    1357           0 :         sc->sc_rrun = 1;
    1358             : #endif
    1359             :         DPRINTF(("cs4280_trigger_input: sc=%p start=%p end=%p "
    1360             :             "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
    1361           0 :         sc->sc_rintr = intr;
    1362           0 :         sc->sc_rarg  = arg;
    1363             : 
    1364           0 :         sc->sc_ri = 0;
    1365           0 :         sc->sc_rcount = blksize / CS4280_ICHUNK; /* CS4280_ICHUNK is fixed hardware blksize*/
    1366           0 :         sc->sc_rs = (char *)start;
    1367           0 :         sc->sc_re = (char *)end;
    1368           0 :         sc->sc_rn = sc->sc_rs;
    1369             : 
    1370             :         /* setup format information for internal converter */
    1371           0 :         sc->sc_rparam = 0;
    1372           0 :         if (param->precision == 8) {
    1373           0 :                 sc->sc_rparam += CF_8BIT;
    1374           0 :                 sc->sc_rcount <<= 1;
    1375           0 :         }
    1376           0 :         if (param->channels  == 1) {
    1377           0 :                 sc->sc_rparam += CF_MONO;
    1378           0 :                 sc->sc_rcount <<= 1;
    1379           0 :         }
    1380             : 
    1381             :         /* stop capture DMA */
    1382           0 :         cctl = BA1READ4(sc, CS4280_CCTL) & ~CCTL_MASK;
    1383           0 :         BA1WRITE4(sc, CS4280_CCTL, cctl);
    1384             :         
    1385           0 :         for (p = sc->sc_dmas; p && BUFADDR(p) != start; p = p->next)
    1386             :                 ;
    1387           0 :         if (!p) {
    1388           0 :                 printf("cs4280_trigger_input: bad addr %p\n", start);
    1389           0 :                 return (EINVAL);
    1390             :         }
    1391           0 :         if (DMAADDR(p) % CS4280_DALIGN != 0) {
    1392           0 :                 printf("cs4280_trigger_input: DMAADDR(p)=0x%lx does not start"
    1393             :                        "4kB align\n", DMAADDR(p));
    1394           0 :                 return (EINVAL);
    1395             :         }
    1396           0 :         sc->sc_rdma = p;
    1397           0 :         sc->sc_rbuf = KERNADDR(p);
    1398             :         
    1399             :         /* initiate capture dma */
    1400           0 :         mtx_enter(&audio_lock);
    1401           0 :         BA1WRITE4(sc, CS4280_CBA, DMAADDR(p));
    1402             : 
    1403             :         /* set CIE */
    1404           0 :         cie = BA1READ4(sc, CS4280_CIE) & ~CIE_CI_MASK;
    1405           0 :         BA1WRITE4(sc, CS4280_CIE, cie | CIE_CI_ENABLE);
    1406             : 
    1407           0 :         cs4280_set_adc_rate(sc, param->sample_rate);
    1408             : 
    1409           0 :         cctl = BA1READ4(sc, CS4280_CCTL) & ~CCTL_MASK;
    1410           0 :         cctl |= sc->cctl;
    1411           0 :         BA1WRITE4(sc, CS4280_CCTL, cctl);
    1412           0 :         mtx_leave(&audio_lock);
    1413           0 :         return (0);
    1414           0 : }
    1415             : 
    1416             : 
    1417             : int
    1418           0 : cs4280_init(struct cs4280_softc *sc, int init)
    1419             : {
    1420             :         int n;
    1421             :         u_int32_t mem;
    1422             : 
    1423             :         /* Start PLL out in known state */
    1424           0 :         BA0WRITE4(sc, CS4280_CLKCR1, 0);
    1425             :         /* Start serial ports out in known state */
    1426           0 :         BA0WRITE4(sc, CS4280_SERMC1, 0);
    1427             : 
    1428             :         /* Specify type of CODEC */
    1429             : /* XXX should no be here */
    1430             : #define SERACC_CODEC_TYPE_1_03
    1431             : #ifdef  SERACC_CODEC_TYPE_1_03
    1432           0 :         BA0WRITE4(sc, CS4280_SERACC, SERACC_HSP | SERACC_CTYPE_1_03); /* AC 97 1.03 */
    1433             : #else
    1434             :         BA0WRITE4(sc, CS4280_SERACC, SERACC_HSP | SERACC_CTYPE_2_0);  /* AC 97 2.0 */
    1435             : #endif
    1436             : 
    1437             :         /* Reset codec */
    1438           0 :         BA0WRITE4(sc, CS4280_ACCTL, 0);
    1439           0 :         delay(100);    /* delay 100us */
    1440           0 :         BA0WRITE4(sc, CS4280_ACCTL, ACCTL_RSTN);
    1441             :         
    1442             :         /* Enable AC-link sync generation */
    1443           0 :         BA0WRITE4(sc, CS4280_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
    1444           0 :         delay(50*1000); /* delay 50ms */
    1445             : 
    1446             :         /* Set the serial port timing configuration */
    1447           0 :         BA0WRITE4(sc, CS4280_SERMC1, SERMC1_PTC_AC97);
    1448             :         
    1449             :         /* Setup clock control */
    1450           0 :         BA0WRITE4(sc, CS4280_PLLCC, PLLCC_CDR_STATE|PLLCC_LPF_STATE);
    1451           0 :         BA0WRITE4(sc, CS4280_PLLM, PLLM_STATE);
    1452           0 :         BA0WRITE4(sc, CS4280_CLKCR2, CLKCR2_PDIVS_8);
    1453             :         
    1454             :         /* Power up the PLL */
    1455           0 :         BA0WRITE4(sc, CS4280_CLKCR1, CLKCR1_PLLP);
    1456           0 :         delay(50*1000); /* delay 50ms */
    1457             :         
    1458             :         /* Turn on clock */
    1459           0 :         mem = BA0READ4(sc, CS4280_CLKCR1) | CLKCR1_SWCE;
    1460           0 :         BA0WRITE4(sc, CS4280_CLKCR1, mem);
    1461             :         
    1462             :         /* Set the serial port FIFO pointer to the
    1463             :          * first sample in FIFO. (not documented) */
    1464           0 :         cs4280_clear_fifos(sc);
    1465             : 
    1466             : #if 0
    1467             :         /* Set the serial port FIFO pointer to the first sample in the FIFO */
    1468             :         BA0WRITE4(sc, CS4280_SERBSP, 0);
    1469             : #endif
    1470             :         
    1471             :         /* Configure the serial port */
    1472           0 :         BA0WRITE4(sc, CS4280_SERC1,  SERC1_SO1EN | SERC1_SO1F_AC97);
    1473           0 :         BA0WRITE4(sc, CS4280_SERC2,  SERC2_SI1EN | SERC2_SI1F_AC97);
    1474           0 :         BA0WRITE4(sc, CS4280_SERMC1, SERMC1_MSPE | SERMC1_PTC_AC97);
    1475             :         
    1476             :         /* Wait for CODEC ready */
    1477             :         n = 0;
    1478           0 :         while ((BA0READ4(sc, CS4280_ACSTS) & ACSTS_CRDY) == 0) {
    1479           0 :                 delay(125);
    1480           0 :                 if (++n > 1000) {
    1481           0 :                         printf("%s: codec ready timeout\n",
    1482           0 :                                sc->sc_dev.dv_xname);
    1483           0 :                         return(1);
    1484             :                 }
    1485             :         }
    1486             : 
    1487             :         /* Assert valid frame signal */
    1488           0 :         BA0WRITE4(sc, CS4280_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
    1489             : 
    1490             :         /* Wait for valid AC97 input slot */
    1491             :         n = 0;
    1492           0 :         while ((BA0READ4(sc, CS4280_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) !=
    1493             :                (ACISV_ISV3 | ACISV_ISV4)) {
    1494           0 :                 delay(1000);
    1495           0 :                 if (++n > 1000) {
    1496           0 :                         printf("AC97 inputs slot ready timeout\n");
    1497           0 :                         return(1);
    1498             :                 }
    1499             :         }
    1500             :         
    1501             :         /* Set AC97 output slot valid signals */
    1502           0 :         BA0WRITE4(sc, CS4280_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
    1503             : 
    1504             :         /* reset the processor */
    1505           0 :         cs4280_reset(sc);
    1506           0 :         return (0);
    1507           0 : }
    1508             : 
    1509             : int
    1510           0 : cs4280_init2(struct cs4280_softc *sc, int init)
    1511             : {
    1512             :         int n;
    1513             :         u_int32_t mem;
    1514             : 
    1515             :         /* Download the image to the processor */
    1516           0 :         if (cs4280_download_image(sc) != 0) {
    1517           0 :                 printf("%s: image download error\n", sc->sc_dev.dv_xname);
    1518           0 :                 return(1);
    1519             :         }
    1520             : 
    1521             :         /* Save playback parameter and then write zero.
    1522             :          * this ensures that DMA doesn't immediately occur upon
    1523             :          * starting the processor core 
    1524             :          */
    1525           0 :         mem = BA1READ4(sc, CS4280_PCTL);
    1526           0 :         sc->pctl = mem & PCTL_MASK; /* save startup value */
    1527           0 :         cs4280_halt_output(sc);
    1528             :         
    1529             :         /* Save capture parameter and then write zero.
    1530             :          * this ensures that DMA doesn't immediately occur upon
    1531             :          * starting the processor core 
    1532             :          */
    1533           0 :         mem = BA1READ4(sc, CS4280_CCTL);
    1534           0 :         sc->cctl = mem & CCTL_MASK; /* save startup value */
    1535           0 :         cs4280_halt_input(sc);
    1536             : 
    1537             :         /* MSH: need to power up ADC and DAC? */
    1538             : 
    1539             :         /* Processor Startup Procedure */
    1540           0 :         BA1WRITE4(sc, CS4280_FRMT, FRMT_FTV);
    1541           0 :         BA1WRITE4(sc, CS4280_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN);
    1542             : 
    1543             :         /* Monitor RUNFR bit in SPCR for 1 to 0 transition */
    1544             :         n = 0;
    1545           0 :         while (BA1READ4(sc, CS4280_SPCR) & SPCR_RUNFR) {
    1546           0 :                 delay(10);
    1547           0 :                 if (++n > 1000) {
    1548           0 :                         printf("SPCR 1->0 transition timeout\n");
    1549           0 :                         return(1);
    1550             :                 }
    1551             :         }
    1552             :         
    1553             :         n = 0;
    1554           0 :         while (!(BA1READ4(sc, CS4280_SPCS) & SPCS_SPRUN)) {
    1555           0 :                 delay(10);
    1556           0 :                 if (++n > 1000) {
    1557           0 :                         printf("SPCS 0->1 transition timeout\n");
    1558           0 :                         return(1);
    1559             :                 }
    1560             :         }
    1561             :         /* Processor is now running !!! */
    1562             : 
    1563             :         /* Setup  volume */
    1564           0 :         BA1WRITE4(sc, CS4280_PVOL, 0x80008000);
    1565           0 :         BA1WRITE4(sc, CS4280_CVOL, 0x80008000);
    1566             : 
    1567             :         /* Interrupt enable */
    1568           0 :         BA0WRITE4(sc, CS4280_HICR, HICR_IEV|HICR_CHGM);
    1569             : 
    1570             :         /* playback interrupt enable */
    1571           0 :         mem = BA1READ4(sc, CS4280_PFIE) & ~PFIE_PI_MASK;
    1572             :         mem |= PFIE_PI_ENABLE;
    1573           0 :         BA1WRITE4(sc, CS4280_PFIE, mem);
    1574             :         /* capture interrupt enable */
    1575           0 :         mem = BA1READ4(sc, CS4280_CIE) & ~CIE_CI_MASK;
    1576           0 :         mem |= CIE_CI_ENABLE;
    1577           0 :         BA1WRITE4(sc, CS4280_CIE, mem);
    1578             : 
    1579             : #if NMIDI > 0
    1580             :         /* Reset midi port */
    1581             :         mem = BA0READ4(sc, CS4280_MIDCR) & ~MIDCR_MASK;
    1582             :         BA0WRITE4(sc, CS4280_MIDCR, mem | MIDCR_MRST);
    1583             :         DPRINTF(("midi reset: 0x%x\n", BA0READ4(sc, CS4280_MIDCR)));
    1584             :         /* midi interrupt enable */
    1585             :         mem |= MIDCR_TXE | MIDCR_RXE | MIDCR_RIE | MIDCR_TIE;
    1586             :         BA0WRITE4(sc, CS4280_MIDCR, mem);
    1587             : #endif
    1588           0 :         return(0);
    1589           0 : }
    1590             : 
    1591             : int
    1592           0 : cs4280_activate(struct device *self, int act)
    1593             : {
    1594           0 :         struct cs4280_softc *sc = (struct cs4280_softc *)self;
    1595             :         int rv = 0;
    1596             : 
    1597           0 :         switch (act) {
    1598             :         case DVACT_SUSPEND:
    1599             :                 /* should I powerdown here ? */
    1600           0 :                 cs4280_write_codec(sc, AC97_REG_POWER, CS4280_POWER_DOWN_ALL);
    1601           0 :                 break;
    1602             :         case DVACT_RESUME:
    1603           0 :                 cs4280_close(sc);
    1604           0 :                 cs4280_init(sc, 0);
    1605           0 :                 cs4280_init2(sc, 0);
    1606           0 :                 ac97_resume(&sc->host_if, sc->codec_if);
    1607           0 :                 rv = config_activate_children(self, act);
    1608           0 :                 break;
    1609             :         default:
    1610           0 :                 rv = config_activate_children(self, act);
    1611           0 :                 break;
    1612             :         }
    1613           0 :         return (rv);
    1614             : }
    1615             : 
    1616             : void
    1617           0 : cs4280_clear_fifos(struct cs4280_softc *sc)
    1618             : {
    1619             :         int pd = 0, cnt, n;
    1620             :         u_int32_t mem;
    1621             :         
    1622             :         /* 
    1623             :          * If device power down, power up the device and keep power down
    1624             :          * state.
    1625             :          */
    1626           0 :         mem = BA0READ4(sc, CS4280_CLKCR1);
    1627           0 :         if (!(mem & CLKCR1_SWCE)) {
    1628           0 :                 printf("cs4280_clear_fifo: power down found.\n");
    1629           0 :                 BA0WRITE4(sc, CS4280_CLKCR1, mem | CLKCR1_SWCE);
    1630             :                 pd = 1;
    1631           0 :         }
    1632           0 :         BA0WRITE4(sc, CS4280_SERBWP, 0);
    1633           0 :         for (cnt = 0; cnt < 256; cnt++) {
    1634             :                 n = 0;
    1635           0 :                 while (BA0READ4(sc, CS4280_SERBST) & SERBST_WBSY) {
    1636           0 :                         delay(1000);
    1637           0 :                         if (++n > 1000) {
    1638           0 :                                 printf("clear_fifo: fist timeout cnt=%d\n", cnt);
    1639           0 :                                 break;
    1640             :                         }
    1641             :                 }
    1642           0 :                 BA0WRITE4(sc, CS4280_SERBAD, cnt);
    1643           0 :                 BA0WRITE4(sc, CS4280_SERBCM, SERBCM_WRC);
    1644             :         }
    1645           0 :         if (pd)
    1646           0 :                 BA0WRITE4(sc, CS4280_CLKCR1, mem);
    1647           0 : }
    1648             : 
    1649             : #if NMIDI > 0
    1650             : int
    1651             : cs4280_midi_open(void *addr, int flags, void (*iintr)(void, int),
    1652             :     void (*ointr)(void *), void *arg)
    1653             : {
    1654             :         struct cs4280_softc *sc = addr;
    1655             :         u_int32_t mem;
    1656             : 
    1657             :         DPRINTF(("midi_open\n"));
    1658             :         sc->sc_iintr = iintr;
    1659             :         sc->sc_ointr = ointr;
    1660             :         sc->sc_arg = arg;
    1661             : 
    1662             :         /* midi interrupt enable */
    1663             :         mem = BA0READ4(sc, CS4280_MIDCR) & ~MIDCR_MASK;
    1664             :         mem |= MIDCR_TXE | MIDCR_RXE | MIDCR_RIE | MIDCR_TIE | MIDCR_MLB;
    1665             :         BA0WRITE4(sc, CS4280_MIDCR, mem);
    1666             : #ifdef CS4280_DEBUG
    1667             :         if (mem != BA0READ4(sc, CS4280_MIDCR)) {
    1668             :                 DPRINTF(("midi_open: MIDCR=%d\n", BA0READ4(sc, CS4280_MIDCR)));
    1669             :                 return(EINVAL);
    1670             :         }
    1671             :         DPRINTF(("MIDCR=0x%x\n", BA0READ4(sc, CS4280_MIDCR)));
    1672             : #endif
    1673             :         return (0);
    1674             : }
    1675             : 
    1676             : void
    1677             : cs4280_midi_close(void *addr)
    1678             : {
    1679             :         struct cs4280_softc *sc = addr;
    1680             :         u_int32_t mem;
    1681             :         
    1682             :         DPRINTF(("midi_close\n"));
    1683             :         mem = BA0READ4(sc, CS4280_MIDCR);
    1684             :         mem &= ~MIDCR_MASK;
    1685             :         BA0WRITE4(sc, CS4280_MIDCR, mem);
    1686             : 
    1687             :         sc->sc_iintr = 0;
    1688             :         sc->sc_ointr = 0;
    1689             : }
    1690             : 
    1691             : int
    1692             : cs4280_midi_output(void *addr, int d)
    1693             : {
    1694             :         struct cs4280_softc *sc = addr;
    1695             :         u_int32_t mem;
    1696             :         int x;
    1697             : 
    1698             :         for (x = 0; x != MIDI_BUSY_WAIT; x++) {
    1699             :                 if ((BA0READ4(sc, CS4280_MIDSR) & MIDSR_TBF) == 0) {
    1700             :                         mem = BA0READ4(sc, CS4280_MIDWP) & ~MIDWP_MASK;
    1701             :                         mem |= d & MIDWP_MASK;
    1702             :                         DPRINTFN(5,("midi_output d=0x%08x",d));
    1703             :                         BA0WRITE4(sc, CS4280_MIDWP, mem);
    1704             :                         if (mem != BA0READ4(sc, CS4280_MIDWP)) {
    1705             :                                 DPRINTF(("Bad write data: %d %d",
    1706             :                                          mem, BA0READ4(sc, CS4280_MIDWP)));
    1707             :                                 return(EIO);
    1708             :                         }
    1709             :                         return (0);
    1710             :                 }
    1711             :                 delay(MIDI_BUSY_DELAY);
    1712             :         }
    1713             :         return (EIO);
    1714             : }
    1715             : 
    1716             : void
    1717             : cs4280_midi_getinfo(void *addr, struct midi_info *mi)
    1718             : {
    1719             :         mi->name = "CS4280 MIDI UART";
    1720             :         mi->props = MIDI_PROP_CAN_INPUT | MIDI_PROP_OUT_INTR;
    1721             : }
    1722             : 
    1723             : #endif

Generated by: LCOV version 1.13