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/mips/ingenic/jz4780_aic.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2016-2018 Ruslan Bukin <br@bsdpad.com>
    3  * All rights reserved.
    4  *
    5  * This software was developed by SRI International and the University of
    6  * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
    7  * ("CTSRD"), as part of the DARPA CRASH research programme.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  */
   30 
   31 /* Ingenic JZ4780 Audio Interface Controller (AIC). */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD: stable/12/sys/mips/ingenic/jz4780_aic.c 332435 2018-04-12 15:36:24Z br $");
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/conf.h>
   39 #include <sys/bus.h>
   40 #include <sys/kernel.h>
   41 #include <sys/module.h>
   42 #include <sys/lock.h>
   43 #include <sys/mutex.h>
   44 #include <sys/resource.h>
   45 #include <sys/rman.h>
   46 
   47 #include <machine/bus.h>
   48 
   49 #include <dev/fdt/fdt_common.h>
   50 #include <dev/ofw/ofw_bus.h>
   51 #include <dev/ofw/ofw_bus_subr.h>
   52 
   53 #include <dev/sound/pcm/sound.h>
   54 #include <dev/sound/chip.h>
   55 #include <mixer_if.h>
   56 
   57 #include <dev/extres/clk/clk.h>
   58 #include <dev/xdma/xdma.h>
   59 
   60 #include <mips/ingenic/jz4780_common.h>
   61 #include <mips/ingenic/jz4780_aic.h>
   62 
   63 #define AIC_NCHANNELS           1
   64 
   65 struct aic_softc {
   66         device_t                dev;
   67         struct resource         *res[1];
   68         bus_space_tag_t         bst;
   69         bus_space_handle_t      bsh;
   70         struct mtx              *lock;
   71         int                     pos;
   72         bus_dma_tag_t           dma_tag;
   73         bus_dmamap_t            dma_map;
   74         bus_addr_t              buf_base_phys;
   75         uint32_t                *buf_base;
   76         uintptr_t               aic_fifo_paddr;
   77         int                     dma_size;
   78         clk_t                   clk_aic;
   79         clk_t                   clk_i2s;
   80         struct aic_rate         *sr;
   81         void                    *ih;
   82         int                     internal_codec;
   83 
   84         /* xDMA */
   85         struct xdma_channel     *xchan;
   86         xdma_controller_t       *xdma_tx;
   87         struct xdma_request     req;
   88 };
   89 
   90 /* Channel registers */
   91 struct sc_chinfo {
   92         struct snd_dbuf         *buffer;
   93         struct pcm_channel      *channel;
   94         struct sc_pcminfo       *parent;
   95 
   96         /* Channel information */
   97         uint32_t        dir;
   98         uint32_t        format;
   99 
  100         /* Flags */
  101         uint32_t        run;
  102 };
  103 
  104 /* PCM device private data */
  105 struct sc_pcminfo {
  106         device_t                dev;
  107         uint32_t                chnum;
  108         struct sc_chinfo        chan[AIC_NCHANNELS];
  109         struct aic_softc        *sc;
  110 };
  111 
  112 static struct resource_spec aic_spec[] = {
  113         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
  114         { -1, 0 }
  115 };
  116 
  117 static int aic_probe(device_t dev);
  118 static int aic_attach(device_t dev);
  119 static int aic_detach(device_t dev);
  120 static int setup_xdma(struct sc_pcminfo *scp);
  121 
  122 struct aic_rate {
  123         uint32_t speed;
  124 };
  125 
  126 static struct aic_rate rate_map[] = {
  127         { 48000 },
  128         /* TODO: add more frequences */
  129         { 0 },
  130 };
  131 
  132 /*
  133  * Mixer interface.
  134  */
  135 static int
  136 aicmixer_init(struct snd_mixer *m)
  137 {
  138         struct sc_pcminfo *scp;
  139         struct aic_softc *sc;
  140         int mask;
  141 
  142         scp = mix_getdevinfo(m);
  143         sc = scp->sc;
  144 
  145         if (sc == NULL)
  146                 return -1;
  147 
  148         mask = SOUND_MASK_PCM;
  149 
  150         snd_mtxlock(sc->lock);
  151         pcm_setflags(scp->dev, pcm_getflags(scp->dev) | SD_F_SOFTPCMVOL);
  152         mix_setdevs(m, mask);
  153         snd_mtxunlock(sc->lock);
  154 
  155         return (0);
  156 }
  157 
  158 static int
  159 aicmixer_set(struct snd_mixer *m, unsigned dev,
  160     unsigned left, unsigned right)
  161 {
  162         struct sc_pcminfo *scp;
  163 
  164         scp = mix_getdevinfo(m);
  165 
  166         /* Here we can configure hardware volume on our DAC */
  167 
  168         return (0);
  169 }
  170 
  171 static kobj_method_t aicmixer_methods[] = {
  172         KOBJMETHOD(mixer_init,      aicmixer_init),
  173         KOBJMETHOD(mixer_set,       aicmixer_set),
  174         KOBJMETHOD_END
  175 };
  176 MIXER_DECLARE(aicmixer);
  177 
  178 /*
  179  * Channel interface.
  180  */
  181 static void *
  182 aicchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
  183     struct pcm_channel *c, int dir)
  184 {
  185         struct sc_pcminfo *scp;
  186         struct sc_chinfo *ch;
  187         struct aic_softc *sc;
  188 
  189         scp = (struct sc_pcminfo *)devinfo;
  190         sc = scp->sc;
  191 
  192         snd_mtxlock(sc->lock);
  193         ch = &scp->chan[0];
  194         ch->dir = dir;
  195         ch->run = 0;
  196         ch->buffer = b;
  197         ch->channel = c;
  198         ch->parent = scp;
  199         snd_mtxunlock(sc->lock);
  200 
  201         if (sndbuf_setup(ch->buffer, sc->buf_base, sc->dma_size) != 0) {
  202                 device_printf(scp->dev, "Can't setup sndbuf.\n");
  203                 return NULL;
  204         }
  205 
  206         return (ch);
  207 }
  208 
  209 static int
  210 aicchan_free(kobj_t obj, void *data)
  211 {
  212         struct sc_chinfo *ch = data;
  213         struct sc_pcminfo *scp = ch->parent;
  214         struct aic_softc *sc = scp->sc;
  215 
  216         snd_mtxlock(sc->lock);
  217         /* TODO: free channel buffer */
  218         snd_mtxunlock(sc->lock);
  219 
  220         return (0);
  221 }
  222 
  223 static int
  224 aicchan_setformat(kobj_t obj, void *data, uint32_t format)
  225 {
  226         struct sc_pcminfo *scp;
  227         struct sc_chinfo *ch;
  228 
  229         ch = data;
  230         scp = ch->parent;
  231 
  232         ch->format = format;
  233 
  234         return (0);
  235 }
  236 
  237 static uint32_t
  238 aicchan_setspeed(kobj_t obj, void *data, uint32_t speed)
  239 {
  240         struct sc_pcminfo *scp;
  241         struct sc_chinfo *ch;
  242         struct aic_rate *sr;
  243         struct aic_softc *sc;
  244         int threshold;
  245         int i;
  246 
  247         ch = data;
  248         scp = ch->parent;
  249         sc = scp->sc;
  250 
  251         sr = NULL;
  252 
  253         /* First look for equal frequency. */
  254         for (i = 0; rate_map[i].speed != 0; i++) {
  255                 if (rate_map[i].speed == speed)
  256                         sr = &rate_map[i];
  257         }
  258 
  259         /* If no match, just find nearest. */
  260         if (sr == NULL) {
  261                 for (i = 0; rate_map[i].speed != 0; i++) {
  262                         sr = &rate_map[i];
  263                         threshold = sr->speed + ((rate_map[i + 1].speed != 0) ?
  264                             ((rate_map[i + 1].speed - sr->speed) >> 1) : 0);
  265                         if (speed < threshold)
  266                                 break;
  267                 }
  268         }
  269 
  270         sc->sr = sr;
  271 
  272         /* Clocks can be reconfigured here. */
  273 
  274         return (sr->speed);
  275 }
  276 
  277 static uint32_t
  278 aicchan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
  279 {
  280         struct sc_pcminfo *scp;
  281         struct sc_chinfo *ch;
  282         struct aic_softc *sc;
  283 
  284         ch = data;
  285         scp = ch->parent;
  286         sc = scp->sc;
  287 
  288         sndbuf_resize(ch->buffer, sc->dma_size / blocksize, blocksize);
  289 
  290         return (sndbuf_getblksz(ch->buffer));
  291 }
  292 
  293 static int
  294 aic_intr(void *arg, xdma_transfer_status_t *status)
  295 {
  296         struct sc_pcminfo *scp;
  297         struct xdma_request *req;
  298         xdma_channel_t *xchan;
  299         struct sc_chinfo *ch;
  300         struct aic_softc *sc;
  301         int bufsize;
  302 
  303         scp = arg;
  304         sc = scp->sc;
  305         ch = &scp->chan[0];
  306         req = &sc->req;
  307 
  308         xchan = sc->xchan;
  309 
  310         bufsize = sndbuf_getsize(ch->buffer);
  311 
  312         sc->pos += req->block_len;
  313         if (sc->pos >= bufsize)
  314                 sc->pos -= bufsize;
  315 
  316         if (ch->run)
  317                 chn_intr(ch->channel);
  318 
  319         return (0);
  320 }
  321 
  322 static int
  323 setup_xdma(struct sc_pcminfo *scp)
  324 {
  325         struct aic_softc *sc;
  326         struct sc_chinfo *ch;
  327         int fmt;
  328         int err;
  329 
  330         ch = &scp->chan[0];
  331         sc = scp->sc;
  332 
  333         fmt = sndbuf_getfmt(ch->buffer);
  334 
  335         KASSERT(fmt & AFMT_16BIT, ("16-bit audio supported only."));
  336 
  337         sc->req.operation = XDMA_CYCLIC;
  338         sc->req.req_type = XR_TYPE_PHYS;
  339         sc->req.direction = XDMA_MEM_TO_DEV;
  340         sc->req.src_addr = sc->buf_base_phys;
  341         sc->req.dst_addr = sc->aic_fifo_paddr;
  342         sc->req.src_width = 2;
  343         sc->req.dst_width = 2;
  344         sc->req.block_len = sndbuf_getblksz(ch->buffer);
  345         sc->req.block_num = sndbuf_getblkcnt(ch->buffer);
  346 
  347         err = xdma_request(sc->xchan, &sc->req);
  348         if (err != 0) {
  349                 device_printf(sc->dev, "Can't configure virtual channel\n");
  350                 return (-1);
  351         }
  352 
  353         xdma_control(sc->xchan, XDMA_CMD_BEGIN);
  354 
  355         return (0);
  356 }
  357 
  358 static int
  359 aic_start(struct sc_pcminfo *scp)
  360 {
  361         struct aic_softc *sc;
  362         int reg;
  363 
  364         sc = scp->sc;
  365 
  366         /* Ensure clock enabled. */
  367         reg = READ4(sc, I2SCR);
  368         reg |= (I2SCR_ESCLK);
  369         WRITE4(sc, I2SCR, reg);
  370 
  371         setup_xdma(scp);
  372 
  373         reg = (AICCR_OSS_16 | AICCR_ISS_16);
  374         reg |= (AICCR_CHANNEL_2);
  375         reg |= (AICCR_TDMS);
  376         reg |= (AICCR_ERPL);
  377         WRITE4(sc, AICCR, reg);
  378 
  379         return (0);
  380 }
  381 
  382 static int
  383 aic_stop(struct sc_pcminfo *scp)
  384 {
  385         struct aic_softc *sc;
  386         int reg;
  387 
  388         sc = scp->sc;
  389 
  390         reg = READ4(sc, AICCR);
  391         reg &= ~(AICCR_TDMS | AICCR_ERPL);
  392         WRITE4(sc, AICCR, reg);
  393 
  394         xdma_control(sc->xchan, XDMA_CMD_TERMINATE);
  395 
  396         return (0);
  397 }
  398 
  399 static int
  400 aicchan_trigger(kobj_t obj, void *data, int go)
  401 {
  402         struct sc_pcminfo *scp;
  403         struct sc_chinfo *ch;
  404         struct aic_softc *sc;
  405 
  406         ch = data;
  407         scp = ch->parent;
  408         sc = scp->sc;
  409 
  410         snd_mtxlock(sc->lock);
  411 
  412         switch (go) {
  413         case PCMTRIG_START:
  414                 ch->run = 1;
  415 
  416                 sc->pos = 0;
  417 
  418                 aic_start(scp);
  419 
  420                 break;
  421 
  422         case PCMTRIG_STOP:
  423         case PCMTRIG_ABORT:
  424                 ch->run = 0;
  425 
  426                 aic_stop(scp);
  427 
  428                 sc->pos = 0;
  429 
  430                 bzero(sc->buf_base, sc->dma_size);
  431 
  432                 break;
  433         }
  434 
  435         snd_mtxunlock(sc->lock);
  436 
  437         return (0);
  438 }
  439 
  440 static uint32_t
  441 aicchan_getptr(kobj_t obj, void *data)
  442 {
  443         struct sc_pcminfo *scp;
  444         struct sc_chinfo *ch;
  445         struct aic_softc *sc;
  446 
  447         ch = data;
  448         scp = ch->parent;
  449         sc = scp->sc;
  450 
  451         return (sc->pos);
  452 }
  453 
  454 static uint32_t aic_pfmt[] = {
  455         SND_FORMAT(AFMT_S16_LE, 2, 0),
  456         0
  457 };
  458 
  459 static struct pcmchan_caps aic_pcaps = {48000, 48000, aic_pfmt, 0};
  460 
  461 static struct pcmchan_caps *
  462 aicchan_getcaps(kobj_t obj, void *data)
  463 {
  464 
  465         return (&aic_pcaps);
  466 }
  467 
  468 static kobj_method_t aicchan_methods[] = {
  469         KOBJMETHOD(channel_init,         aicchan_init),
  470         KOBJMETHOD(channel_free,         aicchan_free),
  471         KOBJMETHOD(channel_setformat,    aicchan_setformat),
  472         KOBJMETHOD(channel_setspeed,     aicchan_setspeed),
  473         KOBJMETHOD(channel_setblocksize, aicchan_setblocksize),
  474         KOBJMETHOD(channel_trigger,      aicchan_trigger),
  475         KOBJMETHOD(channel_getptr,       aicchan_getptr),
  476         KOBJMETHOD(channel_getcaps,      aicchan_getcaps),
  477         KOBJMETHOD_END
  478 };
  479 CHANNEL_DECLARE(aicchan);
  480 
  481 static void
  482 aic_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
  483 {
  484         bus_addr_t *addr;
  485 
  486         if (err)
  487                 return;
  488 
  489         addr = (bus_addr_t*)arg;
  490         *addr = segs[0].ds_addr;
  491 }
  492 
  493 static int
  494 aic_dma_setup(struct aic_softc *sc)
  495 {
  496         device_t dev;
  497         int err;
  498 
  499         dev = sc->dev;
  500 
  501         /* DMA buffer size. */
  502         sc->dma_size = 131072;
  503 
  504         /*
  505          * Must use dma_size boundary as modulo feature required.
  506          * Modulo feature allows setup circular buffer.
  507          */
  508         err = bus_dma_tag_create(
  509             bus_get_dma_tag(sc->dev),
  510             4, sc->dma_size,            /* alignment, boundary */
  511             BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
  512             BUS_SPACE_MAXADDR,          /* highaddr */
  513             NULL, NULL,                 /* filter, filterarg */
  514             sc->dma_size, 1,            /* maxsize, nsegments */
  515             sc->dma_size, 0,            /* maxsegsize, flags */
  516             NULL, NULL,                 /* lockfunc, lockarg */
  517             &sc->dma_tag);
  518         if (err) {
  519                 device_printf(dev, "cannot create bus dma tag\n");
  520                 return (-1);
  521         }
  522 
  523         err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->buf_base,
  524             BUS_DMA_WAITOK | BUS_DMA_COHERENT, &sc->dma_map);
  525         if (err) {
  526                 device_printf(dev, "cannot allocate memory\n");
  527                 return (-1);
  528         }
  529 
  530         err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->buf_base,
  531             sc->dma_size, aic_dmamap_cb, &sc->buf_base_phys, BUS_DMA_WAITOK);
  532         if (err) {
  533                 device_printf(dev, "cannot load DMA map\n");
  534                 return (-1);
  535         }
  536 
  537         bzero(sc->buf_base, sc->dma_size);
  538 
  539         return (0);
  540 }
  541 
  542 static int
  543 aic_configure_clocks(struct aic_softc *sc)
  544 {
  545         uint64_t aic_freq;
  546         uint64_t i2s_freq;
  547         device_t dev;
  548         int err;
  549 
  550         dev = sc->dev;
  551 
  552         err = clk_get_by_ofw_name(sc->dev, 0, "aic", &sc->clk_aic);
  553         if (err != 0) {
  554                 device_printf(dev, "Can't find aic clock.\n");
  555                 return (-1);
  556         }
  557 
  558         err = clk_enable(sc->clk_aic);
  559         if (err != 0) {
  560                 device_printf(dev, "Can't enable aic clock.\n");
  561                 return (-1);
  562         }
  563 
  564         err = clk_get_by_ofw_name(sc->dev, 0, "i2s", &sc->clk_i2s);
  565         if (err != 0) {
  566                 device_printf(dev, "Can't find i2s clock.\n");
  567                 return (-1);
  568         }
  569 
  570         err = clk_enable(sc->clk_i2s);
  571         if (err != 0) {
  572                 device_printf(dev, "Can't enable i2s clock.\n");
  573                 return (-1);
  574         }
  575 
  576         err = clk_set_freq(sc->clk_i2s, 12000000, 0);
  577         if (err != 0) {
  578                 device_printf(dev, "Can't set i2s frequency.\n");
  579                 return (-1);
  580         }
  581 
  582         clk_get_freq(sc->clk_aic, &aic_freq);
  583         clk_get_freq(sc->clk_i2s, &i2s_freq);
  584 
  585         device_printf(dev, "Frequency aic %d i2s %d\n",
  586             (uint32_t)aic_freq, (uint32_t)i2s_freq);
  587 
  588         return (0);
  589 }
  590 
  591 static int
  592 aic_configure(struct aic_softc *sc)
  593 {
  594         int reg;
  595 
  596         WRITE4(sc, AICFR, AICFR_RST);
  597 
  598         /* Configure AIC */
  599         reg = 0;
  600         if (sc->internal_codec) {
  601                 reg |= (AICFR_ICDC);
  602         } else {
  603                 reg |= (AICFR_SYNCD | AICFR_BCKD);
  604         }
  605         reg |= (AICFR_AUSEL);   /* I2S/MSB-justified format. */
  606         reg |= (AICFR_TFTH(8)); /* Transmit FIFO threshold */
  607         reg |= (AICFR_RFTH(7)); /* Receive FIFO threshold */
  608         WRITE4(sc, AICFR, reg);
  609 
  610         reg = READ4(sc, AICFR);
  611         reg |= (AICFR_ENB);     /* Enable the controller. */
  612         WRITE4(sc, AICFR, reg);
  613 
  614         return (0);
  615 }
  616 
  617 static int
  618 sysctl_hw_pcm_internal_codec(SYSCTL_HANDLER_ARGS)
  619 {
  620         struct sc_pcminfo *scp;
  621         struct sc_chinfo *ch;
  622         struct aic_softc *sc;
  623         int error, val;
  624 
  625         if (arg1 == NULL)
  626                 return (EINVAL);
  627 
  628         scp = arg1;
  629         sc = scp->sc;
  630         ch = &scp->chan[0];
  631 
  632         snd_mtxlock(sc->lock);
  633 
  634         val = sc->internal_codec;
  635         error = sysctl_handle_int(oidp, &val, 0, req);
  636         if (error || req->newptr == NULL) {
  637                 snd_mtxunlock(sc->lock);
  638                 return (error);
  639         }
  640         if (val < 0 || val > 1) {
  641                 snd_mtxunlock(sc->lock);
  642                 return (EINVAL);
  643         }
  644 
  645         if (sc->internal_codec != val) {
  646                 sc->internal_codec = val;
  647                 if (ch->run)
  648                         aic_stop(scp);
  649                 aic_configure(sc);
  650                 if (ch->run)
  651                         aic_start(scp);
  652         }
  653 
  654         snd_mtxunlock(sc->lock);
  655 
  656         return (0);
  657 }
  658 
  659 static int
  660 aic_probe(device_t dev)
  661 {
  662 
  663         if (!ofw_bus_status_okay(dev))
  664                 return (ENXIO);
  665 
  666         if (!ofw_bus_is_compatible(dev, "ingenic,jz4780-i2s"))
  667                 return (ENXIO);
  668 
  669         device_set_desc(dev, "Audio Interface Controller");
  670 
  671         return (BUS_PROBE_DEFAULT);
  672 }
  673 
  674 static int
  675 aic_attach(device_t dev)
  676 {
  677         char status[SND_STATUSLEN];
  678         struct sc_pcminfo *scp;
  679         struct aic_softc *sc;
  680         int err;
  681 
  682         sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
  683         sc->dev = dev;
  684         sc->pos = 0;
  685         sc->internal_codec = 1;
  686 
  687         /* Get xDMA controller */
  688         sc->xdma_tx = xdma_ofw_get(sc->dev, "tx");
  689         if (sc->xdma_tx == NULL) {
  690                 device_printf(dev, "Can't find DMA controller.\n");
  691                 return (ENXIO);
  692         }
  693 
  694         /* Alloc xDMA virtual channel. */
  695         sc->xchan = xdma_channel_alloc(sc->xdma_tx, 0);
  696         if (sc->xchan == NULL) {
  697                 device_printf(dev, "Can't alloc virtual DMA channel.\n");
  698                 return (ENXIO);
  699         }
  700 
  701         /* Setup sound subsystem */
  702         sc->lock = snd_mtxcreate(device_get_nameunit(dev), "aic softc");
  703         if (sc->lock == NULL) {
  704                 device_printf(dev, "Can't create mtx.\n");
  705                 return (ENXIO);
  706         }
  707 
  708         if (bus_alloc_resources(dev, aic_spec, sc->res)) {
  709                 device_printf(dev,
  710                     "could not allocate resources for device\n");
  711                 return (ENXIO);
  712         }
  713 
  714         /* Memory interface */
  715         sc->bst = rman_get_bustag(sc->res[0]);
  716         sc->bsh = rman_get_bushandle(sc->res[0]);
  717         sc->aic_fifo_paddr = rman_get_start(sc->res[0]) + AICDR;
  718 
  719         /* Setup PCM. */
  720         scp = malloc(sizeof(struct sc_pcminfo), M_DEVBUF, M_WAITOK | M_ZERO);
  721         scp->sc = sc;
  722         scp->dev = dev;
  723 
  724         /* Setup audio buffer. */
  725         err = aic_dma_setup(sc);
  726         if (err != 0) {
  727                 device_printf(dev, "Can't setup sound buffer.\n");
  728                 return (ENXIO);
  729         }
  730 
  731         /* Setup clocks. */
  732         err = aic_configure_clocks(sc);
  733         if (err != 0) {
  734                 device_printf(dev, "Can't configure clocks.\n");
  735                 return (ENXIO);
  736         }
  737 
  738         err = aic_configure(sc);
  739         if (err != 0) {
  740                 device_printf(dev, "Can't configure AIC.\n");
  741                 return (ENXIO);
  742         }
  743 
  744         pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE);
  745 
  746         /* Setup interrupt handler. */
  747         err = xdma_setup_intr(sc->xchan, aic_intr, scp, &sc->ih);
  748         if (err) {
  749                 device_printf(sc->dev,
  750                     "Can't setup xDMA interrupt handler.\n");
  751                 return (ENXIO);
  752         }
  753 
  754         err = pcm_register(dev, scp, 1, 0);
  755         if (err) {
  756                 device_printf(dev, "Can't register pcm.\n");
  757                 return (ENXIO);
  758         }
  759 
  760         scp->chnum = 0;
  761         pcm_addchan(dev, PCMDIR_PLAY, &aicchan_class, scp);
  762         scp->chnum++;
  763 
  764         snprintf(status, SND_STATUSLEN, "at %s", ofw_bus_get_name(dev));
  765         pcm_setstatus(dev, status);
  766 
  767         mixer_init(dev, &aicmixer_class, scp);
  768 
  769         /* Create device sysctl node. */
  770         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
  771             SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  772             OID_AUTO, "internal_codec", CTLTYPE_INT | CTLFLAG_RW,
  773             scp, 0, sysctl_hw_pcm_internal_codec, "I",
  774             "use internal audio codec");
  775 
  776         return (0);
  777 }
  778 
  779 static int
  780 aic_detach(device_t dev)
  781 {
  782         struct aic_softc *sc;
  783 
  784         sc = device_get_softc(dev);
  785 
  786         xdma_channel_free(sc->xchan);
  787 
  788         bus_release_resources(dev, aic_spec, sc->res);
  789 
  790         return (0);
  791 }
  792 
  793 static device_method_t aic_pcm_methods[] = {
  794         /* Device interface */
  795         DEVMETHOD(device_probe,         aic_probe),
  796         DEVMETHOD(device_attach,        aic_attach),
  797         DEVMETHOD(device_detach,        aic_detach),
  798         DEVMETHOD_END
  799 };
  800 
  801 static driver_t aic_pcm_driver = {
  802         "pcm",
  803         aic_pcm_methods,
  804         PCM_SOFTC_SIZE,
  805 };
  806 
  807 DRIVER_MODULE(aic, simplebus, aic_pcm_driver, pcm_devclass, 0, 0);
  808 MODULE_DEPEND(aic, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
  809 MODULE_VERSION(aic, 1);

Cache object: efed909f02fb658fa9f8a5f6b02daa76


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