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/sound/macio/davbus.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 /*-
    2  * Copyright 2008 by Marco Trillo. All rights reserved.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
   10  *    notice, this list of conditions and the following disclaimer in the
   11  *    documentation and/or other materials provided with the distribution.
   12  *
   13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   18  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   20  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   21  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   23  * SUCH DAMAGE.
   24  *
   25  * $FreeBSD$
   26  */
   27 
   28 /*
   29  *      Apple DAVbus audio controller.
   30  */
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/bus.h>
   35 #include <sys/kernel.h>
   36 #include <sys/lock.h>
   37 #include <sys/malloc.h>
   38 #include <sys/module.h>
   39 #include <sys/mutex.h>
   40 #include <sys/rman.h>
   41 
   42 #include <dev/ofw/ofw_bus.h>
   43 
   44 #ifdef HAVE_KERNEL_OPTION_HEADERS
   45 #include "opt_snd.h"
   46 #endif
   47 
   48 #include <dev/sound/pcm/sound.h>
   49 
   50 #include <dev/sound/macio/aoa.h>
   51 #include <dev/sound/macio/davbusreg.h>
   52 
   53 #include <machine/intr_machdep.h>
   54 #include <machine/resource.h>
   55 #include <machine/bus.h>
   56 
   57 #include "mixer_if.h"
   58 
   59 struct davbus_softc {
   60         struct aoa_softc         aoa;
   61         phandle_t                node;
   62         phandle_t                soundnode;
   63         struct resource         *reg;
   64         struct mtx               mutex;
   65         int                      device_id;
   66         u_int                    output_mask;
   67         u_int                   (*read_status)(struct davbus_softc *, u_int);
   68         void                    (*set_outputs)(struct davbus_softc *, u_int);
   69 };
   70 
   71 static int      davbus_probe(device_t);
   72 static int      davbus_attach(device_t);
   73 static void     davbus_cint(void *);
   74 
   75 static device_method_t pcm_davbus_methods[] = {
   76         /* Device interface. */
   77         DEVMETHOD(device_probe,         davbus_probe),
   78         DEVMETHOD(device_attach,        davbus_attach),
   79 
   80         { 0, 0 }
   81 };
   82 
   83 static driver_t pcm_davbus_driver = {
   84         "pcm",
   85         pcm_davbus_methods,
   86         PCM_SOFTC_SIZE
   87 };
   88 
   89 DRIVER_MODULE(pcm_davbus, macio, pcm_davbus_driver, pcm_devclass, 0, 0);
   90 MODULE_DEPEND(pcm_davbus, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
   91 
   92 /*****************************************************************************
   93                         Probe and attachment routines.
   94  *****************************************************************************/
   95 static int
   96 davbus_probe(device_t self)
   97 {
   98         const char              *name;
   99 
  100         name = ofw_bus_get_name(self);
  101         if (!name)
  102                 return (ENXIO);
  103 
  104         if (strcmp(name, "davbus") != 0)
  105                 return (ENXIO);
  106         
  107         device_set_desc(self, "Apple DAVBus Audio Controller");
  108 
  109         return (0);
  110 }
  111 
  112 /*
  113  * Burgundy codec control
  114  */
  115 
  116 static int      burgundy_init(struct snd_mixer *m);
  117 static int      burgundy_uninit(struct snd_mixer *m);
  118 static int      burgundy_reinit(struct snd_mixer *m);
  119 static void     burgundy_write_locked(struct davbus_softc *, u_int, u_int);
  120 static void     burgundy_set_outputs(struct davbus_softc *d, u_int mask);
  121 static u_int    burgundy_read_status(struct davbus_softc *d, u_int status);
  122 static int      burgundy_set(struct snd_mixer *m, unsigned dev, unsigned left,
  123                     unsigned right);
  124 static u_int32_t        burgundy_setrecsrc(struct snd_mixer *m, u_int32_t src);
  125 
  126 static kobj_method_t burgundy_mixer_methods[] = {
  127         KOBJMETHOD(mixer_init,          burgundy_init),
  128         KOBJMETHOD(mixer_uninit,        burgundy_uninit),
  129         KOBJMETHOD(mixer_reinit,        burgundy_reinit),
  130         KOBJMETHOD(mixer_set,           burgundy_set),
  131         KOBJMETHOD(mixer_setrecsrc,     burgundy_setrecsrc),
  132         KOBJMETHOD_END
  133 };
  134 
  135 MIXER_DECLARE(burgundy_mixer);
  136 
  137 static int
  138 burgundy_init(struct snd_mixer *m)
  139 {
  140         struct davbus_softc *d;
  141 
  142         d = mix_getdevinfo(m);
  143 
  144         d->read_status = burgundy_read_status;
  145         d->set_outputs = burgundy_set_outputs;
  146 
  147         /*
  148          * We configure the Burgundy codec as follows:
  149          *
  150          *      o Input subframe 0 is connected to input digital
  151          *        stream A (ISA).
  152          *      o Stream A (ISA) is mixed in mixer 2 (MIX2).
  153          *      o Output of mixer 2 (MIX2) is routed to output sources
  154          *        OS0 and OS1 which can be converted to analog.
  155          *
  156          */
  157         mtx_lock(&d->mutex);
  158 
  159         burgundy_write_locked(d, 0x16700, 0x40);
  160         
  161         burgundy_write_locked(d, BURGUNDY_MIX0_REG, 0); 
  162         burgundy_write_locked(d, BURGUNDY_MIX1_REG, 0);
  163         burgundy_write_locked(d, BURGUNDY_MIX2_REG, BURGUNDY_MIX_ISA);
  164         burgundy_write_locked(d, BURGUNDY_MIX3_REG, 0);
  165 
  166         burgundy_write_locked(d, BURGUNDY_OS_REG, BURGUNDY_OS0_MIX2 | 
  167             BURGUNDY_OS1_MIX2);
  168 
  169         burgundy_write_locked(d, BURGUNDY_SDIN_REG, BURGUNDY_ISA_SF0);
  170 
  171         /* Set several digital scalers to unity gain. */
  172         burgundy_write_locked(d, BURGUNDY_MXS2L_REG, BURGUNDY_MXS_UNITY);
  173         burgundy_write_locked(d, BURGUNDY_MXS2R_REG, BURGUNDY_MXS_UNITY);
  174         burgundy_write_locked(d, BURGUNDY_OSS0L_REG, BURGUNDY_OSS_UNITY);
  175         burgundy_write_locked(d, BURGUNDY_OSS0R_REG, BURGUNDY_OSS_UNITY);
  176         burgundy_write_locked(d, BURGUNDY_OSS1L_REG, BURGUNDY_OSS_UNITY);
  177         burgundy_write_locked(d, BURGUNDY_OSS1R_REG, BURGUNDY_OSS_UNITY);
  178         burgundy_write_locked(d, BURGUNDY_ISSAL_REG, BURGUNDY_ISS_UNITY);
  179         burgundy_write_locked(d, BURGUNDY_ISSAR_REG, BURGUNDY_ISS_UNITY);
  180 
  181         burgundy_set_outputs(d, burgundy_read_status(d, 
  182             bus_read_4(d->reg, DAVBUS_CODEC_STATUS)));
  183 
  184         mtx_unlock(&d->mutex);
  185 
  186         mix_setdevs(m, SOUND_MASK_VOLUME);
  187 
  188         return (0);
  189 }
  190 
  191 static int
  192 burgundy_uninit(struct snd_mixer *m)
  193 {
  194         return (0);
  195 }
  196 
  197 static int
  198 burgundy_reinit(struct snd_mixer *m)
  199 {
  200         return (0);
  201 }
  202 
  203 static void
  204 burgundy_write_locked(struct davbus_softc *d, u_int reg, u_int val)
  205 {
  206         u_int size, addr, offset, data, i;
  207 
  208         size = (reg & 0x00FF0000) >> 16;
  209         addr = (reg & 0x0000FF00) >> 8;
  210         offset = reg & 0xFF;
  211 
  212         for (i = offset; i < offset + size; ++i) {
  213                 data = BURGUNDY_CTRL_WRITE | (addr << 12) | 
  214                     ((size + offset - 1) << 10) | (i << 8) | (val & 0xFF);
  215                 if (i == offset)
  216                         data |= BURGUNDY_CTRL_RESET;
  217 
  218                 bus_write_4(d->reg, DAVBUS_CODEC_CTRL, data);
  219 
  220                 while (bus_read_4(d->reg, DAVBUS_CODEC_CTRL) &
  221                     DAVBUS_CODEC_BUSY)
  222                         DELAY(1);
  223                 
  224                 val >>= 8; /* next byte. */
  225         }       
  226 }
  227 
  228 /* Must be called with d->mutex held. */
  229 static void
  230 burgundy_set_outputs(struct davbus_softc *d, u_int mask)
  231 {
  232         u_int   x = 0;
  233 
  234         if (mask == d->output_mask)
  235                 return;
  236 
  237         /*
  238          *      Bordeaux card wirings:
  239          *              Port 15:        RCA out
  240          *              Port 16:        Minijack out
  241          *              Port 17:        Internal speaker
  242          *
  243          *      B&W G3 wirings:
  244          *              Port 14:        Minijack out
  245          *              Port 17:        Internal speaker
  246          */
  247 
  248         DPRINTF(("Enabled outputs:"));
  249         if (mask & (1 << 0)) {
  250                 DPRINTF((" SPEAKER"));
  251                 x |= BURGUNDY_P17M_EN;
  252         }
  253         if (mask & (1 << 1)) {
  254                 DPRINTF((" HEADPHONES"));
  255                 x |= BURGUNDY_P14L_EN | BURGUNDY_P14R_EN;       
  256         }
  257         DPRINTF(("\n"));
  258 
  259         burgundy_write_locked(d, BURGUNDY_MUTE_REG, x);
  260         d->output_mask = mask;
  261 }
  262 
  263 static u_int
  264 burgundy_read_status(struct davbus_softc *d, u_int status)
  265 {
  266         if (status & 0x4)
  267                 return (1 << 1);
  268         else
  269                 return (1 << 0);
  270 }
  271 
  272 static int
  273 burgundy_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
  274 {
  275         struct davbus_softc *d;
  276         int lval, rval;
  277 
  278         lval = ((100 - left) * 15 / 100) & 0xf;
  279         rval = ((100 - right) * 15 / 100) & 0xf;
  280         DPRINTF(("volume %d %d\n", lval, rval));
  281 
  282         d = mix_getdevinfo(m);
  283 
  284         switch (dev) {
  285         case SOUND_MIXER_VOLUME:
  286                 mtx_lock(&d->mutex);
  287 
  288                 burgundy_write_locked(d, BURGUNDY_OL13_REG, lval);
  289                 burgundy_write_locked(d, BURGUNDY_OL14_REG, (rval << 4) | lval);
  290                 burgundy_write_locked(d, BURGUNDY_OL15_REG, (rval << 4) | lval);
  291                 burgundy_write_locked(d, BURGUNDY_OL16_REG, (rval << 4) | lval);
  292                 burgundy_write_locked(d, BURGUNDY_OL17_REG, lval);
  293 
  294                 mtx_unlock(&d->mutex);
  295 
  296                 return (left | (right << 8));
  297         }
  298 
  299         return (0);
  300 }
  301 
  302 static u_int32_t
  303 burgundy_setrecsrc(struct snd_mixer *m, u_int32_t src)
  304 {
  305         return (0);
  306 }
  307 
  308 /*
  309  * Screamer Codec Control
  310  */
  311 
  312 static int      screamer_init(struct snd_mixer *m);
  313 static int      screamer_uninit(struct snd_mixer *m);
  314 static int      screamer_reinit(struct snd_mixer *m);
  315 static void     screamer_write_locked(struct davbus_softc *, u_int, u_int);
  316 static void     screamer_set_outputs(struct davbus_softc *d, u_int mask);
  317 static u_int    screamer_read_status(struct davbus_softc *d, u_int status);
  318 static int      screamer_set(struct snd_mixer *m, unsigned dev, unsigned left,
  319                     unsigned right);
  320 static u_int32_t        screamer_setrecsrc(struct snd_mixer *m, u_int32_t src);
  321 
  322 static kobj_method_t screamer_mixer_methods[] = {
  323         KOBJMETHOD(mixer_init,          screamer_init),
  324         KOBJMETHOD(mixer_uninit,        screamer_uninit),
  325         KOBJMETHOD(mixer_reinit,        screamer_reinit),
  326         KOBJMETHOD(mixer_set,           screamer_set),
  327         KOBJMETHOD(mixer_setrecsrc,     screamer_setrecsrc),
  328         KOBJMETHOD_END
  329 };
  330 
  331 MIXER_DECLARE(screamer_mixer);
  332 
  333 static int
  334 screamer_init(struct snd_mixer *m)
  335 {
  336         struct davbus_softc *d;
  337 
  338         d = mix_getdevinfo(m);
  339 
  340         d->read_status = screamer_read_status;
  341         d->set_outputs = screamer_set_outputs;
  342 
  343         mtx_lock(&d->mutex);
  344 
  345         screamer_write_locked(d, SCREAMER_CODEC_ADDR0, SCREAMER_INPUT_CD | 
  346             SCREAMER_DEFAULT_CD_GAIN);
  347 
  348         screamer_set_outputs(d, screamer_read_status(d, 
  349             bus_read_4(d->reg, DAVBUS_CODEC_STATUS)));
  350 
  351         screamer_write_locked(d, SCREAMER_CODEC_ADDR2, 0);
  352         screamer_write_locked(d, SCREAMER_CODEC_ADDR4, 0);
  353         screamer_write_locked(d, SCREAMER_CODEC_ADDR5, 0);
  354         screamer_write_locked(d, SCREAMER_CODEC_ADDR6, 0);
  355 
  356         mtx_unlock(&d->mutex);
  357 
  358         mix_setdevs(m, SOUND_MASK_VOLUME);
  359 
  360         return (0);
  361 }
  362 
  363 static int
  364 screamer_uninit(struct snd_mixer *m)
  365 {
  366         return (0);
  367 }
  368 
  369 static int
  370 screamer_reinit(struct snd_mixer *m)
  371 {
  372         return (0);
  373 }
  374 
  375 
  376 static void
  377 screamer_write_locked(struct davbus_softc *d, u_int reg, u_int val)
  378 {
  379         u_int           x;
  380 
  381         KASSERT(val == (val & 0xfff), ("bad val"));
  382 
  383         while (bus_read_4(d->reg, DAVBUS_CODEC_CTRL) & DAVBUS_CODEC_BUSY)
  384                 DELAY(100);
  385 
  386         x = reg;
  387         x |= SCREAMER_CODEC_EMSEL0;
  388         x |= val;
  389         bus_write_4(d->reg, DAVBUS_CODEC_CTRL, x);
  390 
  391         while (bus_read_4(d->reg, DAVBUS_CODEC_CTRL) & DAVBUS_CODEC_BUSY)
  392                 DELAY(100);
  393 }
  394 
  395 /* Must be called with d->mutex held. */
  396 static void
  397 screamer_set_outputs(struct davbus_softc *d, u_int mask)
  398 {
  399         u_int   x;
  400 
  401         if (mask == d->output_mask) {
  402                 return;
  403         }
  404 
  405         x = SCREAMER_MUTE_SPEAKER | SCREAMER_MUTE_HEADPHONES;
  406 
  407         DPRINTF(("Enabled outputs: "));
  408 
  409         if (mask & (1 << 0)) {
  410                 DPRINTF(("SPEAKER "));
  411                 x &= ~SCREAMER_MUTE_SPEAKER;
  412         }
  413         if (mask & (1 << 1)) {
  414                 DPRINTF(("HEADPHONES "));
  415                 x &= ~SCREAMER_MUTE_HEADPHONES;
  416         }
  417 
  418         DPRINTF(("\n"));
  419 
  420         if (d->device_id == 5 || d->device_id == 11) {
  421                 DPRINTF(("Enabling programmable output.\n"));
  422                 x |= SCREAMER_PROG_OUTPUT0;
  423         }
  424         if (d->device_id == 8 || d->device_id == 11) {
  425                 x &= ~SCREAMER_MUTE_SPEAKER;
  426 
  427                 if (mask & (1 << 0))
  428                         x |= SCREAMER_PROG_OUTPUT1; /* enable speaker. */
  429         }
  430 
  431         screamer_write_locked(d, SCREAMER_CODEC_ADDR1, x);
  432         d->output_mask = mask;
  433 }
  434 
  435 static u_int
  436 screamer_read_status(struct davbus_softc *d, u_int status)
  437 {
  438         int     headphones;
  439 
  440         switch (d->device_id) {
  441         case 5: /* Sawtooth */
  442                 headphones = (status & 0x4);
  443                 break;
  444 
  445         case 8:
  446         case 11: /* iMac DV */
  447                 /* The iMac DV has 2 headphone outputs. */
  448                 headphones = (status & 0x7);
  449                 break;
  450 
  451         default:
  452                 headphones = (status & 0x8);
  453         }
  454 
  455         if (headphones)
  456                 return (1 << 1);
  457         else
  458                 return (1 << 0);
  459 }
  460 
  461 static int
  462 screamer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
  463 {
  464         struct davbus_softc *d;
  465         int lval, rval;
  466 
  467         lval = ((100 - left) * 15 / 100) & 0xf;
  468         rval = ((100 - right) * 15 / 100) & 0xf;
  469         DPRINTF(("volume %d %d\n", lval, rval));
  470 
  471         d = mix_getdevinfo(m);
  472 
  473         switch (dev) {
  474         case SOUND_MIXER_VOLUME:
  475                 mtx_lock(&d->mutex);
  476                 screamer_write_locked(d, SCREAMER_CODEC_ADDR2, (lval << 6) |
  477                     rval);
  478                 screamer_write_locked(d, SCREAMER_CODEC_ADDR4, (lval << 6) | 
  479                     rval);
  480                 mtx_unlock(&d->mutex);
  481 
  482                 return (left | (right << 8));
  483         }
  484 
  485         return (0);
  486 }
  487 
  488 static u_int32_t
  489 screamer_setrecsrc(struct snd_mixer *m, u_int32_t src)
  490 {
  491         return (0);
  492 }
  493 
  494 static int
  495 davbus_attach(device_t self)
  496 {
  497         struct davbus_softc     *sc;
  498         struct resource         *dbdma_irq, *cintr;
  499         void                    *cookie;
  500         char                     compat[64];
  501         int                      rid, oirq, err;
  502 
  503         sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
  504 
  505         sc->aoa.sc_dev = self;
  506         sc->node = ofw_bus_get_node(self);
  507         sc->soundnode = OF_child(sc->node);
  508 
  509         /* Map the controller register space. */
  510         rid = 0;
  511         sc->reg = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
  512         if (sc->reg == NULL) 
  513                 return (ENXIO);
  514 
  515         /* Map the DBDMA channel register space. */
  516         rid = 1;
  517         sc->aoa.sc_odma = bus_alloc_resource_any(self, SYS_RES_MEMORY, 
  518             &rid, RF_ACTIVE);
  519         if (sc->aoa.sc_odma == NULL)
  520                 return (ENXIO);
  521 
  522         /* Establish the DBDMA channel edge-triggered interrupt. */
  523         rid = 1;
  524         dbdma_irq = bus_alloc_resource_any(self, SYS_RES_IRQ, 
  525             &rid, RF_SHAREABLE | RF_ACTIVE);
  526         if (dbdma_irq == NULL)
  527                 return (ENXIO);
  528 
  529         oirq = rman_get_start(dbdma_irq);
  530         
  531         DPRINTF(("interrupting at irq %d\n", oirq));
  532 
  533         err = powerpc_config_intr(oirq, INTR_TRIGGER_EDGE, INTR_POLARITY_LOW);
  534         if (err != 0)
  535                 return (err);
  536                 
  537         snd_setup_intr(self, dbdma_irq, INTR_MPSAFE, aoa_interrupt,
  538             sc, &cookie);
  539 
  540         /* Now initialize the controller. */
  541 
  542         bzero(compat, sizeof(compat));
  543         OF_getprop(sc->soundnode, "compatible", compat, sizeof(compat));
  544         OF_getprop(sc->soundnode, "device-id", &sc->device_id, sizeof(u_int));
  545 
  546         mtx_init(&sc->mutex, "DAVbus", NULL, MTX_DEF);
  547 
  548         device_printf(self, "codec: <%s>\n", compat);
  549 
  550         /* Setup the control interrupt. */
  551         rid = 0;
  552         cintr = bus_alloc_resource_any(self, SYS_RES_IRQ, 
  553              &rid, RF_SHAREABLE | RF_ACTIVE);
  554         if (cintr != NULL) 
  555                 bus_setup_intr(self, cintr, INTR_TYPE_MISC | INTR_MPSAFE,
  556                     NULL, davbus_cint, sc, &cookie);
  557         
  558         /* Initialize controller registers. */
  559         bus_write_4(sc->reg, DAVBUS_SOUND_CTRL, DAVBUS_INPUT_SUBFRAME0 | 
  560             DAVBUS_OUTPUT_SUBFRAME0 | DAVBUS_RATE_44100 | DAVBUS_INTR_PORTCHG);
  561 
  562         /* Attach DBDMA engine and PCM layer */
  563         err = aoa_attach(sc);
  564         if (err)
  565                 return (err);
  566 
  567         /* Install codec module */
  568         if (strcmp(compat, "screamer") == 0)
  569                 mixer_init(self, &screamer_mixer_class, sc);
  570         else if (strcmp(compat, "burgundy") == 0)
  571                 mixer_init(self, &burgundy_mixer_class, sc);
  572 
  573         return (0);
  574 }
  575 
  576 static void 
  577 davbus_cint(void *ptr)
  578 {
  579         struct davbus_softc *d = ptr;
  580         u_int   reg, status, mask;
  581 
  582         mtx_lock(&d->mutex);
  583 
  584         reg = bus_read_4(d->reg, DAVBUS_SOUND_CTRL);
  585         if (reg & DAVBUS_PORTCHG) {
  586                 
  587                 status = bus_read_4(d->reg, DAVBUS_CODEC_STATUS);
  588                 
  589                 if (d->read_status && d->set_outputs) {
  590 
  591                         mask = (*d->read_status)(d, status);
  592                         (*d->set_outputs)(d, mask);
  593                 }
  594 
  595                 /* Clear the interrupt. */
  596                 bus_write_4(d->reg, DAVBUS_SOUND_CTRL, reg);
  597         }
  598 
  599         mtx_unlock(&d->mutex);
  600 }
  601 

Cache object: 9d98f00317d000515b504da53b9aed40


[ 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.