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/atiixp.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) 2005 Ariff Abdullah <ariff@FreeBSD.org>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 /*
   30  * FreeBSD pcm driver for ATI IXP 150/200/250/300 AC97 controllers
   31  *
   32  * Features
   33  *      * 16bit playback / recording
   34  *      * 32bit native playback - yay!
   35  *      * 32bit native recording (seems broken on few hardwares)
   36  *
   37  * Issues / TODO:
   38  *      * SPDIF
   39  *      * Support for more than 2 channels.
   40  *      * VRA ? VRM ? DRA ?
   41  *      * 32bit native recording seems broken on few hardwares, most
   42  *        probably because of incomplete VRA/DRA cleanup.
   43  *
   44  *
   45  * Thanks goes to:
   46  *
   47  *   Shaharil @ SCAN Associates whom relentlessly providing me the
   48  *   mind blowing Acer Ferrari 4002 WLMi with this ATI IXP hardware.
   49  *
   50  *   Reinoud Zandijk <reinoud@NetBSD.org> (auixp), which this driver is
   51  *   largely based upon although large part of it has been reworked. His
   52  *   driver is the primary reference and pretty much well documented.
   53  *
   54  *   Takashi Iwai (ALSA snd-atiixp), for register definitions and some
   55  *   random ninja hackery.
   56  */
   57 
   58 #ifdef HAVE_KERNEL_OPTION_HEADERS
   59 #include "opt_snd.h"
   60 #endif
   61 
   62 #include <dev/sound/pcm/sound.h>
   63 #include <dev/sound/pcm/ac97.h>
   64 
   65 #include <dev/pci/pcireg.h>
   66 #include <dev/pci/pcivar.h>
   67 #include <sys/sysctl.h>
   68 #include <sys/endian.h>
   69 
   70 #include <dev/sound/pci/atiixp.h>
   71 
   72 SND_DECLARE_FILE("$FreeBSD$");
   73 
   74 #define ATI_IXP_DMA_RETRY_MAX   100
   75 
   76 #define ATI_IXP_BUFSZ_MIN       4096
   77 #define ATI_IXP_BUFSZ_MAX       65536
   78 #define ATI_IXP_BUFSZ_DEFAULT   16384
   79 
   80 #define ATI_IXP_BLK_MIN         32
   81 #define ATI_IXP_BLK_ALIGN       (~(ATI_IXP_BLK_MIN - 1))
   82 
   83 #define ATI_IXP_CHN_RUNNING     0x00000001
   84 #define ATI_IXP_CHN_SUSPEND     0x00000002
   85 
   86 struct atiixp_dma_op {
   87         volatile uint32_t addr;
   88         volatile uint16_t status;
   89         volatile uint16_t size;
   90         volatile uint32_t next;
   91 };
   92 
   93 struct atiixp_info;
   94 
   95 struct atiixp_chinfo {
   96         struct snd_dbuf *buffer;
   97         struct pcm_channel *channel;
   98         struct atiixp_info *parent;
   99         struct atiixp_dma_op *sgd_table;
  100         bus_addr_t sgd_addr;
  101         uint32_t enable_bit, flush_bit, linkptr_bit, dt_cur_bit;
  102         uint32_t blksz, blkcnt;
  103         uint32_t ptr, prevptr;
  104         uint32_t fmt;
  105         uint32_t flags;
  106         int caps_32bit, dir;
  107 };
  108 
  109 struct atiixp_info {
  110         device_t dev;
  111 
  112         bus_space_tag_t st;
  113         bus_space_handle_t sh;
  114         bus_dma_tag_t parent_dmat;
  115         bus_dma_tag_t sgd_dmat;
  116         bus_dmamap_t sgd_dmamap;
  117         bus_addr_t sgd_addr;
  118 
  119         struct resource *reg, *irq;
  120         int regtype, regid, irqid;
  121         void *ih;
  122         struct ac97_info *codec;
  123 
  124         struct atiixp_chinfo pch;
  125         struct atiixp_chinfo rch;
  126         struct atiixp_dma_op *sgd_table;
  127         struct intr_config_hook delayed_attach;
  128 
  129         uint32_t bufsz;
  130         uint32_t codec_not_ready_bits, codec_idx, codec_found;
  131         uint32_t blkcnt;
  132         int registered_channels;
  133 
  134         struct mtx *lock;
  135         struct callout poll_timer;
  136         int poll_ticks, polling;
  137 };
  138 
  139 #define atiixp_rd(_sc, _reg)    \
  140                 bus_space_read_4((_sc)->st, (_sc)->sh, _reg)
  141 #define atiixp_wr(_sc, _reg, _val)      \
  142                 bus_space_write_4((_sc)->st, (_sc)->sh, _reg, _val)
  143 
  144 #define atiixp_lock(_sc)        snd_mtxlock((_sc)->lock)
  145 #define atiixp_unlock(_sc)      snd_mtxunlock((_sc)->lock)
  146 #define atiixp_assert(_sc)      snd_mtxassert((_sc)->lock)
  147 
  148 static uint32_t atiixp_fmt_32bit[] = {
  149         SND_FORMAT(AFMT_S16_LE, 2, 0),
  150         SND_FORMAT(AFMT_S32_LE, 2, 0),
  151         0
  152 };
  153 
  154 static uint32_t atiixp_fmt[] = {
  155         SND_FORMAT(AFMT_S16_LE, 2, 0),
  156         0
  157 };
  158 
  159 static struct pcmchan_caps atiixp_caps_32bit = {
  160         ATI_IXP_BASE_RATE,
  161         ATI_IXP_BASE_RATE,
  162         atiixp_fmt_32bit, 0
  163 };
  164 
  165 static struct pcmchan_caps atiixp_caps = {
  166         ATI_IXP_BASE_RATE,
  167         ATI_IXP_BASE_RATE,
  168         atiixp_fmt, 0
  169 };
  170 
  171 static const struct {
  172         uint16_t vendor;
  173         uint16_t devid;
  174         char     *desc;
  175 } atiixp_hw[] = {
  176         { ATI_VENDOR_ID, ATI_IXP_200_ID, "ATI IXP 200" },
  177         { ATI_VENDOR_ID, ATI_IXP_300_ID, "ATI IXP 300" },
  178         { ATI_VENDOR_ID, ATI_IXP_400_ID, "ATI IXP 400" },
  179         { ATI_VENDOR_ID, ATI_IXP_SB600_ID, "ATI IXP SB600" },
  180 };
  181 
  182 static void atiixp_enable_interrupts(struct atiixp_info *);
  183 static void atiixp_disable_interrupts(struct atiixp_info *);
  184 static void atiixp_reset_aclink(struct atiixp_info *);
  185 static void atiixp_flush_dma(struct atiixp_chinfo *);
  186 static void atiixp_enable_dma(struct atiixp_chinfo *);
  187 static void atiixp_disable_dma(struct atiixp_chinfo *);
  188 
  189 static int atiixp_waitready_codec(struct atiixp_info *);
  190 static int atiixp_rdcd(kobj_t, void *, int);
  191 static int atiixp_wrcd(kobj_t, void *, int, uint32_t);
  192 
  193 static void  *atiixp_chan_init(kobj_t, void *, struct snd_dbuf *,
  194                                                 struct pcm_channel *, int);
  195 static int    atiixp_chan_setformat(kobj_t, void *, uint32_t);
  196 static uint32_t    atiixp_chan_setspeed(kobj_t, void *, uint32_t);
  197 static int         atiixp_chan_setfragments(kobj_t, void *, uint32_t, uint32_t);
  198 static uint32_t    atiixp_chan_setblocksize(kobj_t, void *, uint32_t);
  199 static void   atiixp_buildsgdt(struct atiixp_chinfo *);
  200 static int    atiixp_chan_trigger(kobj_t, void *, int);
  201 static __inline uint32_t atiixp_dmapos(struct atiixp_chinfo *);
  202 static uint32_t          atiixp_chan_getptr(kobj_t, void *);
  203 static struct pcmchan_caps *atiixp_chan_getcaps(kobj_t, void *);
  204 
  205 static void atiixp_intr(void *);
  206 static void atiixp_dma_cb(void *, bus_dma_segment_t *, int, int);
  207 static void atiixp_chip_pre_init(struct atiixp_info *);
  208 static void atiixp_chip_post_init(void *);
  209 static void atiixp_release_resource(struct atiixp_info *);
  210 static int  atiixp_pci_probe(device_t);
  211 static int  atiixp_pci_attach(device_t);
  212 static int  atiixp_pci_detach(device_t);
  213 static int  atiixp_pci_suspend(device_t);
  214 static int  atiixp_pci_resume(device_t);
  215 
  216 /*
  217  * ATI IXP helper functions
  218  */
  219 static void
  220 atiixp_enable_interrupts(struct atiixp_info *sc)
  221 {
  222         uint32_t value;
  223 
  224         /* clear all pending */
  225         atiixp_wr(sc, ATI_REG_ISR, 0xffffffff);
  226 
  227         /* enable all relevant interrupt sources we can handle */
  228         value = atiixp_rd(sc, ATI_REG_IER);
  229 
  230         value |= ATI_REG_IER_IO_STATUS_EN;
  231 
  232         /*
  233          * Disable / ignore internal xrun/spdf interrupt flags
  234          * since it doesn't interest us (for now).
  235          */
  236 #if 1
  237         value &= ~(ATI_REG_IER_IN_XRUN_EN | ATI_REG_IER_OUT_XRUN_EN |
  238             ATI_REG_IER_SPDF_XRUN_EN | ATI_REG_IER_SPDF_STATUS_EN);
  239 #else
  240         value |= ATI_REG_IER_IN_XRUN_EN;
  241         value |= ATI_REG_IER_OUT_XRUN_EN;
  242 
  243         value |= ATI_REG_IER_SPDF_XRUN_EN;
  244         value |= ATI_REG_IER_SPDF_STATUS_EN;
  245 #endif
  246 
  247         atiixp_wr(sc, ATI_REG_IER, value);
  248 }
  249 
  250 static void
  251 atiixp_disable_interrupts(struct atiixp_info *sc)
  252 {
  253         /* disable all interrupt sources */
  254         atiixp_wr(sc, ATI_REG_IER, 0);
  255 
  256         /* clear all pending */
  257         atiixp_wr(sc, ATI_REG_ISR, 0xffffffff);
  258 }
  259 
  260 static void
  261 atiixp_reset_aclink(struct atiixp_info *sc)
  262 {
  263         uint32_t value, timeout;
  264 
  265         /* if power is down, power it up */
  266         value = atiixp_rd(sc, ATI_REG_CMD);
  267         if (value & ATI_REG_CMD_POWERDOWN) {
  268                 /* explicitly enable power */
  269                 value &= ~ATI_REG_CMD_POWERDOWN;
  270                 atiixp_wr(sc, ATI_REG_CMD, value);
  271 
  272                 /* have to wait at least 10 usec for it to initialise */
  273                 DELAY(20);
  274         }
  275 
  276         /* perform a soft reset */
  277         value  = atiixp_rd(sc, ATI_REG_CMD);
  278         value |= ATI_REG_CMD_AC_SOFT_RESET;
  279         atiixp_wr(sc, ATI_REG_CMD, value);
  280 
  281         /* need to read the CMD reg and wait aprox. 10 usec to init */
  282         value  = atiixp_rd(sc, ATI_REG_CMD);
  283         DELAY(20);
  284 
  285         /* clear soft reset flag again */
  286         value  = atiixp_rd(sc, ATI_REG_CMD);
  287         value &= ~ATI_REG_CMD_AC_SOFT_RESET;
  288         atiixp_wr(sc, ATI_REG_CMD, value);
  289 
  290         /* check if the ac-link is working; reset device otherwise */
  291         timeout = 10;
  292         value = atiixp_rd(sc, ATI_REG_CMD);
  293         while (!(value & ATI_REG_CMD_ACLINK_ACTIVE) && --timeout) {
  294 #if 0
  295                 device_printf(sc->dev, "not up; resetting aclink hardware\n");
  296 #endif
  297 
  298                 /* dip aclink reset but keep the acsync */
  299                 value &= ~ATI_REG_CMD_AC_RESET;
  300                 value |=  ATI_REG_CMD_AC_SYNC;
  301                 atiixp_wr(sc, ATI_REG_CMD, value);
  302 
  303                 /* need to read CMD again and wait again (clocking in issue?) */
  304                 value = atiixp_rd(sc, ATI_REG_CMD);
  305                 DELAY(20);
  306 
  307                 /* assert aclink reset again */
  308                 value = atiixp_rd(sc, ATI_REG_CMD);
  309                 value |=  ATI_REG_CMD_AC_RESET;
  310                 atiixp_wr(sc, ATI_REG_CMD, value);
  311 
  312                 /* check if its active now */
  313                 value = atiixp_rd(sc, ATI_REG_CMD);
  314         }
  315 
  316         if (timeout == 0)
  317                 device_printf(sc->dev, "giving up aclink reset\n");
  318 #if 0
  319         if (timeout != 10)
  320                 device_printf(sc->dev, "aclink hardware reset successful\n");
  321 #endif
  322 
  323         /* assert reset and sync for safety */
  324         value  = atiixp_rd(sc, ATI_REG_CMD);
  325         value |= ATI_REG_CMD_AC_SYNC | ATI_REG_CMD_AC_RESET;
  326         atiixp_wr(sc, ATI_REG_CMD, value);
  327 }
  328 
  329 static void
  330 atiixp_flush_dma(struct atiixp_chinfo *ch)
  331 {
  332         atiixp_wr(ch->parent, ATI_REG_FIFO_FLUSH, ch->flush_bit);
  333 }
  334 
  335 static void
  336 atiixp_enable_dma(struct atiixp_chinfo *ch)
  337 {
  338         uint32_t value;
  339 
  340         value = atiixp_rd(ch->parent, ATI_REG_CMD);
  341         if (!(value & ch->enable_bit)) {
  342                 value |= ch->enable_bit;
  343                 atiixp_wr(ch->parent, ATI_REG_CMD, value);
  344         }
  345 }
  346 
  347 static void
  348 atiixp_disable_dma(struct atiixp_chinfo *ch)
  349 {
  350         uint32_t value;
  351 
  352         value = atiixp_rd(ch->parent, ATI_REG_CMD);
  353         if (value & ch->enable_bit) {
  354                 value &= ~ch->enable_bit;
  355                 atiixp_wr(ch->parent, ATI_REG_CMD, value);
  356         }
  357 }
  358 
  359 /*
  360  * AC97 interface
  361  */
  362 static int
  363 atiixp_waitready_codec(struct atiixp_info *sc)
  364 {
  365         int timeout = 500;
  366 
  367         do {
  368                 if ((atiixp_rd(sc, ATI_REG_PHYS_OUT_ADDR) &
  369                     ATI_REG_PHYS_OUT_ADDR_EN) == 0)
  370                         return (0);
  371                 DELAY(1);
  372         } while (--timeout);
  373 
  374         return (-1);
  375 }
  376 
  377 static int
  378 atiixp_rdcd(kobj_t obj, void *devinfo, int reg)
  379 {
  380         struct atiixp_info *sc = devinfo;
  381         uint32_t data;
  382         int timeout;
  383 
  384         if (atiixp_waitready_codec(sc))
  385                 return (-1);
  386 
  387         data = (reg << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
  388             ATI_REG_PHYS_OUT_ADDR_EN | ATI_REG_PHYS_OUT_RW | sc->codec_idx;
  389 
  390         atiixp_wr(sc, ATI_REG_PHYS_OUT_ADDR, data);
  391 
  392         if (atiixp_waitready_codec(sc))
  393                 return (-1);
  394 
  395         timeout = 500;
  396         do {
  397                 data = atiixp_rd(sc, ATI_REG_PHYS_IN_ADDR);
  398                 if (data & ATI_REG_PHYS_IN_READ_FLAG)
  399                         return (data >> ATI_REG_PHYS_IN_DATA_SHIFT);
  400                 DELAY(1);
  401         } while (--timeout);
  402 
  403         if (reg < 0x7c)
  404                 device_printf(sc->dev, "codec read timeout! (reg 0x%x)\n", reg);
  405 
  406         return (-1);
  407 }
  408 
  409 static int
  410 atiixp_wrcd(kobj_t obj, void *devinfo, int reg, uint32_t data)
  411 {
  412         struct atiixp_info *sc = devinfo;
  413 
  414         if (atiixp_waitready_codec(sc))
  415                 return (-1);
  416 
  417         data = (data << ATI_REG_PHYS_OUT_DATA_SHIFT) |
  418             (((uint32_t)reg) << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
  419             ATI_REG_PHYS_OUT_ADDR_EN | sc->codec_idx;
  420 
  421         atiixp_wr(sc, ATI_REG_PHYS_OUT_ADDR, data);
  422 
  423         return (0);
  424 }
  425 
  426 static kobj_method_t atiixp_ac97_methods[] = {
  427         KOBJMETHOD(ac97_read,           atiixp_rdcd),
  428         KOBJMETHOD(ac97_write,          atiixp_wrcd),
  429         KOBJMETHOD_END
  430 };
  431 AC97_DECLARE(atiixp_ac97);
  432 
  433 /*
  434  * Playback / Record channel interface
  435  */
  436 static void *
  437 atiixp_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
  438                                         struct pcm_channel *c, int dir)
  439 {
  440         struct atiixp_info *sc = devinfo;
  441         struct atiixp_chinfo *ch;
  442         int num;
  443 
  444         atiixp_lock(sc);
  445 
  446         if (dir == PCMDIR_PLAY) {
  447                 ch = &sc->pch;
  448                 ch->linkptr_bit = ATI_REG_OUT_DMA_LINKPTR;
  449                 ch->enable_bit = ATI_REG_CMD_OUT_DMA_EN | ATI_REG_CMD_SEND_EN;
  450                 ch->flush_bit = ATI_REG_FIFO_OUT_FLUSH;
  451                 ch->dt_cur_bit = ATI_REG_OUT_DMA_DT_CUR;
  452                 /* Native 32bit playback working properly */
  453                 ch->caps_32bit = 1;
  454         } else {
  455                 ch = &sc->rch;
  456                 ch->linkptr_bit = ATI_REG_IN_DMA_LINKPTR;
  457                 ch->enable_bit = ATI_REG_CMD_IN_DMA_EN | ATI_REG_CMD_RECEIVE_EN;
  458                 ch->flush_bit = ATI_REG_FIFO_IN_FLUSH;
  459                 ch->dt_cur_bit = ATI_REG_IN_DMA_DT_CUR;
  460                 /* XXX Native 32bit recording appear to be broken */
  461                 ch->caps_32bit = 1;
  462         }
  463 
  464         ch->buffer = b;
  465         ch->parent = sc;
  466         ch->channel = c;
  467         ch->dir = dir;
  468         ch->blkcnt = sc->blkcnt;
  469         ch->blksz = sc->bufsz / ch->blkcnt;
  470 
  471         atiixp_unlock(sc);
  472 
  473         if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) == -1)
  474                 return (NULL);
  475 
  476         atiixp_lock(sc);
  477         num = sc->registered_channels++;
  478         ch->sgd_table = &sc->sgd_table[num * ATI_IXP_DMA_CHSEGS_MAX];
  479         ch->sgd_addr = sc->sgd_addr + (num * ATI_IXP_DMA_CHSEGS_MAX *
  480             sizeof(struct atiixp_dma_op));
  481         atiixp_disable_dma(ch);
  482         atiixp_unlock(sc);
  483 
  484         return (ch);
  485 }
  486 
  487 static int
  488 atiixp_chan_setformat(kobj_t obj, void *data, uint32_t format)
  489 {
  490         struct atiixp_chinfo *ch = data;
  491         struct atiixp_info *sc = ch->parent;
  492         uint32_t value;
  493 
  494         atiixp_lock(sc);
  495         if (ch->dir == PCMDIR_REC) {
  496                 value = atiixp_rd(sc, ATI_REG_CMD);
  497                 value &= ~ATI_REG_CMD_INTERLEAVE_IN;
  498                 if ((format & AFMT_32BIT) == 0)
  499                         value |= ATI_REG_CMD_INTERLEAVE_IN;
  500                 atiixp_wr(sc, ATI_REG_CMD, value);
  501         } else {
  502                 value = atiixp_rd(sc, ATI_REG_OUT_DMA_SLOT);
  503                 value &= ~ATI_REG_OUT_DMA_SLOT_MASK;
  504                 /* We do not have support for more than 2 channels, _yet_. */
  505                 value |= ATI_REG_OUT_DMA_SLOT_BIT(3) |
  506                     ATI_REG_OUT_DMA_SLOT_BIT(4);
  507                 value |= 0x04 << ATI_REG_OUT_DMA_THRESHOLD_SHIFT;
  508                 atiixp_wr(sc, ATI_REG_OUT_DMA_SLOT, value);
  509                 value = atiixp_rd(sc, ATI_REG_CMD);
  510                 value &= ~ATI_REG_CMD_INTERLEAVE_OUT;
  511                 if ((format & AFMT_32BIT) == 0)
  512                         value |= ATI_REG_CMD_INTERLEAVE_OUT;
  513                 atiixp_wr(sc, ATI_REG_CMD, value);
  514                 value = atiixp_rd(sc, ATI_REG_6CH_REORDER);
  515                 value &= ~ATI_REG_6CH_REORDER_EN;
  516                 atiixp_wr(sc, ATI_REG_6CH_REORDER, value);
  517         }
  518         ch->fmt = format;
  519         atiixp_unlock(sc);
  520 
  521         return (0);
  522 }
  523 
  524 static uint32_t
  525 atiixp_chan_setspeed(kobj_t obj, void *data, uint32_t spd)
  526 {
  527         /* XXX We're supposed to do VRA/DRA processing right here */
  528         return (ATI_IXP_BASE_RATE);
  529 }
  530 
  531 static int
  532 atiixp_chan_setfragments(kobj_t obj, void *data,
  533                                         uint32_t blksz, uint32_t blkcnt)
  534 {
  535         struct atiixp_chinfo *ch = data;
  536         struct atiixp_info *sc = ch->parent;
  537 
  538         blksz &= ATI_IXP_BLK_ALIGN;
  539 
  540         if (blksz > (sndbuf_getmaxsize(ch->buffer) / ATI_IXP_DMA_CHSEGS_MIN))
  541                 blksz = sndbuf_getmaxsize(ch->buffer) / ATI_IXP_DMA_CHSEGS_MIN;
  542         if (blksz < ATI_IXP_BLK_MIN)
  543                 blksz = ATI_IXP_BLK_MIN;
  544         if (blkcnt > ATI_IXP_DMA_CHSEGS_MAX)
  545                 blkcnt = ATI_IXP_DMA_CHSEGS_MAX;
  546         if (blkcnt < ATI_IXP_DMA_CHSEGS_MIN)
  547                 blkcnt = ATI_IXP_DMA_CHSEGS_MIN;
  548 
  549         while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->buffer)) {
  550                 if ((blkcnt >> 1) >= ATI_IXP_DMA_CHSEGS_MIN)
  551                         blkcnt >>= 1;
  552                 else if ((blksz >> 1) >= ATI_IXP_BLK_MIN)
  553                         blksz >>= 1;
  554                 else
  555                         break;
  556         }
  557 
  558         if ((sndbuf_getblksz(ch->buffer) != blksz ||
  559             sndbuf_getblkcnt(ch->buffer) != blkcnt) &&
  560             sndbuf_resize(ch->buffer, blkcnt, blksz) != 0)
  561                 device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n",
  562                     __func__, blksz, blkcnt);
  563 
  564         ch->blksz = sndbuf_getblksz(ch->buffer);
  565         ch->blkcnt = sndbuf_getblkcnt(ch->buffer);
  566 
  567         return (0);
  568 }
  569 
  570 static uint32_t
  571 atiixp_chan_setblocksize(kobj_t obj, void *data, uint32_t blksz)
  572 {
  573         struct atiixp_chinfo *ch = data;
  574         struct atiixp_info *sc = ch->parent;
  575 
  576         atiixp_chan_setfragments(obj, data, blksz, sc->blkcnt);
  577 
  578         return (ch->blksz);
  579 }
  580 
  581 static void
  582 atiixp_buildsgdt(struct atiixp_chinfo *ch)
  583 {
  584         struct atiixp_info *sc = ch->parent;
  585         uint32_t addr, blksz, blkcnt;
  586         int i;
  587 
  588         addr = sndbuf_getbufaddr(ch->buffer);
  589 
  590         if (sc->polling != 0) {
  591                 blksz = ch->blksz * ch->blkcnt;
  592                 blkcnt = 1;
  593         } else {
  594                 blksz = ch->blksz;
  595                 blkcnt = ch->blkcnt;
  596         }
  597 
  598         for (i = 0; i < blkcnt; i++) {
  599                 ch->sgd_table[i].addr = htole32(addr + (i * blksz));
  600                 ch->sgd_table[i].status = htole16(0);
  601                 ch->sgd_table[i].size = htole16(blksz >> 2);
  602                 ch->sgd_table[i].next = htole32((uint32_t)ch->sgd_addr +
  603                     (((i + 1) % blkcnt) * sizeof(struct atiixp_dma_op)));
  604         }
  605 }
  606 
  607 static __inline uint32_t
  608 atiixp_dmapos(struct atiixp_chinfo *ch)
  609 {
  610         struct atiixp_info *sc = ch->parent;
  611         uint32_t reg, addr, sz, retry;
  612         volatile uint32_t ptr;
  613 
  614         reg = ch->dt_cur_bit;
  615         addr = sndbuf_getbufaddr(ch->buffer);
  616         sz = ch->blkcnt * ch->blksz;
  617         retry = ATI_IXP_DMA_RETRY_MAX;
  618 
  619         do {
  620                 ptr = atiixp_rd(sc, reg);
  621                 if (ptr < addr)
  622                         continue;
  623                 ptr -= addr;
  624                 if (ptr < sz) {
  625 #if 0
  626 #ifdef ATI_IXP_DEBUG
  627                         if ((ptr & ~(ch->blksz - 1)) != ch->ptr) {
  628                                 uint32_t delta;
  629 
  630                                 delta = (sz + ptr - ch->prevptr) % sz;
  631 #ifndef ATI_IXP_DEBUG_VERBOSE
  632                                 if (delta < ch->blksz)
  633 #endif
  634                                         device_printf(sc->dev,
  635                                                 "PCMDIR_%s: incoherent DMA "
  636                                                 "prevptr=%u ptr=%u "
  637                                                 "ptr=%u blkcnt=%u "
  638                                                 "[delta=%u != blksz=%u] "
  639                                                 "(%s)\n",
  640                                                 (ch->dir == PCMDIR_PLAY) ?
  641                                                 "PLAY" : "REC",
  642                                                 ch->prevptr, ptr,
  643                                                 ch->ptr, ch->blkcnt,
  644                                                 delta, ch->blksz,
  645                                                 (delta < ch->blksz) ?
  646                                                 "OVERLAPPED!" : "Ok");
  647                                 ch->ptr = ptr & ~(ch->blksz - 1);
  648                         }
  649                         ch->prevptr = ptr;
  650 #endif
  651 #endif
  652                         return (ptr);
  653                 }
  654         } while (--retry);
  655 
  656         device_printf(sc->dev, "PCMDIR_%s: invalid DMA pointer ptr=%u\n",
  657             (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", ptr);
  658 
  659         return (0);
  660 }
  661 
  662 static __inline int
  663 atiixp_poll_channel(struct atiixp_chinfo *ch)
  664 {
  665         uint32_t sz, delta;
  666         volatile uint32_t ptr;
  667 
  668         if (!(ch->flags & ATI_IXP_CHN_RUNNING))
  669                 return (0);
  670 
  671         sz = ch->blksz * ch->blkcnt;
  672         ptr = atiixp_dmapos(ch);
  673         ch->ptr = ptr;
  674         ptr %= sz;
  675         ptr &= ~(ch->blksz - 1);
  676         delta = (sz + ptr - ch->prevptr) % sz;
  677 
  678         if (delta < ch->blksz)
  679                 return (0);
  680 
  681         ch->prevptr = ptr;
  682 
  683         return (1);
  684 }
  685 
  686 #define atiixp_chan_active(sc)  (((sc)->pch.flags | (sc)->rch.flags) &  \
  687                                  ATI_IXP_CHN_RUNNING)
  688 
  689 static void
  690 atiixp_poll_callback(void *arg)
  691 {
  692         struct atiixp_info *sc = arg;
  693         uint32_t trigger = 0;
  694 
  695         if (sc == NULL)
  696                 return;
  697 
  698         atiixp_lock(sc);
  699         if (sc->polling == 0 || atiixp_chan_active(sc) == 0) {
  700                 atiixp_unlock(sc);
  701                 return;
  702         }
  703 
  704         trigger |= (atiixp_poll_channel(&sc->pch) != 0) ? 1 : 0;
  705         trigger |= (atiixp_poll_channel(&sc->rch) != 0) ? 2 : 0;
  706 
  707         /* XXX */
  708         callout_reset(&sc->poll_timer, 1/*sc->poll_ticks*/,
  709             atiixp_poll_callback, sc);
  710 
  711         atiixp_unlock(sc);
  712 
  713         if (trigger & 1)
  714                 chn_intr(sc->pch.channel);
  715         if (trigger & 2)
  716                 chn_intr(sc->rch.channel);
  717 }
  718 
  719 static int
  720 atiixp_chan_trigger(kobj_t obj, void *data, int go)
  721 {
  722         struct atiixp_chinfo *ch = data;
  723         struct atiixp_info *sc = ch->parent;
  724         uint32_t value;
  725         int pollticks;
  726 
  727         if (!PCMTRIG_COMMON(go))
  728                 return (0);
  729 
  730         atiixp_lock(sc);
  731 
  732         switch (go) {
  733         case PCMTRIG_START:
  734                 atiixp_flush_dma(ch);
  735                 atiixp_buildsgdt(ch);
  736                 atiixp_wr(sc, ch->linkptr_bit, 0);
  737                 atiixp_enable_dma(ch);
  738                 atiixp_wr(sc, ch->linkptr_bit,
  739                     (uint32_t)ch->sgd_addr | ATI_REG_LINKPTR_EN);
  740                 if (sc->polling != 0) {
  741                         ch->ptr = 0;
  742                         ch->prevptr = 0;
  743                         pollticks = ((uint64_t)hz * ch->blksz) /
  744                             ((uint64_t)sndbuf_getalign(ch->buffer) *
  745                             sndbuf_getspd(ch->buffer));
  746                         pollticks >>= 2;
  747                         if (pollticks > hz)
  748                                 pollticks = hz;
  749                         if (pollticks < 1)
  750                                 pollticks = 1;
  751                         if (atiixp_chan_active(sc) == 0 ||
  752                             pollticks < sc->poll_ticks) {
  753                                 if (bootverbose) {
  754                                         if (atiixp_chan_active(sc) == 0)
  755                                                 device_printf(sc->dev,
  756                                                     "%s: pollticks=%d\n",
  757                                                     __func__, pollticks);
  758                                         else
  759                                                 device_printf(sc->dev,
  760                                                     "%s: pollticks %d -> %d\n",
  761                                                     __func__, sc->poll_ticks,
  762                                                     pollticks);
  763                                 }
  764                                 sc->poll_ticks = pollticks;
  765                                 callout_reset(&sc->poll_timer, 1,
  766                                     atiixp_poll_callback, sc);
  767                         }
  768                 }
  769                 ch->flags |= ATI_IXP_CHN_RUNNING;
  770                 break;
  771         case PCMTRIG_STOP:
  772         case PCMTRIG_ABORT:
  773                 atiixp_disable_dma(ch);
  774                 atiixp_flush_dma(ch);
  775                 ch->flags &= ~ATI_IXP_CHN_RUNNING;
  776                 if (sc->polling != 0) {
  777                         if (atiixp_chan_active(sc) == 0) {
  778                                 callout_stop(&sc->poll_timer);
  779                                 sc->poll_ticks = 1;
  780                         } else {
  781                                 if (sc->pch.flags & ATI_IXP_CHN_RUNNING)
  782                                         ch = &sc->pch;
  783                                 else
  784                                         ch = &sc->rch;
  785                                 pollticks = ((uint64_t)hz * ch->blksz) /
  786                                     ((uint64_t)sndbuf_getalign(ch->buffer) *
  787                                     sndbuf_getspd(ch->buffer));
  788                                 pollticks >>= 2;
  789                                 if (pollticks > hz)
  790                                         pollticks = hz;
  791                                 if (pollticks < 1)
  792                                         pollticks = 1;
  793                                 if (pollticks > sc->poll_ticks) {
  794                                         if (bootverbose)
  795                                                 device_printf(sc->dev,
  796                                                     "%s: pollticks %d -> %d\n",
  797                                                     __func__, sc->poll_ticks,
  798                                                     pollticks);
  799                                         sc->poll_ticks = pollticks;
  800                                         callout_reset(&sc->poll_timer,
  801                                             1, atiixp_poll_callback,
  802                                             sc);
  803                                 }
  804                         }
  805                 }
  806                 break;
  807         default:
  808                 atiixp_unlock(sc);
  809                 return (0);
  810                 break;
  811         }
  812 
  813         /* Update bus busy status */
  814         value = atiixp_rd(sc, ATI_REG_IER);
  815         if (atiixp_rd(sc, ATI_REG_CMD) & (ATI_REG_CMD_SEND_EN |
  816             ATI_REG_CMD_RECEIVE_EN | ATI_REG_CMD_SPDF_OUT_EN))
  817                 value |= ATI_REG_IER_SET_BUS_BUSY;
  818         else
  819                 value &= ~ATI_REG_IER_SET_BUS_BUSY;
  820         atiixp_wr(sc, ATI_REG_IER, value);
  821 
  822         atiixp_unlock(sc);
  823 
  824         return (0);
  825 }
  826 
  827 static uint32_t
  828 atiixp_chan_getptr(kobj_t obj, void *data)
  829 {
  830         struct atiixp_chinfo *ch = data;
  831         struct atiixp_info *sc = ch->parent;
  832         uint32_t ptr;
  833 
  834         atiixp_lock(sc);
  835         if (sc->polling != 0)
  836                 ptr = ch->ptr;
  837         else
  838                 ptr = atiixp_dmapos(ch);
  839         atiixp_unlock(sc);
  840 
  841         return (ptr);
  842 }
  843 
  844 static struct pcmchan_caps *
  845 atiixp_chan_getcaps(kobj_t obj, void *data)
  846 {
  847         struct atiixp_chinfo *ch = data;
  848 
  849         if (ch->caps_32bit)
  850                 return (&atiixp_caps_32bit);
  851         return (&atiixp_caps);
  852 }
  853 
  854 static kobj_method_t atiixp_chan_methods[] = {
  855         KOBJMETHOD(channel_init,                atiixp_chan_init),
  856         KOBJMETHOD(channel_setformat,           atiixp_chan_setformat),
  857         KOBJMETHOD(channel_setspeed,            atiixp_chan_setspeed),
  858         KOBJMETHOD(channel_setblocksize,        atiixp_chan_setblocksize),
  859         KOBJMETHOD(channel_setfragments,        atiixp_chan_setfragments),
  860         KOBJMETHOD(channel_trigger,             atiixp_chan_trigger),
  861         KOBJMETHOD(channel_getptr,              atiixp_chan_getptr),
  862         KOBJMETHOD(channel_getcaps,             atiixp_chan_getcaps),
  863         KOBJMETHOD_END
  864 };
  865 CHANNEL_DECLARE(atiixp_chan);
  866 
  867 /*
  868  * PCI driver interface
  869  */
  870 static void
  871 atiixp_intr(void *p)
  872 {
  873         struct atiixp_info *sc = p;
  874         uint32_t status, enable, detected_codecs;
  875         uint32_t trigger = 0;
  876 
  877         atiixp_lock(sc);
  878         if (sc->polling != 0) {
  879                 atiixp_unlock(sc);
  880                 return;
  881         }
  882         status = atiixp_rd(sc, ATI_REG_ISR);
  883 
  884         if (status == 0) {
  885                 atiixp_unlock(sc);
  886                 return;
  887         }
  888 
  889         if ((status & ATI_REG_ISR_OUT_STATUS) &&
  890             (sc->pch.flags & ATI_IXP_CHN_RUNNING))
  891                 trigger |= 1;
  892         if ((status & ATI_REG_ISR_IN_STATUS) &&
  893             (sc->rch.flags & ATI_IXP_CHN_RUNNING))
  894                 trigger |= 2;
  895 
  896 #if 0
  897         if (status & ATI_REG_ISR_IN_XRUN) {
  898                 device_printf(sc->dev,
  899                         "Recieve IN XRUN interrupt\n");
  900         }
  901         if (status & ATI_REG_ISR_OUT_XRUN) {
  902                 device_printf(sc->dev,
  903                         "Recieve OUT XRUN interrupt\n");
  904         }
  905 #endif
  906 
  907         if (status & CODEC_CHECK_BITS) {
  908                 /* mark missing codecs as not ready */
  909                 detected_codecs = status & CODEC_CHECK_BITS;
  910                 sc->codec_not_ready_bits |= detected_codecs;
  911 
  912                 /* disable detected interrupt sources */
  913                 enable  = atiixp_rd(sc, ATI_REG_IER);
  914                 enable &= ~detected_codecs;
  915                 atiixp_wr(sc, ATI_REG_IER, enable);
  916                 wakeup(sc);
  917         }
  918 
  919         /* acknowledge */
  920         atiixp_wr(sc, ATI_REG_ISR, status);
  921         atiixp_unlock(sc);
  922 
  923         if (trigger & 1)
  924                 chn_intr(sc->pch.channel);
  925         if (trigger & 2)
  926                 chn_intr(sc->rch.channel);
  927 }
  928 
  929 static void
  930 atiixp_dma_cb(void *p, bus_dma_segment_t *bds, int a, int b)
  931 {
  932         struct atiixp_info *sc = (struct atiixp_info *)p;
  933         sc->sgd_addr = bds->ds_addr;
  934 }
  935 
  936 static void
  937 atiixp_chip_pre_init(struct atiixp_info *sc)
  938 {
  939         uint32_t value;
  940 
  941         atiixp_lock(sc);
  942 
  943         /* disable interrupts */
  944         atiixp_disable_interrupts(sc);
  945 
  946         /* clear all DMA enables (preserving rest of settings) */
  947         value = atiixp_rd(sc, ATI_REG_CMD);
  948         value &= ~(ATI_REG_CMD_IN_DMA_EN | ATI_REG_CMD_OUT_DMA_EN |
  949             ATI_REG_CMD_SPDF_OUT_EN );
  950         atiixp_wr(sc, ATI_REG_CMD, value);
  951 
  952         /* reset aclink */
  953         atiixp_reset_aclink(sc);
  954 
  955         sc->codec_not_ready_bits = 0;
  956 
  957         /* enable all codecs to interrupt as well as the new frame interrupt */
  958         atiixp_wr(sc, ATI_REG_IER, CODEC_CHECK_BITS);
  959 
  960         atiixp_unlock(sc);
  961 }
  962 
  963 static int
  964 sysctl_atiixp_polling(SYSCTL_HANDLER_ARGS)
  965 {
  966         struct atiixp_info *sc;
  967         device_t dev;
  968         int err, val;
  969 
  970         dev = oidp->oid_arg1;
  971         sc = pcm_getdevinfo(dev);
  972         if (sc == NULL)
  973                 return (EINVAL);
  974         atiixp_lock(sc);
  975         val = sc->polling;
  976         atiixp_unlock(sc);
  977         err = sysctl_handle_int(oidp, &val, 0, req);
  978 
  979         if (err || req->newptr == NULL)
  980                 return (err);
  981         if (val < 0 || val > 1)
  982                 return (EINVAL);
  983 
  984         atiixp_lock(sc);
  985         if (val != sc->polling) {
  986                 if (atiixp_chan_active(sc) != 0)
  987                         err = EBUSY;
  988                 else if (val == 0) {
  989                         atiixp_enable_interrupts(sc);
  990                         sc->polling = 0;
  991                         DELAY(1000);
  992                 } else {
  993                         atiixp_disable_interrupts(sc);
  994                         sc->polling = 1;
  995                         DELAY(1000);
  996                 }
  997         }
  998         atiixp_unlock(sc);
  999 
 1000         return (err);
 1001 }
 1002 
 1003 static void
 1004 atiixp_chip_post_init(void *arg)
 1005 {
 1006         struct atiixp_info *sc = (struct atiixp_info *)arg;
 1007         uint32_t subdev;
 1008         int i, timeout, found, polling;
 1009         char status[SND_STATUSLEN];
 1010 
 1011         atiixp_lock(sc);
 1012 
 1013         if (sc->delayed_attach.ich_func) {
 1014                 config_intrhook_disestablish(&sc->delayed_attach);
 1015                 sc->delayed_attach.ich_func = NULL;
 1016         }
 1017 
 1018         polling = sc->polling;
 1019         sc->polling = 0;
 1020 
 1021         timeout = 10;
 1022         if (sc->codec_not_ready_bits == 0) {
 1023                 /* wait for the interrupts to happen */
 1024                 do {
 1025                         msleep(sc, sc->lock, PWAIT, "ixpslp", max(hz / 10, 1));
 1026                         if (sc->codec_not_ready_bits != 0)
 1027                                 break;
 1028                 } while (--timeout);
 1029         }
 1030 
 1031         sc->polling = polling;
 1032         atiixp_disable_interrupts(sc);
 1033 
 1034         if (sc->codec_not_ready_bits == 0 && timeout == 0) {
 1035                 device_printf(sc->dev,
 1036                         "WARNING: timeout during codec detection; "
 1037                         "codecs might be present but haven't interrupted\n");
 1038                 atiixp_unlock(sc);
 1039                 goto postinitbad;
 1040         }
 1041 
 1042         found = 0;
 1043 
 1044         /*
 1045          * ATI IXP can have upto 3 codecs, but single codec should be
 1046          * suffice for now.
 1047          */
 1048         if (!(sc->codec_not_ready_bits & ATI_REG_ISR_CODEC0_NOT_READY)) {
 1049                 /* codec 0 present */
 1050                 sc->codec_found++;
 1051                 sc->codec_idx = 0;
 1052                 found++;
 1053         }
 1054 
 1055         if (!(sc->codec_not_ready_bits & ATI_REG_ISR_CODEC1_NOT_READY)) {
 1056                 /* codec 1 present */
 1057                 sc->codec_found++;
 1058         }
 1059 
 1060         if (!(sc->codec_not_ready_bits & ATI_REG_ISR_CODEC2_NOT_READY)) {
 1061                 /* codec 2 present */
 1062                 sc->codec_found++;
 1063         }
 1064 
 1065         atiixp_unlock(sc);
 1066 
 1067         if (found == 0)
 1068                 goto postinitbad;
 1069 
 1070         /* create/init mixer */
 1071         sc->codec = AC97_CREATE(sc->dev, sc, atiixp_ac97);
 1072         if (sc->codec == NULL)
 1073                 goto postinitbad;
 1074 
 1075         subdev = (pci_get_subdevice(sc->dev) << 16) |
 1076             pci_get_subvendor(sc->dev);
 1077         switch (subdev) {
 1078         case 0x11831043:        /* ASUS A6R */
 1079         case 0x2043161f:        /* Maxselect x710s - http://maxselect.ru/ */
 1080                 ac97_setflags(sc->codec, ac97_getflags(sc->codec) |
 1081                     AC97_F_EAPD_INV);
 1082                 break;
 1083         default:
 1084                 break;
 1085         }
 1086 
 1087         mixer_init(sc->dev, ac97_getmixerclass(), sc->codec);
 1088 
 1089         if (pcm_register(sc->dev, sc, ATI_IXP_NPCHAN, ATI_IXP_NRCHAN))
 1090                 goto postinitbad;
 1091 
 1092         for (i = 0; i < ATI_IXP_NPCHAN; i++)
 1093                 pcm_addchan(sc->dev, PCMDIR_PLAY, &atiixp_chan_class, sc);
 1094         for (i = 0; i < ATI_IXP_NRCHAN; i++)
 1095                 pcm_addchan(sc->dev, PCMDIR_REC, &atiixp_chan_class, sc);
 1096 
 1097         SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev),
 1098             SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO,
 1099             "polling", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc->dev,
 1100             sizeof(sc->dev), sysctl_atiixp_polling, "I", "Enable polling mode");
 1101 
 1102         snprintf(status, SND_STATUSLEN, "at memory 0x%jx irq %jd %s",
 1103             rman_get_start(sc->reg), rman_get_start(sc->irq),
 1104             PCM_KLDSTRING(snd_atiixp));
 1105 
 1106         pcm_setstatus(sc->dev, status);
 1107 
 1108         atiixp_lock(sc);
 1109         if (sc->polling == 0)
 1110                 atiixp_enable_interrupts(sc);
 1111         atiixp_unlock(sc);
 1112 
 1113         return;
 1114 
 1115 postinitbad:
 1116         atiixp_release_resource(sc);
 1117 }
 1118 
 1119 static void
 1120 atiixp_release_resource(struct atiixp_info *sc)
 1121 {
 1122         if (sc == NULL)
 1123                 return;
 1124         if (sc->registered_channels != 0) {
 1125                 atiixp_lock(sc);
 1126                 sc->polling = 0;
 1127                 callout_stop(&sc->poll_timer);
 1128                 atiixp_unlock(sc);
 1129                 callout_drain(&sc->poll_timer);
 1130         }
 1131         if (sc->codec) {
 1132                 ac97_destroy(sc->codec);
 1133                 sc->codec = NULL;
 1134         }
 1135         if (sc->ih) {
 1136                 bus_teardown_intr(sc->dev, sc->irq, sc->ih);
 1137                 sc->ih = NULL;
 1138         }
 1139         if (sc->reg) {
 1140                 bus_release_resource(sc->dev, sc->regtype, sc->regid, sc->reg);
 1141                 sc->reg = NULL;
 1142         }
 1143         if (sc->irq) {
 1144                 bus_release_resource(sc->dev, SYS_RES_IRQ, sc->irqid, sc->irq);
 1145                 sc->irq = NULL;
 1146         }
 1147         if (sc->parent_dmat) {
 1148                 bus_dma_tag_destroy(sc->parent_dmat);
 1149                 sc->parent_dmat = NULL;
 1150         }
 1151         if (sc->sgd_addr) {
 1152                 bus_dmamap_unload(sc->sgd_dmat, sc->sgd_dmamap);
 1153                 sc->sgd_addr = 0;
 1154         }
 1155         if (sc->sgd_table) {
 1156                 bus_dmamem_free(sc->sgd_dmat, sc->sgd_table, sc->sgd_dmamap);
 1157                 sc->sgd_table = NULL;
 1158         }
 1159         if (sc->sgd_dmat) {
 1160                 bus_dma_tag_destroy(sc->sgd_dmat);
 1161                 sc->sgd_dmat = NULL;
 1162         }
 1163         if (sc->lock) {
 1164                 snd_mtxfree(sc->lock);
 1165                 sc->lock = NULL;
 1166         }
 1167         free(sc, M_DEVBUF);
 1168 }
 1169 
 1170 static int
 1171 atiixp_pci_probe(device_t dev)
 1172 {
 1173         int i;
 1174         uint16_t devid, vendor;
 1175 
 1176         vendor = pci_get_vendor(dev);
 1177         devid = pci_get_device(dev);
 1178         for (i = 0; i < sizeof(atiixp_hw) / sizeof(atiixp_hw[0]); i++) {
 1179                 if (vendor == atiixp_hw[i].vendor &&
 1180                     devid == atiixp_hw[i].devid) {
 1181                         device_set_desc(dev, atiixp_hw[i].desc);
 1182                         return (BUS_PROBE_DEFAULT);
 1183                 }
 1184         }
 1185 
 1186         return (ENXIO);
 1187 }
 1188 
 1189 static int
 1190 atiixp_pci_attach(device_t dev)
 1191 {
 1192         struct atiixp_info *sc;
 1193         int i;
 1194 
 1195         sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
 1196         sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_atiixp softc");
 1197         sc->dev = dev;
 1198 
 1199         callout_init(&sc->poll_timer, 1);
 1200         sc->poll_ticks = 1;
 1201 
 1202         if (resource_int_value(device_get_name(sc->dev),
 1203             device_get_unit(sc->dev), "polling", &i) == 0 && i != 0)
 1204                 sc->polling = 1;
 1205         else
 1206                 sc->polling = 0;
 1207 
 1208         pci_enable_busmaster(dev);
 1209 
 1210         sc->regid = PCIR_BAR(0);
 1211         sc->regtype = SYS_RES_MEMORY;
 1212         sc->reg = bus_alloc_resource_any(dev, sc->regtype,
 1213             &sc->regid, RF_ACTIVE);
 1214 
 1215         if (!sc->reg) {
 1216                 device_printf(dev, "unable to allocate register space\n");
 1217                 goto bad;
 1218         }
 1219 
 1220         sc->st = rman_get_bustag(sc->reg);
 1221         sc->sh = rman_get_bushandle(sc->reg);
 1222 
 1223         sc->bufsz = pcm_getbuffersize(dev, ATI_IXP_BUFSZ_MIN,
 1224             ATI_IXP_BUFSZ_DEFAULT, ATI_IXP_BUFSZ_MAX);
 1225 
 1226         sc->irqid = 0;
 1227         sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
 1228             RF_ACTIVE | RF_SHAREABLE);
 1229         if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE,
 1230             atiixp_intr, sc, &sc->ih)) {
 1231                 device_printf(dev, "unable to map interrupt\n");
 1232                 goto bad;
 1233         }
 1234 
 1235         /*
 1236          * Let the user choose the best DMA segments.
 1237          */
 1238         if (resource_int_value(device_get_name(dev),
 1239             device_get_unit(dev), "blocksize", &i) == 0 && i > 0) {
 1240                 i &= ATI_IXP_BLK_ALIGN;
 1241                 if (i < ATI_IXP_BLK_MIN)
 1242                         i = ATI_IXP_BLK_MIN;
 1243                 sc->blkcnt = sc->bufsz / i;
 1244                 i = 0;
 1245                 while (sc->blkcnt >> i)
 1246                         i++;
 1247                 sc->blkcnt = 1 << (i - 1);
 1248                 if (sc->blkcnt < ATI_IXP_DMA_CHSEGS_MIN)
 1249                         sc->blkcnt = ATI_IXP_DMA_CHSEGS_MIN;
 1250                 else if (sc->blkcnt > ATI_IXP_DMA_CHSEGS_MAX)
 1251                         sc->blkcnt = ATI_IXP_DMA_CHSEGS_MAX;
 1252 
 1253         } else
 1254                 sc->blkcnt = ATI_IXP_DMA_CHSEGS;
 1255 
 1256         /*
 1257          * DMA tag for scatter-gather buffers and link pointers
 1258          */
 1259         if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
 1260                 /*boundary*/0,
 1261                 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
 1262                 /*highaddr*/BUS_SPACE_MAXADDR,
 1263                 /*filter*/NULL, /*filterarg*/NULL,
 1264                 /*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
 1265                 /*flags*/0, /*lockfunc*/NULL,
 1266                 /*lockarg*/NULL, &sc->parent_dmat) != 0) {
 1267                 device_printf(dev, "unable to create dma tag\n");
 1268                 goto bad;
 1269         }
 1270 
 1271         if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
 1272                 /*boundary*/0,
 1273                 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
 1274                 /*highaddr*/BUS_SPACE_MAXADDR,
 1275                 /*filter*/NULL, /*filterarg*/NULL,
 1276                 /*maxsize*/ATI_IXP_DMA_CHSEGS_MAX * ATI_IXP_NCHANS *
 1277                 sizeof(struct atiixp_dma_op),
 1278                 /*nsegments*/1, /*maxsegz*/0x3ffff,
 1279                 /*flags*/0, /*lockfunc*/NULL,
 1280                 /*lockarg*/NULL, &sc->sgd_dmat) != 0) {
 1281                 device_printf(dev, "unable to create dma tag\n");
 1282                 goto bad;
 1283         }
 1284 
 1285         if (bus_dmamem_alloc(sc->sgd_dmat, (void **)&sc->sgd_table,
 1286             BUS_DMA_NOWAIT, &sc->sgd_dmamap) == -1)
 1287                 goto bad;
 1288 
 1289         if (bus_dmamap_load(sc->sgd_dmat, sc->sgd_dmamap, sc->sgd_table,
 1290             ATI_IXP_DMA_CHSEGS_MAX * ATI_IXP_NCHANS *
 1291             sizeof(struct atiixp_dma_op), atiixp_dma_cb, sc, 0))
 1292                 goto bad;
 1293 
 1294         atiixp_chip_pre_init(sc);
 1295 
 1296         sc->delayed_attach.ich_func = atiixp_chip_post_init;
 1297         sc->delayed_attach.ich_arg = sc;
 1298         if (cold == 0 ||
 1299             config_intrhook_establish(&sc->delayed_attach) != 0) {
 1300                 sc->delayed_attach.ich_func = NULL;
 1301                 atiixp_chip_post_init(sc);
 1302         }
 1303 
 1304         return (0);
 1305 
 1306 bad:
 1307         atiixp_release_resource(sc);
 1308         return (ENXIO);
 1309 }
 1310 
 1311 static int
 1312 atiixp_pci_detach(device_t dev)
 1313 {
 1314         int r;
 1315         struct atiixp_info *sc;
 1316 
 1317         sc = pcm_getdevinfo(dev);
 1318         if (sc != NULL) {
 1319                 if (sc->codec != NULL) {
 1320                         r = pcm_unregister(dev);
 1321                         if (r)
 1322                                 return (r);
 1323                 }
 1324                 sc->codec = NULL;
 1325                 if (sc->st != 0 && sc->sh != 0)
 1326                         atiixp_disable_interrupts(sc);
 1327                 atiixp_release_resource(sc);
 1328         }
 1329         return (0);
 1330 }
 1331 
 1332 static int
 1333 atiixp_pci_suspend(device_t dev)
 1334 {
 1335         struct atiixp_info *sc = pcm_getdevinfo(dev);
 1336 
 1337         /* quickly disable interrupts and save channels active state */
 1338         atiixp_lock(sc);
 1339         atiixp_disable_interrupts(sc);
 1340         atiixp_unlock(sc);
 1341 
 1342         /* stop everything */
 1343         if (sc->pch.flags & ATI_IXP_CHN_RUNNING) {
 1344                 atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_STOP);
 1345                 sc->pch.flags |= ATI_IXP_CHN_SUSPEND;
 1346         }
 1347         if (sc->rch.flags & ATI_IXP_CHN_RUNNING) {
 1348                 atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_STOP);
 1349                 sc->rch.flags |= ATI_IXP_CHN_SUSPEND;
 1350         }
 1351 
 1352         /* power down aclink and pci bus */
 1353         atiixp_lock(sc);
 1354         atiixp_wr(sc, ATI_REG_CMD, ATI_REG_CMD_POWERDOWN);
 1355         atiixp_unlock(sc);
 1356 
 1357         return (0);
 1358 }
 1359 
 1360 static int
 1361 atiixp_pci_resume(device_t dev)
 1362 {
 1363         struct atiixp_info *sc = pcm_getdevinfo(dev);
 1364 
 1365         atiixp_lock(sc);
 1366         /* reset / power up aclink */
 1367         atiixp_reset_aclink(sc);
 1368         atiixp_unlock(sc);
 1369 
 1370         if (mixer_reinit(dev) == -1) {
 1371                 device_printf(dev, "unable to reinitialize the mixer\n");
 1372                 return (ENXIO);
 1373         }
 1374 
 1375         /*
 1376          * Resume channel activities. Reset channel format regardless
 1377          * of its previous state.
 1378          */
 1379         if (sc->pch.channel != NULL) {
 1380                 if (sc->pch.fmt != 0)
 1381                         atiixp_chan_setformat(NULL, &sc->pch, sc->pch.fmt);
 1382                 if (sc->pch.flags & ATI_IXP_CHN_SUSPEND) {
 1383                         sc->pch.flags &= ~ATI_IXP_CHN_SUSPEND;
 1384                         atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_START);
 1385                 }
 1386         }
 1387         if (sc->rch.channel != NULL) {
 1388                 if (sc->rch.fmt != 0)
 1389                         atiixp_chan_setformat(NULL, &sc->rch, sc->rch.fmt);
 1390                 if (sc->rch.flags & ATI_IXP_CHN_SUSPEND) {
 1391                         sc->rch.flags &= ~ATI_IXP_CHN_SUSPEND;
 1392                         atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_START);
 1393                 }
 1394         }
 1395 
 1396         /* enable interrupts */
 1397         atiixp_lock(sc);
 1398         if (sc->polling == 0)
 1399                 atiixp_enable_interrupts(sc);
 1400         atiixp_unlock(sc);
 1401 
 1402         return (0);
 1403 }
 1404 
 1405 static device_method_t atiixp_methods[] = {
 1406         DEVMETHOD(device_probe,         atiixp_pci_probe),
 1407         DEVMETHOD(device_attach,        atiixp_pci_attach),
 1408         DEVMETHOD(device_detach,        atiixp_pci_detach),
 1409         DEVMETHOD(device_suspend,       atiixp_pci_suspend),
 1410         DEVMETHOD(device_resume,        atiixp_pci_resume),
 1411         { 0, 0 }
 1412 };
 1413 
 1414 static driver_t atiixp_driver = {
 1415         "pcm",
 1416         atiixp_methods,
 1417         PCM_SOFTC_SIZE,
 1418 };
 1419 
 1420 DRIVER_MODULE(snd_atiixp, pci, atiixp_driver, 0, 0);
 1421 MODULE_DEPEND(snd_atiixp, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
 1422 MODULE_VERSION(snd_atiixp, 1);

Cache object: caca98b814b91f5b6665fce5cd6fe92e


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