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


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

FreeBSD/Linux Kernel Cross Reference
sys/dev/sbus/cs4231_sbus.c

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

    1 /*      $NetBSD: cs4231_sbus.c,v 1.29 2003/09/10 11:45:45 uwe Exp $     */
    2 
    3 /*-
    4  * Copyright (c) 1998, 1999, 2002 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Paul Kranenburg.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: cs4231_sbus.c,v 1.29 2003/09/10 11:45:45 uwe Exp $");
   41 
   42 #include "audio.h"
   43 #if NAUDIO > 0
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/errno.h>
   48 #include <sys/device.h>
   49 #include <sys/malloc.h>
   50 
   51 #include <machine/bus.h>
   52 #include <machine/intr.h>
   53 
   54 #include <dev/sbus/sbusvar.h>
   55 
   56 #include <sys/audioio.h>
   57 #include <dev/audio_if.h>
   58 
   59 #include <dev/ic/ad1848reg.h>
   60 #include <dev/ic/cs4231reg.h>
   61 #include <dev/ic/ad1848var.h>
   62 #include <dev/ic/cs4231var.h>
   63 
   64 #include <dev/ic/apcdmareg.h>
   65 
   66 #ifdef AUDIO_DEBUG
   67 int cs4231_sbus_debug = 0;
   68 #define DPRINTF(x)      if (cs4231_sbus_debug) printf x
   69 #else
   70 #define DPRINTF(x)
   71 #endif
   72 
   73 /* where APC DMA registers are located */
   74 #define CS4231_APCDMA_OFFSET    16
   75 
   76 /* interrupt enable bits except those specific for playback/capture */
   77 #define APC_ENABLE              (APC_EI | APC_IE | APC_EIE)
   78 
   79 struct cs4231_sbus_softc {
   80         struct cs4231_softc sc_cs4231;
   81 
   82         struct sbusdev sc_sd;                   /* sbus device */
   83         bus_space_tag_t sc_bt;                  /* DMA controller tag */
   84         bus_space_handle_t sc_bh;               /* DMA controller registers */
   85 };
   86 
   87 
   88 static int      cs4231_sbus_match(struct device *, struct cfdata *, void *);
   89 static void     cs4231_sbus_attach(struct device *, struct device *, void *);
   90 
   91 CFATTACH_DECL(audiocs_sbus, sizeof(struct cs4231_sbus_softc),
   92     cs4231_sbus_match, cs4231_sbus_attach, NULL, NULL);
   93 
   94 /* audio_hw_if methods specific to apc DMA */
   95 static int      cs4231_sbus_trigger_output(void *, void *, void *, int,
   96                                            void (*)(void *), void *,
   97                                            struct audio_params *);
   98 static int      cs4231_sbus_trigger_input(void *, void *, void *, int,
   99                                           void (*)(void *), void *,
  100                                           struct audio_params *);
  101 static int      cs4231_sbus_halt_output(void *);
  102 static int      cs4231_sbus_halt_input(void *);
  103 
  104 struct audio_hw_if audiocs_sbus_hw_if = {
  105         cs4231_open,
  106         cs4231_close,
  107         NULL,                   /* drain */
  108         ad1848_query_encoding,
  109         ad1848_set_params,
  110         NULL,                   /* round_blocksize */
  111         ad1848_commit_settings,
  112         NULL,                   /* init_output */
  113         NULL,                   /* init_input */
  114         NULL,                   /* start_output */
  115         NULL,                   /* start_input */
  116         cs4231_sbus_halt_output,
  117         cs4231_sbus_halt_input,
  118         NULL,                   /* speaker_ctl */
  119         cs4231_getdev,
  120         NULL,                   /* setfd */
  121         cs4231_set_port,
  122         cs4231_get_port,
  123         cs4231_query_devinfo,
  124         cs4231_malloc,
  125         cs4231_free,
  126         NULL,                   /* round_buffersize */
  127         NULL,                   /* mappage */
  128         cs4231_get_props,
  129         cs4231_sbus_trigger_output,
  130         cs4231_sbus_trigger_input,
  131         NULL,                   /* dev_ioctl */
  132 };
  133 
  134 
  135 #ifdef AUDIO_DEBUG
  136 static void     cs4231_sbus_regdump(char *, struct cs4231_sbus_softc *);
  137 #endif
  138 
  139 static int      cs4231_sbus_intr(void *);
  140 
  141 
  142 
  143 static int
  144 cs4231_sbus_match(parent, cf, aux)
  145         struct device *parent;
  146         struct cfdata *cf;
  147         void *aux;
  148 {
  149         struct sbus_attach_args *sa = aux;
  150 
  151         return (strcmp(sa->sa_name, AUDIOCS_PROM_NAME) == 0);
  152 }
  153 
  154 
  155 static void
  156 cs4231_sbus_attach(parent, self, aux)
  157         struct device *parent, *self;
  158         void *aux;
  159 {
  160         struct cs4231_sbus_softc *sbsc = (struct cs4231_sbus_softc *)self;
  161         struct cs4231_softc *sc = &sbsc->sc_cs4231;
  162         struct sbus_attach_args *sa = aux;
  163         bus_space_handle_t bh;
  164 
  165         sbsc->sc_bt = sc->sc_bustag = sa->sa_bustag;
  166         sc->sc_dmatag = sa->sa_dmatag;
  167 
  168         /*
  169          * Map my registers in, if they aren't already in virtual
  170          * address space.
  171          */
  172         if (sa->sa_npromvaddrs) {
  173                 sbus_promaddr_to_handle(sa->sa_bustag,
  174                         sa->sa_promvaddrs[0], &bh);
  175         } else {
  176                 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
  177                         sa->sa_offset, sa->sa_size, 0, &bh) != 0) {
  178                         printf("%s @ sbus: cannot map registers\n",
  179                                 self->dv_xname);
  180                         return;
  181                 }
  182         }
  183 
  184         bus_space_subregion(sa->sa_bustag, bh, CS4231_APCDMA_OFFSET,
  185                 APC_DMA_SIZE, &sbsc->sc_bh);
  186 
  187         cs4231_common_attach(sc, bh);
  188         printf("\n");
  189 
  190         sbus_establish(&sbsc->sc_sd, &sc->sc_ad1848.sc_dev);
  191 
  192         /* Establish interrupt channel */
  193         if (sa->sa_nintr)
  194                 bus_intr_establish(sa->sa_bustag,
  195                                    sa->sa_pri, IPL_AUDIO,
  196                                    cs4231_sbus_intr, sbsc);
  197 
  198         audio_attach_mi(&audiocs_sbus_hw_if, sbsc, &sc->sc_ad1848.sc_dev);
  199 }
  200 
  201 
  202 #ifdef AUDIO_DEBUG
  203 static void
  204 cs4231_sbus_regdump(label, sc)
  205         char *label;
  206         struct cs4231_sbus_softc *sc;
  207 {
  208         char bits[128];
  209 
  210         printf("cs4231regdump(%s): regs:", label);
  211         printf("dmapva: 0x%x; ",
  212                 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_PVA));
  213         printf("dmapc: 0x%x; ",
  214                 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_PC));
  215         printf("dmapnva: 0x%x; ",
  216                 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_PNVA));
  217         printf("dmapnc: 0x%x\n",
  218                 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_PNC));
  219         printf("dmacva: 0x%x; ", 
  220                 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_CVA));
  221         printf("dmacc: 0x%x; ", 
  222                 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_CC));
  223         printf("dmacnva: 0x%x; ", 
  224                 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_CNVA));
  225         printf("dmacnc: 0x%x\n", 
  226                 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_CNC));
  227 
  228         printf("apc_dmacsr=%s\n",
  229                 bitmask_snprintf(
  230                         bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_CSR),
  231                                 APC_BITS, bits, sizeof(bits)));
  232 
  233         ad1848_dump_regs(&sc->sc_cs4231.sc_ad1848);
  234 }
  235 #endif /* AUDIO_DEBUG */
  236 
  237 
  238 static int
  239 cs4231_sbus_trigger_output(addr, start, end, blksize, intr, arg, param)
  240         void *addr;
  241         void *start, *end;
  242         int blksize;
  243         void (*intr)(void *);
  244         void *arg;
  245         struct audio_params *param;
  246 {
  247         struct cs4231_sbus_softc *sbsc = addr;
  248         struct cs4231_softc *sc = &sbsc->sc_cs4231;
  249         struct cs_transfer *t = &sc->sc_playback;
  250         u_int32_t csr;
  251         bus_addr_t dmaaddr;
  252         bus_size_t dmasize;
  253         int ret;
  254 #ifdef AUDIO_DEBUG
  255         char bits[128];
  256 #endif
  257 
  258         ret = cs4231_transfer_init(sc, t, &dmaaddr, &dmasize,
  259                                    start, end, blksize, intr, arg);
  260         if (ret != 0)
  261                 return (ret);
  262 
  263         DPRINTF(("trigger_output: was: %x %d, %x %d\n",
  264                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PVA), 
  265                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PC),
  266                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA),
  267                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC)));
  268 
  269         /* load first block */
  270         bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA, dmaaddr);
  271         bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC, dmasize);
  272 
  273         DPRINTF(("trigger_output: 1st: %x %d, %x %d\n",
  274                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PVA),
  275                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PC),
  276                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA),
  277                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC)));
  278 
  279         csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
  280         DPRINTF(("trigger_output: csr=%s\n",
  281                  bitmask_snprintf(csr, APC_BITS, bits, sizeof(bits))));
  282         if ((csr & PDMA_GO) == 0 || (csr & APC_PPAUSE) != 0) {
  283                 int cfg;
  284 
  285                 csr &= ~(APC_PPAUSE | APC_PMIE | APC_INTR_MASK);
  286                 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
  287 
  288                 csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
  289                 csr &= ~APC_INTR_MASK;
  290                 csr |= APC_ENABLE | APC_PIE | APC_PMIE | PDMA_GO;
  291                 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
  292 
  293                 ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff);
  294                 ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff);
  295 
  296                 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
  297                 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG,
  298                          (cfg | PLAYBACK_ENABLE));
  299         } else {
  300                 DPRINTF(("trigger_output: already: csr=%s\n",
  301                          bitmask_snprintf(csr, APC_BITS, bits, sizeof(bits))));
  302         }
  303 
  304         /* load next block if we can */
  305         csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
  306         if (csr & APC_PD) {
  307                 cs4231_transfer_advance(t, &dmaaddr, &dmasize);
  308                 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA, dmaaddr);
  309                 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC, dmasize);
  310 
  311                 DPRINTF(("trigger_output: 2nd: %x %d, %x %d\n",
  312                     bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PVA),
  313                     bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PC),
  314                     bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA),
  315                     bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC)));
  316         }
  317 
  318         return (0);
  319 }
  320 
  321 
  322 static int
  323 cs4231_sbus_halt_output(addr)
  324         void *addr;
  325 {
  326         struct cs4231_sbus_softc *sbsc = addr;
  327         struct cs4231_softc *sc = &sbsc->sc_cs4231;
  328         u_int32_t csr;
  329         int cfg;
  330 #ifdef AUDIO_DEBUG
  331         char bits[128];
  332 #endif
  333 
  334         sc->sc_playback.t_active = 0;
  335 
  336         csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
  337         DPRINTF(("halt_output: csr=%s\n",
  338                  bitmask_snprintf(csr, APC_BITS, bits, sizeof(bits))));
  339 
  340         csr &= ~APC_INTR_MASK;  /* do not clear interrupts accidentally */
  341         csr |= APC_PPAUSE;      /* pause playback (let current complete) */
  342         bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
  343         
  344         /* let the curernt transfer complete */
  345         if (csr & PDMA_GO)
  346                 do {
  347                         csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, 
  348                                 APC_DMA_CSR);
  349                         DPRINTF(("halt_output: csr=%s\n",
  350                                  bitmask_snprintf(csr, APC_BITS,
  351                                                   bits, sizeof(bits))));
  352                 } while ((csr & APC_PM) == 0);
  353 
  354         cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
  355         ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG,(cfg & ~PLAYBACK_ENABLE));
  356 
  357         return (0);
  358 }
  359 
  360 
  361 /* NB: we don't enable APC_CMIE and won't use APC_CM */
  362 static int
  363 cs4231_sbus_trigger_input(addr, start, end, blksize, intr, arg, param)
  364         void *addr;
  365         void *start, *end;
  366         int blksize;
  367         void (*intr)(void *);
  368         void *arg;
  369         struct audio_params *param;
  370 {
  371         struct cs4231_sbus_softc *sbsc = addr;
  372         struct cs4231_softc *sc = &sbsc->sc_cs4231;
  373         struct cs_transfer *t = &sc->sc_capture;
  374         u_int32_t csr;
  375         bus_addr_t dmaaddr;
  376         bus_size_t dmasize;
  377         int ret;
  378 #ifdef AUDIO_DEBUG
  379         char bits[128];
  380 #endif
  381 
  382         ret = cs4231_transfer_init(sc, t, &dmaaddr, &dmasize,
  383                                    start, end, blksize, intr, arg);
  384         if (ret != 0)
  385                 return (ret);
  386 
  387         csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
  388         DPRINTF(("trigger_input: csr=%s\n",
  389                  bitmask_snprintf(csr, APC_BITS, bits, sizeof(bits))));
  390         DPRINTF(("trigger_input: was: %x %d, %x %d\n",
  391                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CVA), 
  392                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CC),
  393                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA),
  394                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC)));
  395 
  396         /* supply first block */
  397         bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA, dmaaddr);
  398         bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC, dmasize);
  399 
  400         DPRINTF(("trigger_input: 1st: %x %d, %x %d\n",
  401                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CVA), 
  402                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CC),
  403                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA),
  404                 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC)));
  405 
  406         csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
  407         if ((csr & CDMA_GO) == 0 || (csr & APC_CPAUSE) != 0) {
  408                 int cfg;
  409 
  410                 csr &= ~(APC_CPAUSE | APC_CMIE | APC_INTR_MASK);
  411                 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
  412 
  413                 csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
  414                 csr &= ~APC_INTR_MASK;
  415                 csr |= APC_ENABLE | APC_CIE | CDMA_GO;
  416                 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
  417 
  418                 ad_write(&sc->sc_ad1848, CS_LOWER_REC_CNT, 0xff);
  419                 ad_write(&sc->sc_ad1848, CS_UPPER_REC_CNT, 0xff);
  420 
  421                 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
  422                 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG,
  423                          (cfg | CAPTURE_ENABLE));
  424         } else {
  425                 DPRINTF(("trigger_input: already: csr=%s\n",
  426                          bitmask_snprintf(csr, APC_BITS, bits, sizeof(bits))));
  427         }
  428 
  429         /* supply next block if we can */
  430         csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
  431         if (csr & APC_CD) {
  432                 cs4231_transfer_advance(t, &dmaaddr, &dmasize);
  433                 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA, dmaaddr);
  434                 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC, dmasize);
  435                 DPRINTF(("trigger_input: 2nd: %x %d, %x %d\n",
  436                     bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CVA),
  437                     bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CC),
  438                     bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA),
  439                     bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC)));
  440         }
  441 
  442         return (0);
  443 }
  444 
  445 
  446 static int
  447 cs4231_sbus_halt_input(addr)
  448         void *addr;
  449 {
  450         struct cs4231_sbus_softc *sbsc = addr;
  451         struct cs4231_softc *sc = &sbsc->sc_cs4231;
  452         u_int32_t csr;
  453         int cfg;
  454 #ifdef AUDIO_DEBUG
  455         char bits[128];
  456 #endif
  457 
  458         sc->sc_capture.t_active = 0;
  459 
  460         csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
  461         DPRINTF(("halt_input: csr=%s\n",
  462                  bitmask_snprintf(csr, APC_BITS, bits, sizeof(bits))));
  463 
  464         csr &= ~APC_INTR_MASK;  /* do not clear interrupts accidentally */
  465         csr |= APC_CPAUSE;
  466         bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
  467 
  468         /* let the curernt transfer complete */
  469         if (csr & CDMA_GO)
  470                 do {
  471                         csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh,
  472                                 APC_DMA_CSR);
  473                         DPRINTF(("halt_input: csr=%s\n",
  474                                  bitmask_snprintf(csr, APC_BITS,
  475                                                   bits, sizeof(bits))));
  476                 } while ((csr & APC_CM) == 0);
  477 
  478         cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
  479         ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, (cfg & ~CAPTURE_ENABLE));
  480 
  481         return (0);
  482 }
  483 
  484 
  485 static int
  486 cs4231_sbus_intr(arg)
  487         void *arg;
  488 {
  489         struct cs4231_sbus_softc *sbsc = arg;
  490         struct cs4231_softc *sc = &sbsc->sc_cs4231;
  491         u_int32_t csr;
  492         int status;
  493         bus_addr_t dmaaddr;
  494         bus_size_t dmasize;
  495         int served;
  496 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
  497         char bits[128];
  498 #endif
  499 
  500         csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
  501         if ((csr & APC_INTR_MASK) == 0) /* any interrupt pedning? */
  502                 return (0);
  503 
  504         /* write back DMA status to clear interrupt */
  505         bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
  506         ++sc->sc_intrcnt.ev_count;
  507         served = 0;
  508 
  509 #ifdef AUDIO_DEBUG
  510         if (cs4231_sbus_debug > 1)
  511                 cs4231_sbus_regdump("audiointr", sbsc);
  512 #endif
  513 
  514         status = ADREAD(&sc->sc_ad1848, AD1848_STATUS);
  515         DPRINTF(("%s: status: %s\n", sc->sc_ad1848.sc_dev.dv_xname,
  516                 bitmask_snprintf(status, AD_R2_BITS, bits, sizeof(bits))));
  517         if (status & INTERRUPT_STATUS) {
  518 #ifdef AUDIO_DEBUG
  519                 int reason;
  520 
  521                 reason = ad_read(&sc->sc_ad1848, CS_IRQ_STATUS);
  522                 DPRINTF(("%s: i24: %s\n", sc->sc_ad1848.sc_dev.dv_xname,
  523                   bitmask_snprintf(reason, CS_I24_BITS, bits, sizeof(bits))));
  524 #endif
  525                 /* clear ad1848 interrupt */
  526                 ADWRITE(&sc->sc_ad1848, AD1848_STATUS, 0);
  527         }
  528         
  529         if (csr & APC_CI) {
  530                 if (csr & APC_CD) { /* can supply new block */
  531                         struct cs_transfer *t = &sc->sc_capture;
  532 
  533                         cs4231_transfer_advance(t, &dmaaddr, &dmasize);
  534                         bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh,
  535                                 APC_DMA_CNVA, dmaaddr);
  536                         bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh,
  537                                 APC_DMA_CNC, dmasize);
  538 
  539                         if (t->t_intr != NULL)
  540                                 (*t->t_intr)(t->t_arg);
  541                         ++t->t_intrcnt.ev_count;
  542                         served = 1;
  543                 }
  544         }
  545 
  546         if (csr & APC_PMI) {
  547                 if (!sc->sc_playback.t_active)
  548                         served = 1; /* draining in halt_output() */
  549         }
  550 
  551         if (csr & APC_PI) {
  552                 if (csr & APC_PD) { /* can load new block */
  553                         struct cs_transfer *t = &sc->sc_playback;
  554 
  555                         if (t->t_active) {
  556                                 cs4231_transfer_advance(t, &dmaaddr, &dmasize);
  557                                 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh,
  558                                         APC_DMA_PNVA, dmaaddr);
  559                                 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh,
  560                                         APC_DMA_PNC, dmasize);
  561                         }
  562 
  563                         if (t->t_intr != NULL)
  564                                 (*t->t_intr)(t->t_arg);
  565                         ++t->t_intrcnt.ev_count;
  566                         served = 1;
  567                 }
  568         }
  569 
  570         /* got an interrupt we don't know how to handle */
  571         if (!served) {
  572 #ifdef DIAGNOSTIC
  573                 printf("%s: unhandled csr=%s\n", sc->sc_ad1848.sc_dev.dv_xname,
  574                        bitmask_snprintf(csr, APC_BITS, bits, sizeof(bits)));
  575 #endif
  576                 /* evcnt? */
  577         }
  578 
  579         return (1);
  580 }
  581 
  582 #endif /* NAUDIO > 0 */

Cache object: 0c8fc6e8ac1b3d76226154053ed939ff


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


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