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/pci/neomagic.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
    5  * All rights reserved.
    6  *
    7  * Derived from the public domain Linux driver
    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, WHETHERIN 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 THEPOSSIBILITY OF
   28  * SUCH DAMAGE.
   29  */
   30 
   31 #ifdef HAVE_KERNEL_OPTION_HEADERS
   32 #include "opt_snd.h"
   33 #endif
   34 
   35 #include <dev/sound/pcm/sound.h>
   36 #include <dev/sound/pcm/ac97.h>
   37 #include <dev/sound/pci/neomagic.h>
   38 #include <dev/sound/pci/neomagic-coeff.h>
   39 
   40 #include <dev/pci/pcireg.h>
   41 #include <dev/pci/pcivar.h>
   42 
   43 SND_DECLARE_FILE("$FreeBSD$");
   44 
   45 /* -------------------------------------------------------------------- */
   46 
   47 #define NM_BUFFSIZE     16384
   48 
   49 #define NM256AV_PCI_ID  0x800510c8
   50 #define NM256ZX_PCI_ID  0x800610c8
   51 
   52 struct sc_info;
   53 
   54 /* channel registers */
   55 struct sc_chinfo {
   56         int active, spd, dir, fmt;
   57         u_int32_t blksize, wmark;
   58         struct snd_dbuf *buffer;
   59         struct pcm_channel *channel;
   60         struct sc_info *parent;
   61 };
   62 
   63 /* device private data */
   64 struct sc_info {
   65         device_t        dev;
   66         u_int32_t       type;
   67 
   68         struct resource *reg, *irq, *buf;
   69         int             regid, irqid, bufid;
   70         void            *ih;
   71 
   72         u_int32_t       ac97_base, ac97_status, ac97_busy;
   73         u_int32_t       buftop, pbuf, rbuf, cbuf, acbuf;
   74         u_int32_t       playint, recint, misc1int, misc2int;
   75         u_int32_t       irsz, badintr;
   76 
   77         struct sc_chinfo pch, rch;
   78 };
   79 
   80 /* -------------------------------------------------------------------- */
   81 
   82 /*
   83  * prototypes
   84  */
   85 
   86 /* stuff */
   87 static int       nm_loadcoeff(struct sc_info *sc, int dir, int num);
   88 static int       nm_setch(struct sc_chinfo *ch);
   89 static int       nm_init(struct sc_info *);
   90 static void      nm_intr(void *);
   91 
   92 /* talk to the card */
   93 static u_int32_t nm_rd(struct sc_info *, int, int);
   94 static void      nm_wr(struct sc_info *, int, u_int32_t, int);
   95 static u_int32_t nm_rdbuf(struct sc_info *, int, int);
   96 static void      nm_wrbuf(struct sc_info *, int, u_int32_t, int);
   97 
   98 static u_int32_t badcards[] = {
   99         0x0007103c,
  100         0x008f1028,
  101         0x00dd1014,
  102         0x8005110a,
  103 };
  104 #define NUM_BADCARDS (sizeof(badcards) / sizeof(u_int32_t))
  105 
  106 /* The actual rates supported by the card. */
  107 static int samplerates[9] = {
  108         8000,
  109         11025,
  110         16000,
  111         22050,
  112         24000,
  113         32000,
  114         44100,
  115         48000,
  116         99999999
  117 };
  118 
  119 /* -------------------------------------------------------------------- */
  120 
  121 static u_int32_t nm_fmt[] = {
  122         SND_FORMAT(AFMT_U8, 1, 0),
  123         SND_FORMAT(AFMT_U8, 2, 0),
  124         SND_FORMAT(AFMT_S16_LE, 1, 0),
  125         SND_FORMAT(AFMT_S16_LE, 2, 0),
  126         0
  127 };
  128 static struct pcmchan_caps nm_caps = {4000, 48000, nm_fmt, 0};
  129 
  130 /* -------------------------------------------------------------------- */
  131 
  132 /* Hardware */
  133 static u_int32_t
  134 nm_rd(struct sc_info *sc, int regno, int size)
  135 {
  136         bus_space_tag_t st = rman_get_bustag(sc->reg);
  137         bus_space_handle_t sh = rman_get_bushandle(sc->reg);
  138 
  139         switch (size) {
  140         case 1:
  141                 return bus_space_read_1(st, sh, regno);
  142         case 2:
  143                 return bus_space_read_2(st, sh, regno);
  144         case 4:
  145                 return bus_space_read_4(st, sh, regno);
  146         default:
  147                 return 0xffffffff;
  148         }
  149 }
  150 
  151 static void
  152 nm_wr(struct sc_info *sc, int regno, u_int32_t data, int size)
  153 {
  154         bus_space_tag_t st = rman_get_bustag(sc->reg);
  155         bus_space_handle_t sh = rman_get_bushandle(sc->reg);
  156 
  157         switch (size) {
  158         case 1:
  159                 bus_space_write_1(st, sh, regno, data);
  160                 break;
  161         case 2:
  162                 bus_space_write_2(st, sh, regno, data);
  163                 break;
  164         case 4:
  165                 bus_space_write_4(st, sh, regno, data);
  166                 break;
  167         }
  168 }
  169 
  170 static u_int32_t
  171 nm_rdbuf(struct sc_info *sc, int regno, int size)
  172 {
  173         bus_space_tag_t st = rman_get_bustag(sc->buf);
  174         bus_space_handle_t sh = rman_get_bushandle(sc->buf);
  175 
  176         switch (size) {
  177         case 1:
  178                 return bus_space_read_1(st, sh, regno);
  179         case 2:
  180                 return bus_space_read_2(st, sh, regno);
  181         case 4:
  182                 return bus_space_read_4(st, sh, regno);
  183         default:
  184                 return 0xffffffff;
  185         }
  186 }
  187 
  188 static void
  189 nm_wrbuf(struct sc_info *sc, int regno, u_int32_t data, int size)
  190 {
  191         bus_space_tag_t st = rman_get_bustag(sc->buf);
  192         bus_space_handle_t sh = rman_get_bushandle(sc->buf);
  193 
  194         switch (size) {
  195         case 1:
  196                 bus_space_write_1(st, sh, regno, data);
  197                 break;
  198         case 2:
  199                 bus_space_write_2(st, sh, regno, data);
  200                 break;
  201         case 4:
  202                 bus_space_write_4(st, sh, regno, data);
  203                 break;
  204         }
  205 }
  206 
  207 /* -------------------------------------------------------------------- */
  208 /* ac97 codec */
  209 static int
  210 nm_waitcd(struct sc_info *sc)
  211 {
  212         int cnt = 10;
  213         int fail = 1;
  214 
  215         while (cnt-- > 0) {
  216                 if (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy) {
  217                         DELAY(100);
  218                 } else {
  219                         fail = 0;
  220                         break;
  221                 }
  222         }
  223         return (fail);
  224 }
  225 
  226 static u_int32_t
  227 nm_initcd(kobj_t obj, void *devinfo)
  228 {
  229         struct sc_info *sc = (struct sc_info *)devinfo;
  230 
  231         nm_wr(sc, 0x6c0, 0x01, 1);
  232 #if 0
  233         /*
  234          * The following code-line may cause a hang for some chipsets, see
  235          * PR 56617.
  236          * In case of a bugreport without this line have a look at the PR and
  237          * conditionize the code-line based upon the specific version of
  238          * the chip.
  239          */
  240         nm_wr(sc, 0x6cc, 0x87, 1);
  241 #endif
  242         nm_wr(sc, 0x6cc, 0x80, 1);
  243         nm_wr(sc, 0x6cc, 0x00, 1);
  244         return 1;
  245 }
  246 
  247 static int
  248 nm_rdcd(kobj_t obj, void *devinfo, int regno)
  249 {
  250         struct sc_info *sc = (struct sc_info *)devinfo;
  251         u_int32_t x;
  252 
  253         if (!nm_waitcd(sc)) {
  254                 x = nm_rd(sc, sc->ac97_base + regno, 2);
  255                 DELAY(1000);
  256                 return x;
  257         } else {
  258                 device_printf(sc->dev, "ac97 codec not ready\n");
  259                 return -1;
  260         }
  261 }
  262 
  263 static int
  264 nm_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
  265 {
  266         struct sc_info *sc = (struct sc_info *)devinfo;
  267         int cnt = 3;
  268 
  269         if (!nm_waitcd(sc)) {
  270                 while (cnt-- > 0) {
  271                         nm_wr(sc, sc->ac97_base + regno, data, 2);
  272                         if (!nm_waitcd(sc)) {
  273                                 DELAY(1000);
  274                                 return 0;
  275                         }
  276                 }
  277         }
  278         device_printf(sc->dev, "ac97 codec not ready\n");
  279         return -1;
  280 }
  281 
  282 static kobj_method_t nm_ac97_methods[] = {
  283         KOBJMETHOD(ac97_init,           nm_initcd),
  284         KOBJMETHOD(ac97_read,           nm_rdcd),
  285         KOBJMETHOD(ac97_write,          nm_wrcd),
  286         KOBJMETHOD_END
  287 };
  288 AC97_DECLARE(nm_ac97);
  289 
  290 /* -------------------------------------------------------------------- */
  291 
  292 static void
  293 nm_ackint(struct sc_info *sc, u_int32_t num)
  294 {
  295         if (sc->type == NM256AV_PCI_ID) {
  296                 nm_wr(sc, NM_INT_REG, num << 1, 2);
  297         } else if (sc->type == NM256ZX_PCI_ID) {
  298                 nm_wr(sc, NM_INT_REG, num, 4);
  299         }
  300 }
  301 
  302 static int
  303 nm_loadcoeff(struct sc_info *sc, int dir, int num)
  304 {
  305         int ofs, sz, i;
  306         u_int32_t addr;
  307 
  308         addr = (dir == PCMDIR_PLAY)? 0x01c : 0x21c;
  309         if (dir == PCMDIR_REC)
  310                 num += 8;
  311         sz = coefficientSizes[num];
  312         ofs = 0;
  313         while (num-- > 0)
  314                 ofs+= coefficientSizes[num];
  315         for (i = 0; i < sz; i++)
  316                 nm_wrbuf(sc, sc->cbuf + i, coefficients[ofs + i], 1);
  317         nm_wr(sc, addr, sc->cbuf, 4);
  318         if (dir == PCMDIR_PLAY)
  319                 sz--;
  320         nm_wr(sc, addr + 4, sc->cbuf + sz, 4);
  321         return 0;
  322 }
  323 
  324 static int
  325 nm_setch(struct sc_chinfo *ch)
  326 {
  327         struct sc_info *sc = ch->parent;
  328         u_int32_t base;
  329         u_int8_t x;
  330 
  331         for (x = 0; x < 8; x++)
  332                 if (ch->spd < (samplerates[x] + samplerates[x + 1]) / 2)
  333                         break;
  334 
  335         if (x == 8) return 1;
  336 
  337         ch->spd = samplerates[x];
  338         nm_loadcoeff(sc, ch->dir, x);
  339 
  340         x <<= 4;
  341         x &= NM_RATE_MASK;
  342         if (ch->fmt & AFMT_16BIT) x |= NM_RATE_BITS_16;
  343         if (AFMT_CHANNEL(ch->fmt) > 1) x |= NM_RATE_STEREO;
  344 
  345         base = (ch->dir == PCMDIR_PLAY)? NM_PLAYBACK_REG_OFFSET : NM_RECORD_REG_OFFSET;
  346         nm_wr(sc, base + NM_RATE_REG_OFFSET, x, 1);
  347         return 0;
  348 }
  349 
  350 /* channel interface */
  351 static void *
  352 nmchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
  353 {
  354         struct sc_info *sc = devinfo;
  355         struct sc_chinfo *ch;
  356         u_int32_t chnbuf;
  357 
  358         chnbuf = (dir == PCMDIR_PLAY)? sc->pbuf : sc->rbuf;
  359         ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
  360         ch->active = 0;
  361         ch->blksize = 0;
  362         ch->wmark = 0;
  363         ch->buffer = b;
  364         sndbuf_setup(ch->buffer, (u_int8_t *)rman_get_virtual(sc->buf) + chnbuf, NM_BUFFSIZE);
  365         if (bootverbose)
  366                 device_printf(sc->dev, "%s buf %p\n", (dir == PCMDIR_PLAY)?
  367                               "play" : "rec", sndbuf_getbuf(ch->buffer));
  368         ch->parent = sc;
  369         ch->channel = c;
  370         ch->dir = dir;
  371         return ch;
  372 }
  373 
  374 static int
  375 nmchan_free(kobj_t obj, void *data)
  376 {
  377         return 0;
  378 }
  379 
  380 static int
  381 nmchan_setformat(kobj_t obj, void *data, u_int32_t format)
  382 {
  383         struct sc_chinfo *ch = data;
  384 
  385         ch->fmt = format;
  386         return nm_setch(ch);
  387 }
  388 
  389 static u_int32_t
  390 nmchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
  391 {
  392         struct sc_chinfo *ch = data;
  393 
  394         ch->spd = speed;
  395         return nm_setch(ch)? 0 : ch->spd;
  396 }
  397 
  398 static u_int32_t
  399 nmchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
  400 {
  401         struct sc_chinfo *ch = data;
  402 
  403         ch->blksize = blocksize;
  404 
  405         return blocksize;
  406 }
  407 
  408 static int
  409 nmchan_trigger(kobj_t obj, void *data, int go)
  410 {
  411         struct sc_chinfo *ch = data;
  412         struct sc_info *sc = ch->parent;
  413         int ssz;
  414 
  415         if (!PCMTRIG_COMMON(go))
  416                 return 0;
  417 
  418         ssz = (ch->fmt & AFMT_16BIT)? 2 : 1;
  419         if (AFMT_CHANNEL(ch->fmt) > 1)
  420                 ssz <<= 1;
  421 
  422         if (ch->dir == PCMDIR_PLAY) {
  423                 if (go == PCMTRIG_START) {
  424                         ch->active = 1;
  425                         ch->wmark = ch->blksize;
  426                         nm_wr(sc, NM_PBUFFER_START, sc->pbuf, 4);
  427                         nm_wr(sc, NM_PBUFFER_END, sc->pbuf + NM_BUFFSIZE - ssz, 4);
  428                         nm_wr(sc, NM_PBUFFER_CURRP, sc->pbuf, 4);
  429                         nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + ch->wmark, 4);
  430                         nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
  431                                 NM_PLAYBACK_ENABLE_FLAG, 1);
  432                         nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2);
  433                 } else {
  434                         ch->active = 0;
  435                         nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1);
  436                         nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2);
  437                 }
  438         } else {
  439                 if (go == PCMTRIG_START) {
  440                         ch->active = 1;
  441                         ch->wmark = ch->blksize;
  442                         nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
  443                                 NM_RECORD_ENABLE_FLAG, 1);
  444                         nm_wr(sc, NM_RBUFFER_START, sc->rbuf, 4);
  445                         nm_wr(sc, NM_RBUFFER_END, sc->rbuf + NM_BUFFSIZE, 4);
  446                         nm_wr(sc, NM_RBUFFER_CURRP, sc->rbuf, 4);
  447                         nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + ch->wmark, 4);
  448                 } else {
  449                         ch->active = 0;
  450                         nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
  451                 }
  452         }
  453         return 0;
  454 }
  455 
  456 static u_int32_t
  457 nmchan_getptr(kobj_t obj, void *data)
  458 {
  459         struct sc_chinfo *ch = data;
  460         struct sc_info *sc = ch->parent;
  461 
  462         if (ch->dir == PCMDIR_PLAY)
  463                 return nm_rd(sc, NM_PBUFFER_CURRP, 4) - sc->pbuf;
  464         else
  465                 return nm_rd(sc, NM_RBUFFER_CURRP, 4) - sc->rbuf;
  466 }
  467 
  468 static struct pcmchan_caps *
  469 nmchan_getcaps(kobj_t obj, void *data)
  470 {
  471         return &nm_caps;
  472 }
  473 
  474 static kobj_method_t nmchan_methods[] = {
  475         KOBJMETHOD(channel_init,                nmchan_init),
  476         KOBJMETHOD(channel_free,                nmchan_free),
  477         KOBJMETHOD(channel_setformat,           nmchan_setformat),
  478         KOBJMETHOD(channel_setspeed,            nmchan_setspeed),
  479         KOBJMETHOD(channel_setblocksize,        nmchan_setblocksize),
  480         KOBJMETHOD(channel_trigger,             nmchan_trigger),
  481         KOBJMETHOD(channel_getptr,              nmchan_getptr),
  482         KOBJMETHOD(channel_getcaps,             nmchan_getcaps),
  483         KOBJMETHOD_END
  484 };
  485 CHANNEL_DECLARE(nmchan);
  486 
  487 /* The interrupt handler */
  488 static void
  489 nm_intr(void *p)
  490 {
  491         struct sc_info *sc = (struct sc_info *)p;
  492         int status, x;
  493 
  494         status = nm_rd(sc, NM_INT_REG, sc->irsz);
  495         if (status == 0)
  496                 return;
  497 
  498         if (status & sc->playint) {
  499                 status &= ~sc->playint;
  500                 sc->pch.wmark += sc->pch.blksize;
  501                 sc->pch.wmark %= NM_BUFFSIZE;
  502                 nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + sc->pch.wmark, 4);
  503 
  504                 nm_ackint(sc, sc->playint);
  505                 chn_intr(sc->pch.channel);
  506         }
  507         if (status & sc->recint) {
  508                 status &= ~sc->recint;
  509                 sc->rch.wmark += sc->rch.blksize;
  510                 sc->rch.wmark %= NM_BUFFSIZE;
  511                 nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + sc->rch.wmark, 4);
  512 
  513                 nm_ackint(sc, sc->recint);
  514                 chn_intr(sc->rch.channel);
  515         }
  516         if (status & sc->misc1int) {
  517                 status &= ~sc->misc1int;
  518                 nm_ackint(sc, sc->misc1int);
  519                 x = nm_rd(sc, 0x400, 1);
  520                 nm_wr(sc, 0x400, x | 2, 1);
  521                 device_printf(sc->dev, "misc int 1\n");
  522         }
  523         if (status & sc->misc2int) {
  524                 status &= ~sc->misc2int;
  525                 nm_ackint(sc, sc->misc2int);
  526                 x = nm_rd(sc, 0x400, 1);
  527                 nm_wr(sc, 0x400, x & ~2, 1);
  528                 device_printf(sc->dev, "misc int 2\n");
  529         }
  530         if (status) {
  531                 nm_ackint(sc, status);
  532                 device_printf(sc->dev, "unknown int\n");
  533         }
  534 }
  535 
  536 /* -------------------------------------------------------------------- */
  537 
  538 /*
  539  * Probe and attach the card
  540  */
  541 
  542 static int
  543 nm_init(struct sc_info *sc)
  544 {
  545         u_int32_t ofs, i;
  546 
  547         if (sc->type == NM256AV_PCI_ID) {
  548                 sc->ac97_base = NM_MIXER_OFFSET;
  549                 sc->ac97_status = NM_MIXER_STATUS_OFFSET;
  550                 sc->ac97_busy = NM_MIXER_READY_MASK;
  551 
  552                 sc->buftop = 2560 * 1024;
  553 
  554                 sc->irsz = 2;
  555                 sc->playint = NM_PLAYBACK_INT;
  556                 sc->recint = NM_RECORD_INT;
  557                 sc->misc1int = NM_MISC_INT_1;
  558                 sc->misc2int = NM_MISC_INT_2;
  559         } else if (sc->type == NM256ZX_PCI_ID) {
  560                 sc->ac97_base = NM_MIXER_OFFSET;
  561                 sc->ac97_status = NM2_MIXER_STATUS_OFFSET;
  562                 sc->ac97_busy = NM2_MIXER_READY_MASK;
  563 
  564                 sc->buftop = (nm_rd(sc, 0xa0b, 2)? 6144 : 4096) * 1024;
  565 
  566                 sc->irsz = 4;
  567                 sc->playint = NM2_PLAYBACK_INT;
  568                 sc->recint = NM2_RECORD_INT;
  569                 sc->misc1int = NM2_MISC_INT_1;
  570                 sc->misc2int = NM2_MISC_INT_2;
  571         } else return -1;
  572         sc->badintr = 0;
  573         ofs = sc->buftop - 0x0400;
  574         sc->buftop -= 0x1400;
  575 
  576         if (bootverbose)
  577                 device_printf(sc->dev, "buftop is 0x%08x\n", sc->buftop);
  578         if ((nm_rdbuf(sc, ofs, 4) & NM_SIG_MASK) == NM_SIGNATURE) {
  579                 i = nm_rdbuf(sc, ofs + 4, 4);
  580                 if (i != 0 && i != 0xffffffff) {
  581                         if (bootverbose)
  582                                 device_printf(sc->dev, "buftop is changed to 0x%08x\n", i);
  583                         sc->buftop = i;
  584                 }
  585         }
  586 
  587         sc->cbuf = sc->buftop - NM_MAX_COEFFICIENT;
  588         sc->rbuf = sc->cbuf - NM_BUFFSIZE;
  589         sc->pbuf = sc->rbuf - NM_BUFFSIZE;
  590         sc->acbuf = sc->pbuf - (NM_TOTAL_COEFF_COUNT * 4);
  591 
  592         nm_wr(sc, 0, 0x11, 1);
  593         nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
  594         nm_wr(sc, 0x214, 0, 2);
  595 
  596         return 0;
  597 }
  598 
  599 static int
  600 nm_pci_probe(device_t dev)
  601 {
  602         struct sc_info *sc = NULL;
  603         char *s = NULL;
  604         u_int32_t subdev, i;
  605 
  606         subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
  607         switch (pci_get_devid(dev)) {
  608         case NM256AV_PCI_ID:
  609                 i = 0;
  610                 while ((i < NUM_BADCARDS) && (badcards[i] != subdev))
  611                         i++;
  612 
  613                 /* Try to catch other non-ac97 cards */
  614 
  615                 if (i == NUM_BADCARDS) {
  616                         if (!(sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO))) {
  617                                 device_printf(dev, "cannot allocate softc\n");
  618                                 return ENXIO;
  619                         }
  620 
  621                         sc->regid = PCIR_BAR(1);
  622                         sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  623                                                          &sc->regid,
  624                                                          RF_ACTIVE);
  625 
  626                         if (!sc->reg) {
  627                                 device_printf(dev, "unable to map register space\n");
  628                                 free(sc, M_DEVBUF);
  629                                 return ENXIO;
  630                         }
  631 
  632                         /*
  633                          * My Panasonic CF-M2EV needs resetting device
  634                          * before checking mixer is present or not.
  635                          * t.ichinoseki@nifty.com.
  636                          */
  637                         nm_wr(sc, 0, 0x11, 1); /* reset device */
  638                         if ((nm_rd(sc, NM_MIXER_PRESENCE, 2) &
  639                                 NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) {
  640                                 i = 0;  /* non-ac97 card, but not listed */
  641                                 DEB(device_printf(dev, "subdev = 0x%x - badcard?\n",
  642                                     subdev));
  643                         }
  644                         bus_release_resource(dev, SYS_RES_MEMORY, sc->regid,
  645                                              sc->reg);
  646                         free(sc, M_DEVBUF);
  647                 }
  648 
  649                 if (i == NUM_BADCARDS)
  650                         s = "NeoMagic 256AV";
  651                 DEB(else)
  652                         DEB(device_printf(dev, "this is a non-ac97 NM256AV, not attaching\n"));
  653 
  654                 break;
  655 
  656         case NM256ZX_PCI_ID:
  657                 s = "NeoMagic 256ZX";
  658                 break;
  659         }
  660 
  661         if (s) device_set_desc(dev, s);
  662         return s? 0 : ENXIO;
  663 }
  664 
  665 static int
  666 nm_pci_attach(device_t dev)
  667 {
  668         struct sc_info *sc;
  669         struct ac97_info *codec = NULL;
  670         char            status[SND_STATUSLEN];
  671 
  672         sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
  673         sc->dev = dev;
  674         sc->type = pci_get_devid(dev);
  675 
  676         pci_enable_busmaster(dev);
  677 
  678         sc->bufid = PCIR_BAR(0);
  679         sc->buf = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->bufid,
  680                                          RF_ACTIVE);
  681         sc->regid = PCIR_BAR(1);
  682         sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->regid,
  683                                          RF_ACTIVE);
  684 
  685         if (!sc->buf || !sc->reg) {
  686                 device_printf(dev, "unable to map register space\n");
  687                 goto bad;
  688         }
  689 
  690         if (nm_init(sc) == -1) {
  691                 device_printf(dev, "unable to initialize the card\n");
  692                 goto bad;
  693         }
  694 
  695         codec = AC97_CREATE(dev, sc, nm_ac97);
  696         if (codec == NULL) goto bad;
  697         if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
  698 
  699         sc->irqid = 0;
  700         sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
  701                                          RF_ACTIVE | RF_SHAREABLE);
  702         if (!sc->irq || snd_setup_intr(dev, sc->irq, 0, nm_intr, sc, &sc->ih)) {
  703                 device_printf(dev, "unable to map interrupt\n");
  704                 goto bad;
  705         }
  706 
  707         snprintf(status, SND_STATUSLEN, "at memory 0x%jx, 0x%jx irq %jd %s",
  708                  rman_get_start(sc->buf), rman_get_start(sc->reg),
  709                  rman_get_start(sc->irq),PCM_KLDSTRING(snd_neomagic));
  710 
  711         if (pcm_register(dev, sc, 1, 1)) goto bad;
  712         pcm_addchan(dev, PCMDIR_REC, &nmchan_class, sc);
  713         pcm_addchan(dev, PCMDIR_PLAY, &nmchan_class, sc);
  714         pcm_setstatus(dev, status);
  715 
  716         return 0;
  717 
  718 bad:
  719         if (codec) ac97_destroy(codec);
  720         if (sc->buf) bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
  721         if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
  722         if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih);
  723         if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
  724         free(sc, M_DEVBUF);
  725         return ENXIO;
  726 }
  727 
  728 static int
  729 nm_pci_detach(device_t dev)
  730 {
  731         int r;
  732         struct sc_info *sc;
  733 
  734         r = pcm_unregister(dev);
  735         if (r)
  736                 return r;
  737 
  738         sc = pcm_getdevinfo(dev);
  739         bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
  740         bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
  741         bus_teardown_intr(dev, sc->irq, sc->ih);
  742         bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
  743         free(sc, M_DEVBUF);
  744 
  745         return 0;
  746 }
  747 
  748 static int
  749 nm_pci_suspend(device_t dev)
  750 {
  751         struct sc_info *sc;
  752 
  753         sc = pcm_getdevinfo(dev);
  754 
  755         /* stop playing */
  756         if (sc->pch.active) {
  757                 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1);
  758                 nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2);
  759         }
  760         /* stop recording */
  761         if (sc->rch.active) {
  762                 nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
  763         }
  764         return 0;
  765 }
  766 
  767 static int
  768 nm_pci_resume(device_t dev)
  769 {
  770         struct sc_info *sc;
  771 
  772         sc = pcm_getdevinfo(dev);
  773 
  774         /*
  775          * Reinit audio device.
  776          * Don't call nm_init(). It would change buftop if X ran or
  777          * is running. This makes playing and recording buffer address
  778          * shift but these buffers of channel layer are not changed.
  779          * As a result of this inconsistency, periodic noise will be
  780          * generated while playing.
  781          */
  782         nm_wr(sc, 0, 0x11, 1);
  783         nm_wr(sc, 0x214, 0, 2);
  784 
  785         /* Reinit mixer */
  786         if (mixer_reinit(dev) == -1) {
  787                 device_printf(dev, "unable to reinitialize the mixer\n");
  788                 return ENXIO;
  789         }
  790         /* restart playing */
  791         if (sc->pch.active) {
  792                 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
  793                           NM_PLAYBACK_ENABLE_FLAG, 1);
  794                 nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2);
  795         }
  796         /* restart recording */
  797         if (sc->rch.active) {
  798                 nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
  799                           NM_RECORD_ENABLE_FLAG, 1);
  800         }
  801         return 0;
  802 }
  803 
  804 static device_method_t nm_methods[] = {
  805         /* Device interface */
  806         DEVMETHOD(device_probe,         nm_pci_probe),
  807         DEVMETHOD(device_attach,        nm_pci_attach),
  808         DEVMETHOD(device_detach,        nm_pci_detach),
  809         DEVMETHOD(device_suspend,       nm_pci_suspend),
  810         DEVMETHOD(device_resume,        nm_pci_resume),
  811         { 0, 0 }
  812 };
  813 
  814 static driver_t nm_driver = {
  815         "pcm",
  816         nm_methods,
  817         PCM_SOFTC_SIZE,
  818 };
  819 
  820 DRIVER_MODULE(snd_neomagic, pci, nm_driver, 0, 0);
  821 MODULE_DEPEND(snd_neomagic, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
  822 MODULE_VERSION(snd_neomagic, 1);

Cache object: 68ade6ef320a4f1d761eb75ce359e533


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